diff options
author | non <non@FreeBSD.org> | 2000-10-23 12:55:51 +0000 |
---|---|---|
committer | non <non@FreeBSD.org> | 2000-10-23 12:55:51 +0000 |
commit | 8e8d8815fad836120f63c84071f89cb9552db1e2 (patch) | |
tree | a86ab047759aa8e4af097dccf6d2615932b9bc7e /sys/dev/ncv | |
parent | 7885ad000050949f99433ec9baa0babf83709052 (diff) | |
download | FreeBSD-src-8e8d8815fad836120f63c84071f89cb9552db1e2.zip FreeBSD-src-8e8d8815fad836120f63c84071f89cb9552db1e2.tar.gz |
Add PC-Card/ISA SCSI host adpater drivers from NetBSD/pc98
(a NetBSD port for NEC PC-98x1 machines). They are ncv for NCR 53C500,
nsp for Workbit Ninja SCSI-3, and stg for TMC 18C30 and 18C50.
I thank NetBSD/pc98 and bsd-nomads people.
Obtained from: NetBSD/pc98
Diffstat (limited to 'sys/dev/ncv')
-rw-r--r-- | sys/dev/ncv/ncr53c500.c | 1197 | ||||
-rw-r--r-- | sys/dev/ncv/ncr53c500_pccard.c | 414 | ||||
-rw-r--r-- | sys/dev/ncv/ncr53c500hw.h | 67 | ||||
-rw-r--r-- | sys/dev/ncv/ncr53c500hwtab.h | 47 | ||||
-rw-r--r-- | sys/dev/ncv/ncr53c500reg.h | 192 | ||||
-rw-r--r-- | sys/dev/ncv/ncr53c500var.h | 90 |
6 files changed, 2007 insertions, 0 deletions
diff --git a/sys/dev/ncv/ncr53c500.c b/sys/dev/ncv/ncr53c500.c new file mode 100644 index 0000000..dfbfd3f --- /dev/null +++ b/sys/dev/ncv/ncr53c500.c @@ -0,0 +1,1197 @@ +/* $FreeBSD$ */ +/* $NecBSD: ncr53c500.c,v 1.30 1999/07/23 21:00:04 honda Exp $ */ +/* $NetBSD$ */ + +#define NCV_DEBUG +#define NCV_STATICS + +/* + * [NetBSD for NEC PC-98 series] + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * NetBSD/pc98 porting staff. All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998, 1999 + * Naofumi HONDA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/disklabel.h> +#if defined(__FreeBSD__) && __FreeBSD_version >= 500001 +#include <sys/bio.h> +#endif +#include <sys/buf.h> +#include <sys/queue.h> +#include <sys/malloc.h> +#include <sys/device_port.h> +#include <sys/errno.h> + +#include <vm/vm.h> + +#ifdef __NetBSD__ +#include <machine/bus.h> +#include <machine/intr.h> + +#include <dev/scsipi/scsi_all.h> +#include <dev/scsipi/scsipi_all.h> +#include <dev/scsipi/scsiconf.h> +#include <dev/scsipi/scsi_disk.h> + +#include <machine/dvcfg.h> +#include <machine/physio_proc.h> + +#include <i386/Cbus/dev/scsi_low.h> + +#include <i386/Cbus/dev/ncr53c500reg.h> +#include <i386/Cbus/dev/ncr53c500hw.h> +#include <i386/Cbus/dev/ncr53c500var.h> + +#include <i386/Cbus/dev/ncr53c500hwtab.h> +#endif /* __NetBSD__ */ + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#define delay(time) DELAY(time) + +#include <machine/cpu.h> +#include <machine/bus_pio.h> +#include <machine/bus.h> + +#include <machine/dvcfg.h> +#include <machine/physio_proc.h> + +#include <cam/scsi/scsi_low.h> + +#include <dev/ncv/ncr53c500reg.h> +#include <dev/ncv/ncr53c500hw.h> +#include <dev/ncv/ncr53c500var.h> + +#include <dev/ncv/ncr53c500hwtab.h> + +#if __FreeBSD_version < 400001 +#include "ncv.h" +struct ncv_softc *ncvdata[NNCV]; +#endif +#endif /* __FreeBSD__ */ + +/*************************************************** + * DEBUG + ***************************************************/ +#ifndef DDB +#define Debugger() panic("should call debugger here (ncr53c500.c)") +#else /* ! DDB */ +#ifdef __FreeBSD__ +#define Debugger() Debugger("ncv") +#endif /* __FreeBSD__ */ +#endif + +#ifdef NCV_DEBUG +int ncv_debug; +#endif /* NCV_DEBUG */ + +#ifdef NCV_STATICS +struct ncv_statics { + int disconnect; + int reselect; +} ncv_statics[NCV_NTARGETS]; +#endif /* NCV_STATICS */ + +/*************************************************** + * ISA DEVICE STRUCTURE + ***************************************************/ +extern struct cfdriver ncv_cd; + +/************************************************************** + * DECLARE + **************************************************************/ +/* static */ +static void ncv_pio_read __P((struct ncv_softc *, u_int8_t *, u_int)); +static void ncv_pio_write __P((struct ncv_softc *, u_int8_t *, u_int)); +static int ncv_msg __P((struct ncv_softc *, struct targ_info *, u_int)); +static __inline int ncv_reselected __P((struct ncv_softc *)); +static __inline int ncv_disconnected __P((struct ncv_softc *, struct targ_info *)); +static __inline void ncv_pdma_end __P((struct ncv_softc *sc, struct targ_info *)); + +static __inline void ncvhw_set_count __P((bus_space_tag_t, bus_space_handle_t, int)); +static __inline u_int ncvhw_get_count __P((bus_space_tag_t, bus_space_handle_t)); +static __inline void ncvhw_select_register_0 __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *)); +static __inline void ncvhw_select_register_1 __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *)); +static __inline void ncvhw_fpush __P((bus_space_tag_t, bus_space_handle_t, u_int8_t *, int)); + +static int ncv_world_start __P((struct ncv_softc *, int)); +static void ncvhw_bus_reset __P((struct ncv_softc *)); +static void ncvhw_reset __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *)); +static int ncvhw_check __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *)); +static void ncvhw_init __P((bus_space_tag_t, bus_space_handle_t, struct ncv_hw *)); +static int ncvhw_start_selection __P((struct ncv_softc *sc, struct slccb *)); +static void ncvhw_attention __P((struct ncv_softc *)); +static int ncv_nexus __P((struct ncv_softc *, struct targ_info *)); +#ifdef NCV_POWER_CONTROL +static int ncvhw_power __P((struct ncv_softc *, u_int)); +#endif +static int ncv_lun_init __P((struct ncv_softc *, struct targ_info *, struct lun_info *)); +static void settimeout __P((void *)); + +struct scsi_low_funcs ncv_funcs = { + SC_LOW_INIT_T ncv_world_start, + SC_LOW_BUSRST_T ncvhw_bus_reset, + SC_LOW_LUN_INIT_T ncv_lun_init, + + SC_LOW_SELECT_T ncvhw_start_selection, + SC_LOW_NEXUS_T ncv_nexus, + + SC_LOW_ATTEN_T ncvhw_attention, + SC_LOW_MSG_T ncv_msg, + + SC_LOW_POLL_T ncvintr, + + NULL, /* SC_LOW_POWER_T ncvhw_power, */ +}; + +/************************************************************** + * hwfuncs + **************************************************************/ +static __inline void +ncvhw_select_register_0(iot, ioh, hw) + bus_space_tag_t iot; + bus_space_handle_t ioh; + struct ncv_hw *hw; +{ + + bus_space_write_1(iot, ioh, cr0_cfg4, hw->cfg4); +} + +static __inline void +ncvhw_select_register_1(iot, ioh, hw) + bus_space_tag_t iot; + bus_space_handle_t ioh; + struct ncv_hw *hw; +{ + + bus_space_write_1(iot, ioh, cr1_cfg5, hw->cfg5); +} + +static __inline void +ncvhw_fpush(iot, ioh, buf, len) + bus_space_tag_t iot; + bus_space_handle_t ioh; + u_int8_t *buf; + int len; +{ + int ptr; + + for (ptr = 0; ptr < len; ptr ++) + bus_space_write_1(iot, ioh, cr0_sfifo, buf[ptr]); +} + +static int +ncvhw_check(iot, ioh, hw) + bus_space_tag_t iot; + bus_space_handle_t ioh; + struct ncv_hw *hw; +{ + u_int8_t stat; + + ncvhw_select_register_0(iot, ioh, hw); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA); + if (bus_space_read_1(iot, ioh, cr0_cmd) != (CMD_NOP | CMD_DMA)) + { +#ifdef NCV_DEBUG + printf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n"); +#endif /* NCV_DEBUG */ + return ENODEV; + } + + bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP); + if (bus_space_read_1(iot, ioh, cr0_cmd) != CMD_NOP) + { +#ifdef NCV_DEBUG + printf("ncv: cr0_cmd CMD_NOP failed\n"); +#endif /* NCV_DEBUG */ + return ENODEV; + } + + /* hardware reset */ + ncvhw_reset(iot, ioh, hw); + ncvhw_init(iot, ioh, hw); + + /* bus reset */ + ncvhw_select_register_0(iot, ioh, hw); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA); + delay(100 * 1000); + + /* check response */ + bus_space_read_1(iot, ioh, cr0_stat); + stat = bus_space_read_1(iot, ioh, cr0_istat); + delay(1000); + + if (((stat & INTR_SBR) == 0) || + (bus_space_read_1(iot, ioh, cr0_istat) & INTR_SBR)) + { +#ifdef NCV_DEBUG + printf("ncv: cr0_istat SCSI BUS RESET failed\n"); +#endif /* NCV_DEBUG */ + return ENODEV; + } + + return 0; +} + +static void +ncvhw_reset(iot, ioh, hw) + bus_space_tag_t iot; + bus_space_handle_t ioh; + struct ncv_hw *hw; +{ + + ncvhw_select_register_0(iot, ioh, hw); + + /* dummy cmd twice */ + bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP); + + /* chip reset */ + bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTCHIP); + + /* again dummy cmd twice */ + bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP); +} + +static void +ncvhw_init(iot, ioh, hw) + bus_space_tag_t iot; + bus_space_handle_t ioh; + struct ncv_hw *hw; +{ + + ncvhw_select_register_0(iot, ioh, hw); + bus_space_write_1(iot, ioh, cr0_clk, hw->clk); + bus_space_write_1(iot, ioh, cr0_srtout, SEL_TOUT); + bus_space_write_1(iot, ioh, cr0_period, 0); + bus_space_write_1(iot, ioh, cr0_offs, 0); + + bus_space_write_1(iot, ioh, cr0_cfg1, hw->cfg1); + bus_space_write_1(iot, ioh, cr0_cfg2, hw->cfg2); + bus_space_write_1(iot, ioh, cr0_cfg3, hw->cfg3); + bus_space_write_1(iot, ioh, cr0_tchsb, 0); + + ncvhw_select_register_1(iot, ioh, hw); + bus_space_write_1(iot, ioh, cr1_fstat, 0x0); + bus_space_write_1(iot, ioh, cr1_pflag, 0x0); + bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE); + + ncvhw_select_register_0(iot, ioh, hw); +} + +#ifdef NCV_POWER_CONTROL +static int +ncvhw_power(sc, flags) + struct ncv_softc *sc; + u_int flags; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + + if (flags == SCSI_LOW_POWDOWN) + { + printf("%s power down\n", slp->sl_xname); + ncvhw_select_register_1(iot, ioh, &sc->sc_hw); + bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_POWDOWN); + } + else + { + switch (sc->sc_rstep) + { + case 0: + printf("%s resume step O\n", slp->sl_xname); + ncvhw_select_register_1(iot, ioh, &sc->sc_hw); + bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE); + break; + + case 1: + printf("%s resume step I\n", slp->sl_xname); + ncvhw_reset(iot, ioh, &sc->sc_hw); + ncvhw_init(iot, ioh, &sc->sc_hw); + break; + } + } + + return 0; +} +#endif /* NCV_POWER_CONTROL */ + +/************************************************************** + * scsi low interface + **************************************************************/ +static void +ncvhw_attention(sc) + struct ncv_softc *sc; +{ + + bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd, CMD_SETATN); + delay(10); +} + +static void +ncvhw_bus_reset(sc) + struct ncv_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + + ncvhw_select_register_0(iot, ioh, &sc->sc_hw); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA); +} + +static int +ncvhw_start_selection(sc, cb) + struct ncv_softc *sc; + struct slccb *cb; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + struct targ_info *ti = cb->ti; + int s; + u_int8_t msg; + + msg = ID_MSG_SETUP(ti); + sc->sc_compseq = 0; + ncvhw_select_register_0(iot, ioh, &sc->sc_hw); + + s = splhigh(); + + if (slp->sl_disc > 0 && + (bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_stat) & STAT_INT)) + { + splx(s); + return SCSI_LOW_START_FAIL; + } + + bus_space_write_1(iot, ioh, cr0_dstid, ti->ti_id); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH); + bus_space_write_1(iot, ioh, cr0_sfifo, msg); + + if (scsi_low_is_msgout_continue(ti) != 0) + { + bus_space_write_1(iot, ioh, cr0_cmd, CMD_SELATNS); + sc->sc_selstop = 1; + } + else + { + /* XXX: + * emulate nexus call because ncv bypasses CMD phase. + */ + scsi_low_cmd(slp, ti); + ncvhw_fpush(iot, ioh, + slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_SELATN); + sc->sc_selstop = 0; + } + splx(s); + + SCSI_LOW_TARGET_ASSERT_ATN(ti); + SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART); + return SCSI_LOW_START_OK; +} + +static int +ncv_world_start(sc, fdone) + struct ncv_softc *sc; + int fdone; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + u_int8_t stat; + intrmask_t s; + + ncvhw_reset(iot, ioh, &sc->sc_hw); + ncvhw_init(iot, ioh, &sc->sc_hw); + + s = splcam(); + scsi_low_bus_reset((struct scsi_low_softc *) sc); + + ncvhw_select_register_0(iot, ioh, &sc->sc_hw); + bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_stat); + stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat); + splx(s); + delay(1000); + + if (((stat & INTR_SBR) == 0) || + (bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat) & INTR_SBR)) + return ENODEV; + + SOFT_INTR_REQUIRED(slp); + return 0; +} + +static int +ncv_msg(sc, ti, msg) + struct ncv_softc *sc; + struct targ_info *ti; + u_int msg; +{ + struct lun_info *li = ti->ti_li; + struct ncv_lun_info *nli = (void *) li; + u_int hwcycle, period; + + if ((msg & SCSI_LOW_MSG_SYNCH) == 0) + return 0; + + period = li->li_maxsynch.period; + hwcycle = 1000 / ((sc->sc_hw.clk == 0) ? 40 : (5 * sc->sc_hw.clk)); + + if (period < 200 / 4 && period >= 100 / 4) + nli->nli_reg_cfg3 |= C3_FSCSI; + else + nli->nli_reg_cfg3 &= ~C3_FSCSI; + + period = ((period * 40 / hwcycle) + 5) / 10; + nli->nli_reg_period = period & 0x1f; + nli->nli_reg_offset = li->li_maxsynch.offset; + return 0; +} + +static int +ncv_lun_init(sc, ti, li) + struct ncv_softc *sc; + struct targ_info *ti; + struct lun_info *li; +{ + struct ncv_lun_info *nli = (void *) li; + + li->li_maxsynch.period = sc->sc_hw.mperiod; + li->li_maxsynch.offset = sc->sc_hw.moffset; + + nli->nli_reg_cfg3 = sc->sc_hw.cfg3; + nli->nli_reg_period = 0; + nli->nli_reg_offset = 0; + return 0; +} + +/************************************************************** + * General probe attach + **************************************************************/ +static int ncv_setup_img __P((struct ncv_hw *, u_int, int)); + +static int +ncv_setup_img(hw, dvcfg, hsid) + struct ncv_hw *hw; + u_int dvcfg; + int hsid; +{ + + if (NCV_CLKFACTOR(dvcfg) > CLK_35M_F) + { + printf("ncv: invalid dvcfg flags\n"); + return EINVAL; + } + + if (NCV_C5IMG(dvcfg) != 0) + { + hw->cfg5 = NCV_C5IMG(dvcfg); + hw->clk = NCV_CLKFACTOR(dvcfg); + + if (NCV_SPECIAL(dvcfg) & NCVHWCFG_MAX10M) + hw->mperiod = 100 / 4; + + /* XXX: + * RATOC scsi cards have fatal fifo asic bug. + * To avoid it, currently make sync offset 0 (async)! + */ + if (NCV_SPECIAL(dvcfg) & NCVHWCFG_FIFOBUG) + { + hw->mperiod = 0; + hw->moffset = 0; + } + + if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SCSI1) + hw->cfg2 &= ~C2_SCSI2; + + if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SLOW) + hw->cfg1 |= C1_SLOW; + } + + /* setup configuration image 3 */ + if (hw->clk != CLK_40M_F && hw->clk <= CLK_25M_F) + hw->cfg3 &= ~C3_FCLK; + + /* setup configuration image 1 */ + hw->cfg1 = (hw->cfg1 & 0xf0) | hsid; + return 0; +} + +int +ncvprobesubr(iot, ioh, dvcfg, hsid) + bus_space_tag_t iot; + bus_space_handle_t ioh; + u_int dvcfg; + int hsid; +{ + struct ncv_hw hwtab; + + hwtab = ncv_template; + if (ncv_setup_img(&hwtab, dvcfg, hsid)) + return 0; + if (ncvhw_check(iot, ioh, &hwtab) != 0) + return 0; + + return 1; +} + +int +ncvprint(aux, name) + void *aux; + const char *name; +{ + + if (name != NULL) + printf("%s: scsibus ", name); + return UNCONF; +} + +void +ncvattachsubr(sc) + struct ncv_softc *sc; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + + printf("\n"); + sc->sc_hw = ncv_template; + ncv_setup_img(&sc->sc_hw, slp->sl_cfgflags, slp->sl_hostid); + slp->sl_funcs = &ncv_funcs; + (void) scsi_low_attach(slp, 2, NCV_NTARGETS, NCV_NLUNS, + sizeof(struct ncv_lun_info)); +} + +/************************************************************** + * PDMA + **************************************************************/ +static __inline void +ncvhw_set_count(iot, ioh, count) + bus_space_tag_t iot; + bus_space_handle_t ioh; + int count; +{ + + bus_space_write_1(iot, ioh, cr0_tclsb, (u_int8_t) count); + bus_space_write_1(iot, ioh, cr0_tcmsb, (u_int8_t) (count >> NBBY)); + bus_space_write_1(iot, ioh, cr0_tchsb, (u_int8_t) (count >> (NBBY * 2))); +} + +static __inline u_int +ncvhw_get_count(iot, ioh) + bus_space_tag_t iot; + bus_space_handle_t ioh; +{ + u_int count; + + count = (u_int) bus_space_read_1(iot, ioh, cr0_tclsb); + count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tcmsb)) << NBBY; + count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tchsb)) << (NBBY * 2); + return count; +} + +static __inline void +ncv_pdma_end(sc, ti) + struct ncv_softc *sc; + struct targ_info *ti; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int len; + + slp->sl_flags &= ~HW_PDMASTART; + if (ti->ti_phase == PH_DATA) + { + len = ncvhw_get_count(sc->sc_iot, sc->sc_ioh); + if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE) + len += (bus_space_read_1(sc->sc_iot, sc->sc_ioh, + cr0_sffl) & CR0_SFFLR_BMASK); + + if ((u_int) len <= (u_int) slp->sl_scp.scp_datalen) + { + slp->sl_scp.scp_data += (slp->sl_scp.scp_datalen - len); + slp->sl_scp.scp_datalen = len; + if ((slp->sl_scp.scp_direction == SCSI_LOW_READ) && + sc->sc_tdatalen != len) + goto bad; + } + else + { +bad: + slp->sl_error |= PDMAERR; + printf("%s stragne count hw 0x%x soft 0x%x tlen 0x%x\n", + slp->sl_xname, len, slp->sl_scp.scp_datalen, + sc->sc_tdatalen); + } + } + else + { + printf("%s data phase miss\n", slp->sl_xname); + slp->sl_error |= PDMAERR; + } + + ncvhw_select_register_1(iot, ioh, &sc->sc_hw); + bus_space_write_1(iot, ioh, cr1_fstat, 0); + ncvhw_select_register_0(iot, ioh, &sc->sc_hw); +} + +static void +ncv_pio_read(sc, buf, reqlen) + struct ncv_softc *sc; + u_int8_t *buf; + u_int reqlen; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int s; + int tout = 0; + register u_int8_t fstat; +#ifdef __FreeBSD__ + struct callout_handle ch; +#endif + + ncvhw_select_register_1(iot, ioh, &sc->sc_hw); + bus_space_write_1(iot, ioh, cr1_pflag, 0); + + ncvhw_select_register_0(iot, ioh, &sc->sc_hw); + ncvhw_set_count(iot, ioh, reqlen); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS | CMD_DMA); + + ncvhw_select_register_1(iot, ioh, &sc->sc_hw); + bus_space_write_1(iot, ioh, cr1_fstat, FIFO_EN); + slp->sl_flags |= HW_PDMASTART; + +#ifdef __FreeBSD__ + ch = timeout(settimeout, &tout, 2 * hz); +#else + timeout(settimeout, &tout, 2 * hz); +#endif + while (reqlen >= FIFO_F_SZ && tout == 0) + { + fstat = bus_space_read_1(iot, ioh, cr1_fstat); + if (fstat & FIFO_F) + { +#define NCV_FAST32_ACCESS +#ifdef NCV_FAST32_ACCESS + bus_space_read_multi_4(iot, ioh, cr1_fdata, + (u_int32_t *) buf, FIFO_F_SZ / 4); +#else /* !NCV_FAST32_ACCESS */ + bus_space_read_multi_2(iot, ioh, cr1_fdata, + (u_int16_t *) buf, FIFO_F_SZ / 2); +#endif /* !NCV_FAST32_ACCESS */ + buf += FIFO_F_SZ; + reqlen -= FIFO_F_SZ; + continue; + } + else if (fstat & FIFO_BRK) + break; + + } + + if (reqlen >= FIFO_2_SZ) + { + fstat = bus_space_read_1(iot, ioh, cr1_fstat); + if (fstat & FIFO_2) + { +#ifdef NCV_FAST32_ACCESS + bus_space_read_multi_4(iot, ioh, cr1_fdata, + (u_int32_t *) buf, FIFO_2_SZ / 4); +#else /* !NCV_FAST32_ACCESS */ + bus_space_read_multi_2(iot, ioh, cr1_fdata, + (u_int16_t *) buf, FIFO_2_SZ / 2); +#endif /* !NCV_FAST32_ACCESS */ + buf += FIFO_2_SZ; + reqlen -= FIFO_2_SZ; + } + } + + while (reqlen > 0 && tout == 0) + { + fstat = bus_space_read_1(iot, ioh, cr1_fstat); + if ((fstat & FIFO_E) == 0) + { + *buf++ = bus_space_read_1(iot, ioh, cr1_fdata); + reqlen --; + continue; + } + else if (fstat & FIFO_BRK) + break; + + } + + ncvhw_select_register_0(iot, ioh, &sc->sc_hw); + sc->sc_tdatalen = reqlen; + + s = splhigh(); + if (tout == 0) { +#ifdef __FreeBSD__ + untimeout(settimeout, &tout, ch); +#else + untimeout(settimeout, &tout); +#endif + splx(s); + } else { + splx(s); + printf("%s pio read timeout\n", slp->sl_xname); + } +} + +static void +ncv_pio_write(sc, buf, reqlen) + struct ncv_softc *sc; + u_int8_t *buf; + u_int reqlen; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int s; + int tout = 0; + register u_int8_t fstat; +#ifdef __FreeBSD__ + struct callout_handle ch; +#endif + + ncvhw_select_register_1(iot, ioh, &sc->sc_hw); + bus_space_write_1(iot, ioh, cr1_pflag, 0); + + ncvhw_select_register_0(iot, ioh, &sc->sc_hw); + ncvhw_set_count(iot, ioh, reqlen); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS | CMD_DMA); + + ncvhw_select_register_1(iot, ioh, &sc->sc_hw); + bus_space_write_1(iot, ioh, cr1_fstat, FIFO_EN); + slp->sl_flags |= HW_PDMASTART; + +#ifdef __FreeBSD__ + ch = timeout(settimeout, &tout, 2 * hz); +#else + timeout(settimeout, &tout, 2 * hz); +#endif + while (reqlen >= FIFO_F_SZ && tout == 0) + { + fstat = bus_space_read_1(iot, ioh, cr1_fstat); + if (fstat & FIFO_BRK) + goto done; + + if (fstat & FIFO_E) + { +#ifdef NCV_FAST32_ACCESS + bus_space_write_multi_4(iot, ioh, cr1_fdata, + (u_int32_t *) buf, FIFO_F_SZ / 4); +#else /* !NCV_FAST32_ACCESS */ + bus_space_write_multi_2(iot, ioh, cr1_fdata, + (u_int16_t *) buf, FIFO_F_SZ / 2); +#endif /* !NCV_FAST32_ACCESS */ + buf += FIFO_F_SZ; + reqlen -= FIFO_F_SZ; + } + } + + while (reqlen > 0 && tout == 0) + { + fstat = bus_space_read_1(iot, ioh, cr1_fstat); + if (fstat & FIFO_BRK) + break; + + if ((fstat & FIFO_F) == 0) /* fifo not full */ + { + bus_space_write_1(iot, ioh, cr1_fdata, *buf++); + reqlen --; + } + } + +done: + ncvhw_select_register_0(iot, ioh, &sc->sc_hw); + + s = splhigh(); + if (tout == 0) { +#ifdef __FreeBSD__ + untimeout(settimeout, &tout, ch); +#else + untimeout(settimeout, &tout); +#endif + splx(s); + } else { + splx(s); + printf("%s pio write timeout\n", slp->sl_xname); + } +} + +static void +settimeout(arg) + void *arg; +{ + int *tout = arg; + + *tout = 1; +} + +/************************************************************** + * disconnect & reselect (HW low) + **************************************************************/ +static __inline int +ncv_reselected(sc) + struct ncv_softc *sc; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + struct targ_info *ti; + u_int sid; + + if ((bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK) != 2) + { + printf("%s illegal fifo bytes\n", slp->sl_xname); + scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "chip confused"); + return EJUSTRETURN; + } + + sid = (u_int) bus_space_read_1(iot, ioh, cr0_sfifo); + sid = ffs(sid) - 1; + ti = scsi_low_reselected((struct scsi_low_softc *) sc, sid); + if (ti == NULL) + return EJUSTRETURN; + +#ifdef NCV_STATICS + ncv_statics[sid].reselect ++; +#endif /* NCV_STATICS */ + bus_space_write_1(iot, ioh, cr0_dstid, sid); + return 0; +} + +static __inline int +ncv_disconnected(sc, ti) + struct ncv_softc *sc; + struct targ_info *ti; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + + bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH); + bus_space_write_1(iot, ioh, cr0_cfg1, sc->sc_hw.cfg1); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_ENSEL); + +#ifdef NCV_STATICS + if (slp->sl_msgphase == MSGPH_DISC) + ncv_statics[ti->ti_id].disconnect ++; +#endif /* NCV_STATICS */ + + scsi_low_disconnected(slp, ti); + return 1; +} + +/************************************************************** + * SEQUENCER + **************************************************************/ +static int +ncv_nexus(sc, ti) + struct ncv_softc *sc; + struct targ_info *ti; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + struct lun_info *li = ti->ti_li; + struct ncv_lun_info *nli = (void *) li; + + if (li->li_flags & SCSI_LOW_NOPARITY) + bus_space_write_1(iot, ioh, cr0_cfg1, sc->sc_hw.cfg1); + else + bus_space_write_1(iot, ioh, cr0_cfg1, sc->sc_hw.cfg1 | C1_PARENB); + bus_space_write_1(iot, ioh, cr0_period, nli->nli_reg_period); + bus_space_write_1(iot, ioh, cr0_offs, nli->nli_reg_offset); + bus_space_write_1(iot, ioh, cr0_cfg3, nli->nli_reg_cfg3); + return 0; +} + +int +ncvintr(arg) + void *arg; +{ + struct ncv_softc *sc = arg; + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + struct targ_info *ti; + struct physio_proc *pp; + struct buf *bp; + int len, identify; + u_int8_t regv, status, ireason; + + if (slp->sl_flags & HW_INACTIVE) + return 0; + + /******************************************** + * Status + ********************************************/ + ncvhw_select_register_0(iot, ioh, &sc->sc_hw); + status = bus_space_read_1(iot, ioh, cr0_stat); + if ((status & STAT_INT) == 0) + return 0; + + ireason = bus_space_read_1(iot, ioh, cr0_istat); + if (ireason & INTR_SBR) + { + u_int8_t val; + + /* avoid power off hangup */ + val = bus_space_read_1(iot, ioh, cr0_cfg1); + bus_space_write_1(iot, ioh, cr0_cfg1, val | C1_SRR); + + /* status init */ + scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT, + "bus reset (power off?)"); + return 1; + } + + /******************************************** + * Debug section + ********************************************/ +#ifdef NCV_DEBUG + if (ncv_debug) + { + scsi_low_print(slp, NULL); + printf("%s st %x ist %x\n\n", slp->sl_xname, + status, ireason); + if (ncv_debug > 1) + Debugger(); + } +#endif /* NCV_DEBUG */ + + /******************************************** + * Reselect or Disconnect or Nexus check + ********************************************/ + /* (I) reselect */ + if (ireason == INTR_RESELECT) + { + if (ncv_reselected(sc) == EJUSTRETURN) + return 1; + } + + /* (II) nexus */ + if ((ti = slp->sl_nexus) == NULL) + return 0; + + if ((status & (STAT_PE | STAT_GE)) != 0) + { + slp->sl_error |= PARITYERR; + if (ti->ti_phase == PH_MSGIN) + scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 1); + else + scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1); + } + + if ((ireason & (INTR_DIS | INTR_ILL)) != 0) + { + if ((ireason & INTR_ILL) == 0) + return ncv_disconnected(sc, ti); + + slp->sl_error |= FATALIO; + scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "illegal cmd"); + return 1; + } + + /******************************************** + * Internal scsi phase + ********************************************/ + switch (ti->ti_phase) + { + case PH_SELSTART: + scsi_low_arbit_win(slp, ti); + SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); + identify = 0; + + if (sc->sc_selstop == 0) + { + /* XXX: + * Here scsi phases expected are + * DATA PHASE: + * MSGIN : target wants to disconnect the host. + * STATUSIN : immediate command completed. + * MSGOUT : identify command failed. + */ + if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE) + break; + identify = 1; + } + else + { + /* XXX: + * Here scsi phase should be MSGOUT. + * The driver NEVER supports devices + * which neglect ATN singal. + */ + if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE) + { + slp->sl_error |= FATALIO; + scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, + "msgout error"); + return 1; + } + + if ((ireason & INTR_FC) == 0) + identify = 1; + } + + if (identify != 0) + { + printf("%s msg identify failed\n", slp->sl_xname); + scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_IDENTIFY, 0); + } + break; + + case PH_RESEL: + if ((status & PHASE_MASK) != MESSAGE_IN_PHASE) + { + scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1); + return 1; + } + break; + + default: + if (slp->sl_flags & HW_PDMASTART) + ncv_pdma_end(sc, ti); + break; + } + + /******************************************** + * Scsi phase sequencer + ********************************************/ + switch (status & PHASE_MASK) + { + case DATA_OUT_PHASE: /* data out */ + SCSI_LOW_SETUP_PHASE(ti, PH_DATA); + if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0) + break; + + pp = physio_proc_enter(bp); + ncv_pio_write(sc, slp->sl_scp.scp_data, slp->sl_scp.scp_datalen); + physio_proc_leave(pp); + break; + + case DATA_IN_PHASE: /* data in */ + SCSI_LOW_SETUP_PHASE(ti, PH_DATA); + if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0) + break; + + pp = physio_proc_enter(bp); + ncv_pio_read(sc, slp->sl_scp.scp_data, slp->sl_scp.scp_datalen); + physio_proc_leave(pp); + break; + + case COMMAND_PHASE: /* cmd out */ + SCSI_LOW_SETUP_PHASE(ti, PH_CMD); + if (scsi_low_cmd(slp, ti) != 0) + break; + + bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH); + ncvhw_fpush(iot, ioh, + slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS); + break; + + case STATUS_PHASE: /* status in */ + SCSI_LOW_SETUP_PHASE(ti, PH_STAT); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_ICCS); + sc->sc_compseq = 1; + break; + + default: + break; + + case MESSAGE_OUT_PHASE: /* msg out */ + SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH); + + len = scsi_low_msgout(slp, ti); + ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS); + if (scsi_low_is_msgout_continue(ti) == 0) + bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTATN); + break; + + case MESSAGE_IN_PHASE: /* msg in */ + SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); + + len = bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK; + if (sc->sc_compseq != 0) + { + sc->sc_compseq = 0; + if ((ireason & INTR_FC) && len == 2) + { + ti->ti_status = + bus_space_read_1(iot, ioh, cr0_sfifo); + len --; + } + else + { + scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, + "compseq error"); + break; + } + } + else if (ireason & INTR_BS) + { + bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH); + bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS); + break; + } + + if ((ireason & INTR_FC) && len == 1) + { + regv = bus_space_read_1(sc->sc_iot, sc->sc_ioh, + cr0_sfifo); + scsi_low_msgin(slp, ti, regv); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd, + CMD_MSGOK); + } + else + { + slp->sl_error |= MSGERR; + printf("%s st %x ist %x\n\n", slp->sl_xname, + status, ireason); + scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, + "hw msgin error"); + } + break; + } + + return 1; +} diff --git a/sys/dev/ncv/ncr53c500_pccard.c b/sys/dev/ncv/ncr53c500_pccard.c new file mode 100644 index 0000000..d1ffd89 --- /dev/null +++ b/sys/dev/ncv/ncr53c500_pccard.c @@ -0,0 +1,414 @@ +/* $FreeBSD$ */ +/* $NecBSD: ncr53c500_pisa.c,v 1.28 1998/11/26 01:59:11 honda Exp $ */ +/* $NetBSD$ */ + +/* + * [Ported for FreeBSD] + * Copyright (c) 2000 + * Noriaki Mitsunaga, Mitsuru Iwasaki and Takanori Watanabe. + * All rights reserved. + * [NetBSD for NEC PC-98 series] + * Copyright (c) 1995, 1996, 1997, 1998 + * NetBSD/pc98 porting staff. All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998 + * Naofumi HONDA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/disklabel.h> +#if defined(__FreeBSD__) && __FreeBSD_version >= 500001 +#include <sys/bio.h> +#endif +#include <sys/buf.h> +#include <sys/queue.h> +#include <sys/malloc.h> +#include <sys/errno.h> + +#include <vm/vm.h> + +#include <machine/bus.h> +#include <machine/bus_pio.h> +#include <i386/isa/isa_device.h> + +#include <machine/dvcfg.h> + +#if defined(__FreeBSD__) && __FreeBSD_version < 400001 +static struct ncv_softc *ncv_get_softc(int); +extern struct ncv_softc *ncvdata[]; +#define DEVPORT_ALLOCSOFTCFUNC ncv_get_softc +#define DEVPORT_SOFTCARRAY ncvdata +#endif +#include <sys/device_port.h> + +#include <cam/scsi/scsi_low.h> +#include <cam/scsi/scsi_low_pisa.h> + +#include <dev/ncv/ncr53c500reg.h> +#include <dev/ncv/ncr53c500hw.h> +#include <dev/ncv/ncr53c500var.h> +#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD_version < 400001) +#include "ncv.h" +#endif + +#define KME_KXLC004_01 0x1 +#define OFFSET_KME_KXLC004_01 0x10 + +/* pccard support */ +#include "apm.h" +#if NAPM > 0 +#include <machine/apm_bios.h> +#endif /* NAPM > 0 */ + +#include "card.h" +#if NCARD > 0 +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/select.h> +#include <pccard/cardinfo.h> +#include <pccard/slot.h> + +static int ncvprobe(DEVPORT_PDEVICE devi); +static int ncvattach(DEVPORT_PDEVICE devi); + +static int ncv_card_intr __P((DEVPORT_PDEVICE)); +static void ncv_card_unload __P((DEVPORT_PDEVICE)); +#if defined(__FreeBSD__) && __FreeBSD_version < 400001 +static int ncv_card_init __P((DEVPORT_PDEVICE)); +#endif + +#if defined(__FreeBSD__) && __FreeBSD_version >= 400001 +/* + * Additional code for FreeBSD new-bus PCCard frontend + */ + +static void +ncv_pccard_intr(void * arg) +{ + ncvintr(arg); +} + +static void +ncv_release_resource(DEVPORT_PDEVICE dev) +{ + struct ncv_softc *sc = device_get_softc(dev); + + if (sc->ncv_intrhand) { + bus_teardown_intr(dev, sc->irq_res, sc->ncv_intrhand); + } + + if (sc->port_res) { + bus_release_resource(dev, SYS_RES_IOPORT, + sc->port_rid, sc->port_res); + } + + if (sc->irq_res) { + bus_release_resource(dev, SYS_RES_IRQ, + sc->irq_rid, sc->irq_res); + } + + if (sc->mem_res) { + bus_release_resource(dev, SYS_RES_MEMORY, + sc->mem_rid, sc->mem_res); + } +} + +static int +ncv_alloc_resource(DEVPORT_PDEVICE dev) +{ + struct ncv_softc *sc = device_get_softc(dev); + u_int32_t flags = DEVPORT_PDEVFLAGS(dev); + u_int iobase = DEVPORT_PDEVIOBASE(dev); + u_long maddr, msize; + int error; + bus_addr_t offset = 0; + + if(flags & KME_KXLC004_01) + offset = OFFSET_KME_KXLC004_01; + + sc->port_rid = 0; + sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, + iobase+offset, ~0, NCVIOSZ, RF_ACTIVE); + if (sc->port_res == NULL) { + ncv_release_resource(dev); + return(ENOMEM); + } + + sc->irq_rid = 0; + sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->irq_res == NULL) { + ncv_release_resource(dev); + return(ENOMEM); + } + + error = bus_get_resource(dev, SYS_RES_MEMORY, 0, &maddr, &msize); + if (error) { + return(0); /* XXX */ + } + + /* no need to allocate memory if not configured */ + if (maddr == 0 || msize == 0) { + return(0); + } + + sc->mem_rid = 0; + sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid, + 0, ~0, msize, RF_ACTIVE); + if (sc->mem_res == NULL) { + ncv_release_resource(dev); + return(ENOMEM); + } + + return(0); +} + +static int +ncv_pccard_probe(DEVPORT_PDEVICE dev) +{ + struct ncv_softc *sc = device_get_softc(dev); + int error; + + bzero(sc, sizeof(struct ncv_softc)); + + error = ncv_alloc_resource(dev); + if (error) { + return(error); + } + + if (ncvprobe(dev) == 0) { + ncv_release_resource(dev); + return(ENXIO); + } + + ncv_release_resource(dev); + + return(0); +} + +static int +ncv_pccard_attach(DEVPORT_PDEVICE dev) +{ + struct ncv_softc *sc = device_get_softc(dev); + int error; + + error = ncv_alloc_resource(dev); + if (error) { + return(error); + } + + error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CAM, + ncv_pccard_intr, (void *)sc, &sc->ncv_intrhand); + if (error) { + ncv_release_resource(dev); + return(error); + } + + if (ncvattach(dev) == 0) { + ncv_release_resource(dev); + return(ENXIO); + } + + return(0); +} + +static void +ncv_pccard_detach(DEVPORT_PDEVICE dev) +{ + ncv_card_unload(dev); + ncv_release_resource(dev); +} + +static device_method_t ncv_pccard_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ncv_pccard_probe), + DEVMETHOD(device_attach, ncv_pccard_attach), + DEVMETHOD(device_detach, ncv_pccard_detach), + + { 0, 0 } +}; + +static driver_t ncv_pccard_driver = { + "ncv", + ncv_pccard_methods, + sizeof(struct ncv_softc), +}; + +static devclass_t ncv_devclass; + +DRIVER_MODULE(ncv, pccard, ncv_pccard_driver, ncv_devclass, 0, 0); + +#else + +PCCARD_MODULE(ncv, ncv_card_init, ncv_card_unload, ncv_card_intr, 0, cam_imask); + +#endif + +#if defined(__FreeBSD__) && __FreeBSD_version < 400001 +static struct ncv_softc * +ncv_get_softc(int unit) +{ + struct ncv_softc *sc; + + if (unit >= NNCV) { + return(NULL); + } + + if (ncvdata[unit] == NULL) { + sc = malloc(sizeof(struct ncv_softc), M_TEMP,M_NOWAIT); + if (sc == NULL) { + printf("ncv_get_softc: cannot malloc!\n"); + return(NULL); + } + ncvdata[unit] = sc; + } else { + sc = ncvdata[unit]; + } + + return(sc); +} + +static int +ncv_card_init(DEVPORT_PDEVICE devi) +{ + int unit = DEVPORT_PDEVUNIT(devi); + + if (NNCV <= unit) + return (ENODEV); + + if (ncvprobe(devi) == 0) + return (ENXIO); + + if (ncvattach(devi) == 0) + return (ENXIO); + return (0); +} +#endif + +static void +ncv_card_unload(DEVPORT_PDEVICE devi) +{ + struct ncv_softc *sc = DEVPORT_PDEVGET_SOFTC(devi); + + printf("%s: unload\n", sc->sc_sclow.sl_xname); + scsi_low_deactivate((struct scsi_low_softc *)sc); + scsi_low_dettach(&sc->sc_sclow); +} + +static int +ncv_card_intr(DEVPORT_PDEVICE devi) +{ + + ncvintr(DEVPORT_PDEVGET_SOFTC(devi)); + return 1; +} + +static int +ncvprobe(DEVPORT_PDEVICE devi) +{ + int rv; + struct ncv_softc *sc = device_get_softc(devi); + u_int32_t flags = DEVPORT_PDEVFLAGS(devi); + +#if defined(__FreeBSD__) && __FreeBSD_version >= 400001 + rv = ncvprobesubr(rman_get_bustag(sc->port_res), + rman_get_bushandle(sc->port_res), + flags, NCV_HOSTID); +#else + bus_addr_t offset = 0; + u_int iobase = DEVPORT_PDEVIOBASE(devi); + + if(flags & KME_KXLC004_01) + offset = OFFSET_KME_KXLC004_01; + + rv = ncvprobesubr(I386_BUS_SPACE_IO, + iobase + offset, + flags, NCV_HOSTID); +#endif + + return rv; +} + +static int +ncvattach(DEVPORT_PDEVICE devi) +{ + struct ncv_softc *sc; + struct scsi_low_softc *slp; + u_int32_t flags = DEVPORT_PDEVFLAGS(devi); +#if defined(__FreeBSD__) && __FreeBSD_version < 400001 + int unit = DEVPORT_PDEVUNIT(devi); + bus_addr_t offset = 0; + u_int iobase = DEVPORT_PDEVIOBASE(devi); +#endif + char dvname[16]; /* SCSI_LOW_DVNAME_LEN */ + + strcpy(dvname, "ncv"); + +#if defined(__FreeBSD__) && __FreeBSD_version < 400001 + if (unit >= NNCV) + { + printf("%s: unit number too high\n", dvname); + return (0); + } + + if (iobase == 0) + { + printf("%s: no ioaddr is given\n", dvname); + return (0); + } + + if(flags & KME_KXLC004_01) + offset = OFFSET_KME_KXLC004_01; +#endif + + sc = DEVPORT_PDEVALLOC_SOFTC(devi); + if (sc == NULL) { + return(0); + } + + slp = &sc->sc_sclow; +#if defined(__FreeBSD__) && __FreeBSD_version >= 400001 + slp->sl_dev = devi; + sc->sc_iot = rman_get_bustag(sc->port_res); + sc->sc_ioh = rman_get_bushandle(sc->port_res); +#else + bzero(sc, sizeof(struct ncv_softc)); + strcpy(slp->sl_dev.dv_xname, dvname); + slp->sl_dev.dv_unit = unit; + sc->sc_iot = I386_BUS_SPACE_IO; + sc->sc_ioh = iobase + offset; +#endif + + slp->sl_hostid = NCV_HOSTID; + slp->sl_cfgflags = flags; + + ncvattachsubr(sc); + + sc->sc_ih = ncvintr; + + return(NCVIOSZ); +} +#endif /* NCARD */ diff --git a/sys/dev/ncv/ncr53c500hw.h b/sys/dev/ncv/ncr53c500hw.h new file mode 100644 index 0000000..e318959 --- /dev/null +++ b/sys/dev/ncv/ncr53c500hw.h @@ -0,0 +1,67 @@ +/* $FreeBSD$ */ +/* $NecBSD: ncr53c500hw.h,v 1.6 1998/11/26 01:59:12 honda Exp $ */ +/* $NetBSD$ */ + +/* + * [NetBSD for NEC PC-98 series] + * Copyright (c) 1996, 1997, 1998 + * NetBSD/pc98 porting staff. All rights reserved. + * Copyright (c) 1996, 1997, 1998 + * Naofumi HONDA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __NCR53C500HW_H_ +#define __NCR53C500HW_H_ + +#include <machine/dvcfg.h> + +#define NCV_HOSTID 7 +#define NCV_NTARGETS 8 +#define NCV_NLUNS 8 + +struct ncv_hw { + /* configuration images */ + u_int8_t cfg1; + u_int8_t cfg2; + u_int8_t cfg3; + u_int8_t cfg4; + u_int8_t cfg5; + + /* synch */ + u_int8_t clk; + u_int8_t mperiod; + u_int8_t moffset; +}; + +/* dvcfg */ +#define NCV_C5IMG(flags) ((DVCFG_MAJOR(flags) >> 8) & 0xff) +#define NCV_CLKFACTOR(flags) (DVCFG_MAJOR(flags) & 0x0f) +#define NCVHWCFG_MAX10M 0x01 +#define NCVHWCFG_SCSI1 0x02 +#define NCVHWCFG_SLOW 0x04 +#define NCVHWCFG_FIFOBUG 0x08 +#define NCV_SPECIAL(flags) ((DVCFG_MAJOR(flags) >> 4) & 0x0f) +#endif /* !__NCR53C500HW_H_ */ diff --git a/sys/dev/ncv/ncr53c500hwtab.h b/sys/dev/ncv/ncr53c500hwtab.h new file mode 100644 index 0000000..c95787e9 --- /dev/null +++ b/sys/dev/ncv/ncr53c500hwtab.h @@ -0,0 +1,47 @@ +/* $FreeBSD$ */ +/* $NecBSD: ncr53c500hwtab.h,v 1.2 1998/11/26 01:59:13 honda Exp $ */ +/* $NetBSD$ */ + +/* + * [NetBSD for NEC PC-98 series] + * Copyright (c) 1996, 1997, 1998 + * NetBSD/pc98 porting staff. All rights reserved. + * Copyright (c) 1996, 1997, 1998 + * Naofumi HONDA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +static struct ncv_hw ncv_template = { + NCV_HOSTID, + C2_FE | C2_SCSI2, + C3_FCLK, + C4_ANE, + 0x80, + + CLK_40M_F, + + 200 / 4, + 15, +}; diff --git a/sys/dev/ncv/ncr53c500reg.h b/sys/dev/ncv/ncr53c500reg.h new file mode 100644 index 0000000..ac39e1b --- /dev/null +++ b/sys/dev/ncv/ncr53c500reg.h @@ -0,0 +1,192 @@ +/* $FreeBSD$ */ +/* $NecBSD: ncr53c500reg.h,v 1.5 1998/12/26 11:50:01 honda Exp $ */ +/* $NetBSD$ */ + +/* + * [NetBSD for NEC PC-98 series] + * Copyright (c) 1995, 1996, 1997, 1998 + * NetBSD/pc98 porting staff. All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998 + * Naofumi HONDA. All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998 + * Kouichi Matsuda. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NCR53C500REG_H_ +#define _NCR53C500REG_H_ + +/* Control Register Set 0 */ +#define NCVIOSZ 0x10 + +#define cr0_tclsb 0x00 /* RW - Transfer Count Low */ +#define cr0_tcmsb 0x01 /* RW - Transfer Count Mid */ +#define cr0_sfifo 0x02 /* RW - FIFO data */ +#define cr0_cmd 0x03 /* RW - Command (2 deep) */ +#define cr0_stat 0x04 /* RO - Status */ +#define cr0_dstid 0x04 /* WO - Select/Reselect Bus ID */ +#define cr0_istat 0x05 /* RO - Interrupt */ +#define cr0_srtout 0x05 /* WO - Select/Reselect Timeout */ +#define cr0_seq 0x06 /* RO - Sequence Step */ +#define cr0_period 0x06 /* WO - Synch Transfer Period */ +#define cr0_sffl 0x07 /* RO - FIFO FLags */ +#define cr0_offs 0x07 /* WO - Synch Ofset */ +#define cr0_cfg1 0x08 /* RW - Configuration #1 */ +#define cr0_clk 0x09 /* WO - Clock Conversion Factor */ +#define cr0_tst 0x0a /* WO - Test (Chip Test Only) */ +#define cr0_cfg2 0x0b /* RW - Configuration #2 */ +#define cr0_cfg3 0x0c /* RW - Configuration #3 */ +#define cr0_cfg4 0x0d /* RW - Configuration #4 */ +#define cr0_tchsb 0x0e /* RW - Transfer Count High */ +#define cr0_fifo_bottom 0x0f /* WO - FIFO bottom */ + +/* Control Register Set 1 */ +#define cr1_jumper 0x00 /* RW - Jumper Sense Port */ +#define cr1_sram_ptr 0x01 /* RW - SRAM Address Pointer */ +#define cr1_sram_data 0x02 /* RW - SRAM Data */ +#define cr1_fdata 0x04 /* RW - PIO FIFO */ +#define cr1_fstat 0x08 /* RW - PIO Status */ +#define cr1_atacmd 0x09 /* RW - ATA Command/Status */ +#define cr1_ataerr 0x0a /* RW - ATA Features/Error */ +#define cr1_pflag 0x0b /* RW - PIO Flag Interrupt Enable */ +#define cr1_cfg5 0x0d /* RW - Configuration #5 */ +#define cr1_sig 0x0e /* RO - Signature */ +#define cr1_cfg6 0x0f /* RW - Configuration #6 */ + +/* atacmd (MPS110 ONLY) */ +#define ATACMD_POWDOWN 0x2d +#define ATACMD_ENGAGE 0x24 + +/* cr0_sffl regster */ +#define CR0_SFFLR_BMASK 0x1f /* scsi fifo byte mask */ + +/* cfg4 */ +#define C4_ANE 0x04 + +/* cfg3 */ +#define C3_NULL 0x00 +#define C3_FCLK 0x08 /* Fast SCSI */ +#define C3_FSCSI 0x10 /* Fast Clock (>25Mhz) */ + +/* cfg2 */ +#define C2_SCSI2 0x08 /* SCSI-2 Enable */ +#define C2_FE 0x40 /* Features Enable */ + +/* cfg1 */ +#define C1_SLOW 0x80 /* Slow Cable Mode */ +#define C1_SRR 0x40 /* SCSI Reset Rep Int Dis */ +#define C1_PARENB 0x10 /* Enable Parity Check */ + +/* clk factor */ +#define CLK_40M_F 0x00 +#define CLK_25M_F 0x05 +#define CLK_30M_F 0x06 +#define CLK_35M_F 0x07 + +/* interrupt status register */ +#define INTR_SBR 0x80 /* SCSI Bus Reset */ +#define INTR_ILL 0x40 /* Illegal Command */ +#define INTR_DIS 0x20 /* Disconnect */ +#define INTR_BS 0x10 /* Bus Service */ +#define INTR_FC 0x08 /* Function Complete */ +#define INTR_RESEL 0x04 /* Reselected */ +#define INTR_SELATN 0x02 /* Select with ATN */ +#define INTR_SEL 0x01 /* Selected */ +#define INTR_RESELECT (INTR_RESEL | INTR_FC) + +/* status register */ +#define STAT_INT 0x80 /* Interrupt */ +#define STAT_GE 0x40 /* Gross Error */ +#define STAT_PE 0x20 /* Parity Error */ +#define STAT_TC 0x10 /* Terminal Count */ + +/* phase bits */ +#define IOI 0x01 +#define CDI 0x02 +#define MSGI 0x04 + +/* Information transfer phases */ +#define DATA_OUT_PHASE (0) +#define DATA_IN_PHASE (IOI) +#define COMMAND_PHASE (CDI) +#define STATUS_PHASE (CDI|IOI) +#define MESSAGE_OUT_PHASE (MSGI|CDI) +#define MESSAGE_IN_PHASE (MSGI|CDI|IOI) + +#define PHASE_MASK (MSGI|CDI|IOI) + +/* fifo status register */ +#define FIFO_SMASK 0x1e +#define FIFO_E 0x10 /* fifo empty */ +#define FIFO_B 0x00 /* there exists any */ +#define FIFO_1 0x08 /* 1/3 <= bytes < 2/3 */ +#define FIFO_2 0x04 /* 2/3 <= bytes < full */ +#define FIFO_F 0x02 /* full */ +#define FIFO_EN 0x01 /* fifo direction */ +#define FIFO_BRK 0x40 /* phase miss */ + +#define FIFO_F_SZ 128 +#define FIFO_1_SZ 44 +#define FIFO_2_SZ 84 + +/* pflags */ +#define PFR_WRITE 0x01 + +/* Commands */ +#define CMD_DMA 0x80 /* DMA Bit */ +#define CMD_NOP 0x00 /* No Operation */ +#define CMD_FLUSH 0x01 /* Flush FIFO */ +#define CMD_RSTCHIP 0x02 /* Reset Chip */ +#define CMD_RSTSCSI 0x03 /* Reset SCSI Bus */ +#define CMD_RESEL 0x40 /* Reselect Sequence */ +#define CMD_SELNATN 0x41 /* Select without ATN */ +#define CMD_SELATN 0x42 /* Select with ATN */ +#define CMD_SELATNS 0x43 /* Select with ATN & Stop */ +#define CMD_ENSEL 0x44 /* Enable (Re)Selection */ +#define CMD_DISSEL 0x45 /* Disable (Re)Selection */ +#define CMD_SELATN3 0x46 /* Select with ATN3 */ +#define CMD_RESEL3 0x47 /* Reselect3 Sequence */ +#define CMD_SNDMSG 0x20 /* Send Message */ +#define CMD_SNDSTAT 0x21 /* Send Status */ +#define CMD_SNDDATA 0x22 /* Send Data */ +#define CMD_DISCSEQ 0x23 /* Disconnect Sequence */ +#define CMD_TERMSEQ 0x24 /* Terminate Sequence */ +#define CMD_TCCS 0x25 /* Target Command Comp Seq */ +#define CMD_DISC 0x27 /* Disconnect */ +#define CMD_RECMSG 0x28 /* Receive Message */ +#define CMD_RECCMD 0x29 /* Receive Command */ +#define CMD_RECDATA 0x2a /* Receive Data */ +#define CMD_RECCSEQ 0x2b /* Receive Command Sequence */ +#define CMD_ABORT 0x04 /* Target Abort DMA */ +#define CMD_TRANS 0x10 /* Transfer Information */ +#define CMD_ICCS 0x11 /* Initiator Cmd Comp Seq */ +#define CMD_MSGOK 0x12 /* Message Accepted */ +#define CMD_TRPAD 0x18 /* Transfer Pad */ +#define CMD_SETATN 0x1a /* Set ATN */ +#define CMD_RSTATN 0x1b /* Reset ATN */ + +/* Default timeout */ +#define SEL_TOUT 0xa3 +#endif /* !_NCR53C500REG_H_ */ diff --git a/sys/dev/ncv/ncr53c500var.h b/sys/dev/ncv/ncr53c500var.h new file mode 100644 index 0000000..07e85f8 --- /dev/null +++ b/sys/dev/ncv/ncr53c500var.h @@ -0,0 +1,90 @@ +/* $FreeBSD$ */ +/* $NecBSD: ncr53c500var.h,v 1.11 1998/11/28 18:42:42 honda Exp $ */ +/* $NetBSD$ */ + +/* + * [NetBSD for NEC PC-98 series] + * Copyright (c) 1995, 1996, 1997, 1998 + * NetBSD/pc98 porting staff. All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998 + * Naofumi HONDA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NCR53C500VAR_H_ +#define _NCR53C500VAR_H_ + +/***************************************************************** + * Host adapter structure + *****************************************************************/ +struct ncv_softc { + struct scsi_low_softc sc_sclow; /* generic data */ + + bus_space_tag_t sc_iot; + bus_space_tag_t sc_memt; + bus_space_handle_t sc_ioh; + + void *sc_ih; + int sc_selstop; /* sel atn stop asserted */ + int sc_compseq; /* completion seq cmd asserted */ + int sc_tdatalen; /* temp xfer data len */ + + struct ncv_hw sc_hw; /* hardware register images */ +#if defined (__FreeBSD__) && __FreeBSD_version >= 400001 + int port_rid; + int irq_rid; + int mem_rid; + struct resource *port_res; + struct resource *irq_res; + struct resource *mem_res; + void *ncv_intrhand; +#endif +}; + +/***************************************************************** + * Lun information + *****************************************************************/ +struct ncv_lun_info { + struct lun_info nli_li; + + u_int8_t nli_reg_cfg3; /* cfg3 images per lun */ + u_int8_t nli_reg_offset; /* synch offset register per lun */ + u_int8_t nli_reg_period; /* synch period register per lun */ +}; + +/***************************************************************** + * Proto + *****************************************************************/ +int ncvprobesubr __P((bus_space_tag_t, bus_space_handle_t ioh, u_int, int)); +void ncvattachsubr __P((struct ncv_softc *)); +int ncvprint __P((void *, const char *)); +int ncvintr __P((void *)); + +#if defined(i386) +#define SOFT_INTR_REQUIRED(slp) (softintr((slp)->sl_irq)) +#else /* !i386 */ +#define SOFT_INTR_REQUIRED(slp) +#endif /* !i386 */ +#endif /* !_NCR53C500VAR_H_ */ |