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>
45 #include <sys/queue.h>
46 #include <sys/malloc.h>
47 #include <sys/errno.h>
49 #include <sys/thread2.h>
51 #include <machine/clock.h>
52 #include <machine/cpu.h>
56 #include <bus/cam/scsi/scsi_low.h>
58 #include "ncr53c500reg.h"
59 #include "ncr53c500hw.h"
60 #include "ncr53c500var.h"
62 #include "ncr53c500hwtab.h"
64 #define NCV_MAX_DATA_SIZE (64 * 1024)
65 #define NCV_DELAY_MAX (2 * 1000 * 1000)
66 #define NCV_DELAY_INTERVAL (1)
67 #define NCV_PADDING_SIZE (32)
69 /***************************************************
71 ***************************************************/
72 #define NCV_READ_INTERRUPTS_DRIVEN 0x0001
73 #define NCV_WRITE_INTERRUPTS_DRIVEN 0x0002
74 #define NCV_ENABLE_FAST_SCSI 0x0010
75 #define NCV_FAST_INTERRUPTS 0x0100
77 u_int ncv_io_control = NCV_IO_CONTROL_FLAGS;
78 int ncv_data_read_bytes = 4096;
79 int ncv_data_write_bytes = 4096;
81 /***************************************************
83 ***************************************************/
86 #endif /* NCV_DEBUG */
93 #endif /* NCV_STATICS */
95 /**************************************************************
97 **************************************************************/
99 static void ncv_pio_read (struct ncv_softc *, u_int8_t *, u_int);
100 static void ncv_pio_write (struct ncv_softc *, u_int8_t *, u_int);
101 static int ncv_msg (struct ncv_softc *, struct targ_info *, u_int);
102 static int ncv_reselected (struct ncv_softc *);
103 static int ncv_disconnected (struct ncv_softc *, struct targ_info *);
105 static __inline void ncvhw_set_count (bus_space_tag_t, bus_space_handle_t, int);
106 static __inline u_int ncvhw_get_count (bus_space_tag_t, bus_space_handle_t);
107 static __inline void ncvhw_select_register_0 (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
108 static __inline void ncvhw_select_register_1 (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
109 static __inline void ncvhw_fpush (bus_space_tag_t, bus_space_handle_t, u_int8_t *, int);
111 static void ncv_pdma_end (struct ncv_softc *sc, struct targ_info *);
112 static int ncv_world_start (struct ncv_softc *, int);
113 static void ncvhw_bus_reset (struct ncv_softc *);
114 static void ncvhw_reset (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
115 static int ncvhw_check (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
116 static void ncvhw_init (bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
117 static int ncvhw_start_selection (struct ncv_softc *sc, struct slccb *);
118 static void ncvhw_attention (struct ncv_softc *);
119 static int ncv_ccb_nexus_establish (struct ncv_softc *);
120 static int ncv_lun_nexus_establish (struct ncv_softc *);
121 static int ncv_target_nexus_establish (struct ncv_softc *);
122 static int ncv_targ_init (struct ncv_softc *, struct targ_info *, int);
123 static int ncv_catch_intr (struct ncv_softc *);
124 #ifdef NCV_POWER_CONTROL
125 static int ncvhw_power (struct ncv_softc *, u_int);
126 #endif /* NCV_POWER_CONTROL */
127 static __inline void ncv_setup_and_start_pio (struct ncv_softc *, u_int);
129 struct scsi_low_funcs ncv_funcs = {
130 SC_LOW_INIT_T ncv_world_start,
131 SC_LOW_BUSRST_T ncvhw_bus_reset,
132 SC_LOW_TARG_INIT_T ncv_targ_init,
133 SC_LOW_LUN_INIT_T NULL,
135 SC_LOW_SELECT_T ncvhw_start_selection,
136 SC_LOW_NEXUS_T ncv_lun_nexus_establish,
137 SC_LOW_NEXUS_T ncv_ccb_nexus_establish,
139 SC_LOW_ATTEN_T ncvhw_attention,
140 SC_LOW_MSG_T ncv_msg,
142 SC_LOW_TIMEOUT_T NULL,
143 SC_LOW_POLL_T ncvintr,
145 NULL, /* SC_LOW_POWER_T ncvhw_power, */
148 /**************************************************************
150 **************************************************************/
152 ncvhw_select_register_0(bus_space_tag_t iot, bus_space_handle_t ioh,
156 bus_space_write_1(iot, ioh, cr0_cfg4, hw->hw_cfg4);
160 ncvhw_select_register_1(bus_space_tag_t iot, bus_space_handle_t ioh,
164 bus_space_write_1(iot, ioh, cr1_cfg5, hw->hw_cfg5);
168 ncvhw_fpush(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t *buf,
173 for (ptr = 0; ptr < len; ptr ++)
174 bus_space_write_1(iot, ioh, cr0_sfifo, buf[ptr]);
178 ncvhw_set_count(bus_space_tag_t iot, bus_space_handle_t ioh, int count)
181 bus_space_write_1(iot, ioh, cr0_tclsb, (u_int8_t) count);
182 bus_space_write_1(iot, ioh, cr0_tcmsb, (u_int8_t) (count >> NBBY));
183 bus_space_write_1(iot, ioh, cr0_tchsb, (u_int8_t) (count >> (NBBY * 2)));
186 static __inline u_int
187 ncvhw_get_count(bus_space_tag_t iot, bus_space_handle_t ioh)
191 count = (u_int) bus_space_read_1(iot, ioh, cr0_tclsb);
192 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tcmsb)) << NBBY;
193 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tchsb)) << (NBBY * 2);
198 ncvhw_check(bus_space_tag_t iot, bus_space_handle_t ioh, struct ncv_hw *hw)
202 ncvhw_select_register_0(iot, ioh, hw);
203 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
204 if (bus_space_read_1(iot, ioh, cr0_cmd) != (CMD_NOP | CMD_DMA))
207 kprintf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n");
208 #endif /* NCV_DEBUG */
212 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
213 if (bus_space_read_1(iot, ioh, cr0_cmd) != CMD_NOP)
216 kprintf("ncv: cr0_cmd CMD_NOP failed\n");
217 #endif /* NCV_DEBUG */
222 ncvhw_reset(iot, ioh, hw);
223 ncvhw_init(iot, ioh, hw);
226 ncvhw_select_register_0(iot, ioh, hw);
227 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
228 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
229 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
230 SCSI_LOW_DELAY(100 * 1000);
233 bus_space_read_1(iot, ioh, cr0_stat);
234 stat = bus_space_read_1(iot, ioh, cr0_istat);
235 SCSI_LOW_DELAY(1000);
237 if (((stat & INTR_SBR) == 0) ||
238 (bus_space_read_1(iot, ioh, cr0_istat) & INTR_SBR))
241 kprintf("ncv: cr0_istat SCSI BUS RESET failed\n");
242 #endif /* NCV_DEBUG */
250 ncvhw_reset(bus_space_tag_t iot, bus_space_handle_t ioh,
254 ncvhw_select_register_0(iot, ioh, hw);
256 /* dummy cmd twice */
257 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
258 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
261 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTCHIP);
263 /* again dummy cmd twice */
264 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
265 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
269 ncvhw_init(bus_space_tag_t iot, bus_space_handle_t ioh,
273 ncvhw_select_register_0(iot, ioh, hw);
274 bus_space_write_1(iot, ioh, cr0_clk, hw->hw_clk);
275 bus_space_write_1(iot, ioh, cr0_srtout, SEL_TOUT);
276 bus_space_write_1(iot, ioh, cr0_period, 0);
277 bus_space_write_1(iot, ioh, cr0_offs, 0);
279 bus_space_write_1(iot, ioh, cr0_cfg1, hw->hw_cfg1);
280 bus_space_write_1(iot, ioh, cr0_cfg2, hw->hw_cfg2);
281 bus_space_write_1(iot, ioh, cr0_cfg3, hw->hw_cfg3);
282 bus_space_write_1(iot, ioh, cr0_tchsb, 0);
284 ncvhw_select_register_1(iot, ioh, hw);
285 bus_space_write_1(iot, ioh, cr1_fstat, 0x0);
286 bus_space_write_1(iot, ioh, cr1_pflag, 0x0);
287 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
289 ncvhw_select_register_0(iot, ioh, hw);
292 #ifdef NCV_POWER_CONTROL
294 ncvhw_power(struct ncv_softc *sc, u_int flags)
296 struct scsi_low_softc *slp = &sc->sc_sclow;
297 bus_space_tag_t iot = sc->sc_iot;
298 bus_space_handle_t ioh = sc->sc_ioh;
300 if (flags == SCSI_LOW_POWDOWN)
302 kprintf("%s power down\n", slp->sl_xname);
303 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
304 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_POWDOWN);
308 switch (sc->sc_rstep)
311 kprintf("%s resume step O\n", slp->sl_xname);
312 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
313 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
317 kprintf("%s resume step I\n", slp->sl_xname);
318 ncvhw_reset(iot, ioh, &sc->sc_hw);
319 ncvhw_init(iot, ioh, &sc->sc_hw);
326 #endif /* NCV_POWER_CONTROL */
328 /**************************************************************
330 **************************************************************/
332 ncvhw_attention(struct ncv_softc *sc)
335 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd, CMD_SETATN);
340 ncvhw_bus_reset(struct ncv_softc *sc)
342 bus_space_tag_t iot = sc->sc_iot;
343 bus_space_handle_t ioh = sc->sc_ioh;
345 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
346 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
347 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
348 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
352 ncvhw_start_selection(struct ncv_softc *sc, struct slccb *cb)
354 struct scsi_low_softc *slp = &sc->sc_sclow;
355 bus_space_tag_t iot = sc->sc_iot;
356 bus_space_handle_t ioh = sc->sc_ioh;
357 struct targ_info *ti = cb->ti;
362 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
364 if (scsi_low_is_msgout_continue(ti, SCSI_LOW_MSG_IDENTIFY) == 0)
368 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
370 else if (scsi_low_is_msgout_continue(ti,
371 SCSI_LOW_MSG_IDENTIFY | SCSI_LOW_MSG_SIMPLE_QTAG) == 0)
375 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
381 flags = SCSI_LOW_MSGOUT_INIT;
384 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
385 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
386 return SCSI_LOW_START_FAIL;
388 ncv_target_nexus_establish(sc);
390 len = scsi_low_msgout(slp, ti, flags);
391 if (sc->sc_selstop == 0)
392 scsi_low_cmd(slp, ti);
395 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
398 return SCSI_LOW_START_FAIL;
401 bus_space_write_1(iot, ioh, cr0_dstid, ti->ti_id);
402 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
403 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
404 if (sc->sc_selstop == 0)
406 ncvhw_fpush(iot, ioh,
407 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
409 bus_space_write_1(iot, ioh, cr0_cmd, cmd);
412 SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
413 return SCSI_LOW_START_OK;
417 ncv_world_start(struct ncv_softc *sc, int fdone)
419 struct scsi_low_softc *slp = &sc->sc_sclow;
420 bus_space_tag_t iot = sc->sc_iot;
421 bus_space_handle_t ioh = sc->sc_ioh;
424 if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
425 sc->sc_hw.hw_cfg1 |= C1_PARENB;
427 sc->sc_hw.hw_cfg1 &= ~C1_PARENB;
429 ncvhw_reset(iot, ioh, &sc->sc_hw);
430 ncvhw_init(iot, ioh, &sc->sc_hw);
432 scsi_low_bus_reset(slp);
434 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
435 bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_stat);
436 stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat);
437 SCSI_LOW_DELAY(1000);
439 if (((stat & INTR_SBR) == 0) ||
440 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat) & INTR_SBR))
443 SOFT_INTR_REQUIRED(slp);
448 ncv_msg(struct ncv_softc *sc, struct targ_info *ti, u_int msg)
450 bus_space_tag_t iot = sc->sc_iot;
451 bus_space_handle_t ioh = sc->sc_ioh;
452 struct ncv_targ_info *nti = (void *) ti;
453 u_int hwcycle, period;
455 if ((msg & SCSI_LOW_MSG_WIDE) != 0)
457 if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
459 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
465 if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
468 period = ti->ti_maxsynch.period;
469 hwcycle = (sc->sc_hw.hw_clk == 0) ? 40 : (5 * sc->sc_hw.hw_clk);
470 hwcycle = 1000 / hwcycle;
472 if (period < 200 / 4 && period >= 100 / 4)
473 nti->nti_reg_cfg3 |= sc->sc_hw.hw_cfg3_fscsi;
475 nti->nti_reg_cfg3 &= ~sc->sc_hw.hw_cfg3_fscsi;
477 period = ((period * 40 / hwcycle) + 5) / 10;
478 nti->nti_reg_period = period & 0x1f;
479 nti->nti_reg_offset = ti->ti_maxsynch.offset;
481 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
482 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
483 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
488 ncv_targ_init(struct ncv_softc *sc, struct targ_info *ti, int action)
490 struct ncv_targ_info *nti = (void *) ti;
492 if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
494 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
495 ti->ti_maxsynch.period = sc->sc_hw.hw_mperiod;
496 ti->ti_maxsynch.offset = sc->sc_hw.hw_moffset;
498 nti->nti_reg_cfg3 = sc->sc_hw.hw_cfg3;
499 nti->nti_reg_period = 0;
500 nti->nti_reg_offset = 0;
505 /**************************************************************
506 * General probe attach
507 **************************************************************/
508 static int ncv_setup_img (struct ncv_hw *, u_int, int);
511 ncv_setup_img(struct ncv_hw *hw, u_int dvcfg, int hostid)
514 if (NCV_CLKFACTOR(dvcfg) > CLK_35M_F)
516 kprintf("ncv: invalid dvcfg flags\n");
520 if (NCV_C5IMG(dvcfg) != 0)
522 hw->hw_cfg5 = NCV_C5IMG(dvcfg);
523 hw->hw_clk = NCV_CLKFACTOR(dvcfg);
525 if ((ncv_io_control & NCV_ENABLE_FAST_SCSI) != 0 &&
526 (NCV_SPECIAL(dvcfg) & NCVHWCFG_MAX10M) != 0)
527 hw->hw_mperiod = 100 / 4;
529 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_FIFOBUG)
530 hw->hw_cfg3_fclk = 0x04;
532 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SCSI1)
533 hw->hw_cfg2 &= ~C2_SCSI2;
535 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SLOW)
536 hw->hw_cfg1 |= C1_SLOW;
539 /* setup configuration image 3 */
540 if (hw->hw_clk != CLK_40M_F && hw->hw_clk <= CLK_25M_F)
541 hw->hw_cfg3 &= ~hw->hw_cfg3_fclk;
543 hw->hw_cfg3 |= hw->hw_cfg3_fclk;
545 /* setup configuration image 1 */
546 hw->hw_cfg1 = (hw->hw_cfg1 & 0xf0) | hostid;
551 ncvprobesubr(bus_space_tag_t iot, bus_space_handle_t ioh, u_int dvcfg,
556 hwtab = ncv_template;
557 if (ncv_setup_img(&hwtab, dvcfg, hsid))
559 if (ncvhw_check(iot, ioh, &hwtab) != 0)
566 ncvprint(void *aux, const char *name)
570 kprintf("%s: scsibus ", name);
575 ncvattachsubr(struct ncv_softc *sc)
577 struct scsi_low_softc *slp = &sc->sc_sclow;
580 sc->sc_hw = ncv_template;
581 ncv_setup_img(&sc->sc_hw, slp->sl_cfgflags, slp->sl_hostid);
582 slp->sl_funcs = &ncv_funcs;
583 slp->sl_flags |= HW_READ_PADDING;
584 sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
586 (void) scsi_low_attach(slp, 0, NCV_NTARGETS, NCV_NLUNS,
587 sizeof(struct ncv_targ_info), 0);
590 /**************************************************************
592 **************************************************************/
594 ncv_setup_and_start_pio(struct ncv_softc *sc, u_int reqlen)
596 bus_space_tag_t iot = sc->sc_iot;
597 bus_space_handle_t ioh = sc->sc_ioh;
599 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
600 ncvhw_set_count(iot, ioh, reqlen);
601 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS | CMD_DMA);
603 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
604 bus_space_write_1(iot, ioh, cr1_fstat, FIFO_EN);
608 ncv_pdma_end(struct ncv_softc *sc, struct targ_info *ti)
610 struct scsi_low_softc *slp = &sc->sc_sclow;
611 bus_space_tag_t iot = sc->sc_iot;
612 bus_space_handle_t ioh = sc->sc_ioh;
615 slp->sl_flags &= ~HW_PDMASTART;
616 if (slp->sl_Qnexus == NULL)
618 slp->sl_error |= PDMAERR;
622 if (ti->ti_phase == PH_DATA)
624 len = ncvhw_get_count(sc->sc_iot, sc->sc_ioh);
625 if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE)
626 len += (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
627 cr0_sffl) & CR0_SFFLR_BMASK);
629 if ((u_int) len <= (u_int) sc->sc_sdatalen)
631 if ((slp->sl_scp.scp_direction == SCSI_LOW_READ) &&
632 sc->sc_tdatalen != len)
635 len = sc->sc_sdatalen - len;
636 if ((u_int) len > (u_int) slp->sl_scp.scp_datalen)
639 slp->sl_scp.scp_data += len;
640 slp->sl_scp.scp_datalen -= len;
645 if ((slp->sl_error & PDMAERR) == 0)
647 kprintf("%s: strange cnt hw 0x%x soft 0x%x\n",
649 slp->sl_scp.scp_datalen);
651 slp->sl_error |= PDMAERR;
653 scsi_low_data_finish(slp);
657 kprintf("%s: data phase miss\n", slp->sl_xname);
658 slp->sl_error |= PDMAERR;
662 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
663 bus_space_write_1(iot, ioh, cr1_fstat, 0);
664 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
668 ncv_pio_read(struct ncv_softc *sc, u_int8_t *buf, u_int reqlen)
670 struct scsi_low_softc *slp = &sc->sc_sclow;
671 bus_space_tag_t iot = sc->sc_iot;
672 bus_space_handle_t ioh = sc->sc_ioh;
676 ncv_setup_and_start_pio(sc, reqlen);
677 slp->sl_flags |= HW_PDMASTART;
678 sc->sc_sdatalen = reqlen;
679 tout = sc->sc_tmaxcnt;
681 while (reqlen >= FIFO_F_SZ && tout -- > 0)
683 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
684 if (fstat == (u_int8_t) -1)
688 #define NCV_FAST32_ACCESS
689 #ifdef NCV_FAST32_ACCESS
690 bus_space_read_multi_4(iot, ioh, cr1_fdata,
691 (u_int32_t *) buf, FIFO_F_SZ / 4);
692 #else /* !NCV_FAST32_ACCESS */
693 bus_space_read_multi_2(iot, ioh, cr1_fdata,
694 (u_int16_t *) buf, FIFO_F_SZ / 2);
695 #endif /* !NCV_FAST32_ACCESS */
701 if (fstat & FIFO_BRK)
708 while (reqlen > 0 && tout -- > 0)
710 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
711 if ((fstat & FIFO_E) == 0)
713 *buf++ = bus_space_read_1(iot, ioh, cr1_fdata);
718 if (fstat & FIFO_BRK)
726 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
727 sc->sc_tdatalen = reqlen;
731 ncv_pio_write(struct ncv_softc *sc, u_int8_t *buf, u_int reqlen)
733 struct scsi_low_softc *slp = &sc->sc_sclow;
734 bus_space_tag_t iot = sc->sc_iot;
735 bus_space_handle_t ioh = sc->sc_ioh;
739 ncv_setup_and_start_pio(sc, reqlen);
740 sc->sc_sdatalen = reqlen;
741 tout = sc->sc_tmaxcnt;
742 slp->sl_flags |= HW_PDMASTART;
744 while (reqlen >= FIFO_F_SZ && tout -- > 0)
746 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
747 if (fstat & FIFO_BRK)
750 if ((fstat & FIFO_E) != 0)
752 #ifdef NCV_FAST32_ACCESS
753 bus_space_write_multi_4(iot, ioh, cr1_fdata,
754 (u_int32_t *) buf, FIFO_F_SZ / 4);
755 #else /* !NCV_FAST32_ACCESS */
756 bus_space_write_multi_2(iot, ioh, cr1_fdata,
757 (u_int16_t *) buf, FIFO_F_SZ / 2);
758 #endif /* !NCV_FAST32_ACCESS */
768 while (reqlen > 0 && tout -- > 0)
770 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
771 if (fstat & FIFO_BRK)
774 if ((fstat & FIFO_F) == 0) /* fifo not full */
776 bus_space_write_1(iot, ioh, cr1_fdata, *buf++);
786 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
789 /**************************************************************
790 * disconnect & reselect (HW low)
791 **************************************************************/
793 ncv_reselected(struct ncv_softc *sc)
795 struct scsi_low_softc *slp = &sc->sc_sclow;
796 bus_space_tag_t iot = sc->sc_iot;
797 bus_space_handle_t ioh = sc->sc_ioh;
798 struct targ_info *ti;
801 if ((bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK) != 2)
803 kprintf("%s illegal fifo bytes\n", slp->sl_xname);
804 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "chip confused");
808 sid = (u_int) bus_space_read_1(iot, ioh, cr0_sfifo);
809 sid &= ~(1 << slp->sl_hostid);
811 ti = scsi_low_reselected((struct scsi_low_softc *) sc, sid);
816 ncv_statics.reselect ++;
817 #endif /* NCV_STATICS */
818 bus_space_write_1(iot, ioh, cr0_dstid, sid);
823 ncv_disconnected(struct ncv_softc *sc, struct targ_info *ti)
825 struct scsi_low_softc *slp = &sc->sc_sclow;
826 bus_space_tag_t iot = sc->sc_iot;
827 bus_space_handle_t ioh = sc->sc_ioh;
829 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
830 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ENSEL);
833 ncv_statics.disconnect ++;
834 #endif /* NCV_STATICS */
836 scsi_low_disconnected(slp, ti);
840 /**************************************************************
842 **************************************************************/
844 ncv_target_nexus_establish(struct ncv_softc *sc)
846 struct scsi_low_softc *slp = &sc->sc_sclow;
847 struct targ_info *ti = slp->sl_Tnexus;
848 struct ncv_targ_info *nti = (void *) ti;
849 bus_space_tag_t iot = sc->sc_iot;
850 bus_space_handle_t ioh = sc->sc_ioh;
852 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
853 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
854 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
859 ncv_lun_nexus_establish(struct ncv_softc *sc)
866 ncv_ccb_nexus_establish(struct ncv_softc *sc)
868 struct scsi_low_softc *slp = &sc->sc_sclow;
869 struct slccb *cb = slp->sl_Qnexus;
871 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
876 ncv_catch_intr(struct ncv_softc *sc)
878 bus_space_tag_t iot = sc->sc_iot;
879 bus_space_handle_t ioh = sc->sc_ioh;
883 for (wc = 0; wc < NCV_DELAY_MAX / NCV_DELAY_INTERVAL; wc ++)
885 status = bus_space_read_1(iot, ioh, cr0_stat);
886 if ((status & STAT_INT) != 0)
889 SCSI_LOW_DELAY(NCV_DELAY_INTERVAL);
897 struct ncv_softc *sc = arg;
898 struct scsi_low_softc *slp = &sc->sc_sclow;
899 bus_space_tag_t iot = sc->sc_iot;
900 bus_space_handle_t ioh = sc->sc_ioh;
901 struct targ_info *ti;
905 u_int8_t regv, status, ireason;
908 if (slp->sl_flags & HW_INACTIVE)
911 /********************************************
913 ********************************************/
914 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
915 status = bus_space_read_1(iot, ioh, cr0_stat);
916 if ((status & STAT_INT) == 0 || status == (u_int8_t) -1)
919 ireason = bus_space_read_1(iot, ioh, cr0_istat);
920 if ((ireason & INTR_SBR) != 0)
924 /* avoid power off hangup */
925 val = bus_space_read_1(iot, ioh, cr0_cfg1);
926 bus_space_write_1(iot, ioh, cr0_cfg1, val | C1_SRR);
929 scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
930 "bus reset (power off?)");
934 /********************************************
936 ********************************************/
940 scsi_low_print(slp, NULL);
941 kprintf("%s st %x ist %x\n\n", slp->sl_xname,
945 SCSI_LOW_DEBUGGER("ncv");
948 #endif /* NCV_DEBUG */
950 /********************************************
951 * Reselect or Disconnect or Nexus check
952 ********************************************/
954 if (ireason == INTR_RESELECT)
956 if (ncv_reselected(sc) == EJUSTRETURN)
961 if ((ti = slp->sl_Tnexus) == NULL)
965 if ((status & (STAT_PE | STAT_GE)) != 0)
967 slp->sl_error |= PARITYERR;
968 if ((status & PHASE_MASK) == MESSAGE_IN_PHASE)
969 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
971 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
972 derror = SCSI_LOW_DATA_PE;
975 if ((ireason & (INTR_DIS | INTR_ILL)) != 0)
977 if ((ireason & INTR_ILL) == 0)
978 return ncv_disconnected(sc, ti);
980 slp->sl_error |= FATALIO;
981 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "illegal cmd");
985 /********************************************
986 * Internal scsi phase
987 ********************************************/
988 switch (ti->ti_phase)
991 scsi_low_arbit_win(slp);
992 SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
994 if (sc->sc_selstop == 0)
997 * Here scsi phases expected are
999 * MSGIN : target wants to disconnect the host.
1000 * STATUSIN : immediate command completed.
1001 * CMD PHASE : command out failed
1002 * MSGOUT : identify command failed.
1004 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1009 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1011 if ((ireason & INTR_FC) != 0)
1013 SCSI_LOW_ASSERT_ATN(slp);
1016 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1020 ncv_target_nexus_establish(sc);
1021 if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
1023 kprintf("%s: unexpected phase after reselect\n",
1025 slp->sl_error |= FATALIO;
1026 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1032 if ((slp->sl_flags & HW_PDMASTART) != 0)
1034 ncv_pdma_end(sc, ti);
1039 /********************************************
1040 * Scsi phase sequencer
1041 ********************************************/
1042 switch (status & PHASE_MASK)
1044 case DATA_OUT_PHASE: /* data out */
1045 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1046 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
1048 scsi_low_attention(slp);
1051 if (slp->sl_scp.scp_datalen <= 0)
1053 if ((ireason & INTR_BS) == 0)
1056 if ((slp->sl_error & PDMAERR) == 0)
1057 kprintf("%s: data underrun\n", slp->sl_xname);
1058 slp->sl_error |= PDMAERR;
1060 if ((slp->sl_flags & HW_WRITE_PADDING) != 0)
1062 u_int8_t padding[NCV_PADDING_SIZE];
1064 SCSI_LOW_BZERO(padding, sizeof(padding));
1065 ncv_pio_write(sc, padding, sizeof(padding));
1069 kprintf("%s: write padding required\n",
1075 len = slp->sl_scp.scp_datalen;
1076 if ((ncv_io_control & NCV_WRITE_INTERRUPTS_DRIVEN) != 0)
1078 if (len > ncv_data_write_bytes)
1079 len = ncv_data_write_bytes;
1081 ncv_pio_write(sc, slp->sl_scp.scp_data, len);
1085 case DATA_IN_PHASE: /* data in */
1086 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1087 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
1089 scsi_low_attention(slp);
1092 if (slp->sl_scp.scp_datalen <= 0)
1094 if ((ireason & INTR_BS) == 0)
1097 if ((slp->sl_error & PDMAERR) == 0)
1098 kprintf("%s: data overrun\n", slp->sl_xname);
1099 slp->sl_error |= PDMAERR;
1101 if ((slp->sl_flags & HW_READ_PADDING) != 0)
1103 u_int8_t padding[NCV_PADDING_SIZE];
1105 ncv_pio_read(sc, padding, sizeof(padding));
1109 kprintf("%s: read padding required\n",
1116 len = slp->sl_scp.scp_datalen;
1117 if ((ncv_io_control & NCV_READ_INTERRUPTS_DRIVEN) != 0)
1119 if (len > ncv_data_read_bytes)
1120 len = ncv_data_read_bytes;
1122 ncv_pio_read(sc, slp->sl_scp.scp_data, len);
1126 case COMMAND_PHASE: /* cmd out */
1127 SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
1128 if (scsi_low_cmd(slp, ti) != 0)
1130 scsi_low_attention(slp);
1133 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1134 ncvhw_fpush(iot, ioh,
1135 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
1136 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1139 case STATUS_PHASE: /* status in */
1140 SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
1141 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1142 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ICCS);
1149 case MESSAGE_OUT_PHASE: /* msg out */
1150 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1151 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1153 flags = SCSI_LOW_MSGOUT_UNIFY;
1154 if (ti->ti_ophase != ti->ti_phase)
1155 flags |= SCSI_LOW_MSGOUT_INIT;
1156 len = scsi_low_msgout(slp, ti, flags);
1158 if (len > 1 && slp->sl_atten == 0)
1160 scsi_low_attention(slp);
1163 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
1164 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1165 SCSI_LOW_DEASSERT_ATN(slp);
1168 case MESSAGE_IN_PHASE: /* msg in */
1169 SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
1171 len = bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK;
1172 if (sc->sc_compseq != 0)
1175 if ((ireason & INTR_FC) && len == 2)
1177 regv = bus_space_read_1(iot, ioh, cr0_sfifo);
1178 scsi_low_statusin(slp, ti, regv | derror);
1183 slp->sl_error |= FATALIO;
1184 scsi_low_assert_msg(slp, ti,
1185 SCSI_LOW_MSG_ABORT, 1);
1186 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1187 cr0_cmd, CMD_MSGOK);
1191 else if (ireason & INTR_BS)
1193 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1194 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1195 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1197 if (ncv_catch_intr(sc) == 0)
1203 if ((ireason & INTR_FC) && len == 1)
1205 regv = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1207 if (scsi_low_msgin(slp, ti, regv | derror) == 0)
1209 if (scsi_low_is_msgout_continue(ti, 0) != 0)
1211 scsi_low_attention(slp);
1214 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,
1216 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1219 * clear a pending interrupt and sync with
1227 slp->sl_error |= FATALIO;
1228 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1229 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,