aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ncv
diff options
context:
space:
mode:
authorNoriaki Mitsunaga <non@FreeBSD.org>2000-10-23 12:55:51 +0000
committerNoriaki Mitsunaga <non@FreeBSD.org>2000-10-23 12:55:51 +0000
commitae94720d12549fbb06c8acbac3a7c44561e71a95 (patch)
tree214b5df8a560511864739b5e8e373d2d0e0391a7 /sys/dev/ncv
parent1e832bf81d5a4c0b90bdfca13bb48f7cff9876f5 (diff)
downloadsrc-ae94720d12549fbb06c8acbac3a7c44561e71a95.tar.gz
src-ae94720d12549fbb06c8acbac3a7c44561e71a95.zip
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
Notes
Notes: svn path=/head/; revision=67468
Diffstat (limited to 'sys/dev/ncv')
-rw-r--r--sys/dev/ncv/ncr53c500.c1197
-rw-r--r--sys/dev/ncv/ncr53c500_pccard.c414
-rw-r--r--sys/dev/ncv/ncr53c500hw.h67
-rw-r--r--sys/dev/ncv/ncr53c500hwtab.h47
-rw-r--r--sys/dev/ncv/ncr53c500reg.h192
-rw-r--r--sys/dev/ncv/ncr53c500var.h90
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 000000000000..dfbfd3f1248e
--- /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 000000000000..d1ffd8934bac
--- /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 000000000000..e318959a982c
--- /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 000000000000..c95787e92231
--- /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 000000000000..ac39e1b3ba56
--- /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 000000000000..07e85f8b3cd1
--- /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_ */