summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorasami <asami@FreeBSD.org>1996-12-04 04:32:52 +0000
committerasami <asami@FreeBSD.org>1996-12-04 04:32:52 +0000
commit5fdc748d8c34e6924a223a6dd13a1d3c36104b5b (patch)
treea876bb0feb1b4c4f4191a1d367e088a314cf155a /sys
parent4d75d96d6e8b3a6ef3d9dcc16b1e9414af327f0e (diff)
downloadFreeBSD-src-5fdc748d8c34e6924a223a6dd13a1d3c36104b5b.zip
FreeBSD-src-5fdc748d8c34e6924a223a6dd13a1d3c36104b5b.tar.gz
Replace sbic driver (WD33C93 SCSI card driver) with new bs driver.
Submitted by: The FreeBSD(98) Development Team Obtained from: NetBSD/pc98 based on NetBSD 1.2
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/isa/bs/bs.c1622
-rw-r--r--sys/i386/isa/bs/bs_isa.c60
-rw-r--r--sys/i386/isa/bs/bs_pisa.c126
-rw-r--r--sys/i386/isa/bs/bsfunc.c926
-rw-r--r--sys/i386/isa/bs/bsfunc.h229
-rw-r--r--sys/i386/isa/bs/bshw.c451
-rw-r--r--sys/i386/isa/bs/bshw.h363
-rw-r--r--sys/i386/isa/bs/bshw.lst113
-rw-r--r--sys/i386/isa/bs/bshw_dma.c339
-rw-r--r--sys/i386/isa/bs/bshw_pdma.c242
-rw-r--r--sys/i386/isa/bs/bsif.c520
-rw-r--r--sys/i386/isa/bs/bsif.h201
-rw-r--r--sys/i386/isa/bs/bsvar.h542
-rw-r--r--sys/i386/isa/bs/ccbque.h130
-rw-r--r--sys/i386/isa/bs/dvcfg.h64
-rw-r--r--sys/i386/isa/ic/wd33c93.h274
-rw-r--r--sys/pc98/conf/GENERIC31
-rw-r--r--sys/pc98/conf/GENERIC9831
-rw-r--r--sys/pc98/pc98/sbic55.c917
-rw-r--r--sys/pc98/pc98/sbic55.c.new1745
-rw-r--r--sys/pc98/pc98/sbicreg.h429
-rw-r--r--sys/pc98/pc98/sbicvar.h157
-rw-r--r--sys/pc98/pc98/scsireg.h312
23 files changed, 6115 insertions, 3709 deletions
diff --git a/sys/i386/isa/bs/bs.c b/sys/i386/isa/bs/bs.c
new file mode 100644
index 0000000..022af61
--- /dev/null
+++ b/sys/i386/isa/bs/bs.c
@@ -0,0 +1,1622 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
+ */
+
+#ifdef __NetBSD__
+#include <dev/isa/bs/bsif.h>
+#endif
+#ifdef __FreeBSD__
+#include <i386/isa/bs/bsif.h>
+#endif
+
+/*****************************************************************
+ * Inline phase funcs
+ *****************************************************************/
+/* static inline declare */
+static BS_INLINE struct targ_info *bs_reselect __P((struct bs_softc *));
+static BS_INLINE void bs_sat_continue __P((struct bs_softc *, struct targ_info *, struct ccb *));
+static BS_INLINE struct targ_info *bs_selected __P((struct bs_softc *, struct targ_info *, struct ccb *));
+static BS_INLINE u_int8_t bs_read_1byte __P((struct bs_softc *));
+static BS_INLINE void bs_write_1byte __P((struct bs_softc *, u_int8_t));
+static BS_INLINE void bs_commandout __P((struct bs_softc *, struct targ_info *, struct ccb *));
+static BS_INLINE void bs_status_check __P((struct bs_softc *, struct targ_info *));
+static BS_INLINE void bs_msgin __P((struct bs_softc *, struct targ_info *));
+static BS_INLINE void bs_msgout __P((struct bs_softc *, struct targ_info *, struct ccb *));
+static BS_INLINE void bs_disconnect_phase __P((struct bs_softc *, struct targ_info *, struct ccb *));
+static void bs_phase_error __P((struct targ_info *, struct ccb *));
+static int bs_scsi_cmd_poll_internal __P((struct targ_info *));
+static int bs_xfer __P((struct bs_softc *, char *, int));
+static void bs_io_xfer __P((struct targ_info *));
+static void bs_quick_abort __P((struct targ_info *, u_int));
+static void bs_msgin_error __P((struct targ_info *, u_int));
+static void bs_msgin_ext __P((struct targ_info *));
+static void bs_msg_reject __P((struct targ_info *));
+static void bshoststart __P((struct bs_softc *, struct targ_info *));
+
+/*****************************************************************
+ * Julian scsi interface
+ *****************************************************************/
+XSBS_INT32T
+bs_scsi_cmd(xs)
+ struct scsi_xfer *xs;
+{
+ struct bs_softc *bsc = (struct bs_softc *) xs->sc_link->adapter_softc;
+ int s, target = (u_int) (xs->sc_link->target);
+ struct targ_info *ti;
+ struct ccb *cb;
+ u_int flags = xs->flags;
+
+ if (xs->bp == NULL && (bsc->sc_openf & (1 << target)) == 0)
+ {
+ s = splbio();
+ xs->error = XS_DRIVER_STUFFUP;
+ xs->flags |= XSBS_ITSDONE;
+ scsi_done(xs);
+ splx(s);
+ return COMPLETE;
+ }
+
+ ti = bsc->sc_ti[target];
+ if ((cb = bs_get_ccb(flags & XSBS_SCSI_NOSLEEP)) == NULL)
+ return TRY_AGAIN_LATER;
+
+ /* make up ccb! */
+ cb->xs = xs;
+ cb->lun = xs->sc_link->lun;
+ cb->cmd = (u_int8_t *) xs->cmd;
+ cb->cmdlen = (int) xs->cmdlen;
+ cb->data = (u_int8_t *) xs->data;
+ cb->datalen = (int) xs->datalen;
+ cb->rcnt = 0;
+ cb->msgoutlen = 0;
+ cb->flags = (flags & XSBS_SCSI_POLL) ? BSFORCEIOPOLL : 0;
+ bs_targ_flags(ti, cb);
+ cb->tcmax = (xs->timeout >> 10);
+ if (cb->tcmax < BS_DEFAULT_TIMEOUT_SECOND)
+ cb->tcmax = BS_DEFAULT_TIMEOUT_SECOND;
+
+#ifdef BS_ADDRESS_CHECK
+ /* XXX:
+ * Sanity check, however this is critical!
+ * NetBSD 1.0: WRONG
+ * NetBSD 1.1: OK
+ * FreeBSD: WRONG
+ */
+ if ((caddr_t) cb->data < (caddr_t) KERNBASE)
+ {
+ u_int8_t *altbp;
+
+ altbp = (u_int8_t *) malloc(cb->datalen, M_DEVBUF, M_NOWAIT);
+ if (altbp == NULL)
+ {
+ bs_free_ccb(cb);
+ return TRY_AGAIN_LATER;
+ }
+
+ if (flags & SCSI_DATA_OUT)
+ bcopy(cb->data, altbp, cb->datalen);
+ else
+ bzero(altbp, cb->datalen);
+
+ cb->data = (u_int8_t *) altbp;
+ cb->flags |= BSALTBUF;
+ }
+#endif /* BS_ADDRESS_CHECK */
+
+ s = splbio();
+
+ TAILQ_INSERT_TAIL(&ti->ti_ctab, cb, ccb_chain)
+
+ if (ti->ti_phase == FREE)
+ {
+ if (ti->ti_state == BS_TARG_START)
+ {
+ if ((flags & XSBS_SCSI_POLL) == 0)
+ bs_start_syncmsg(ti, NULL, BS_SYNCMSG_ASSERT);
+ }
+ bscmdstart(ti, BSCMDSTART);
+ }
+
+ if ((flags & XSBS_SCSI_POLL) == 0)
+ {
+ splx(s);
+ return SUCCESSFULLY_QUEUED;
+ }
+
+ bs_scsi_cmd_poll(ti, cb);
+ splx(s);
+
+ return COMPLETE;
+}
+
+/**************************************************
+ * ### NEXUS START and TERMINATE ###
+ **************************************************/
+/*
+ * FLAGS : BSCMDRESTART restart in case of error.
+ */
+int
+bscmdstart(ti, flags)
+ struct targ_info *ti;
+ int flags;
+{
+ struct ccb *cb;
+ struct bs_softc *bsc = ti->ti_bsc;
+
+ if ((cb = ti->ti_ctab.tqh_first) == NULL)
+ {
+ if (bsc->sc_nexus == NULL)
+ bshoststart(bsc, NULL);
+ return 0;
+ }
+
+ ti->ti_lun = cb->lun;
+ ti->ti_error = 0;
+ ti->ti_scsp.data = cb->data;
+ ti->ti_scsp.datalen = cb->datalen;
+ ti->ti_scsp.seglen = 0;
+ if (cb->rcnt)
+ cb->flags &= ~(BSSAT | BSLINK);
+ ti->ti_flags &= ~BSCFLAGSMASK;
+ ti->ti_flags |= cb->flags & BSCFLAGSMASK;
+ cb->tc = cb->tcmax;
+
+ /* GO GO */
+ if (ti->ti_phase == FREE)
+ {
+ if (bsc->sc_nexus == NULL)
+ bshoststart(bsc, ti);
+ else
+ {
+ if (flags & BSCMDRESTART)
+ bs_hostque_head(bsc, ti);
+ else
+ bs_hostque_tail(bsc, ti);
+ BS_SETUP_PHASE(HOSTQUEUE)
+ }
+ }
+ else if (bsc->sc_nexus == NULL)
+ bshoststart(bsc, NULL);
+
+ return 1;
+}
+
+struct ccb *
+bscmddone(ti)
+ struct targ_info *ti;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct ccb *cb = ti->ti_ctab.tqh_first;
+ struct scsi_xfer *xs;
+ int error;
+
+ if (ti->ti_state == BS_TARG_SYNCH)
+ {
+ if (bs_analyze_syncmsg(ti, cb))
+ return cb;
+ }
+
+ if (bsc->sc_p.datalen != 0)
+ ti->ti_error |= BSDMAABNORMAL;
+
+ cb->error = ti->ti_error;
+
+ do
+ {
+ xs = cb->xs;
+ error = XS_NOERROR;
+
+ if (cb->flags & (BSITSDONE | BSSENSECCB | BSCASTAT))
+ {
+ if (cb->flags & BSSENSECCB)
+ {
+ cb->error &= ~BSDMAABNORMAL;
+ if (cb->error == 0)
+ ti->ti_flags |= BSCASTAT;
+
+ ti->ti_flags |= BSERROROK;
+ }
+ else if (cb->flags & BSCASTAT)
+ {
+ if (ti->ti_flags & BSCASTAT)
+ {
+ ti->ti_flags &= ~BSCASTAT;
+ error = XS_SENSE;
+ if (xs)
+ xs->sense = ti->sense;
+ }
+ else
+ error = XS_DRIVER_STUFFUP;
+
+ ti->ti_flags |= BSERROROK;
+ } else
+ bs_panic(bsc, "internal error");
+ }
+
+ while (cb->error)
+ {
+ if (ti->ti_flags & BSERROROK)
+ break;
+
+ if (cb->rcnt >= bsc->sc_retry || (cb->error & BSFATALIO))
+ {
+ if (cb->error & (BSSELTIMEOUT | BSTIMEOUT))
+ error = XS_TIMEOUT;
+ else if (cb->error & BSTARGETBUSY)
+ error = XS_BUSY;
+ else
+ error = XS_DRIVER_STUFFUP;
+ break;
+ }
+
+ if (cb->error & BSREQSENSE)
+ {
+ /* must clear the target's sense state */
+ cb->rcnt++;
+ cb->flags |= (BSITSDONE | BSCASTAT);
+ cb->error &= ~BSREQSENSE;
+ return bs_request_sense(ti);
+ }
+
+ /* XXX: compat with upper driver */
+ if ((cb->error & BSDMAABNORMAL) &&
+ BSHW_CMD_CHECK(cb, BSERROROK))
+ {
+ cb->error &= ~BSDMAABNORMAL;
+ continue;
+ }
+
+ if ((xs && xs->bp) || (cb->error & BSSELTIMEOUT) == 0)
+ bs_debug_print(bsc, ti);
+
+ cb->rcnt++;
+ return cb;
+ }
+
+#ifdef BS_DIAG
+ cb->flags |= BSITSDONE;
+#endif /* BS_DIAG */
+ if (bsc->sc_poll)
+ {
+ bsc->sc_flags |= BSJOBDONE;
+ if (bsc->sc_outccb == cb)
+ bsc->sc_flags |= BSPOLLDONE;
+ }
+
+ TAILQ_REMOVE(&ti->ti_ctab, cb, ccb_chain)
+
+ if (xs)
+ {
+#ifdef BS_ADDRESS_CHECK
+ if (cb->flags & BSALTBUF)
+ {
+ if (xs->flags & SCSI_DATA_IN)
+ bcopy(cb->data, xs->data, cb->datalen);
+ free(cb->data, M_DEVBUF);
+ }
+#endif /* BS_ADDRESS_CHECK */
+
+ if ((xs->error = error) == XS_NOERROR)
+ xs->resid = 0;
+ xs->flags |= XSBS_ITSDONE;
+ scsi_done(xs);
+ }
+
+ bs_free_ccb(cb);
+ cb = ti->ti_ctab.tqh_first;
+
+ }
+ while (cb != NULL && (cb->flags & BSITSDONE) != 0);
+
+ /* complete */
+ return NULL;
+}
+
+/**************************************************
+ * ### PHASE FUNCTIONS ###
+ **************************************************/
+/**************************************************
+ * <SELECTION PHASE>
+ **************************************************/
+static void
+bshoststart(bsc, ti)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+{
+ struct ccb *cb;
+ int s;
+
+ if (bsc->sc_flags & BSINACTIVE)
+ return;
+
+again:
+ if (ti == NULL)
+ {
+ if ((ti = bsc->sc_sttab.tqh_first) == NULL)
+ return;
+ bs_hostque_delete(bsc, ti);
+ }
+
+ if ((cb = ti->ti_ctab.tqh_first) == NULL)
+ {
+ bs_printf(ti, "bshoststart", "Warning: No ccb");
+ BS_SETUP_PHASE(FREE);
+ ti = NULL;
+ goto again;
+ }
+
+#ifdef BS_DIAG
+ if (cb->flags & BSITSDONE)
+ bs_panic(bsc, "bshoststart: already done");
+
+ if (bsc->sc_nexus || (ti->ti_flags & BSNEXUS))
+ {
+ char *s = ((ti->ti_flags & BSNEXUS) ?
+ "nexus already established" : "scsi board busy");
+
+ bs_debug_print(bsc, ti);
+ bs_printf(ti, "bshoststart", s);
+ }
+#endif /* BS_DIAG */
+
+#ifdef BS_STATICS
+ bs_statics[ti->ti_id].select++;
+#endif /* BS_STATICS */
+
+ if (ti->ti_cfgflags & BS_SCSI_WAIT)
+ {
+ struct targ_info *tmpti;
+
+ for (tmpti = bsc->sc_titab.tqh_first; tmpti;
+ tmpti = tmpti->ti_tchain.tqe_next)
+ if (tmpti->ti_phase >= DISCONNECTED)
+ goto retry;
+ }
+
+ /* start selection */
+ ti->ti_status = ST_UNK;
+ if (bs_check_sat(ti))
+ {
+ if ((bshw_get_auxstat(bsc) & STR_BUSY) == 0)
+ {
+ BS_LOAD_SDP
+ bshw_set_dst_id(bsc, ti->ti_id, ti->ti_lun);
+ bshw_setup_ctrl_reg(bsc, ti->ti_cfgflags);
+ bshw_cmd_pass(bsc, 0);
+ bshw_set_sync_reg(bsc, ti->ti_sync);
+ bshw_issue_satcmd(bsc, cb, bs_check_link(ti, cb));
+ if (bs_check_smit(ti) || bsc->sc_p.datalen <= 0)
+ bshw_set_count(bsc, 0);
+ else
+ bs_dma_xfer(ti, BSHW_CMD_CHECK(cb, BSREAD));
+
+ s = splhigh();
+ if ((bshw_get_auxstat(bsc) & STR_BUSY) == 0)
+ {
+ /* XXX:
+ * Reload a lun again here.
+ */
+ bshw_set_lun(bsc, ti->ti_lun);
+ bshw_start_sat(bsc, bs_check_disc(ti));
+ if ((bshw_get_auxstat(bsc) & STR_LCI) == 0)
+ {
+ splx(s);
+ BS_HOST_START
+ BS_SELECTION_START
+ BS_SETUP_PHASE(SATSEL);
+ ti->ti_omsgoutlen = 0;
+ ti->ti_msgout = bs_identify_msg(ti);
+#ifdef BS_DIAG
+ ti->ti_flags |= BSNEXUS;
+#endif /* BS_DIAG */
+#ifdef BS_STATICS
+ bs_statics[ti->ti_id].select_win++;
+#endif /* BS_STATICS */
+ return;
+ }
+ }
+ splx(s);
+
+ if (bs_check_smit(ti) == 0)
+ bshw_dmaabort(bsc, ti);
+#ifdef BS_STATICS
+ bs_statics[ti->ti_id].select_miss_in_assert++;
+#endif /* BS_STATICS */
+ }
+ }
+ else
+ {
+ s = splhigh();
+ if ((bshw_get_auxstat(bsc) & STR_BUSY) == 0)
+ {
+ bshw_set_dst_id(bsc, ti->ti_id, ti->ti_lun);
+ bshw_setup_ctrl_reg(bsc, ti->ti_cfgflags);
+ bshw_set_sync_reg(bsc, ti->ti_sync);
+ bshw_assert_select(bsc);
+
+ if ((bshw_get_auxstat(bsc) & STR_LCI) == 0)
+ {
+ splx(s);
+ BS_HOST_START
+ BS_SELECTION_START
+ BS_SETUP_PHASE(SELECTASSERT);
+#ifdef BS_STATICS
+ bs_statics[ti->ti_id].select_win++;
+#endif /* BS_STATICS */
+ return;
+ }
+#ifdef BS_STATICS
+ bs_statics[ti->ti_id].select_miss_in_assert++;
+#endif /* BS_STATICS */
+ }
+ splx(s);
+ }
+
+ /* RETRY LATER */
+retry:
+#ifdef BS_STATICS
+ bs_statics[ti->ti_id].select_miss++;
+#endif /* BS_STATICS */
+ bs_hostque_head(bsc, ti);
+ BS_SETUP_PHASE(HOSTQUEUE)
+}
+
+static BS_INLINE struct targ_info *
+bs_selected(bsc, ti, cb)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+
+ if (bsc->sc_busstat != BSR_SELECTED)
+ {
+ bs_phase_error(ti, cb);
+ return NULL;
+ }
+
+#ifdef BS_DIAG
+ if (bsc->sc_selwait != ti)
+ panic("%s selection internal error\n", bsc->sc_dvname);
+
+ ti->ti_flags |= BSNEXUS;
+#endif /* BS_DIAG */
+
+ /* clear select wait state */
+ BS_SETUP_PHASE(SELECTED);
+ BS_SELECTION_TERMINATE;
+ BS_LOAD_SDP
+ return ti;
+}
+
+/**************************************************
+ * <RESELECTION>
+ **************************************************/
+static BS_INLINE struct targ_info *
+bs_reselect(bsc)
+ struct bs_softc *bsc;
+{
+ u_int target;
+ struct targ_info *ti;
+
+ /* check collision */
+ if ((ti = bsc->sc_selwait) != NULL)
+ {
+ if (ti->ti_phase == SATSEL)
+ {
+#ifdef BS_DIAG
+ ti->ti_flags &= ~BSNEXUS;
+#endif /* BS_DIAG */
+ ti->ti_msgout = 0;
+ if (bs_check_smit(ti) == 0)
+ bshw_dmaabort(bsc, ti);
+ }
+ bs_hostque_head(bsc, ti);
+ BS_SELECTION_TERMINATE
+ BS_SETUP_PHASE(HOSTQUEUE)
+#ifdef BS_STATICS
+ bs_statics[ti->ti_id].select_miss_by_reselect++;
+ bs_statics[ti->ti_id].select_miss++;
+#endif /* BS_STATICS */
+ }
+
+ /* who are you ? */
+ target = bshw_get_src_id(bsc);
+ if ((ti = bsc->sc_ti[target]) == NULL)
+ {
+ bs_debug_print_all(bsc);
+ printf("reselect: miss reselect. target(%d)\n", target);
+ bs_reset_nexus(bsc);
+ return NULL;
+ }
+
+ /* confirm nexus */
+ BS_HOST_START
+ bshw_setup_ctrl_reg(bsc, ti->ti_cfgflags);
+ if (ti->ti_ctab.tqh_first == NULL || ti->ti_phase != DISCONNECTED)
+ {
+ bs_printf(ti, "reselect", "phase mismatch");
+ BS_SETUP_PHASE(UNDEF)
+ bs_force_abort(ti);
+ bs_hostque_delete(bsc, ti);
+ }
+ else
+ bsc->sc_dtgnum --;
+
+ /* recover host */
+ bshw_set_dst_id(bsc, ti->ti_id, ti->ti_lun);
+ bshw_set_sync_reg(bsc, ti->ti_sync);
+ BS_RESTORE_SDP
+ BS_SETUP_PHASE(RESELECTED)
+#ifdef BS_STATICS
+ bs_statics[ti->ti_id].reselect++;
+#endif /* BS_STATICS */
+ return ti;
+}
+
+static BS_INLINE void
+bs_sat_continue(bsc, ti, cb)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+
+ BS_SETUP_PHASE(SATRESEL);
+ bshw_set_dst_id(bsc, ti->ti_id, ti->ti_lun);
+ bshw_cmd_pass(bsc, 0x44);
+ bshw_set_sync_reg(bsc, ti->ti_sync);
+ bshw_issue_satcmd(bsc, cb, 0);
+ if (bs_check_smit(ti) || bsc->sc_p.datalen <= 0)
+ bshw_set_count(bsc, 0);
+ else
+ bs_dma_xfer(ti, BSHW_CMD_CHECK(cb, BSREAD));
+ bshw_set_lun(bsc, ti->ti_lun); /* XXX */
+ bshw_start_sat(bsc, 0);
+}
+
+/*************************************************
+ * <DATA PHASE>
+ *************************************************/
+#define DR (STR_BSY | STR_DBR)
+
+void
+bs_poll_timeout(bsc, s)
+ struct bs_softc *bsc;
+ char *s;
+{
+ struct targ_info *ti;
+
+ bs_printf(NULL, s, "timeout");
+ bsc->sc_flags |= BSRESET;
+ if ((ti = bsc->sc_nexus) && ti->ti_ctab.tqh_first)
+ ti->ti_error |= BSTIMEOUT;
+}
+
+static BS_INLINE u_int8_t
+bs_read_1byte(bsc)
+ struct bs_softc *bsc;
+{
+ register u_int wc;
+
+ bshw_start_sxfer(bsc);
+ for (wc = bsc->sc_wc; (bshw_get_auxstat(bsc) & DR) != DR && --wc; );
+ if (wc)
+ return bshw_read_data(bsc);
+ else
+ bs_poll_timeout(bsc, "read_1byte");
+
+ return 0;
+}
+
+static BS_INLINE void
+bs_write_1byte(bsc, data)
+ struct bs_softc *bsc;
+ u_int8_t data;
+{
+ register u_int wc;
+
+ bshw_start_sxfer(bsc);
+ for (wc = bsc->sc_wc; (bshw_get_auxstat(bsc) & DR) != DR && --wc; );
+ if (wc)
+ bshw_write_data(bsc, data);
+ else
+ bs_poll_timeout(bsc, "write_1byte");
+}
+
+static int
+bs_xfer(bsc, data, len)
+ struct bs_softc *bsc;
+ char *data;
+ int len;
+{
+ u_int8_t aux;
+ u_int count, wc;
+
+ bshw_set_count(bsc, len);
+ bshw_start_xfer(bsc);
+
+ for (count = 0, wc = bsc->sc_wc; count < len && --wc; )
+ {
+ if (((aux = bshw_get_auxstat(bsc)) & DR) == DR)
+ {
+ if (bsc->sc_busstat & BSHW_READ)
+ *(data++) = bshw_read_data(bsc);
+ else
+ bshw_write_data(bsc, *(data++));
+ count++;
+ wc = bsc->sc_wc;
+ }
+
+ if (aux & STR_INT)
+ break;
+ }
+
+ if (wc == 0)
+ bs_poll_timeout(bsc, "bs_xfer");
+
+ return count;
+}
+#undef DR
+
+static void
+bs_io_xfer(ti)
+ struct targ_info *ti;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct sc_p *sp = &bsc->sc_p;
+ u_int count, dummy;
+
+ /* switch dma trasnfr mode */
+ bshw_set_poll_trans(bsc, ti->ti_cfgflags);
+ sp->seglen = 0;
+ sp->bufp = NULL;
+
+ if (sp->datalen <= 0)
+ {
+ ti->ti_error |= BSDMAABNORMAL;
+ dummy = 0;
+ count = bs_xfer(bsc, (u_int8_t *) &dummy, 1);
+ }
+ else
+ count = bs_xfer(bsc, sp->data, sp->datalen);
+
+ sp->data += count;
+ sp->datalen -= count;
+}
+
+/************************************************
+ * <COMMAND PHASE>
+ ************************************************/
+static BS_INLINE void
+bs_commandout(bsc, ti, cb)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+ u_int8_t scsi_cmd[16];
+ int len;
+
+ BS_SETUP_PHASE(CMDPHASE);
+
+ if (bs_check_link(ti, cb))
+ {
+ bcopy(cb->cmd, scsi_cmd, cb->cmdlen);
+ scsi_cmd[cb->cmdlen - 1] |= 0x01;
+ len = bs_xfer(bsc, scsi_cmd, cb->cmdlen);
+ }
+ else
+ len = bs_xfer(bsc, cb->cmd, cb->cmdlen);
+
+ if (len != cb->cmdlen)
+ ti->ti_error |= BSCMDABNORMAL;
+}
+
+/************************************************
+ * <STATUS IN>
+ ************************************************/
+static BS_INLINE void
+bs_status_check(bsc, ti)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+{
+
+ if (ti->ti_status == ST_GOOD || ti->ti_status == ST_INTERGOOD)
+ return;
+
+ switch (ti->ti_status)
+ {
+ case ST_MET:
+ case ST_INTERMET:
+ case ST_CHKCOND:
+ ti->ti_error |= BSREQSENSE;
+ break;
+
+ case ST_BUSY:
+ ti->ti_error |= BSTARGETBUSY;
+ break;
+
+ default:
+ ti->ti_error |= BSSTATUSERROR;
+ break;
+ }
+}
+
+/************************************************
+ * <MSG IN>
+ ************************************************/
+#define MSGWAIT(cnt) { if (ti->ti_msginptr < (cnt)) return; }
+
+static void
+bs_quick_abort(ti, msg)
+ struct targ_info *ti;
+ u_int msg;
+{
+ struct ccb *cb;
+
+ if ((cb = ti->ti_ctab.tqh_first) == NULL)
+ return;
+
+ cb->msgoutlen = 1;
+ cb->msgout[0] = msg;
+ cb->rcnt++;
+
+ ti->ti_error |= BSMSGERROR;
+}
+
+static void
+bs_msgin_error(ti, count)
+ struct targ_info *ti;
+ u_int count;
+{
+ int n;
+
+ MSGWAIT(count);
+
+ bs_printf(ti, "msgin", "illegal msg");
+
+ for (n = 0; n < ti->ti_msginptr; n ++)
+ printf("[0x%x] ", (u_int) ti->ti_msgin[n]);
+ printf("\n");
+
+ bs_quick_abort(ti, MSG_REJECT);
+ ti->ti_msginptr = 0;
+}
+
+static void
+bs_msgin_ext(ti)
+ struct targ_info *ti;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct ccb *cb = ti->ti_ctab.tqh_first;
+ int count;
+ u_int reqlen;
+ u_int32_t *ptr;
+ struct msgbase msg;
+
+ MSGWAIT(2);
+
+ reqlen = ti->ti_msgin[1];
+ if (reqlen == 0)
+ reqlen = 256;
+
+ if (ti->ti_msginptr >= MAXMSGLEN)
+ ti->ti_msginptr = 3; /* XXX */
+
+ MSGWAIT(reqlen + 2);
+
+ switch (MKMSG_EXTEND(ti->ti_msgin[1], ti->ti_msgin[2]))
+ {
+ case MKMSG_EXTEND(MSG_EXTEND_MDPLEN, MSG_EXTEND_MDPCODE):
+ ptr = (u_int32_t *)(&ti->ti_msgin[3]);
+ count = (int) htonl((long) (*ptr));
+
+ bsc->sc_p.seglen = ti->ti_scsp.seglen = 0;
+ if (bsc->sc_p.datalen - count >= 0 &&
+ bsc->sc_p.datalen - count <= cb->datalen)
+ {
+ bsc->sc_p.datalen -= count;
+ bsc->sc_p.data += count;
+ }
+ else
+ bs_msgin_error(ti, 7);
+ break;
+
+ case MKMSG_EXTEND(MSG_EXTEND_SYNCHLEN, MSG_EXTEND_SYNCHCODE):
+ ti->ti_syncnow.period = ti->ti_msgin[3];
+ ti->ti_syncnow.offset = ti->ti_msgin[4];
+ if (ti->ti_syncnow.offset == 0)
+ ti->ti_syncnow.period = 0;
+
+ if (ti->ti_syncnow.state != BS_SYNCMSG_ASSERT)
+ {
+ bs_start_syncmsg(ti, NULL, BS_SYNCMSG_REQUESTED);
+ bscmdstart(ti, BSCMDSTART);
+ }
+ else
+ BS_SETUP_SYNCSTATE(BS_SYNCMSG_ACCEPT)
+ break;
+
+ case MKMSG_EXTEND(MSG_EXTEND_WIDELEN, MSG_EXTEND_WIDECODE):
+ msg.msglen = MSG_EXTEND_WIDELEN + 2;
+ msg.msg[0] = MSG_EXTEND;
+ msg.msg[1] = MSG_EXTEND_WIDELEN;
+ msg.msg[2] = MSG_EXTEND_WIDECODE;
+ msg.msg[3] = 0;
+ msg.flag = 0;
+ bs_make_msg_ccb(ti, cb->lun, cb, &msg, 0);
+ break;
+
+ default:
+ bs_msgin_error(ti, 0);
+ return;
+ }
+
+ ti->ti_msginptr = 0;
+ return;
+}
+
+static void
+bs_msg_reject(ti)
+ struct targ_info *ti;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct ccb *cb = ti->ti_ctab.tqh_first;
+ char *s = "unexpected msg reject";
+
+ switch (ti->ti_ophase)
+ {
+ case CMDPHASE:
+ s = "cmd rejected";
+ cb->flags &= ~BSLINK;
+ BS_SETUP_MSGPHASE(IOCOMPLETED);
+ break;
+
+ case MSGOUT:
+ if (ti->ti_msgout & 0x80)
+ {
+ s = "identify msg rejected";
+ cb->flags &= ~BSDISC;
+ BS_SETUP_MSGPHASE(IOCOMPLETED);
+ }
+ else if (ti->ti_msgout == MSG_EXTEND)
+ {
+ switch (ti->ti_emsgout)
+ {
+ case MSG_EXTEND_SYNCHCODE:
+ BS_SETUP_SYNCSTATE(BS_SYNCMSG_REJECT);
+ return;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ bs_debug_print(bsc, ti);
+ bs_printf(ti, "msgin", s);
+ ti->ti_error |= BSMSGERROR;
+}
+
+static BS_INLINE void
+bs_msgin(bsc, ti)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+{
+
+ BS_SETUP_PHASE(MSGIN);
+
+ switch (ti->ti_msgin[0])
+ {
+ case MSG_SAVESP:
+ BS_SAVE_SDP
+ break;
+
+ case MSG_RESTORESP:
+ BS_RESTORE_SDP
+ bs_printf(ti, "msgin", "restore scsi pointer");
+ break;
+
+ case MSG_REJECT:
+ bs_msg_reject(ti);
+ break;
+
+ case 0xf:
+ break;
+
+ case MSG_I_ERROR:/* all I -> T : nothing to do*/
+ case MSG_ABORT:
+ case MSG_PARITY:
+ case MSG_RESET:
+ case 0xe:
+ bs_msgin_error(ti, 1);
+ goto resume;
+
+ case MSG_NOOP:
+ break;
+
+ case MSG_EXTEND:
+ bs_msgin_ext(ti);
+ goto resume;
+
+ case 0xd:
+ bs_msgin_error(ti, 2);
+ goto resume;
+
+ case MSG_DISCON:
+ BS_SETUP_MSGPHASE(DISCONNECTASSERT);
+ break;
+
+ case MSG_COMP:
+ BS_SETUP_MSGPHASE(IOCOMPLETED);
+ break;
+
+ case MSG_LCOMP:
+ case MSG_LCOMP_F:
+ bs_status_check(bsc, ti);
+ if (bscmddone(ti) == NULL)
+ {
+ if (bscmdstart(ti, BSCMDSTART) == 0)
+ {
+ bs_printf(ti, "msgin", "cmd line miss");
+ bs_force_abort(ti);
+ }
+ }
+ else
+ bscmdstart(ti, BSCMDRESTART);
+#ifdef BS_STATICS
+ bs_linkcmd_count[ti->ti_id]++;
+#endif /* BS_STATICS */
+ BS_LOAD_SDP
+ ti->ti_status = ST_UNK;
+ break;
+
+ default:
+ if (ti->ti_msgin[0] & 0x80)
+ {
+ if ((ti->ti_msgin[0] & 0x07) != ti->ti_lun)
+ {
+ ti->ti_lun = (ti->ti_msgin[0] & 0x07);
+ bshw_set_dst_id(bsc, ti->ti_id, ti->ti_lun);
+ bshw_set_sync_reg(bsc, ti->ti_sync);
+
+ bs_printf(ti, "msgin", "lun error");
+ bs_quick_abort(ti, MSG_ABORT);
+ }
+ break;
+ }
+ else if (ti->ti_msgin[0] < 0x20)
+ bs_msgin_error(ti, 1);
+ else if (ti->ti_msgin[0] < 0x30)
+ bs_msgin_error(ti, 2);
+ else
+ bs_msgin_error(ti, 1);
+ goto resume;
+ }
+
+ ti->ti_msginptr = 0;
+
+resume:
+ return;
+}
+
+/************************************************
+ * <MSG OUT>
+ ************************************************/
+static BS_INLINE void
+bs_msgout(bsc, ti, cb)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+ u_int8_t msg[MAXMSGLEN + 1];
+
+ if (ti->ti_phase == MSGOUT)
+ {
+ if (cb->rcnt ++ < bsc->sc_retry)
+ cb->msgoutlen = ti->ti_omsgoutlen;
+ }
+ else
+ BS_SETUP_PHASE(MSGOUT);
+
+ if (ti->ti_ophase == SELECTED)
+ {
+identify:
+ if (cb->msgoutlen == 0)
+ {
+ ti->ti_msgout = bs_identify_msg(ti);
+ ti->ti_omsgoutlen = 0;
+ bs_write_1byte(bsc, ti->ti_msgout);
+ }
+ else
+ {
+ if (cb->msgout[0] != MSG_RESET &&
+ cb->msgout[0] != MSG_ABORT)
+ {
+ msg[0] = bs_identify_msg(ti);
+ bcopy(cb->msgout, &msg[1], cb->msgoutlen);
+ bs_xfer(bsc, msg, cb->msgoutlen + 1);
+ }
+ else
+ bs_xfer(bsc, cb->msgout, cb->msgoutlen);
+
+ ti->ti_msgout = cb->msgout[0];
+ ti->ti_emsgout = cb->msgout[2];
+ ti->ti_omsgoutlen = cb->msgoutlen;
+ cb->msgoutlen = 0;
+ }
+ return;
+ }
+
+ if (ti->ti_ophase == SATSEL)
+ {
+ /* XXX:
+ * Maybe identify msg rejected due to
+ * a parity error in target side.
+ */
+
+ bs_printf(ti, "msgout", "msg identify retry (SAT)");
+ goto identify;
+ }
+
+ if (cb->msgoutlen == 0)
+ {
+ ti->ti_msgout = MSG_REJECT;
+ ti->ti_omsgoutlen = 0;
+ bs_write_1byte(bsc, ti->ti_msgout);
+ }
+ else
+ {
+ ti->ti_msgout = cb->msgout[0];
+ ti->ti_emsgout = cb->msgout[2];
+ ti->ti_omsgoutlen = cb->msgoutlen;
+ bs_xfer(bsc, cb->msgout, cb->msgoutlen);
+ cb->msgoutlen = 0;
+ }
+}
+
+/************************************************
+ * <DISCONNECT>
+ ************************************************/
+static BS_INLINE void
+bs_disconnect_phase(bsc, ti, cb)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+
+ switch (bsc->sc_msgphase)
+ {
+ default:
+ panic("%s unknown msg phase\n", bsc->sc_dvname);
+ break;
+
+ case DISCONNECTASSERT:
+ case FREE:
+#ifdef BS_STATICS
+ bs_statics[ti->ti_id].disconnected++;
+#endif /* BS_STATICS */
+ if (ti->ti_cfgflags & BS_SCSI_SAVESP)
+ BS_SAVE_SDP;
+ BS_HOST_TERMINATE;
+ BS_SETUP_PHASE(DISCONNECTED);
+ bsc->sc_dtgnum ++;
+ bshoststart(bsc, NULL);
+ break;
+
+ case IOCOMPLETED:
+ bs_status_check(bsc, ti);
+ cb = bscmddone(ti);
+#ifdef BS_DIAG
+ ti->ti_flags &= ~BSNEXUS;
+#endif /* BS_DIAG */
+ BS_SETUP_PHASE(FREE);
+ if (cb || bsc->sc_sttab.tqh_first == NULL)
+ {
+ BS_HOST_TERMINATE;
+ bscmdstart(ti, BSCMDSTART);
+ }
+ else
+ {
+ /* give a chance to other target */
+ bscmdstart(ti, BSCMDSTART);
+ BS_HOST_TERMINATE;
+ bshoststart(bsc, NULL);
+ }
+ break;
+ }
+
+ BS_SETUP_MSGPHASE(FREE);
+}
+
+/**************************************************
+ * <PHASE ERROR>
+ **************************************************/
+#define scsi_status (bsc->sc_busstat)
+
+struct bs_err {
+ u_char *pe_msg;
+ u_int pe_err;
+ u_int pe_ph;
+};
+
+struct bs_err bs_cmderr[] = {
+/*0*/ { "illegal cmd", BSABNORMAL, UNDEF },
+/*1*/ { "unexpected bus free", BSABNORMAL, FREE },
+/*2*/ { NULL, BSSELTIMEOUT, FREE},
+/*3*/ { "scsi bus parity error", BSPARITY, UNDEF },
+/*4*/ { "scsi bus parity error", BSPARITY, UNDEF },
+/*5*/ { "unknown" , BSFATALIO, UNDEF },
+/*6*/ { "miss reselection (target mode)", BSFATALIO, UNDEF },
+/*7*/ { "wrong status byte", BSPARITY, STATUSIN },
+};
+
+static void
+bs_phase_error(ti, cb)
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct bs_err *pep;
+ char *s = NULL;
+
+ if ((scsi_status & BSR_CM) == BSR_CMDERR &&
+ (scsi_status & BSR_PHVALID) == 0)
+ {
+ pep = &bs_cmderr[scsi_status & BSR_PM];
+ ti->ti_error |= pep->pe_err;
+ if (pep->pe_msg)
+ {
+ bs_debug_print(bsc, ti);
+ bs_printf(ti, "bsintr", pep->pe_msg);
+ }
+ BS_SETUP_PHASE(pep->pe_ph);
+ }
+ else
+ {
+ ti->ti_error |= BSABNORMAL;
+ bs_debug_print(bsc, ti);
+ bs_printf(ti, "bsintr", "phase error");
+ BS_SETUP_PHASE(UNDEF);
+ }
+
+ BS_SETUP_MSGPHASE(FREE);
+ switch (ti->ti_phase)
+ {
+ case FREE:
+ BS_SETUP_PHASE(UNDEF);
+ cb = bscmddone(ti);
+#ifdef BS_DIAG
+ ti->ti_flags &= ~BSNEXUS;
+#endif /* BS_DIAG */
+ BS_HOST_TERMINATE;
+ BS_SETUP_PHASE(FREE);
+ bscmdstart(ti, ((cb == NULL) ? BSCMDSTART : BSCMDRESTART));
+ break;
+
+ case STATUSIN:
+ ti->ti_error |= BSSTATUSERROR;
+ ti->ti_status = bshw_get_status_insat(bsc); /* XXX SAT */
+ bs_debug_print(bsc, ti);
+ break;
+
+ case UNDEF:
+ default:
+ ti->ti_error |= BSABNORMAL;
+ bs_reset_nexus(bsc);
+ break;
+ }
+}
+
+/**************************************************
+ * ### SCSI PHASE SEQUENCER ###
+ **************************************************/
+static inline void bs_ack_wait __P((struct bs_softc *, struct targ_info *, struct ccb *));
+
+static inline void
+bs_ack_wait(bsc, ti, cb)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+ int wc = bsc->sc_wc;
+
+ for (wc = bsc->sc_wc; bshw_get_busstat(bsc) != BSR_ACKREQ && wc > 0; )
+ wc --;
+
+ if (wc <= 0)
+ {
+ bs_printf(ti, "bs_ack_wait", "timeout I");
+ return;
+ }
+
+ bshw_get_auxstat(bsc);
+ scsi_status = bshw_get_busstat(bsc);
+
+ if (cb->msgoutlen > 0)
+ {
+ bshw_assert_atn(bsc);
+ delay(800);
+ BS_SETUP_PHASE(ATTENTIONASSERT);
+ }
+
+ bshw_negate_ack(bsc);
+
+#ifdef WAITNEXTP
+ for (wc = bsc->sc_wc; bshw_get_busstat(bsc) == BSR_ACKREQ && wc > 0; )
+ wc --;
+
+ if (wc <= 0)
+ bs_printf(ti, "bs_ack_wait", "timeout II");
+#endif /* WAITNEXTP */
+}
+
+int
+bs_sequencer(bsc)
+ struct bs_softc *bsc;
+{
+ register struct targ_info *ti;
+ struct ccb *cb;
+
+ /**************************************************
+ * Check reset
+ **************************************************/
+ if (bsc->sc_flags & (BSRESET | BSINACTIVE))
+ {
+ if (bsc->sc_flags & BSRESET)
+ bs_reset_nexus(bsc);
+ return 1;
+ }
+
+ /**************************************************
+ * Get status & bus phase
+ **************************************************/
+ if ((bshw_get_auxstat(bsc) & STR_INT) == 0)
+ return 0;
+
+ scsi_status = bshw_get_busstat(bsc);
+ if (scsi_status == ((u_int8_t) -1))
+ {
+ bs_debug_print_all(bsc);
+ printf("%s strange scsi bus status\n");
+ return 1;
+ }
+ /**************************************************
+ * Check reselection, or nexus
+ **************************************************/
+ if (scsi_status == BSR_RESEL)
+ {
+ bs_reselect(bsc);
+ return 1;
+ }
+
+ ti = bsc->sc_nexus;
+ if (ti == NULL || (cb = ti->ti_ctab.tqh_first) == NULL)
+ {
+ bs_debug_print_all(bsc);
+ bs_printf(ti, "bsintr", "no nexus");
+ bs_reset_nexus(bsc);
+ return 1;
+ }
+
+ /**************************************************
+ * Debug section
+ **************************************************/
+#ifdef BS_DEBUG
+ if (bs_debug_flag)
+ {
+ bs_debug_print(bsc, ti);
+ if (bs_debug_flag > 1)
+ Debugger();
+ }
+#endif /* BS_DEBUG */
+
+ /**************************************************
+ * internal scsi phase
+ **************************************************/
+ switch (ti->ti_phase)
+ {
+ case SELECTASSERT:
+ bs_selected(bsc, ti, cb);
+ return 1;
+
+ case SATSEL:
+ BS_SELECTION_TERMINATE;
+
+ case SATRESEL:
+ if (bsc->sc_flags & (BSDMASTART | BSSMITSTART))
+ {
+ if (bsc->sc_flags & BSSMITSTART)
+ {
+ bs_debug_print_all(bsc);
+ bs_reset_nexus(bsc);
+ bs_printf(ti, "bsintr", "smit transfer");
+ return 1;
+ }
+
+ BS_SETUP_PHASE(DATAPHASE); /* XXX */
+ bs_dma_xfer_end(ti);
+ ti->ti_phase = ti->ti_ophase; /* XXX */
+ }
+ break;
+
+ default:
+ /* XXX:
+ * check check check for safty !!
+ */
+ if (bsc->sc_selwait)
+ {
+ /* Ghaaa! phase error! retry! */
+ bs_phase_error(ti, cb);
+ return 1;
+ }
+
+ if (bsc->sc_flags & (BSDMASTART | BSSMITSTART))
+ {
+ if (bsc->sc_flags & BSDMASTART)
+ bs_dma_xfer_end(ti);
+ else
+ bs_smit_xfer_end(ti);
+ }
+ break;
+ }
+
+ /**************************************************
+ * hw scsi phase
+ **************************************************/
+ if (scsi_status & BSR_PHVALID)
+ {
+ /**************************************************
+ * Normal SCSI phase.
+ **************************************************/
+ if ((scsi_status & BSR_CM) == BSR_CMDABT)
+ {
+ bs_phase_error(ti, cb);
+ return 1;
+ }
+
+ switch (scsi_status & BSR_PM)
+ {
+ case BSR_DATAOUT:
+ case BSR_DATAIN:
+ BS_SETUP_PHASE(DATAPHASE);
+
+ if (bsc->sc_p.datalen <= 0 ||
+ (ti->ti_flags & BSFORCEIOPOLL))
+ {
+ bs_io_xfer(ti);
+ return 1;
+ }
+
+ if (bs_check_smit(ti) &&
+ (bsc->sc_p.datalen % sizeof(u_int32_t)) == 0)
+ {
+ bs_lc_smit_xfer(ti, scsi_status & BSR_IOR);
+ return 1;
+ }
+
+ bs_dma_xfer(ti, scsi_status & BSR_IOR);
+ bshw_start_xfer(bsc);
+ return 1;
+
+ case BSR_CMDOUT:
+ bs_commandout(bsc, ti, cb);
+ return 1;
+
+ case BSR_STATIN:
+ if (bs_check_sat(ti))
+ {
+ BS_SETUP_PHASE(SATCOMPSEQ);
+ bshw_set_count(bsc, 0);
+ bshw_cmd_pass(bsc, 0x41);
+ bshw_start_sat(bsc, 0);
+ }
+ else
+ {
+ BS_SETUP_PHASE(STATUSIN);
+ ti->ti_status = bs_read_1byte(bsc);
+ }
+ return 1;
+
+ case BSR_UNSPINFO0:
+ case BSR_UNSPINFO1:
+ bs_debug_print(bsc, ti);
+ bs_printf(ti, "bsintr", "illegal bus phase");
+ return 1;
+
+ case BSR_MSGOUT:
+ bs_msgout(bsc, ti, cb);
+ return 1;
+
+ case BSR_MSGIN:/* msg in */
+ if (bs_check_sat(ti))
+ {
+ if (ti->ti_phase == RESELECTED)
+ {
+ bs_sat_continue(bsc, ti, cb);
+ return 1;
+ }
+ /* XXX */
+ if (ti->ti_status == ST_UNK)
+ ti->ti_status = bshw_get_status_insat(bsc);
+ }
+
+ ti->ti_msgin[ti->ti_msginptr ++] = bs_read_1byte(bsc);
+ bs_msgin(bsc, ti);
+ if (bsc->sc_cfgflags & BSC_FASTACK)
+ bs_ack_wait(bsc, ti, cb);
+
+ return 1;
+ }
+ }
+ else
+ {
+ /**************************************************
+ * Special SCSI phase
+ **************************************************/
+ switch (scsi_status)
+ {
+ case BSR_SATSDP:/* SAT with save data pointer */
+ BS_SAVE_SDP
+ bshw_cmd_pass(bsc, 0x41);
+ bshw_start_sat(bsc, 0);
+ BS_SETUP_PHASE(SATSDP)
+ return 1;
+
+ case BSR_SATFIN:/* SAT COMPLETE */
+ ti->ti_status = bshw_get_status_insat(bsc);
+ BS_SETUP_MSGPHASE(IOCOMPLETED);
+ bs_disconnect_phase(bsc, ti, cb);
+ return 1;
+
+ case BSR_ACKREQ:/* negate ACK */
+ if (cb->msgoutlen > 0)
+ {
+ bshw_assert_atn(bsc);
+ delay(800);
+ BS_SETUP_PHASE(ATTENTIONASSERT);
+ }
+ bshw_negate_ack(bsc);
+ return 1;
+
+ case BSR_DISC:/* disconnect */
+ bs_disconnect_phase(bsc, ti, cb);
+ return 1;
+
+ default:
+ break;
+ }
+ }
+
+ bs_phase_error(ti, cb);
+ return 1;
+}
+
+/*****************************************************************
+ * INTERNAL POLLING FUNCTIONS
+ *****************************************************************/
+static int
+bs_scsi_cmd_poll_internal(cti)
+ struct targ_info *cti;
+{
+ struct bs_softc *bsc = cti->ti_bsc;
+ struct targ_info *ti;
+ struct ccb *cb;
+ int i, waits, delay_count;
+
+ bsc->sc_poll++;
+
+ /* setup timeout count */
+ if ((ti = bsc->sc_nexus) == NULL ||
+ (cb = ti->ti_ctab.tqh_first) == NULL)
+ waits = BS_DEFAULT_TIMEOUT_SECOND * 1000000;
+ else
+ waits = cb->tcmax * 1000000;
+
+ /* force all current jobs into the polling state. */
+ for (i = 0; i < NTARGETS; i++)
+ {
+ if (ti = bsc->sc_ti[i])
+ {
+ ti->ti_flags |= BSFORCEIOPOLL;
+ if (cb = ti->ti_ctab.tqh_first)
+ cb->flags |= BSFORCEIOPOLL;
+ }
+ }
+
+ /* do io */
+ bsc->sc_flags &= ~BSJOBDONE;
+ do
+ {
+ delay_count = ((bsc->sc_flags & BSDMASTART) ? 1000000 : 100);
+ delay(delay_count);
+ waits -= delay_count;
+ bs_sequencer(bsc);
+ }
+ while (waits >= 0 && (bsc->sc_flags & (BSUNDERRESET | BSJOBDONE)) == 0);
+
+ /* done */
+ bsc->sc_poll--;
+ if (waits < 0 || (bsc->sc_flags & BSUNDERRESET))
+ {
+ bs_printf(NULL, "cmd_poll", "timeout or fatal");
+ return HASERROR;
+ }
+
+ return COMPLETE;
+}
+
+int
+bs_scsi_cmd_poll(cti, targetcb)
+ struct targ_info *cti;
+ struct ccb *targetcb;
+{
+ struct bs_softc *bsc = cti->ti_bsc;
+ struct targ_info *ti;
+ int s, error = COMPLETE;
+
+ s = splbio();
+ bs_terminate_timeout(bsc);
+
+ if (bsc->sc_hstate == BSC_TARG_CHECK)
+ {
+ if ((error = bs_scsi_cmd_poll_internal(cti)) != COMPLETE)
+ bs_reset_nexus(bsc);
+ }
+ else
+ {
+ if (bsc->sc_outccb)
+ bs_panic(bsc, "bs_cmd_poll: internal error");
+
+ bsc->sc_flags &= ~BSPOLLDONE;
+ bsc->sc_outccb = targetcb;
+
+ while ((bsc->sc_flags & BSPOLLDONE) == 0)
+ {
+ if (bs_scsi_cmd_poll_internal(cti) != COMPLETE)
+ {
+ if ((ti = bsc->sc_nexus) && ti->ti_ctab.tqh_first)
+ ti->ti_error |= (BSTIMEOUT | BSABNORMAL);
+ bs_reset_nexus(bsc);
+ }
+ }
+
+ bsc->sc_outccb = NULL;
+ }
+
+ bs_start_timeout(bsc);
+ softintr(bsc->sc_irqmasks);
+ splx(s);
+ return error;
+}
diff --git a/sys/i386/isa/bs/bs_isa.c b/sys/i386/isa/bs/bs_isa.c
new file mode 100644
index 0000000..fa4e2a0
--- /dev/null
+++ b/sys/i386/isa/bs/bs_isa.c
@@ -0,0 +1,60 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1995, 1996 NetBSD/pc98 porting staff.
+ * 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 <dev/isa/bs/bsif.h>
+
+static int bs_isa_probe __P((struct device *, void *, void *));
+static void bs_isa_attach __P((struct device *, struct device *, void *));
+
+struct cfattach bs_isa_ca = {
+ sizeof(struct bs_softc), bs_isa_probe, bs_isa_attach
+};
+
+static int
+bs_isa_probe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct isa_attach_args *ia = aux;
+
+ ia->ia_irq = IRQUNK;
+ ia->ia_drq = DRQUNK;
+
+ return bsprobe(parent, match, aux);
+}
+
+static void
+bs_isa_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+
+ bsattach(parent, self, aux);
+}
diff --git a/sys/i386/isa/bs/bs_pisa.c b/sys/i386/isa/bs/bs_pisa.c
new file mode 100644
index 0000000..2ca9277
--- /dev/null
+++ b/sys/i386/isa/bs/bs_pisa.c
@@ -0,0 +1,126 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1995, 1996 NetBSD/pc98 porting staff.
+ * 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 <dev/isa/bs/bsif.h>
+
+static int bs_pisa_probe __P((struct device *, void *, void *));
+static void bs_pisa_attach __P((struct device *, struct device *, void *));
+static int bs_deactivate __P((pisa_device_args_t));
+static int bs_activate __P((pisa_device_args_t));
+
+struct cfattach bs_pisa_ca = {
+ sizeof(struct bs_softc), bs_pisa_probe, bs_pisa_attach
+};
+
+struct pisa_driver bs_pd = {
+ bs_activate, bs_deactivate,
+};
+
+static int
+bs_pisa_probe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct bs_softc *sc = match;
+ struct pisa_attach_args *pa = aux;
+ struct isa_attach_args *ia = &pa->pa_ia;
+
+ if (ia->ia_iobase == IOBASEUNK ||
+ ia->ia_irq == IRQUNK || ia->ia_drq == DRQUNK)
+ return 0;
+
+ sc->sc_pdv = pa->pa_pdv;
+
+ return bsprobe(parent, match, ia);
+}
+
+static void
+bs_pisa_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct bs_softc *sc = (void *) self;
+ struct pisa_attach_args *pa = aux;
+
+ sc->sc_pdv = PISAMSG_BIND(pa->pa_pdv, sc, &bs_pd);
+
+ bsattach(parent, self, (void *) &pa->pa_ia);
+
+ PISA_INTR_REGISTER(sc->sc_pdv, sc->sc_ih);
+}
+
+static int
+bs_deactivate(arg)
+ pisa_device_args_t arg;
+{
+ struct bs_softc *bsc = arg->id;
+
+ bsc->sc_flags |= BSINACTIVE;
+ bs_terminate_timeout(bsc);
+
+ return 0;
+}
+
+#define SCSIBUS_RESCAN
+
+static int
+bs_activate(arg)
+ pisa_device_args_t arg;
+{
+ struct bs_softc *bsc = arg->id;
+ struct isa_attach_args *ia = arg->ia;
+ struct targ_info *ti;
+ int i;
+
+ bsc->sc_irqmasks = (1 << ia->ia_irq);
+
+ while((ti = bsc->sc_titab.tqh_first) != NULL)
+ TAILQ_REMOVE(&bsc->sc_titab, ti, ti_tchain);
+
+ bsc->sc_openf = 0;
+ for (i = 0; i < NTARGETS; i ++)
+ if (i != bsc->sc_hostid && (ti = bsc->sc_ti[i]) != NULL)
+ {
+ TAILQ_INSERT_TAIL(&bsc->sc_titab, ti, ti_tchain);
+ bsc->sc_openf |= (1 << i);
+ }
+
+ bsc->sc_hstate = BSC_BOOTUP;
+ bsc->sc_flags &= ~BSINACTIVE;
+ bs_reset_nexus(bsc);
+
+#ifdef SCSIBUS_RESCAN
+ if (bsc->sc_nexus == NULL)
+ scsi_probe_busses((int) bsc->sc_link.scsibus, -1, -1);
+#endif
+
+ bs_start_timeout(bsc);
+ return 0;
+}
diff --git a/sys/i386/isa/bs/bsfunc.c b/sys/i386/isa/bs/bsfunc.c
new file mode 100644
index 0000000..89d4acc
--- /dev/null
+++ b/sys/i386/isa/bs/bsfunc.c
@@ -0,0 +1,926 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
+ */
+
+#ifdef __NetBSD__
+#include <dev/isa/bs/bsif.h>
+#endif
+#ifdef __FreeBSD__
+#include <i386/isa/bs/bsif.h>
+#endif
+
+#ifdef BS_STATICS
+struct bs_statics bs_statics[NTARGETS];
+u_int bs_linkcmd_count[NTARGETS];
+u_int bs_bounce_used[NTARGETS];
+#endif /* BS_STATICS */
+
+#ifdef BS_DEBUG
+int bs_debug_flag = 0;
+#endif /* BS_DEBUG */
+
+static void bs_print_syncmsg __P((struct targ_info *, char*));
+static void bs_timeout_target __P((struct targ_info *));
+static void bs_kill_msg __P((struct ccb *cb));
+
+static int bs_start_target __P((struct targ_info *));
+static int bs_check_target __P((struct targ_info *));
+
+/*************************************************************
+ * CCB
+ ************************************************************/
+GENERIC_CCB_STATIC_ALLOC(bs, ccb)
+GENERIC_CCB(bs, ccb, ccb_chain)
+
+/*************************************************************
+ * TIMEOUT
+ ************************************************************/
+static void
+bs_timeout_target(ti)
+ struct targ_info *ti;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+
+ ti->ti_error |= BSTIMEOUT;
+ bsc->sc_flags |= BSRESET;
+
+ if (ti->ti_herrcnt ++ >= HARDRETRIES)
+ {
+ bs_printf(ti, "timeout", "async transfer!");
+ ti->ti_syncmax.period = ti->ti_syncmax.offset = 0;
+ }
+}
+
+void
+bstimeout(arg)
+ void *arg;
+{
+ struct bs_softc *bsc = (struct bs_softc *) arg;
+ struct targ_info *ti;
+ struct ccb *cb;
+ int s;
+
+ s = splbio();
+ bsc->sc_flags &= ~BSSTARTTIMEOUT;
+
+ /* check */
+ if ((ti = bsc->sc_nexus) && (cb = ti->ti_ctab.tqh_first))
+ {
+ if ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0)
+ bs_timeout_target(ti);
+ }
+ else for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
+ {
+ if (bsc->sc_dtgnum && ti->ti_phase < DISCONNECTED)
+ continue;
+
+ cb = ti->ti_ctab.tqh_first;
+ if (cb && ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0))
+ bs_timeout_target(ti);
+ }
+
+ /* try to recover */
+ if (bsc->sc_flags & BSRESET)
+ {
+ bs_debug_print_all(bsc);
+ bs_printf(ti, "timeout", "bus hang up");
+ bs_reset_nexus(bsc);
+ }
+
+ bs_start_timeout(bsc);
+ splx(s);
+}
+
+/**************************************************
+ * MAKE CCB & MSG CCB
+ *************************************************/
+static u_int8_t cmd_unit_ready[6];
+
+struct ccb *
+bs_make_internal_ccb(ti, lun, cmd, cmdlen, data, datalen, flags, timeout)
+ struct targ_info *ti;
+ u_int lun;
+ u_int8_t *cmd;
+ u_int cmdlen;
+ u_int8_t *data;
+ u_int datalen;
+ u_int flags;
+ int timeout;
+{
+ struct ccb *cb;
+
+ if ((cb = bs_get_ccb(XSBS_SCSI_NOSLEEP)) == NULL)
+ bs_panic(ti->ti_bsc, "can not get ccb mem");
+
+ cb->xs = NULL;
+ cb->lun = lun;
+ cb->cmd = (cmd ? cmd : cmd_unit_ready);
+ cb->cmdlen = (cmd ? cmdlen : sizeof(cmd_unit_ready));
+ cb->data = data;
+ cb->datalen = (data ? datalen : 0);
+ cb->msgoutlen = 0;
+ cb->flags = flags & BSCFLAGSMASK;
+ bs_targ_flags(ti, cb);
+ cb->rcnt = 0;
+ cb->tcmax = (timeout > BS_DEFAULT_TIMEOUT_SECOND ? timeout :
+ BS_DEFAULT_TIMEOUT_SECOND);
+
+ TAILQ_INSERT_HEAD(&ti->ti_ctab, cb, ccb_chain);
+
+ return cb;
+}
+
+struct ccb *
+bs_make_msg_ccb(ti, lun, cb, msg, timex)
+ struct targ_info *ti;
+ u_int lun;
+ struct ccb *cb;
+ struct msgbase *msg;
+ u_int timex;
+{
+ u_int flags;
+
+ flags = BSFORCEIOPOLL | msg->flag;
+ if (cb == NULL)
+ cb = bs_make_internal_ccb(ti, lun, NULL, 0, NULL, 0,
+ flags, timex);
+ else
+ cb->flags |= flags & BSCFLAGSMASK;
+
+ cb->msgoutlen = msg->msglen;
+ bcopy(msg->msg, cb->msgout, msg->msglen);
+ return cb;
+}
+
+int
+bs_send_msg(ti, lun, msg, timex)
+ struct targ_info *ti;
+ u_int lun;
+ struct msgbase *msg;
+ int timex;
+{
+ struct ccb *cb;
+
+ cb = bs_make_msg_ccb(ti, lun, NULL, msg, timex);
+ bscmdstart(ti, BSCMDSTART);
+ return bs_scsi_cmd_poll(ti, cb);
+}
+
+static void
+bs_kill_msg(cb)
+ struct ccb *cb;
+{
+ cb->msgoutlen = 0;
+}
+
+/**************************************************
+ * MAKE SENSE CCB
+ **************************************************/
+struct ccb *
+bs_request_sense(ti)
+ struct targ_info *ti;
+{
+ struct ccb *cb;
+
+ bzero(ti->scsi_cmd, sizeof(struct scsi_sense));
+ bzero(&ti->sense, sizeof(struct scsi_sense_data));
+ ti->scsi_cmd[0] = REQUEST_SENSE;
+ ti->scsi_cmd[1] = (ti->ti_lun << 5);
+ ti->scsi_cmd[4] = sizeof(struct scsi_sense_data);
+ cb = bs_make_internal_ccb(ti, ti->ti_lun, ti->scsi_cmd,
+ sizeof(struct scsi_sense),
+ (u_int8_t *) & ti->sense,
+ sizeof(struct scsi_sense_data),
+ BSFORCEIOPOLL,
+ BS_DEFAULT_TIMEOUT_SECOND);
+ cb->flags |= BSSENSECCB;
+ return cb;
+}
+
+/**************************************************
+ * SYNC MSG
+ *************************************************/
+/* sync neg */
+int
+bs_start_syncmsg(ti, cb, flag)
+ struct targ_info *ti;
+ struct ccb *cb;
+ int flag;
+{
+ struct syncdata *negp, *maxp;
+ struct msgbase msg;
+ u_int lun;
+
+ negp = &ti->ti_syncnow;
+ maxp = &ti->ti_syncmax;
+
+ ti->ti_state = BS_TARG_SYNCH;
+
+ if (flag == BS_SYNCMSG_REQUESTED)
+ {
+ if (negp->offset > maxp->offset)
+ negp->offset = maxp->offset;
+ if (negp->offset != 0 && negp->period < maxp->period)
+ negp->period = maxp->period;
+
+ msg.flag = 0;
+ lun = ti->ti_lun;
+ if (cb == NULL)
+ cb = ti->ti_ctab.tqh_first;
+ }
+ else if (ti->ti_cfgflags & BS_SCSI_SYNC)
+ {
+ negp->offset = maxp->offset;
+ negp->period = maxp->period;
+
+ msg.flag = BSERROROK;
+ lun = 0;
+ }
+ else
+ {
+ ti->ti_state = BS_TARG_RDY;
+ return COMPLETE;
+ }
+
+ BS_SETUP_SYNCSTATE(flag);
+ msg.msg[0] = MSG_EXTEND;
+ msg.msg[1] = MSG_EXTEND_SYNCHLEN;
+ msg.msg[2] = MSG_EXTEND_SYNCHCODE;
+ msg.msg[3] = negp->period;
+ msg.msg[4] = negp->offset;
+ msg.msglen = MSG_EXTEND_SYNCHLEN + 2;
+
+ bs_make_msg_ccb(ti, lun, cb, &msg, BS_SYNC_TIMEOUT);
+ return COMPLETE;
+}
+
+static void
+bs_print_syncmsg(ti, s)
+ struct targ_info *ti;
+ char *s;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct syncdata *negp;
+ u_int speed;
+
+ negp = &ti->ti_syncnow;
+ speed = (negp->offset && negp->period) ?
+ (2500 / ((u_int) negp->period)) : 0;
+
+ printf("%s(%d:%d): <%s> ", bsc->sc_dvname, ti->ti_id, ti->ti_lun, s);
+ printf("period 0x%x offset %d chip (0x%x)", negp->period, negp->offset,
+ ti->ti_sync);
+ if (speed)
+ printf(" %d.%d M/s", speed / 10, speed % 10);
+ printf("\n");
+}
+
+int
+bs_analyze_syncmsg(ti, cb)
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ u_int8_t ans = ti->ti_syncnow.state;
+ struct syncdata *negp, *maxp;
+ struct syncdata bdata;
+ char *s = NULL;
+ u_int8_t period;
+
+ negp = &ti->ti_syncnow;
+ bdata = *negp;
+ maxp = &ti->ti_syncmax;
+
+ switch(ans)
+ {
+ case BS_SYNCMSG_REJECT:
+ period = 0;
+ s = "msg reject";
+ break;
+
+ case BS_SYNCMSG_ASSERT:
+ period = 0;
+ s = "no msg";
+ break;
+
+ default:
+ if (negp->offset != 0 && negp->period < maxp->period)
+ {
+ period = 0xff;
+ s = "illegal(period)";
+ }
+ else if (negp->offset > maxp->offset)
+ {
+ period = 0xff;
+ s = "illegal(offset)";
+ }
+ else
+ period = negp->offset ? negp->period : 0;
+ break;
+ }
+
+ if (s == NULL)
+ {
+ bshw_adj_syncdata(negp);
+ *maxp = *negp;
+
+ if (ans == BS_SYNCMSG_REQUESTED)
+ s = "requested";
+ else
+ s = negp->offset ? "synchronous" : "async";
+ }
+ else
+ {
+ negp->offset = maxp->offset = 0;
+ bshw_adj_syncdata(negp);
+ bshw_adj_syncdata(maxp);
+ }
+
+ /* really setup hardware */
+ bshw_set_synchronous(bsc, ti);
+ if (cb == NULL || (period >= negp->period && period <= negp->period + 2))
+ {
+ bs_print_syncmsg(ti, s);
+ BS_SETUP_TARGSTATE(BS_TARG_RDY);
+ BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
+ if (cb)
+ bs_kill_msg(cb);
+
+ return 0;
+ }
+ else
+ {
+ bs_printf(ti, "bs_analyze_syncmsg",
+ "sync(period) mismatch, retry neg...");
+ printf("expect(%d:0x%x) => reply(%d:0x%x)\n",
+ bdata.offset, bdata.period, negp->offset, negp->period);
+
+ bs_start_syncmsg(ti, cb, BS_SYNCMSG_ASSERT);
+ return EINVAL;
+ }
+}
+
+/**************************************************
+ * ABORT AND RESET MSG
+ **************************************************/
+/* send device reset msg and wait */
+void
+bs_reset_device(ti)
+ struct targ_info *ti;
+{
+ struct msgbase msg;
+
+ msg.msglen = 1;
+ msg.msg[0] = MSG_RESET;
+ msg.flag = 0;
+
+ bs_send_msg(ti, 0, &msg, 0);
+
+ delay(ti->ti_bsc->sc_RSTdelay);
+ bs_check_target(ti);
+}
+
+/* send abort msg */
+struct ccb *
+bs_force_abort(ti)
+ struct targ_info *ti;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct msgbase msg;
+ struct ccb *cb = ti->ti_ctab.tqh_first;
+ u_int lun;
+
+ if (cb)
+ {
+ lun = cb->lun;
+ cb->rcnt++;
+ }
+ else
+ lun = 0;
+
+ msg.msglen = 1;
+ msg.msg[0] = MSG_ABORT;
+ msg.flag = 0;
+
+ cb = bs_make_msg_ccb(ti, lun, NULL, &msg, 0);
+ bscmdstart(ti, BSCMDSTART);
+
+ if (bsc->sc_nexus == ti)
+ BS_LOAD_SDP
+
+ return cb;
+}
+
+/**************************************************
+ * COMPLETE SCSI BUS RESET
+ *************************************************/
+/*
+ * XXX:
+ * 1) reset scsi bus (ie. all target reseted).
+ * 2) chip reset.
+ * 3) check target status.
+ * 4) sync neg with all targets.
+ * 5) setup sync reg in host.
+ * 6) recover previous nexus.
+ */
+void
+bs_scsibus_start(bsc)
+ struct bs_softc *bsc;
+{
+ struct targ_info *ti, *nextti = NULL;
+ struct ccb *cb;
+ int error = HASERROR;
+ u_int querm, bits, skip = 0;
+
+ querm = (bsc->sc_hstate == BSC_BOOTUP);
+ bsc->sc_hstate = BSC_TARG_CHECK;
+
+ /* target check */
+ do
+ {
+ if (error != COMPLETE)
+ {
+ printf("%s: scsi bus reset and try to restart ...",
+ bsc->sc_dvname);
+ bshw_smitabort(bsc);
+ bshw_dmaabort(bsc, NULL);
+ bshw_chip_reset(bsc);
+ bshw_bus_reset(bsc);
+ bshw_chip_reset(bsc);
+ printf(" done. scsi bus ready.\n");
+ nextti = bsc->sc_titab.tqh_first;
+ error = COMPLETE;
+ }
+
+ if ((ti = nextti) == NULL)
+ break;
+ nextti = ti->ti_tchain.tqe_next;
+
+ bits = (1 << ti->ti_id);
+ if (skip & bits)
+ continue;
+
+ if ((error = bs_check_target(ti)) != COMPLETE)
+ {
+ if (querm)
+ {
+ TAILQ_REMOVE(&bsc->sc_titab, ti, ti_tchain);
+ bsc->sc_openf &= ~bits;
+ }
+
+ if (error == NOTARGET)
+ error = COMPLETE;
+
+ skip |= bits;
+ }
+ }
+ while (1);
+
+ /* ok now ready */
+ bsc->sc_hstate = BSC_RDY;
+
+ /* recover */
+ for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
+ {
+ ti->ti_ctab = ti->ti_bctab;
+ TAILQ_INIT(&ti->ti_bctab);
+ if (ti->ti_ctab.tqh_first)
+ bscmdstart(ti, BSCMDSTART);
+ }
+}
+
+void
+bs_reset_nexus(bsc)
+ struct bs_softc *bsc;
+{
+ struct targ_info *ti;
+ struct ccb *cb;
+
+ bsc->sc_flags &= ~(BSRESET | BSUNDERRESET);
+ if (bsc->sc_poll)
+ {
+ bsc->sc_flags |= BSUNDERRESET;
+ return;
+ }
+
+ /* host state clear */
+ BS_HOST_TERMINATE
+ BS_SETUP_MSGPHASE(FREE)
+ bsc->sc_dtgnum = 0;
+
+ /* target state clear */
+ for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
+ {
+ if (ti->ti_state == BS_TARG_SYNCH)
+ bs_analyze_syncmsg(ti, NULL);
+ if (ti->ti_state > BS_TARG_START)
+ BS_SETUP_TARGSTATE(BS_TARG_START);
+
+ BS_SETUP_PHASE(UNDEF)
+ bs_hostque_delete(bsc, ti);
+ if (cb = ti->ti_ctab.tqh_first)
+ {
+ if (bsc->sc_hstate == BSC_TARG_CHECK)
+ {
+ ti->ti_error |= BSFATALIO;
+ bscmddone(ti);
+ }
+ else if (cb->rcnt >= bsc->sc_retry)
+ {
+ ti->ti_error |= BSABNORMAL;
+ bscmddone(ti);
+ }
+ else if (ti->ti_error)
+ cb->rcnt++;
+ }
+
+ /* target state clear */
+ BS_SETUP_PHASE(FREE)
+ BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
+ ti->ti_flags &= ~BSCFLAGSMASK;
+ ti->ti_msgout = 0;
+#ifdef BS_DIAG
+ ti->ti_flags &= ~BSNEXUS;
+#endif /* BS_DIAG */
+
+ for ( ; cb; cb = cb->ccb_chain.tqe_next)
+ {
+ bs_kill_msg(cb);
+ cb->flags &= ~(BSITSDONE | BSCASTAT);
+ cb->error = 0;
+ }
+
+ if (bsc->sc_hstate != BSC_TARG_CHECK &&
+ ti->ti_bctab.tqh_first == NULL)
+ ti->ti_bctab = ti->ti_ctab;
+
+ TAILQ_INIT(&ti->ti_ctab);
+ }
+
+ if (bsc->sc_hstate != BSC_TARG_CHECK)
+ bs_scsibus_start(bsc);
+}
+
+/**************************************************
+ * CHECK TARGETS AND START TARGETS
+ *************************************************/
+static int
+bs_start_target(ti)
+ struct targ_info *ti;
+{
+ struct ccb *cb;
+ struct scsi_start_stop cmd;
+
+ bzero(&cmd, sizeof(struct scsi_start_stop));
+#ifdef __NetBSD__
+ cmd.opcode = START_STOP;
+#else
+ cmd.op_code = START_STOP;
+#endif
+ cmd.how = SSS_START;
+ ti->ti_lun = 0;
+ cb = bs_make_internal_ccb(ti, 0, (u_int8_t *) &cmd,
+ sizeof(struct scsi_start_stop),
+ NULL, 0, BSFORCEIOPOLL, BS_MOTOR_TIMEOUT);
+ bscmdstart(ti, BSCMDSTART);
+ return bs_scsi_cmd_poll(ti, cb);
+}
+
+/* test unit ready and check ATN msgout response */
+static int
+bs_check_target(ti)
+ struct targ_info *ti;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct scsi_inquiry scsi_cmd;
+ struct scsi_inquiry_data scsi_inquiry_data;
+ struct ccb *cb;
+ int count, retry = bsc->sc_retry;
+ int s, error = COMPLETE;
+
+ ti->ti_lun = 0;
+ bsc->sc_retry = 2;
+ s = splbio();
+
+ /* inquiry */
+ bzero(&scsi_cmd, sizeof(scsi_cmd));
+#ifdef __NetBSD__
+ scsi_cmd.opcode = INQUIRY;
+#else
+ scsi_cmd.op_code = INQUIRY;
+#endif
+ scsi_cmd.length = sizeof(struct scsi_inquiry_data);
+ cb = bs_make_internal_ccb(ti, 0,
+ (u_int8_t *) &scsi_cmd, sizeof(scsi_cmd),
+ (u_int8_t *) &scsi_inquiry_data,
+ sizeof(scsi_inquiry_data),
+ BSFORCEIOPOLL, BS_STARTUP_TIMEOUT);
+ bscmdstart(ti, BSCMDSTART);
+ error = bs_scsi_cmd_poll(ti, cb);
+ if (error != COMPLETE || (ti->ti_error & BSSELTIMEOUT))
+ goto done;
+ ti->targ_type = scsi_inquiry_data.device;
+ ti->targ_support = scsi_inquiry_data.flags;
+
+ /* test unit ready twice */
+ for (count = 0; count < 2; count++)
+ {
+ cb = bs_make_internal_ccb(ti, 0, NULL, 0, NULL, 0,
+ BSFORCEIOPOLL, BS_STARTUP_TIMEOUT);
+ bscmdstart(ti, BSCMDSTART);
+ error = bs_scsi_cmd_poll(ti, cb);
+ if (error != COMPLETE || (ti->ti_error & BSSELTIMEOUT))
+ goto done;
+ }
+
+ if (cb->flags & BSCASTAT)
+ bs_printf(ti, "check", "could not clear CA state");
+ ti->ti_error = 0;
+
+done:
+ bsc->sc_retry = retry;
+
+ if (ti->ti_error & BSSELTIMEOUT)
+ error = NOTARGET;
+
+ if (error == COMPLETE)
+ error = bs_start_target(ti);
+
+ splx(s);
+ return error;
+}
+
+/**************************************************
+ * TARGET CONTROL
+ **************************************************/
+struct targ_info *
+bs_init_target_info(bsc, target)
+ struct bs_softc *bsc;
+ int target;
+{
+ struct targ_info *ti;
+
+ ti = malloc(sizeof(struct targ_info), M_DEVBUF, M_NOWAIT);
+ if (ti == NULL)
+ {
+ bs_printf(NULL, "bs_init_targ_info", "no target info memory");
+ return ti;
+ }
+
+ bzero(ti, sizeof(*ti));
+
+ ti->ti_bsc = bsc;
+ ti->ti_id = target;
+ ti->sm_vaddr = (u_int8_t *) MADDRUNK;
+ ti->ti_cfgflags = BS_SCSI_NOPARITY | BS_SCSI_NOSAT;
+ ti->ti_mflags = ~(BSSAT | BSDISC | BSSMIT | BSLINK);
+ BS_SETUP_TARGSTATE(BS_TARG_CTRL);
+
+ TAILQ_INIT(&ti->ti_ctab);
+
+ bs_alloc_buf(ti);
+ if (ti->bounce_addr == NULL)
+ {
+ free(ti, M_DEVBUF);
+ return NULL;
+ }
+
+ TAILQ_INSERT_TAIL(&bsc->sc_titab, ti, ti_tchain);
+ bsc->sc_ti[target] = ti;
+ bsc->sc_openf |= (1 << target);
+
+ return ti;
+}
+
+void
+bs_setup_ctrl(ti, quirks, flags)
+ struct targ_info *ti;
+ u_int quirks;
+ u_int flags;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ u_int offset, period, maxperiod;
+
+ if (ti->ti_state == BS_TARG_CTRL)
+ {
+ ti->ti_cfgflags = BS_SCSI_POSITIVE;
+ ti->ti_syncmax.offset = BSHW_MAX_OFFSET;
+ BS_SETUP_TARGSTATE(BS_TARG_START);
+ }
+ else
+ flags |= ti->ti_cfgflags & BS_SCSI_NEGATIVE;
+
+#ifdef BS_TARG_SAFEMODE
+ if (ti->targ_type != 0)
+ {
+ flags &= ~(BS_SCSI_DISC | BS_SCSI_SYNC);
+ flags |= BS_SCSI_NOPARITY;
+ }
+#endif
+
+#ifdef SDEV_NODISC
+ if (quirks & SDEV_NODISC)
+ flags &= ~BS_SCSI_DISC;
+#endif
+#ifdef SDEV_NOPARITY
+ if (quirks & SDEV_NOPARITY)
+ flags |= BS_SCSI_NOPARITY;
+#endif
+#ifdef SDEV_NOCMDLNK
+ if (quirks & SDEV_NOCMDLNK)
+ flags &= ~BS_SCSI_LINK;
+#endif
+#ifdef SDEV_ASYNC
+ if (quirks & SDEV_ASYNC)
+ flags &= ~BS_SCSI_SYNC;
+#endif
+#ifdef SDEV_AUTOSAVE
+ if (quirks & SDEV_AUTOSAVE)
+ flags |= BS_SCSI_SAVESP;
+#endif
+
+ if ((flags & BS_SCSI_DISC) == 0 ||
+ (ti->targ_support & SID_Linked) == 0)
+ flags &= ~BS_SCSI_LINK;
+
+ ti->sm_vaddr = (flags & BS_SCSI_NOSMIT) ?
+ (u_int8_t *) MADDRUNK : bsc->sm_vaddr;
+
+ if (ti->sm_vaddr == (u_int8_t *) MADDRUNK)
+ flags |= BS_SCSI_NOSMIT;
+ else if (bsc->sc_cfgflags & BSC_SMITSAT_DISEN)
+ flags |= BS_SCSI_NOSAT;
+
+ flags &= (ti->ti_cfgflags & BS_SCSI_POSITIVE) | (~BS_SCSI_POSITIVE);
+ ti->ti_cfgflags = flags;
+
+ /* calculate synch setup */
+ period = BS_SCSI_PERIOD(flags);
+ offset = (flags & BS_SCSI_SYNC) ? BS_SCSI_OFFSET(flags) : 0;
+
+ maxperiod = (bsc->sc_cspeed & IDR_FS_15_20) ? 100 : 50;
+ if (period > maxperiod)
+ period = maxperiod;
+
+ if (period)
+ period = 2500 / period;
+
+ if (ti->ti_syncmax.offset > offset)
+ ti->ti_syncmax.offset = offset;
+ if (ti->ti_syncmax.period < period)
+ ti->ti_syncmax.period = period;
+
+ bshw_adj_syncdata(&ti->ti_syncmax);
+
+ /* finally report our info */
+ printf("%s(%d:%d): {%d:0x%x:0x%x:%s} flags 0x%b\n",
+ bsc->sc_dvname, ti->ti_id, ti->ti_lun,
+ (u_int) ti->targ_type,
+ (u_int) ti->targ_support,
+ (u_int) ti->bounce_size,
+ (flags & BS_SCSI_NOSMIT) ? "dma" : "pdma",
+ flags, BS_SCSI_BITS);
+
+ /* internal representation */
+ ti->ti_mflags = ~0;
+ if ((ti->ti_cfgflags & BS_SCSI_DISC) == 0)
+ ti->ti_mflags &= ~BSDISC;
+ if ((ti->ti_cfgflags & BS_SCSI_LINK) == 0)
+ ti->ti_mflags &= ~BSLINK;
+ if (ti->ti_cfgflags & BS_SCSI_NOSAT)
+ ti->ti_mflags &= ~BSSAT;
+ if (ti->ti_cfgflags & BS_SCSI_NOSMIT)
+ ti->ti_mflags &= ~BSSMIT;
+}
+
+/**************************************************
+ * MISC
+ **************************************************/
+void
+bs_printf(ti, ph, c)
+ struct targ_info *ti;
+ char *ph;
+ char *c;
+{
+
+ if (ti)
+ printf("%s(%d:%d): <%s> %s\n",
+ ti->ti_bsc->sc_dvname, ti->ti_id, ti->ti_lun, ph, c);
+ else
+ printf("bs*(*:*): <%s> %s\n", ph, c);
+}
+
+void
+bs_panic(bsc, c)
+ struct bs_softc *bsc;
+ u_char *c;
+{
+
+ panic("%s %s\n", bsc->sc_dvname, c);
+}
+
+/**************************************************
+ * DEBUG FUNC
+ **************************************************/
+#ifdef BS_DEBUG_ROUTINE
+u_int
+bsr(addr)
+ u_int addr;
+{
+
+ outb(0xcc0, addr);
+ return inb(0xcc2);
+}
+
+u_int
+bsw(addr, data)
+ u_int addr;
+ int data;
+{
+
+ outb(0xcc0, addr);
+ outb(0xcc2, data);
+ return 0;
+}
+#endif /* BS_DEBUG_ROUTINE */
+
+void
+bs_debug_print_all(bsc)
+ struct bs_softc *bsc;
+{
+ struct targ_info *ti;
+
+ for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
+ bs_debug_print(bsc, ti);
+}
+
+static u_char *phase[] =
+{
+ "FREE", "HOSTQUE", "DISC", "COMPMSG", "ATN", "DISCMSG", "SELECT",
+ "SELECTED", "RESELECTED", "MSGIN", "MSGOUT", "STATIN", "CMDOUT",
+ "DATA", "SATSEL", "SATRESEL", "SATSDP", "SATCOMPSEQ", "UNDEF",
+};
+
+void
+bs_debug_print(bsc, ti)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+{
+ struct ccb *cb;
+
+ /* host stat */
+ printf("%s <DEBUG INFO> nexus %x bs %x bus status %x \n",
+ bsc->sc_dvname, ti, bsc->sc_nexus, (u_int) bsc->sc_busstat);
+
+ /* target stat */
+ if (ti)
+ {
+ struct sc_p *sp = &bsc->sc_p;
+
+ printf("%s(%d:%d) ph<%s> ", bsc->sc_dvname, ti->ti_id,
+ ti->ti_lun, phase[(int) ti->ti_phase]);
+ printf("msgptr %x msg[0] %x status %x tqh %x fl %x\n",
+ (u_int) (ti->ti_msginptr), (u_int) (ti->ti_msgin[0]),
+ ti->ti_status, cb = ti->ti_ctab.tqh_first, ti->ti_flags);
+ if (cb)
+ printf("cmdlen %x cmdaddr %x cmd[0] %x\n",
+ cb->cmdlen, cb->cmd, (int) cb->cmd[0]);
+ printf("datalen %x dataaddr %x seglen %x ",
+ sp->datalen, sp->data, sp->seglen);
+ if (cb)
+ printf("odatalen %x flags %x\n",
+ cb->datalen, cb->flags);
+ else
+ printf("\n");
+ printf("error flags %b\n", ti->ti_error, BSERRORBITS);
+ }
+}
diff --git a/sys/i386/isa/bs/bsfunc.h b/sys/i386/isa/bs/bsfunc.h
new file mode 100644
index 0000000..274be97
--- /dev/null
+++ b/sys/i386/isa/bs/bsfunc.h
@@ -0,0 +1,229 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
+ */
+
+/**************************************************
+ * FUNC
+ **************************************************/
+/* timeout */
+void bstimeout __P((void *));
+
+/* ctrl setup */
+void bs_setup_ctrl __P((struct targ_info *, u_int, u_int));
+struct targ_info *bs_init_target_info __P((struct bs_softc *, int));
+
+/* msg op */
+int bs_send_msg __P((struct targ_info *, u_int, struct msgbase *, int));
+struct ccb *bs_request_sense __P((struct targ_info *));
+
+/* sync msg op */
+int bs_start_syncmsg __P((struct targ_info *, struct ccb *, int));
+int bs_send_syncmsg __P((struct targ_info *));
+int bs_analyze_syncmsg __P((struct targ_info *, struct ccb *));
+
+/* reset device */
+void bs_scsibus_start __P((struct bs_softc *));
+void bs_reset_nexus __P((struct bs_softc *));
+struct ccb *bs_force_abort __P((struct targ_info *));
+void bs_reset_device __P((struct targ_info *));
+
+/* ccb */
+struct ccb *bs_make_internal_ccb __P((struct targ_info *, u_int, u_int8_t *, u_int, u_int8_t *, u_int, u_int, int));
+struct ccb *bs_make_msg_ccb __P((struct targ_info *, u_int, struct ccb *, struct msgbase *, u_int));
+
+/* misc funcs */
+void bs_printf __P((struct targ_info *, char *, char *));
+void bs_panic __P((struct bs_softc *, u_char *));
+
+/* misc debug */
+u_int bsr __P((u_int));
+u_int bsw __P((u_int, int));
+void bs_debug_print_all __P((struct bs_softc *));
+void bs_debug_print __P((struct bs_softc *, struct targ_info *));
+
+/**************************************************
+ * TARG FLAGS
+ *************************************************/
+static BS_INLINE int bs_check_sat __P((struct targ_info *));
+static BS_INLINE int bs_check_smit __P((struct targ_info *));
+static BS_INLINE int bs_check_disc __P((struct targ_info *));
+static BS_INLINE int bs_check_link __P((struct targ_info *, struct ccb *));
+static BS_INLINE u_int8_t bs_identify_msg __P((struct targ_info *));
+static BS_INLINE void bs_targ_flags __P((struct targ_info *, struct ccb *));
+
+static BS_INLINE int
+bs_check_disc(ti)
+ struct targ_info *ti;
+{
+
+ return (ti->ti_flags & BSDISC);
+}
+
+static BS_INLINE int
+bs_check_sat(ti)
+ struct targ_info *ti;
+{
+
+ return (ti->ti_flags & BSSAT);
+}
+
+static BS_INLINE int
+bs_check_smit(ti)
+ struct targ_info *ti;
+{
+
+ return (ti->ti_flags & BSSMIT);
+}
+
+static BS_INLINE int
+bs_check_link(ti, cb)
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+ struct ccb *nextcb;
+
+ return ((ti->ti_flags & BSLINK) &&
+ (nextcb = cb->ccb_chain.tqe_next) &&
+ (nextcb->flags & BSLINK));
+}
+
+static BS_INLINE u_int8_t
+bs_identify_msg(ti)
+ struct targ_info *ti;
+{
+
+ return ((bs_check_disc(ti) ? 0xc0 : 0x80) | ti->ti_lun);
+}
+
+static BS_INLINE void
+bs_targ_flags(ti, cb)
+ struct targ_info *ti;
+ struct ccb *cb;
+{
+ u_int cmf = (u_int) bshw_cmd[cb->cmd[0]];
+
+ cb->flags |= ((cmf & (BSSAT | BSSMIT | BSLINK)) | BSDISC);
+ cb->flags &= ti->ti_mflags;
+
+ if (cb->datalen < DEV_BSIZE)
+ cb->flags &= ~BSSMIT;
+ if (cb->flags & BSFORCEIOPOLL)
+ cb->flags &= ~(BSLINK | BSSMIT | BSSAT | BSDISC);
+}
+
+/**************************************************
+ * QUEUE OP
+ **************************************************/
+static BS_INLINE void bs_hostque_init __P((struct bs_softc *));
+static BS_INLINE void bs_hostque_head __P((struct bs_softc *, struct targ_info *));
+static BS_INLINE void bs_hostque_tail __P((struct bs_softc *, struct targ_info *));
+static BS_INLINE void bs_hostque_delete __P((struct bs_softc *, struct targ_info *));
+
+static BS_INLINE void
+bs_hostque_init(bsc)
+ struct bs_softc *bsc;
+{
+
+ TAILQ_INIT(&bsc->sc_sttab);
+ TAILQ_INIT(&bsc->sc_titab);
+}
+
+static BS_INLINE void
+bs_hostque_head(bsc, ti)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+{
+
+ if (ti->ti_flags & BSQUEUED)
+ TAILQ_REMOVE(&bsc->sc_sttab, ti, ti_wchain)
+ else
+ ti->ti_flags |= BSQUEUED;
+
+ TAILQ_INSERT_HEAD(&bsc->sc_sttab, ti, ti_wchain);
+}
+
+static BS_INLINE void
+bs_hostque_tail(bsc, ti)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+{
+
+ if (ti->ti_flags & BSQUEUED)
+ TAILQ_REMOVE(&bsc->sc_sttab, ti, ti_wchain)
+ else
+ ti->ti_flags |= BSQUEUED;
+
+ TAILQ_INSERT_TAIL(&bsc->sc_sttab, ti, ti_wchain)
+}
+
+static BS_INLINE void
+bs_hostque_delete(bsc, ti)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+{
+
+ if (ti->ti_flags & BSQUEUED)
+ {
+ ti->ti_flags &= ~BSQUEUED;
+ TAILQ_REMOVE(&bsc->sc_sttab, ti, ti_wchain)
+ }
+}
+
+/*************************************************************
+ * TIMEOUT
+ ************************************************************/
+static BS_INLINE void bs_start_timeout __P((struct bs_softc *));
+static BS_INLINE void bs_terminate_timeout __P((struct bs_softc *));
+
+static BS_INLINE void
+bs_start_timeout(bsc)
+ struct bs_softc *bsc;
+{
+
+ if ((bsc->sc_flags & BSSTARTTIMEOUT) == 0)
+ {
+ bsc->sc_flags |= BSSTARTTIMEOUT;
+ timeout(bstimeout, bsc, BS_TIMEOUT_INTERVAL);
+ }
+}
+
+static BS_INLINE void
+bs_terminate_timeout(bsc)
+ struct bs_softc *bsc;
+{
+
+ if (bsc->sc_flags & BSSTARTTIMEOUT)
+ {
+ untimeout(bstimeout, bsc);
+ bsc->sc_flags &= ~BSSTARTTIMEOUT;
+ }
+}
diff --git a/sys/i386/isa/bs/bshw.c b/sys/i386/isa/bs/bshw.c
new file mode 100644
index 0000000..5d9632b
--- /dev/null
+++ b/sys/i386/isa/bs/bshw.c
@@ -0,0 +1,451 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
+ */
+
+#ifdef __NetBSD__
+#include <dev/isa/isadmareg.h>
+#include <dev/isa/bs/bsif.h>
+#include <dev/isa/bs/bshw.lst>
+#endif
+#ifdef __FreeBSD__
+#include <i386/isa/ic/i8237.h>
+#include <i386/isa/bs/bsif.h>
+#include <i386/isa/bs/bshw.lst>
+#include <machine/clock.h>
+#include <i386/i386/cons.h>
+#endif
+
+static struct bs_softc *gbsc;
+
+/**************************************************
+ * DECLARATION
+ **************************************************/
+static void bshw_force_bsmode __P((struct bs_softc *));
+
+/**************************************************
+ * STATIC VAL
+ **************************************************/
+static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };
+
+/**************************************************
+ * SCSI CMD BRANCH
+ **************************************************/
+#define RS (BSSAT | BSSMIT | BSLINK | BSREAD)
+#define WS (BSSAT | BSSMIT | BSLINK)
+#define EOK (BSERROROK)
+
+u_int8_t bshw_cmd[256] = {
+/* 0 1 2 3 4 5 6 7 8 9 A B C E D F */
+/*0*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,RS ,0 ,WS ,0 ,0 ,0 ,0 ,0 ,
+/*1*/0 ,0 ,EOK,0 ,0 ,0 ,0 ,0 ,0 ,0 ,EOK,0 ,0 ,0 ,0 ,0 ,
+/*2*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,RS ,0 ,WS ,0 ,0 ,0 ,0 ,0 ,
+/*3*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*4*/0 ,0 ,EOK,EOK,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*5*/0 ,0 ,0 ,0 ,EOK,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*6*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*7*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*8*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*9*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*A*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*B*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*C*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*D*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*E*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+/*F*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+};
+
+#undef RS
+#undef WS
+#undef EOK
+
+/**********************************************
+ * init
+ **********************************************/
+static void
+bshw_force_bsmode(bsc)
+ struct bs_softc *bsc;
+{
+
+ if (bsc->sc_flags & BSBSMODE)
+ return;
+ bsc->sc_flags |= BSBSMODE;
+
+ /*
+ * If you have memory over 16M, some stupid boards always force to
+ * use the io polling mode. Check such a case and change mode into
+ * bus master DMA. However this depends heavily on the board's
+ * specifications!
+ */
+
+ if (bsc->sc_hw->dma_init && ((*bsc->sc_hw->dma_init)(bsc)))
+ printf("%s change mode using external DMA (%x)\n",
+ bsc->sc_dvname, (u_int)read_wd33c93(bsc, 0x37));
+}
+
+#define RESET_DEFAULT 2000
+
+int
+bshw_chip_reset(bsc)
+ struct bs_softc *bsc;
+{
+ int ct;
+ u_int8_t aux;
+
+ bshw_lock(bsc);
+
+ bshw_abort_cmd(bsc);
+ delay(10000);
+
+ bshw_get_auxstat(bsc);
+ bshw_get_busstat(bsc);
+
+ write_wd33c93(bsc, wd3s_oid, IDR_EHP | bsc->sc_cspeed | bsc->sc_hostid);
+ write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
+
+ for (ct = RESET_DEFAULT; ct > 0; ct--)
+ {
+ aux = bshw_get_auxstat(bsc);
+ if (aux != 0xff && (aux & STR_INT))
+ {
+ if (bshw_get_busstat(bsc) == 0)
+ break;
+
+ write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
+ }
+ delay(1);
+ }
+
+ if (ct == 0)
+ {
+ bshw_unlock(bsc);
+ return ENXIO;
+ }
+
+ bshw_force_bsmode(bsc);
+
+ write_wd33c93(bsc, wd3s_tout, BSHW_SEL_TIMEOUT);
+ write_wd33c93(bsc, wd3s_sid, SIDR_RESEL);
+ bsc->sc_flags |= BSDMATRANSFER;
+ write_wd33c93(bsc, wd3s_ctrl, CR_DEFAULT);
+ write_wd33c93(bsc, wd3s_synch, 0);
+
+ bshw_get_auxstat(bsc);
+ bsc->sc_busstat = bshw_get_busstat(bsc);
+ bshw_unlock(bsc);
+
+ return 0;
+}
+
+/* scsi bus hard reset */
+#define TWIDDLEWAIT 10000
+static int tw_pos;
+static char tw_chars[] = "|/-\\";
+
+/* this is some jokes */
+static void
+twiddle_wait(void)
+{
+
+ cnputc('\b');
+ cnputc(tw_chars[tw_pos++]);
+ tw_pos %= (sizeof(tw_chars) - 1);
+ delay(TWIDDLEWAIT);
+}
+
+static void bshw_set_vsp __P((struct bs_softc *, u_int, u_int8_t));
+
+static void
+bshw_set_vsp(bsc, chan, spva)
+ struct bs_softc *bsc;
+ u_int chan;
+ u_int8_t spva;
+{
+ struct bshw *hw = bsc->sc_hw;
+
+ if (hw->sregaddr == 0)
+ return;
+
+ write_wd33c93(bsc, hw->sregaddr + chan, spva);
+ if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)
+ write_wd33c93(bsc, hw->sregaddr + chan + 8, spva);
+}
+
+void
+bshw_bus_reset(bsc)
+ struct bs_softc *bsc;
+{
+ struct targ_info *ti;
+ int i, lpc;
+
+ if (bsc->sc_RSTdelay == 0)
+ bsc->sc_RSTdelay = 6 * 1000 * 1000;
+ else
+ {
+ /* XXX:
+ * second time reset will be requested by hardware failuer.
+ */
+ bsc->sc_RSTdelay = 12 * 1000 * 1000;
+ }
+
+ bshw_lock(bsc);
+ write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank | MBR_RST) & ~MBR_IEN);
+ delay(500000);
+ write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank) & ~MBR_IEN);
+ bshw_unlock(bsc);
+
+ for (lpc = 0; lpc < 2; lpc ++)
+ {
+ cnputc(' ');
+ for (i = 0; i <= bsc->sc_RSTdelay / TWIDDLEWAIT; i++)
+ twiddle_wait();
+ cnputc('\b');
+
+ (void) read_wd33c93(bsc, wd3s_auxc);
+
+ delay(10000);
+
+ if ((read_wd33c93(bsc, wd3s_auxc) & AUXCR_RRST) == 0)
+ break;
+
+ printf("\nreset state still continue, wait ...");
+ }
+
+ for (i = 0; i < NTARGETS; i++)
+ {
+ if (ti = bsc->sc_ti[i])
+ {
+ ti->ti_sync = 0;
+ bshw_set_vsp(bsc, i, 0);
+ }
+ }
+}
+
+/* probe */
+int
+bshw_board_probe(bsc, drq, irq)
+ struct bs_softc *bsc;
+ u_int *drq;
+ u_int *irq;
+{
+
+ gbsc = bsc;
+#ifdef SHOW_PORT
+ bshw_print_port(bsc);
+#endif /* SHOW_PORT */
+
+ bsc->sc_hostid = (read_wd33c93(bsc, wd3s_auxc) & AUXCR_HIDM);
+
+ if ((*irq) == IRQUNK)
+ *irq = irq_tbl[(read_wd33c93(bsc, wd3s_auxc) >> 3) & 7];
+
+ if ((*drq) == DRQUNK)
+ *drq = BUS_IOR(cmd_port) & 3;
+
+ bsc->sc_dmachan = *drq;
+ bsc->sc_irqmasks = (1 << (*irq));
+
+ bsc->sc_membank = read_wd33c93(bsc, wd3s_mbank);
+ bsc->sc_membank &= ~MBR_RST;
+ bsc->sc_membank |= MBR_IEN;
+
+ bsc->sc_cspeed = (read_wd33c93(bsc, wd3s_oid) & (~IDR_IDM));
+ switch (BSC_CHIP_CLOCK(bsc->sc_cfgflags))
+ {
+ case 0:
+ break;
+
+ case 1:
+ bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_15_20);
+ break;
+
+ case 2:
+ bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_15_20);
+ bsc->sc_cspeed |= IDR_FS_12_15;
+ break;
+
+ case 3:
+ bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_15_20);
+ bsc->sc_cspeed |= IDR_FS_15_20;
+ break;
+ }
+
+ /* XXX: host id fixed(7) */
+ bsc->sc_hostid = 7;
+
+ if (bshw_chip_reset(bsc))
+ return ENXIO;
+
+ return 0;
+}
+
+/*
+ * XXX:
+ * Assume the board clock rate must be 20Mhz (always satisfied, maybe)!
+ * Only 10M/s 6.6M/s 5.0M/s 3.3M/s for synchronus transfer speed set.
+ */
+#define ILLEGAL_SYNCH
+#ifdef ILLEGAL_SYNCH
+/* A 10 6.6 5.0 4.0 3.3 2.8 2.5 2.0 M/s */
+/* X 100 150 200 250 300 350 400 500 ns */
+static u_int bshw_scsi_period[] =
+ {0, 25, 37, 50, 62, 75, 87, 100, 125};
+static u_int8_t bshw_chip_pval[] =
+ {0, 0xa0, 0xb0, 0x20, 0xd0, 0x30, 0xf0, 0x40, 0x50};
+#else /* !ILLEGAL_SYNCH */
+/* A 10 6.6 5.0 3.3 2.5 M/s */
+/* X 100 150 200 300 400 ns */
+static u_int bshw_scsi_period[] =
+ {0, 25, 37, 50, 75, 100};
+static u_int8_t bshw_chip_pval[] =
+ {0, 0xa0, 0xb0, 0x20, 0x30, 0x40};
+#endif /* !ILLEGAL_SYNCH */
+
+void
+bshw_adj_syncdata(sdp)
+ struct syncdata *sdp;
+{
+ int i;
+
+ if (sdp->offset == 0 || sdp->period < 25 || sdp->period > 100)
+ sdp->offset = sdp->period = 0;
+ else
+ {
+ for (i = 0; sdp->period > bshw_scsi_period[i] + 2; i ++)
+ ;
+ sdp->period = bshw_scsi_period[i];
+ }
+}
+
+void
+bshw_set_synchronous(bsc, ti)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+{
+ struct bshw *hw = bsc->sc_hw;
+ struct syncdata sd;
+ int i;
+
+ sd = ti->ti_syncnow;
+ bshw_adj_syncdata(&sd);
+ for (i = 0; sd.period != bshw_scsi_period[i]; i++)
+ ;
+
+ ti->ti_sync = ((sd.offset & 0x0f) | bshw_chip_pval[i]);
+ bshw_set_vsp(bsc, ti->ti_id, ti->ti_sync);
+
+ if (bsc->sc_nexus == ti)
+ bshw_set_sync_reg(bsc, ti->ti_sync);
+}
+
+/* ctrl reg */
+void
+bshw_setup_ctrl_reg(bsc, flags)
+ struct bs_softc *bsc;
+ u_int flags;
+{
+ u_int8_t regval;
+
+ regval = (flags & BS_SCSI_NOPARITY) ? CR_DEFAULT : CR_DEFAULT_HP;
+ if (bsc->sc_flags & BSDMATRANSFER)
+ regval |= CR_DMA;
+ write_wd33c93(bsc, wd3s_ctrl, regval);
+}
+
+/* sat command */
+void
+bshw_issue_satcmd(bsc, cb, link)
+ struct bs_softc *bsc;
+ struct ccb *cb;
+ int link;
+{
+ int i;
+
+ BUS_IOW(addr_port, wd3s_cdb);
+ for (i = 0; i < cb->cmdlen - 1; i++)
+ BUS_IOW(ctrl_port, cb->cmd[i]);
+ BUS_IOW(ctrl_port, cb->cmd[i] | (link ? 1 : 0));
+}
+
+/* lock */
+void
+bshw_lock(bsc)
+ struct bs_softc *bsc;
+{
+
+ bsc->sc_hwlock++;
+ write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank & (~MBR_IEN));
+}
+
+void
+bshw_unlock(bsc)
+ struct bs_softc *bsc;
+{
+
+ if ((--bsc->sc_hwlock) <= 0)
+ write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank);
+}
+
+/**********************************************
+ * DMA OPERATIONS
+ **********************************************/
+#ifdef __NetBSD__
+#include <dev/isa/bs/bshw_dma.c>
+#include <dev/isa/bs/bshw_pdma.c>
+#endif
+#ifdef __FreeBSD__
+#include <i386/isa/bs/bshw_dma.c>
+#include <i386/isa/bs/bshw_pdma.c>
+#endif
+
+/**********************************************
+ * DEBUG
+ **********************************************/
+/* misc */
+void
+bshw_print_port(bsc)
+ struct bs_softc * bsc;
+{
+ int i, j;
+ int port = 0x0;
+
+ if (bsc == NULL)
+ bsc = gbsc;
+
+ printf("\n");
+ for (j = 0; j <= 0x70; j += 0x10)
+ {
+ printf("port %x: ", port);
+ for (i = 0; i < 0x10; i++)
+ printf("%x ", (u_int) read_wd33c93(bsc, port++));
+ printf("\n");
+ }
+}
diff --git a/sys/i386/isa/bs/bshw.h b/sys/i386/isa/bs/bshw.h
new file mode 100644
index 0000000..ac765ec
--- /dev/null
+++ b/sys/i386/isa/bs/bshw.h
@@ -0,0 +1,363 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
+ */
+
+/* NEC port offsets */
+#define BSHW_DEFAULT_PORT 0xcc0
+#define BSHW_IOSZ 5
+
+#define addr_port 0
+#define stat_port 0
+#define ctrl_port 2
+#define cmd_port 4
+
+#define BSHW_MAX_OFFSET 12
+#define BSHW_SEL_TIMEOUT 0x80
+
+#define BSHW_READ BSR_IOR
+#define BSHW_WRITE 0x0
+
+#define BSHW_CMD_CHECK(CCB, CAT) (bshw_cmd[(CCB)->cmd[0]] & (CAT))
+
+/*********************************************************
+ * static inline declare.
+ *********************************************************/
+static BS_INLINE void write_wd33c93 __P((struct bs_softc *, u_int, u_int8_t));
+static BS_INLINE u_int8_t read_wd33c93 __P((struct bs_softc *, u_int));
+static BS_INLINE u_int8_t bshw_get_auxstat __P((struct bs_softc *));
+static BS_INLINE u_int8_t bshw_get_busstat __P((struct bs_softc *));
+static BS_INLINE u_int8_t bshw_get_status_insat __P((struct bs_softc *));
+static BS_INLINE u_int8_t bshw_read_data __P((struct bs_softc *));
+static BS_INLINE void bshw_write_data __P((struct bs_softc *, u_int8_t));
+static BS_INLINE void bshw_set_count __P((struct bs_softc *, u_int));
+static BS_INLINE u_int bshw_get_count __P((struct bs_softc *));
+static BS_INLINE void bshw_set_dst_id __P((struct bs_softc *, u_int, u_int));
+static BS_INLINE void bshw_set_lun __P((struct bs_softc *, u_int));
+static BS_INLINE u_int bshw_get_src_id __P((struct bs_softc *));
+static BS_INLINE void bshw_negate_ack __P((struct bs_softc *));
+static BS_INLINE void bshw_assert_atn __P((struct bs_softc *));
+static BS_INLINE void bshw_assert_select __P((struct bs_softc *));
+static BS_INLINE void bshw_start_xfer __P((struct bs_softc *));
+static BS_INLINE void bshw_start_sxfer __P((struct bs_softc *));
+static BS_INLINE void bshw_cmd_pass __P((struct bs_softc *, u_int));
+static BS_INLINE void bshw_start_sat __P((struct bs_softc *, u_int));
+static BS_INLINE void bshw_abort_cmd __P((struct bs_softc *));
+static BS_INLINE void bshw_set_sync_reg __P((struct bs_softc *, u_int));
+static BS_INLINE void bshw_set_poll_trans __P((struct bs_softc *, u_int));
+static BS_INLINE void bshw_set_dma_trans __P((struct bs_softc *, u_int));
+
+/*********************************************************
+ * global declare
+ *********************************************************/
+void bs_dma_xfer __P((struct targ_info *, u_int));
+void bs_dma_xfer_end __P((struct targ_info *));
+void bshw_dmaabort __P((struct bs_softc *, struct targ_info *));
+
+void bshw_adj_syncdata __P((struct syncdata *));
+void bshw_set_synchronous __P((struct bs_softc *, struct targ_info *));
+
+void bs_smit_xfer_end __P((struct targ_info *));
+void bshw_smitabort __P((struct bs_softc *));
+
+void bshw_setup_ctrl_reg __P((struct bs_softc *, u_int));
+int bshw_chip_reset __P((struct bs_softc *));
+void bshw_bus_reset __P((struct bs_softc *));
+int bshw_board_probe __P((struct bs_softc *, u_int *, u_int *));
+void bshw_lock __P((struct bs_softc *));
+void bshw_unlock __P((struct bs_softc *));
+void bshw_get_syncreg __P((struct bs_softc *));
+void bshw_issue_satcmd __P((struct bs_softc *, struct ccb *, int));
+void bshw_print_port __P((struct bs_softc *));
+
+void bs_lc_smit_xfer __P((struct targ_info *, u_int));
+
+extern struct dvcfg_hwsel bshw_hwsel;
+extern u_int8_t bshw_cmd[];
+
+/*********************************************************
+ * hw
+ *********************************************************/
+struct bshw {
+#define BSHW_SYNC_RELOAD 0x01
+#define BSHW_SMFIFO 0x02
+#define BSHW_DOUBLE_DMACHAN 0x04
+ u_int hw_flags;
+
+ u_int sregaddr;
+
+ int ((*dma_init) __P((struct bs_softc *)));
+ void ((*dma_start) __P((struct bs_softc *)));
+ void ((*dma_stop) __P((struct bs_softc *)));
+};
+
+/*********************************************************
+ * inline funcs.
+ *********************************************************/
+/*
+ * XXX: If your board does not work well, Please try BS_NEEDS_WEIGHT.
+ */
+static BS_INLINE void
+write_wd33c93(bsc, addr, data)
+ struct bs_softc *bsc;
+ u_int addr;
+ u_int8_t data;
+{
+
+ BUS_IOW(addr_port, addr);
+ BUS_IOW(ctrl_port, data);
+}
+
+static BS_INLINE u_int8_t
+read_wd33c93(bsc, addr)
+ struct bs_softc *bsc;
+ u_int addr;
+{
+
+ BUS_IOW(addr_port, addr);
+ return BUS_IOR(ctrl_port);
+}
+
+/* status */
+static BS_INLINE u_int8_t
+bshw_get_auxstat(bsc)
+ struct bs_softc *bsc;
+{
+
+ return BUS_IOR(stat_port);
+}
+
+static BS_INLINE u_int8_t
+bshw_get_busstat(bsc)
+ struct bs_softc *bsc;
+{
+
+ return read_wd33c93(bsc, wd3s_stat);
+}
+
+static BS_INLINE u_int8_t
+bshw_get_status_insat(bsc)
+ struct bs_softc *bsc;
+{
+
+ return read_wd33c93(bsc, wd3s_lun);
+}
+
+/* data */
+static BS_INLINE u_int8_t
+bshw_read_data(bsc)
+ struct bs_softc *bsc;
+{
+
+ return read_wd33c93(bsc, wd3s_data);
+}
+
+static BS_INLINE void
+bshw_write_data(bsc, data)
+ struct bs_softc *bsc;
+ u_int8_t data;
+{
+
+ write_wd33c93(bsc, wd3s_data, data);
+}
+
+/* counter */
+static BS_INLINE void
+bshw_set_count(bsc, count)
+ struct bs_softc *bsc;
+ u_int count;
+{
+
+ BUS_IOW(addr_port, wd3s_cnt);
+ BUS_IOW(ctrl_port, count >> 16);
+ BUS_IOW(ctrl_port, count >> 8);
+ BUS_IOW(ctrl_port, count);
+}
+
+static BS_INLINE u_int
+bshw_get_count(bsc)
+ struct bs_softc *bsc;
+{
+ u_int count;
+
+ BUS_IOW(addr_port, wd3s_cnt);
+ count = (((u_int) BUS_IOR(ctrl_port)) << 16);
+ count += (((u_int) BUS_IOR(ctrl_port)) << 8);
+ count += ((u_int) BUS_IOR(ctrl_port));
+ return count;
+}
+
+/* ID */
+static BS_INLINE void
+bshw_set_lun(bsc, lun)
+ struct bs_softc *bsc;
+ u_int lun;
+{
+
+ write_wd33c93(bsc, wd3s_lun, lun);
+}
+
+static BS_INLINE void
+bshw_set_dst_id(bsc, target, lun)
+ struct bs_softc *bsc;
+ u_int target, lun;
+{
+
+ write_wd33c93(bsc, wd3s_did, target);
+ write_wd33c93(bsc, wd3s_lun, lun);
+}
+
+static BS_INLINE u_int
+bshw_get_src_id(bsc)
+ struct bs_softc *bsc;
+{
+
+ return (read_wd33c93(bsc, wd3s_sid) & SIDR_IDM);
+}
+
+/* phase */
+static BS_INLINE void
+bshw_negate_ack(bsc)
+ struct bs_softc *bsc;
+{
+
+ write_wd33c93(bsc, wd3s_cmd, WD3S_NEGATE_ACK);
+}
+
+static BS_INLINE void
+bshw_assert_atn(bsc)
+ struct bs_softc *bsc;
+{
+
+ write_wd33c93(bsc, wd3s_cmd, WD3S_ASSERT_ATN);
+}
+
+static BS_INLINE void
+bshw_assert_select(bsc)
+ struct bs_softc *bsc;
+{
+
+ write_wd33c93(bsc, wd3s_cmd, WD3S_SELECT_ATN);
+}
+
+static BS_INLINE void
+bshw_start_xfer(bsc)
+ struct bs_softc *bsc;
+{
+
+ write_wd33c93(bsc, wd3s_cmd, WD3S_TFR_INFO);
+}
+
+static BS_INLINE void
+bshw_start_sxfer(bsc)
+ struct bs_softc *bsc;
+{
+
+ write_wd33c93(bsc, wd3s_cmd, WD3S_SBT | WD3S_TFR_INFO);
+}
+
+static BS_INLINE void
+bshw_cmd_pass(bsc, ph)
+ struct bs_softc *bsc;
+ u_int ph;
+{
+
+ write_wd33c93(bsc, wd3s_cph, ph);
+}
+
+static BS_INLINE void
+bshw_start_sat(bsc, flag)
+ struct bs_softc *bsc;
+ u_int flag;
+{
+
+ write_wd33c93(bsc, wd3s_cmd,
+ (flag ? WD3S_SELECT_ATN_TFR : WD3S_SELECT_NO_ATN_TFR));
+}
+
+
+static BS_INLINE void
+bshw_abort_cmd(bsc)
+ struct bs_softc *bsc;
+{
+
+ write_wd33c93(bsc, wd3s_cmd, WD3S_ABORT);
+}
+
+/* transfer mode */
+static BS_INLINE void
+bshw_set_sync_reg(bsc, val)
+ struct bs_softc *bsc;
+ u_int val;
+{
+
+ write_wd33c93(bsc, wd3s_synch, val);
+}
+
+static BS_INLINE void
+bshw_set_poll_trans(bsc, flags)
+ struct bs_softc *bsc;
+ u_int flags;
+{
+
+ if (bsc->sc_flags & BSDMATRANSFER)
+ {
+ bsc->sc_flags &= ~BSDMATRANSFER;
+ bshw_setup_ctrl_reg(bsc, flags);
+ }
+}
+
+static BS_INLINE void
+bshw_set_dma_trans(bsc, flags)
+ struct bs_softc *bsc;
+ u_int flags;
+{
+
+ if ((bsc->sc_flags & BSDMATRANSFER) == 0)
+ {
+ bsc->sc_flags |= BSDMATRANSFER;
+ bshw_setup_ctrl_reg(bsc, flags);
+ }
+}
+
+static BS_INLINE void memcopy __P((void *from, void *to, register size_t len));
+
+static BS_INLINE void
+memcopy(from, to, len)
+ void *from, *to;
+ register size_t len;
+{
+
+ len >>= 2;
+ __asm __volatile("cld\n\trep\n\tmovsl" : :
+ "S" (from), "D" (to), "c" (len) :
+ "%esi", "%edi", "%ecx");
+}
diff --git a/sys/i386/isa/bs/bshw.lst b/sys/i386/isa/bs/bshw.lst
new file mode 100644
index 0000000..2a3f232
--- /dev/null
+++ b/sys/i386/isa/bs/bshw.lst
@@ -0,0 +1,113 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
+ */
+
+static struct bshw bshw_generic = {
+ BSHW_SYNC_RELOAD,
+
+ 0,
+
+ NULL,
+ NULL,
+ NULL,
+};
+
+static int bshw_dma_init_sc98 __P((struct bs_softc *));
+static void bshw_dma_start_sc98 __P((struct bs_softc *));
+static void bshw_dma_stop_sc98 __P((struct bs_softc *));
+static struct bshw bshw_sc98 = {
+ BSHW_DOUBLE_DMACHAN,
+
+ 0x60,
+
+ bshw_dma_init_sc98,
+ bshw_dma_start_sc98,
+ bshw_dma_stop_sc98,
+};
+
+static int bshw_dma_init_texa __P((struct bs_softc *));
+static struct bshw bshw_texa = {
+ BSHW_DOUBLE_DMACHAN,
+
+ 0x60,
+
+ bshw_dma_init_texa,
+ NULL,
+ NULL,
+};
+
+static void bshw_dma_start_elecom __P((struct bs_softc *));
+static void bshw_dma_stop_elecom __P((struct bs_softc *));
+static struct bshw bshw_elecom = {
+ 0,
+
+ 0x38,
+
+ NULL,
+ bshw_dma_start_elecom,
+ bshw_dma_stop_elecom,
+};
+
+static struct bshw bshw_lc_smit = {
+ BSHW_SMFIFO | BSHW_DOUBLE_DMACHAN,
+
+ 0x60,
+
+ NULL,
+ NULL,
+ NULL,
+};
+
+static struct bshw bshw_lha20X = {
+ BSHW_DOUBLE_DMACHAN,
+
+ 0x60,
+
+ NULL,
+ NULL,
+ NULL,
+};
+
+/* hw tabs */
+static dvcfg_hw_t bshw_hwsel_array[] = {
+/* 0x00 */ &bshw_generic,
+/* 0x01 */ &bshw_sc98,
+/* 0x02 */ &bshw_texa,
+/* 0x03 */ &bshw_elecom,
+/* 0x04 */ &bshw_lc_smit,
+/* 0x05 */ &bshw_lha20X,
+};
+
+struct dvcfg_hwsel bshw_hwsel = {
+ DVCFG_HWSEL_SZ(bshw_hwsel_array),
+ bshw_hwsel_array
+};
diff --git a/sys/i386/isa/bs/bshw_dma.c b/sys/i386/isa/bs/bshw_dma.c
new file mode 100644
index 0000000..22051a9
--- /dev/null
+++ b/sys/i386/isa/bs/bshw_dma.c
@@ -0,0 +1,339 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
+ */
+
+/*********************************************************
+ * static declare.
+ *********************************************************/
+static BS_INLINE void bshw_dmastart __P((struct bs_softc *));
+static void bshw_dmadone __P((struct bs_softc *));
+
+/**********************************************
+ * UPPER INTERFACE FUNCS (all funcs exported)
+ **********************************************/
+void
+bshw_dmaabort(bsc, ti)
+ struct bs_softc *bsc;
+ struct targ_info *ti;
+{
+
+ bshw_dmadone(bsc);
+ bsc->sc_p.seglen = 0;
+ bshw_set_count(bsc, 0);
+
+ if (ti == NULL)
+ {
+ int i;
+ struct targ_info *tmpti;
+
+ for (i = 0; i < NTARGETS; i++)
+ if (tmpti = bsc->sc_ti[i])
+ tmpti->ti_scsp.seglen = 0;
+ }
+ else
+ ti->ti_scsp.seglen = 0;
+}
+
+/* DMA TRANSFER */
+void
+bs_dma_xfer(ti, direction)
+ struct targ_info *ti;
+ u_int direction;
+{
+ vm_offset_t va, endva, phys, nphys;
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct sc_p *sp = &bsc->sc_p;
+
+ bsc->sc_dmadir = direction;
+ bshw_set_dma_trans(bsc, ti->ti_cfgflags);
+
+ if (sp->seglen == 0)
+ {
+ phys = vtophys((vm_offset_t) sp->data);
+ if (phys >= RAM_END)
+ {
+ /* setup segaddr */
+ sp->segaddr = ti->bounce_phys;
+ /* setup seglen */
+ sp->seglen = sp->datalen;
+ if (sp->seglen > ti->bounce_size)
+ sp->seglen = ti->bounce_size;
+ /* setup bufp */
+ sp->bufp = ti->bounce_addr;
+ if (bsc->sc_dmadir != BSHW_READ)
+ bcopy(sp->data, sp->bufp, sp->seglen);
+#ifdef BS_STATICS
+ bs_bounce_used[ti->ti_id]++;
+#endif /* BS_STATICS */
+ }
+ else
+ {
+ /* setup segaddr */
+ sp->segaddr = (u_int8_t *) phys;
+ /* setup seglen */
+ endva = (vm_offset_t)round_page(sp->data + sp->datalen);
+ for (va = (vm_offset_t) sp->data; ; phys = nphys)
+ {
+ if ((va += BSHW_NBPG) >= endva)
+ {
+ sp->seglen = sp->datalen;
+ break;
+ }
+
+ nphys = vtophys(va);
+ if (phys + BSHW_NBPG != nphys || nphys >= RAM_END)
+ {
+ sp->seglen =
+ (u_int8_t *) trunc_page(va) - sp->data;
+ break;
+ }
+ }
+ /* setup bufp */
+ sp->bufp = NULL;
+ }
+ }
+
+ bshw_dmastart(bsc);
+ bshw_set_count(bsc, sp->seglen);
+}
+
+void
+bs_dma_xfer_end(ti)
+ struct targ_info *ti;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct sc_p *sp = &bsc->sc_p;
+ u_int count, transbytes;
+
+ bshw_dmadone(bsc);
+ if (ti->ti_phase == DATAPHASE)
+ {
+ count = bshw_get_count(bsc);
+ if (count < (u_int) sp->seglen)
+ {
+ transbytes = sp->seglen - count;
+ if (sp->bufp)
+ {
+ if (bsc->sc_dmadir == BSHW_READ)
+ bcopy(sp->bufp, sp->data, transbytes);
+ sp->bufp += transbytes;
+ }
+ sp->seglen = count;
+ sp->segaddr += transbytes;
+ sp->data += transbytes;
+ sp->datalen -= transbytes;
+ return;
+ }
+ else if (count == (u_int) sp->seglen)
+ {
+ return;
+ }
+
+ bs_printf(ti, "xfer_end", "strange count");
+ printf("port data %x seglen %x\n", count, sp->seglen);
+ }
+ else
+ bs_printf(ti, "xfer_end", "extra dma interrupt");
+
+ ti->ti_error |= BSDMAABNORMAL;
+ sp->seglen = ti->ti_scsp.seglen = 0; /* XXX */
+}
+
+/**********************************************
+ * GENERIC DMA FUNCS
+ **********************************************/
+static short dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
+
+/* common dma settings */
+#undef DMA1_SMSK
+#define DMA1_SMSK (IO_DMA + 0x14)
+#undef DMA1_MODE
+#define DMA1_MODE (IO_DMA + 0x16)
+#undef DMA1_FFC
+#define DMA1_FFC (IO_DMA + 0x18)
+#undef DMA37SM_SET
+#define DMA37SM_SET 0x04
+#undef DMA1_CHN
+#define DMA1_CHN(c) (IO_DMA + ((c) << 2))
+
+static BS_INLINE void
+bshw_dmastart(bsc)
+ struct bs_softc *bsc;
+{
+ int chan = bsc->sc_dmachan;
+ int waport;
+ u_int8_t *phys = bsc->sc_p.segaddr;
+ u_int nbytes = bsc->sc_p.seglen;
+
+ /*
+ * Program one of DMA channels 0..3. These are
+ * byte mode channels.
+ */
+ /* set dma channel mode, and reset address ff */
+#ifdef __FreeBSD__
+#ifdef CYRIX_5X86
+ asm("wbinvd");
+#endif
+#else /* NetBSD/pc98 */
+ if (cpuspec->cpuspec_cache_flush_before)
+ (*cpuspec->cpuspec_cache_flush_before)();
+#endif
+
+ if (bsc->sc_dmadir & BSHW_READ)
+ outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_WRITE | chan);
+ else
+ outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_READ | chan);
+ outb(DMA1_FFC, 0);
+
+ /* send start address */
+ waport = DMA1_CHN(chan);
+ outb(waport, (u_int) phys);
+ outb(waport, ((u_int) phys) >> 8);
+ outb(dmapageport[chan], ((u_int) phys) >> 16);
+
+ /* send count */
+ outb(waport + 2, --nbytes);
+ outb(waport + 2, nbytes >> 8);
+
+ /* vendor unique hook */
+ if (bsc->sc_hw->dma_start)
+ (*bsc->sc_hw->dma_start)(bsc);
+
+ outb(DMA1_SMSK, chan);
+ BUS_IOW(cmd_port, CMDP_DMES);
+
+ bsc->sc_flags |= BSDMASTART;
+}
+
+static void
+bshw_dmadone(bsc)
+ struct bs_softc *bsc;
+{
+
+ outb(DMA1_SMSK, (bsc->sc_dmachan | DMA37SM_SET));
+ BUS_IOW(cmd_port, CMDP_DMER);
+
+ /* vendor unique hook */
+ if (bsc->sc_hw->dma_stop)
+ (*bsc->sc_hw->dma_stop)(bsc);
+
+#ifdef __FreeBSD__
+#if defined(CYRIX_486DLC) || defined(IBM_486SLC)
+ asm(".byte 0x0f, 0x08");
+#endif
+#else
+ if (cpuspec->cpuspec_cache_flush_after)
+ (*cpuspec->cpuspec_cache_flush_after)();
+#endif
+
+ bsc->sc_flags &= (~BSDMASTART);
+}
+
+/**********************************************
+ * VENDOR UNIQUE DMA FUNCS
+ **********************************************/
+static int
+bshw_dma_init_texa(bsc)
+ struct bs_softc *bsc;
+{
+ u_int8_t regval;
+
+ if ((regval = read_wd33c93(bsc, 0x37)) & 0x08)
+ return 0;
+
+ write_wd33c93(bsc, 0x37, regval | 0x08);
+ regval = read_wd33c93(bsc, 0x3f);
+ write_wd33c93(bsc, 0x3f, regval | 0x08);
+ return 1;
+}
+
+static int
+bshw_dma_init_sc98(bsc)
+ struct bs_softc *bsc;
+{
+
+ if (read_wd33c93(bsc, 0x37) & 0x08)
+ return 0;
+
+ /* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */
+ write_wd33c93(bsc, 0x37, 0x1a);
+ write_wd33c93(bsc, 0x3f, 0x1a);
+#if 0
+ /* only valid for IO */
+ write_wd33c93(bsc, 0x40, 0xf4);
+ write_wd33c93(bsc, 0x41, 0x9);
+ write_wd33c93(bsc, 0x43, 0xff);
+ write_wd33c93(bsc, 0x46, 0x4e);
+
+ write_wd33c93(bsc, 0x48, 0xf4);
+ write_wd33c93(bsc, 0x49, 0x9);
+ write_wd33c93(bsc, 0x4b, 0xff);
+ write_wd33c93(bsc, 0x4e, 0x4e);
+#endif
+ return 1;
+}
+
+static void
+bshw_dma_start_sc98(bsc)
+ struct bs_softc *bsc;
+{
+
+ write_wd33c93(bsc, 0x73, 0x32);
+ write_wd33c93(bsc, 0x74, 0x23);
+}
+
+static void
+bshw_dma_stop_sc98(bsc)
+ struct bs_softc *bsc;
+{
+
+ write_wd33c93(bsc, 0x73, 0x43);
+ write_wd33c93(bsc, 0x74, 0x34);
+}
+
+static void
+bshw_dma_start_elecom(bsc)
+ struct bs_softc *bsc;
+{
+ u_int8_t tmp = read_wd33c93(bsc, 0x4c);
+
+ write_wd33c93(bsc, 0x32, tmp & 0xdf);
+}
+
+static void
+bshw_dma_stop_elecom(bsc)
+ struct bs_softc *bsc;
+{
+ u_int8_t tmp = read_wd33c93(bsc, 0x4c);
+
+ write_wd33c93(bsc, 0x32, tmp | 0x20);
+}
diff --git a/sys/i386/isa/bs/bshw_pdma.c b/sys/i386/isa/bs/bshw_pdma.c
new file mode 100644
index 0000000..612db73
--- /dev/null
+++ b/sys/i386/isa/bs/bshw_pdma.c
@@ -0,0 +1,242 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
+ */
+
+#define LC_SMIT_TIMEOUT 2 /* 2 sec: timeout for a fifo status ready */
+
+static BS_INLINE void bshw_lc_smit_start __P((struct bs_softc *, int, u_int));
+static int bshw_lc_smit_fstat __P((struct bs_softc *, int, int));
+static BS_INLINE void bshw_lc_smit_stop __P((struct bs_softc *));
+
+/*********************************************************
+ * SM FIFO (GENERIC)
+ *********************************************************/
+void
+bshw_smitabort(bsc)
+ struct bs_softc *bsc;
+{
+ if (bsc->sc_hw->hw_flags & BSHW_SMFIFO)
+ bshw_lc_smit_stop(bsc);
+
+ bshw_set_count(bsc, 0);
+ bsc->sc_flags &= ~BSSMITSTART;
+}
+
+void
+bs_smit_xfer_end(ti)
+ struct targ_info *ti;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct sc_p *sp = &bsc->sc_p;
+ u_int count;
+ u_char *s;
+
+ bshw_lc_smit_stop(bsc);
+ bsc->sc_flags &= ~BSSMITSTART;
+
+ if (ti->ti_phase == DATAPHASE)
+ {
+ count = bshw_get_count(bsc);
+ if (count < (u_int) sp->datalen)
+ {
+ sp->data += (sp->datalen - count);
+ sp->datalen = count;
+ /* XXX:
+ * strict double checks!
+ * target => wd33c93c transfer counts
+ * wd33c93c => memory transfer counts
+ */
+ if ((bsc->sc_dmadir & BSHW_READ) &&
+ count != bsc->sm_tdatalen)
+ {
+ s = "read count miss";
+ goto bad;
+ }
+ return;
+ }
+ else if (count == (u_int) sp->datalen)
+ {
+ return;
+ }
+
+ s = "strange count";
+ }
+ else
+ s = "extra smit interrupt";
+
+bad:
+ bs_printf(ti, "smit_xfer_end", s);
+ ti->ti_error |= BSDMAABNORMAL;
+}
+
+/*********************************************************
+ * LOGITEC's SMIT TRANSFER
+ *********************************************************/
+
+#define BSHW_LC_FSET 0x36
+#define BSHW_LC_FCTRL 0x44
+#define FCTRL_EN 0x01
+#define FCTRL_WRITE 0x02
+
+#define SF_ABORT 0x08
+#define SF_RDY 0x10
+
+#define LC_FSZ DEV_BSIZE
+#define LC_SFSZ 0x0c
+#define LC_REST (LC_FSZ - LC_SFSZ)
+
+static BS_INLINE void
+bshw_lc_smit_stop(bsc)
+ struct bs_softc *bsc;
+{
+
+ write_wd33c93(bsc, BSHW_LC_FCTRL, 0);
+ BUS_IOW(cmd_port, CMDP_DMER);
+}
+
+static BS_INLINE void
+bshw_lc_smit_start(bsc, count, direction)
+ struct bs_softc *bsc;
+ int count;
+ u_int direction;
+{
+ u_int8_t pval, val = read_wd33c93(bsc, BSHW_LC_FSET);
+
+ bsc->sc_flags |= BSSMITSTART;
+ bshw_set_count(bsc, count);
+
+ pval = FCTRL_EN;
+ if ((direction & BSHW_READ) == 0)
+ pval |= (val & 0xe0) | FCTRL_WRITE;
+ write_wd33c93(bsc, BSHW_LC_FCTRL, pval);
+ bshw_start_xfer(bsc);
+}
+
+static int
+bshw_lc_smit_fstat(bsc, wc, read)
+ struct bs_softc *bsc;
+ int wc, read;
+{
+ u_int8_t stat;
+
+#define ALWAYS_ABORT
+#ifdef ALWAYS_ABORT
+ if (read == BSHW_READ)
+ {
+ while (wc -- > 0)
+ {
+ BUS_IO_WEIGHT;
+ stat = BUS_IOR(cmd_port);
+ if (stat & SF_RDY)
+ return 0;
+ if (stat & SF_ABORT)
+ return EIO;
+ }
+ }
+ else
+ {
+#endif /* ALWAYS_ABORT */
+ while (wc -- > 0)
+ {
+ BUS_IO_WEIGHT;
+ stat = BUS_IOR(cmd_port);
+ if (stat & SF_ABORT)
+ return EIO;
+ if (stat & SF_RDY)
+ return 0;
+ }
+#ifdef ALWAYS_ABORT
+ }
+#endif /* ALWAYS_ABORT */
+
+ bs_poll_timeout(bsc, "bshw_lc_smit");
+ return EIO;
+}
+
+void
+bs_lc_smit_xfer(ti, direction)
+ struct targ_info *ti;
+ u_int direction;
+{
+ struct bs_softc *bsc = ti->ti_bsc;
+ struct sc_p *sp = &bsc->sc_p;
+ int datalen, count, wc = LC_SMIT_TIMEOUT * 1024 * 1024;
+ u_int8_t *data;
+
+ sp->bufp = NULL;
+ sp->seglen = 0;
+ data = sp->data;
+ datalen = sp->datalen;
+
+ bsc->sc_dmadir = direction;
+ bshw_set_dma_trans(bsc, ti->ti_cfgflags);
+ bshw_lc_smit_start(bsc, sp->datalen, direction);
+
+ if (direction & BSHW_READ)
+ {
+ do
+ {
+ if (bshw_lc_smit_fstat(bsc, wc, BSHW_READ))
+ break;
+
+ count = (datalen > LC_FSZ ? LC_FSZ : datalen);
+ memcopy(ti->sm_vaddr, data, count);
+ data += count;
+ datalen -= count;
+ }
+ while (datalen > 0);
+
+ bsc->sm_tdatalen = datalen;
+ }
+ else
+ {
+ do
+ {
+ if (bshw_lc_smit_fstat(bsc, wc, BSHW_WRITE))
+ break;
+
+ count = (datalen > LC_SFSZ ? LC_SFSZ : datalen);
+ memcopy(data, ti->sm_vaddr, count);
+ data += count;
+ datalen -= count;
+
+ if (bshw_lc_smit_fstat(bsc, wc, BSHW_WRITE))
+ break;
+
+ count = (datalen > LC_REST ? LC_REST : datalen);
+ memcopy(data, ti->sm_vaddr + LC_SFSZ, count);
+ data += count;
+ datalen -= count;
+ }
+ while (datalen > 0);
+ }
+}
diff --git a/sys/i386/isa/bs/bsif.c b/sys/i386/isa/bs/bsif.c
new file mode 100644
index 0000000..08dc069
--- /dev/null
+++ b/sys/i386/isa/bs/bsif.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) HONDA Naofumi, KATO Takenori, 1996. 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 as
+ * the first lines of this file unmodified.
+ * 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.
+ * 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.
+ */
+
+#if 0
+/* WARNING: Any bug report must contain BS_REL_VERSION */
+#define BS_REL_VERSION "NetBSD1.2/030" /* major jump */
+#endif
+
+#ifdef __NetBSD__
+#include <dev/isa/bs/bsif.h>
+#endif /* __NetBSD__ */
+#ifdef __FreeBSD__
+#include "bs.h"
+#include <i386/isa/bs/bsif.h>
+#endif /* __FreeBSD__ */
+
+/**************************************************
+ * DEVICE DECLARE
+ **************************************************/
+#ifdef __NetBSD__
+int bsintr __P((void *));
+static int bsprint __P((void *, char *));
+static void bs_scsi_minphys __P((struct buf *));
+
+struct cfdriver bs_cd = {
+ NULL, "bs", DV_DULL
+};
+
+struct scsi_device bs_dev = {
+ NULL, /* Use default error handler */
+ NULL, /* have a queue, served by this */
+ NULL, /* have no async handler */
+ NULL, /* Use default 'done' routine */
+};
+
+struct scsi_adapter pc98texa55bs = {
+ bs_scsi_cmd,
+ bs_scsi_minphys,
+ bs_target_open,
+ 0,
+};
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+static int bsprobe __P((struct isa_device *));
+static int bsattach __P((struct isa_device *));
+static int bsprint __P((void *, char *));
+static void bs_scsi_minphys __P((struct buf *));
+static int bs_dmarangecheck __P((caddr_t, unsigned));
+
+struct isa_driver bsdriver = {
+ bsprobe,
+ bsattach,
+ "bs"
+};
+
+struct scsi_device bs_dev = {
+ NULL, /* Use default error handler */
+ NULL, /* have a queue, served by this */
+ NULL, /* have no async handler */
+ NULL, /* Use default 'done' routine */
+ "bs",
+ 0, {0, 0}
+};
+
+u_int32_t
+bs_adapter_info(unit)
+ int unit;
+{
+ return (1);
+}
+
+struct scsi_adapter pc98texa55bs = {
+ bs_scsi_cmd,
+ bs_scsi_minphys,
+ bs_target_open,
+ 0,
+ bs_adapter_info,
+ "bs", {0, 0}
+};
+
+static u_short pc98_irq_ball[16] = {
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15
+};
+
+static struct bs_softc *bscdata[NBS];
+#endif /* __FreeBSD__ */
+
+/*****************************************************************
+ * OS <=> BS INTERFACE
+ *****************************************************************/
+#ifdef __FreeBSD__
+static int
+bsprobe(dev)
+ struct isa_device *dev;
+#else /* __NetBSD__ */
+int
+bsprobe(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+#endif /* __NetBSD__ */
+{
+#ifdef __FreeBSD__
+ struct bs_softc *bsc;
+ int unit = dev->id_unit;
+#else /* __NetBSD__ */
+ struct bs_softc *bsc = (void *) self;
+ struct isa_attach_args *ia = aux;
+ bus_chipset_tag_t bc = ia->ia_bc;
+#endif /* __NetBSD__ */
+ u_int irq, drq;
+ int i, rv = 0;
+
+#ifdef __FreeBSD__
+ if (unit >= NBS) {
+ printf("bs%d: unit number too high\n", unit);
+ return rv;
+ }
+ /*
+ * Allocate a storage for us
+ */
+ if (bscdata[unit]) {
+ printf("bs%d: memory already allocated\n", unit);
+ return rv;
+ }
+ if (!(bsc = malloc(sizeof(struct bs_softc), M_TEMP, M_NOWAIT))) {
+ printf("bs%d cannot malloc!\n", unit);
+ return rv;
+ }
+ bzero(bsc, sizeof(struct bs_softc));
+ bscdata[unit] = bsc;
+ bsc->unit = unit;
+#endif /* __FreeBSD__ */
+
+#ifdef __FreeBSD__
+ bsc->sc_cfgflags = DVCFG_MINOR(dev->id_flags);
+ bsc->sc_hw = DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(dev->id_flags));
+#else /* __NetBSD__ */
+ bsc->sc_cfgflags = DVCFG_MINOR(ia->ia_cfgflags);
+ bsc->sc_hw = DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(ia->ia_cfgflags));
+#endif /* __NetBSD__ */
+ if (bsc->sc_hw == NULL)
+ return rv;
+
+#ifdef __FreeBSD__
+ if ((bsc->sc_hw->hw_flags & BSHW_SMFIFO) &&
+ (dev->id_maddr != (caddr_t)MADDRUNK))
+ bsc->sm_vaddr = (u_int8_t *) dev->id_maddr;
+ else
+ bsc->sm_vaddr = (u_int8_t *) MADDRUNK;
+#else /* __NetBSD__ */
+ if ((bsc->sc_hw->hw_flags & BSHW_SMFIFO) && (ia->ia_maddr != MADDRUNK))
+ {
+ ia->ia_maddr &= ~((NBPG * 2) - 1);
+ ia->ia_maddr += NBPG;
+ ia->ia_msize = NBPG;
+ if (bus_mem_map(bc, ia->ia_maddr, NBPG, 0, &bsc->sc_memh))
+ return 0;
+ bsc->sm_vaddr = (u_int8_t *) bsc->sc_memh; /* XXX */
+ }
+ else
+ {
+ bsc->sm_vaddr = (u_int8_t *) MADDRUNK;
+ ia->ia_msize = 0;
+ }
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+ sprintf(bsc->sc_dvname, "bs%d", unit);
+#else /* __NetBSD__ */
+ strcpy(bsc->sc_dvname, bsc->sc_dev.dv_xname);
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+ if (dev->id_iobase == 0)
+#else /* __NetBSD__ */
+ if (ia->ia_iobase == IOBASEUNK)
+#endif /* __NetBSD__ */
+ {
+ printf("%s: iobase not specified. Assume default port(0x%x)\n",
+ bsc->sc_dvname, BSHW_DEFAULT_PORT);
+#ifdef __FreeBSD__
+ dev->id_iobase = BSHW_DEFAULT_PORT;
+#else /* __NetBSD__ */
+ ia->ia_iobase = BSHW_DEFAULT_PORT;
+#endif /* __NetBSD__ */
+ }
+
+#ifdef __FreeBSD__
+ bsc->sc_iobase = dev->id_iobase;
+#else /* __NetBSD__ */
+ bsc->sc_iobase = ia->ia_iobase;
+ bsc->sc_bc = bc;
+ bsc->sc_delayioh = ia->ia_delayioh;
+ if (bus_io_map(bsc->sc_bc, bsc->sc_iobase, BSHW_IOSZ, &bsc->sc_ioh))
+ return rv;
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+ irq = IRQUNK;
+ drq = DRQUNK;
+#else /* __NetBSD__ */
+ irq = ia->ia_irq;
+ drq = ia->ia_drq;
+#endif /* __NetBSD__ */
+ if (bshw_board_probe(bsc, &drq, &irq))
+ goto bad;
+
+#ifdef __FreeBSD__
+ dev->id_irq = pc98_irq_ball[irq];
+ dev->id_drq = (short)drq;
+#else /* __NetBSD__ */
+ ia->ia_irq = irq;
+ ia->ia_drq = drq;
+#endif /* __NetBSD__ */
+
+ /* initialize host queue and target info */
+ bs_hostque_init(bsc);
+ for (i = 0; i < NTARGETS; i++)
+ if (i != bsc->sc_hostid)
+ bs_init_target_info(bsc, i);
+
+ /* initialize ccb queue */
+ bs_init_ccbque(BS_MAX_CCB);
+
+#ifdef __NetBSD__
+ /* init port data */
+ ia->ia_iosize = BSHW_IOSZ;
+#endif /* __NetBSD__ */
+
+ /* scsi bus reset and restart */
+ bsc->sc_hstate = BSC_BOOTUP;
+ bsc->sc_retry = RETRIES;
+ bsc->sc_wc = delaycount * 250; /* about 1 sec */
+ bs_reset_nexus(bsc);
+
+#ifdef __FreeBSD__
+ return BSHW_IOSZ;
+bad:
+ return rv;
+#else /* __NetBSD__ */
+ rv = 1;
+bad:
+ bus_io_unmap(bsc->sc_bc, bsc->sc_ioh, BSHW_IOSZ);
+ return rv;
+#endif /* __NetBSD__ */
+}
+
+static int
+bsprint(aux, name)
+ void *aux;
+ char *name;
+{
+
+ if (name != NULL)
+ printf("%s: scsibus ", name);
+ return UNCONF;
+}
+
+#ifdef __FreeBSD__
+static int
+bsattach(dev)
+ struct isa_device *dev;
+#else /* __NetBSD__ */
+void
+bsattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+#endif /* __NetBSD__ */
+{
+#ifdef __FreeBSD__
+ int unit = dev->id_unit;
+ struct bs_softc *bsc = bscdata[unit];
+ struct scsibus_data *scbus;
+#else /* __NetBSD__ */
+ struct bs_softc *bsc = (void *) self;
+ struct isa_attach_args *ia = aux;
+
+ printf("\n");
+#endif /* __NetBSD__ */
+
+#ifdef __NetBSD__
+ bsc->sc_iobase = ia->ia_iobase;
+ bsc->sc_bc = ia->ia_bc;
+ bsc->sc_delayioh = ia->ia_delayioh;
+ if (bus_io_map(bsc->sc_bc, bsc->sc_iobase, BSHW_IOSZ, &bsc->sc_ioh))
+ panic("%s: bus io map failed\n", bsc->sc_dev.dv_xname);
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+ bsc->sc_link.adapter_unit = unit;
+ bsc->sc_link.adapter_targ = bsc->sc_hostid;
+ bsc->sc_link.flags = SDEV_BOUNCE;
+ bsc->sc_link.opennings = XSMAX;
+#else /* __NetBSD__ */
+ bsc->sc_link.adapter_target = bsc->sc_hostid;
+ bsc->sc_link.openings = XSMAX;
+#endif /* __NetBSD__ */
+ bsc->sc_link.adapter_softc = bsc;
+ bsc->sc_link.adapter = &pc98texa55bs;
+ bsc->sc_link.device = &bs_dev;
+
+#ifdef __FreeBSD__
+ /*
+ * Prepare the scsibus_data area for the upperlevel
+ * scsi code.
+ */
+ scbus = scsi_alloc_bus();
+ if (!scbus)
+ return 0;
+ scbus->adapter_link = &bsc->sc_link;
+ /*
+ * ask the adapter what subunits are present
+ */
+ scsi_attachdevs(scbus);
+#else /* __NetBSD__ */
+ bsc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, bsintr, bsc);
+ config_found(self, &bsc->sc_link, bsprint);
+#endif /* __NetBSD__ */
+ bs_start_timeout(bsc);
+#ifdef __FreeBSD__
+ return 1;
+#endif /* __FreeBSD__ */
+}
+
+#ifdef __NetBSD__
+int
+bsintr(arg)
+ void *arg;
+{
+
+ return bs_sequencer((struct bs_softc *)arg);
+}
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+void
+bsintr(unit)
+ int unit;
+{
+ (void)bs_sequencer(bscdata[unit]);
+}
+#endif /* __FreeBSD__ */
+
+/*****************************************************************
+ * JULIAN SCSI <=> BS INTERFACE
+ *****************************************************************/
+static void
+bs_scsi_minphys(bp)
+ struct buf *bp;
+{
+
+ if (bp->b_bcount > BSDMABUFSIZ)
+ bp->b_bcount = BSDMABUFSIZ;
+ minphys(bp);
+}
+
+XSBS_INT32T
+bs_target_open(sc, cf)
+ struct scsi_link *sc;
+ struct cfdata *cf;
+{
+ u_int target = sc->target;
+ struct bs_softc *bsc = (struct bs_softc *) (sc->adapter_softc);
+ struct targ_info *ti = bsc->sc_ti[target];
+ u_int flags;
+
+ if ((bsc->sc_openf & (1 << target)) == 0)
+ return ENODEV;
+
+ if ((flags = cf->cf_flags) == 0)
+ flags = BS_SCSI_DEFCFG;
+
+ bs_setup_ctrl(ti, (u_int)sc->quirks, flags);
+ return 0;
+}
+
+/*****************************************************************
+ * BS MEMORY ALLOCATION INTERFACE
+ *****************************************************************/
+#ifdef __NetBSD__
+void
+bs_alloc_buf(ti)
+ struct targ_info *ti;
+{
+ extern int cold;
+ caddr_t addr, physaddr;
+ u_int pages;
+
+ /* XXX:
+ * strategy change!
+ * A) total memory >= 16M at boot: MAXBSIZE * 7 = 112k.
+ * B) others: 4K * 7 = 28 K.
+ */
+ if (get_sysinfo(SYSINFO_MEMLEVEL) == MEM_LEVEL1 && cold != 0)
+ pages = 4;
+ else
+ pages = 1;
+
+ ti->bounce_size = NBPG * pages;
+ if ((addr = alloc_bounce_buffer(ti->bounce_size)) == NULL)
+ {
+ ti->bounce_size = NBPG;
+ if ((addr = malloc(NBPG, M_DEVBUF, M_NOWAIT)) == NULL)
+ goto bad;
+ }
+
+ physaddr = (caddr_t) vtophys(addr);
+ if ((u_int) physaddr >= RAM_END)
+ {
+ /* XXX: mem from malloc only! */
+ free(addr, M_DEVBUF);
+ goto bad;
+ }
+
+ ti->bounce_addr = (u_int8_t *) addr;
+ ti->bounce_phys = (u_int8_t *) physaddr;
+ return;
+
+bad:
+ bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
+ printf("WARNING: this target is dislocated\n");
+}
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+static int bs_dmarangecheck(caddr_t va, unsigned length)
+{
+ vm_offset_t phys, priorpage = 0, endva;
+
+ endva = (vm_offset_t)round_page(va+length);
+ for (; va < (caddr_t)endva; va += PAGE_SIZE) {
+ phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va));
+ if (phys == 0)
+ panic("bs_dmarangecheck: no physical page present");
+ if (phys >= RAM_END)
+ return 1;
+ if (priorpage) {
+ if (priorpage + PAGE_SIZE != phys)
+ return 1;
+ }
+ priorpage = phys;
+ }
+ return 0;
+}
+
+void
+bs_alloc_buf(ti)
+ struct targ_info *ti;
+{
+ caddr_t addr, physaddr;
+
+#if BS_BOUNCE_SIZE != 0
+ ti->bounce_size = BS_BOUNCE_SIZE;
+#else
+ ti->bounce_size = BSHW_NBPG;
+#endif
+ /* Try malloc() first. It works better if it works. */
+ addr = malloc(ti->bounce_size, M_DEVBUF, M_NOWAIT);
+ if (addr != NULL) {
+ if (bs_dmarangecheck(addr, ti->bounce_size) == 0) {
+ physaddr = (caddr_t) vtophys(addr);
+ ti->bounce_addr = (u_int8_t *) addr;
+ ti->bounce_phys = (u_int8_t *) physaddr;
+ return;
+ }
+ free(buf, M_DEVBUF);
+ }
+ addr = contigmalloc(ti->bounce_size, M_DEVBUF, M_NOWAIT,
+ 0ul, RAM_END, 1ul, 0x10000ul);
+ if (addr == NULL)
+ goto bad;
+
+ physaddr = (caddr_t) vtophys(addr);
+ if ((u_int) physaddr >= RAM_END)
+ {
+ /* XXX:
+ * must free memory !
+ */
+ goto bad;
+ }
+
+ ti->bounce_addr = (u_int8_t *) addr;
+ ti->bounce_phys = (u_int8_t *) physaddr;
+ return;
+
+bad:
+ bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
+ printf("WARNING: this target is dislocated\n");
+}
+#endif /* __FreeBSD__ */
diff --git a/sys/i386/isa/bs/bsif.h b/sys/i386/isa/bs/bsif.h
new file mode 100644
index 0000000..6a5286e
--- /dev/null
+++ b/sys/i386/isa/bs/bsif.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) HONDA Naofumi, KATO Takenori, 1996. 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 as
+ * the first lines of this file unmodified.
+ * 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.
+ * 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.
+ */
+
+/***************************************************
+ * misc device header in bs_softc
+ ***************************************************/
+#ifdef __NetBSD__
+#define OS_DEPEND_DEVICE_HEADER \
+ struct device sc_dev; \
+ void *sc_ih;
+
+#define OS_DEPEND_SCSI_HEADER \
+ struct scsi_link sc_link;
+
+#define OS_DEPEND_MISC_HEADER \
+ pisa_device_handle_t sc_pdv; \
+ bus_chipset_tag_t sc_bc; \
+ bus_io_handle_t sc_ioh; \
+ bus_io_handle_t sc_delayioh; \
+ bus_mem_handle_t sc_memh;
+
+#endif /* __NetBSD__ */
+#ifdef __FreeBSD__
+#define OS_DEPEND_DEVICE_HEADER \
+ int unit;
+
+#define OS_DEPEND_SCSI_HEADER \
+ struct scsi_link sc_link;
+
+#define OS_DEPEND_MISC_HEADER
+#endif /* __FreeBSD__ */
+
+#if defined(__NetBSD__)
+#define BSHW_NBPG NBPG
+#endif
+#if defined(__FreeBSD__)
+#define BSHW_NBPG PAGE_SIZE
+#endif
+
+/***************************************************
+ * include
+ ***************************************************/
+/* (I) common include */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/disklabel.h>
+#include <sys/buf.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+
+#include <vm/vm.h>
+
+/* (II) os depend include */
+#ifdef __NetBSD__
+#include <sys/device.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <dev/isa/pisaif.h>
+
+#include <machine/cpufunc.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/dvcfg.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_disk.h>
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+#include <sys/device.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <machine/vmparam.h>
+#include <vm/pmap.h>
+#include <sys/proc.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_disk.h>
+
+#include <pc98/pc98/pc98.h>
+#include <i386/isa/isa_device.h>
+#include <i386/isa/icu.h>
+#endif /* __FreeBSD__ */
+
+/***************************************************
+ * BUS IO MAPPINGS & BS specific inclusion
+ ***************************************************/
+#ifdef __NetBSD__
+#define BUS_IO_DELAY ((void) bus_io_read_1(bsc->sc_bc, bsc->sc_delayioh, 0))
+#define BUS_IO_WEIGHT (bus_io_write_1(bsc->sc_bc, bsc->sc_delayioh, 0, 0))
+#define BUS_IOR(offs) (BUS_IO_DELAY, bus_io_read_1(bsc->sc_bc, bsc->sc_ioh, (offs)))
+#define BUS_IOW(offs, val) (BUS_IO_DELAY, bus_io_write_1(bsc->sc_bc, bsc->sc_ioh, (offs), (val)))
+
+#include <dev/ic/wd33c93reg.h>
+#include <dev/isa/ccbque.h>
+
+#include <dev/isa/scsi_dvcfg.h>
+#include <dev/isa/bs/bsvar.h>
+#include <dev/isa/bs/bshw.h>
+#include <dev/isa/bs/bsfunc.h>
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+#define BUS_IO_DELAY ((void) inb(0x5f))
+#define BUS_IO_WEIGHT (outb(0x5f, 0))
+#define BUS_IOR(offs) (BUS_IO_DELAY, inb(bsc->sc_iobase + (offs)))
+#define BUS_IOW(offs, val) (BUS_IO_DELAY, outb(bsc->sc_iobase + (offs), (val)))
+
+#include <i386/isa/ic/wd33c93.h>
+#include <i386/isa/bs/ccbque.h>
+#include <i386/isa/bs/dvcfg.h>
+
+#include <i386/isa/bs/scsi_dvcfg.h>
+#include <i386/isa/bs/bsvar.h>
+#include <i386/isa/bs/bshw.h>
+#include <i386/isa/bs/bsfunc.h>
+#endif /* __FreeBSD__ */
+
+/***************************************************
+ * XS return type
+ ***************************************************/
+#ifdef __NetBSD__
+#define XSBS_INT32T int
+#endif /* __NetBSD__ */
+#ifdef __FreeBSD__
+#define XSBS_INT32T int32_t
+#endif /* __FreeBSD__ */
+
+/***************************************************
+ * xs flags's abstraction (all currently used)
+ ***************************************************/
+#define XSBS_ITSDONE ITSDONE
+#define XSBS_SCSI_NOSLEEP SCSI_NOSLEEP
+#ifdef __NetBSD__
+#define XSBS_SCSI_POLL SCSI_POLL
+#endif /* __NetBSD__ */
+#ifdef __FreeBSD__
+#define XSBS_SCSI_POLL SCSI_NOMASK
+#endif /* __FreeBSD__ */
+
+/***************************************************
+ * Special operations
+ ***************************************************/
+#ifdef __FreeBSD__
+#define BS_ADDRESS_CHECK
+#endif /* __FreeBSD__ */
+
+/***************************************************
+ * declare
+ ***************************************************/
+/* (I) common declare */
+void bs_alloc_buf __P((struct targ_info *));
+XSBS_INT32T bs_target_open __P((struct scsi_link *, struct cfdata *));
+XSBS_INT32T bs_scsi_cmd __P((struct scsi_xfer *));
+
+extern int delaycount;
+
+/* (II) os depend declare */
+#ifdef __NetBSD__
+int bsprobe __P((struct device *, struct device *, void *));
+void bsattach __P((struct device *, struct device *, void *));
+#endif /* __NetBSD__ */
+
+#ifdef __FreeBSD__
+u_int32_t bs_adapter_info __P((int));
+#define delay(y) DELAY(y)
+extern int dma_init_flag;
+#define softintr(y) ipending |= (y)
+#endif /* __FreeBSD__ */
diff --git a/sys/i386/isa/bs/bsvar.h b/sys/i386/isa/bs/bsvar.h
new file mode 100644
index 0000000..8267338
--- /dev/null
+++ b/sys/i386/isa/bs/bsvar.h
@@ -0,0 +1,542 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
+ */
+
+#define BS_INLINE inline
+
+/**************************************************
+ * CONTROL FLAGS (cf_flags)
+ *************************************************/
+#define BSC_FASTACK 0x01
+#define BSC_SMITSAT_DISEN 0x02
+#define BSC_CHIP_CLOCK(dvcfg) (((dvcfg) >> 4) & 0x03)
+
+#define BS_SCSI_SYNC DVF_SCSI_SYNC
+#define BS_SCSI_DISC DVF_SCSI_DISC
+#define BS_SCSI_WAIT DVF_SCSI_WAIT
+#define BS_SCSI_LINK DVF_SCSI_LINK
+#define BS_SCSI_QTAG DVF_SCSI_QTAG
+#define BS_SCSI_NOSAT DVF_SCSI_SP0
+#define BS_SCSI_NOPARITY DVF_SCSI_NOPARITY
+#define BS_SCSI_SAVESP DVF_SCSI_SAVESP
+#define BS_SCSI_NOSMIT DVF_SCSI_SP1
+#define BS_SCSI_PERIOD(XXX) DVF_SCSI_PERIOD(XXX)
+#define BS_SCSI_OFFSET(XXX) DVF_SCSI_OFFSET(XXX)
+#define BS_SCSI_SYNCMASK DVF_SCSI_SYNCMASK
+#define BS_SCSI_BITS DVF_SCSI_BITS
+
+#define BS_SCSI_DEFCFG (BS_SCSI_NOSAT | DVF_SCSI_DEFCFG)
+
+#define BS_SCSI_POSITIVE (BS_SCSI_SYNC | BS_SCSI_DISC | BS_SCSI_LINK)
+#define BS_SCSI_NEGATIVE (BS_SCSI_WAIT | BS_SCSI_NOSAT | BS_SCSI_NOPARITY |\
+ BS_SCSI_SAVESP | BS_SCSI_NOSMIT)
+/*******************************************
+ * CONFIG SECTION
+ ******************************************/
+/* Enable timeout watch dog */
+#define BS_DEFAULT_TIMEOUT_SECOND 16 /* default 16 sec */
+#define BS_SYNC_TIMEOUT 16
+#define BS_STARTUP_TIMEOUT 60
+#define BS_MOTOR_TIMEOUT 120
+#define BS_TIMEOUT_CHECK_INTERVAL 4 /* check each 4 sec */
+
+/* If you use memory over 16M */
+#ifdef SCSI_BOUNCE_SIZE
+#define BS_BOUNCE_SIZE SCSI_BOUNCE_SIZE
+#else /* !SCSI_BOUNCE_SIZE */
+#define BS_BOUNCE_SIZE 0
+#endif /* !SCSI_BOUNCE_SIZE */
+
+/* debug */
+#define BS_STATICS 1
+#define BS_DIAG 1
+#define BS_DEBUG_ROUTINE 1
+#define BS_DEBUG 1
+/* #define SHOW_PORT 1 */
+
+/**************************************************
+ * PARAMETER
+ **************************************************/
+#define NTARGETS 8
+#define RETRIES 4 /* number of retries before giving up */
+#define HARDRETRIES 3
+#define XSMAX 4
+#define BSDMABUFSIZ 0x10000
+#define BS_MAX_CCB (XSMAX * (NTARGETS - 1))
+
+#define BSCMDSTART 0
+#define BSCMDRESTART 0x01
+#define BSCMDFORCE 0x02
+
+#define BS_TIMEOUT_INTERVAL (hz * BS_TIMEOUT_CHECK_INTERVAL)
+
+/**************************************************
+ * SCSI PHASE
+ **************************************************/
+enum scsi_phase {
+ FREE = 0,
+ HOSTQUEUE,
+ DISCONNECTED,
+ IOCOMPLETED,
+ ATTENTIONASSERT,
+ DISCONNECTASSERT,
+ SELECTASSERT,
+ SELECTED,
+ RESELECTED,
+ MSGIN,
+ MSGOUT,
+ STATUSIN,
+ CMDPHASE,
+ DATAPHASE,
+ SATSEL,
+ SATRESEL,
+ SATSDP,
+ SATCOMPSEQ,
+ UNDEF,
+};
+
+/**************************************************
+ * SCSI PHASE CONTROL MACRO
+ **************************************************/
+#define BS_HOST_START \
+{ \
+ bsc->sc_nexus = ti; \
+}
+
+#define BS_HOST_TERMINATE \
+{ \
+ bsc->sc_selwait = NULL; \
+ bsc->sc_nexus = NULL; \
+}
+
+#define BS_SELECTION_START \
+{ \
+ bsc->sc_selwait = ti; \
+}
+
+#define BS_SELECTION_TERMINATE \
+{ \
+ bsc->sc_selwait = NULL; \
+}
+
+#define BS_SETUP_PHASE(PHASE) \
+{ \
+ ti->ti_ophase = ti->ti_phase; \
+ ti->ti_phase = (PHASE); \
+}
+
+#define BS_SETUP_MSGPHASE(PHASE) \
+{ \
+ bsc->sc_msgphase = (PHASE); \
+}
+
+#define BS_SETUP_SYNCSTATE(STATE) \
+{ \
+ ti->ti_syncnow.state = (STATE); \
+}
+
+#define BS_SETUP_TARGSTATE(STATE) \
+{ \
+ ti->ti_state = (STATE); \
+}
+
+#define BS_LOAD_SDP \
+{ \
+ bsc->sc_p.data = ti->ti_scsp.data; \
+ bsc->sc_p.datalen = ti->ti_scsp.datalen; \
+ bsc->sc_p.seglen = ti->ti_scsp.seglen; \
+}
+
+#define BS_RESTORE_SDP \
+{ \
+ bsc->sc_p = ti->ti_scsp; \
+}
+
+#define BS_SAVE_SDP \
+{ \
+ ti->ti_scsp = bsc->sc_p; \
+}
+
+/**************************************************
+ * STRUCTURES
+ **************************************************/
+struct msgbase {
+#define MAXMSGLEN 8
+ u_int8_t msg[MAXMSGLEN];
+ u_int msglen;
+
+ u_int flag;
+};
+
+struct syncdata {
+ u_int8_t period;
+ u_int8_t offset;
+
+#define BS_SYNCMSG_NULL 0x00
+#define BS_SYNCMSG_ASSERT 0x01
+#define BS_SYNCMSG_REJECT 0x02
+#define BS_SYNCMSG_ACCEPT 0x03
+#define BS_SYNCMSG_REQUESTED 0x04
+ u_int state;
+};
+
+struct sc_p {
+ u_int8_t *data;
+ int datalen;
+
+ u_int8_t *segaddr;
+ int seglen;
+
+ u_int8_t *bufp;
+};
+
+/* targ_info error flags */
+#define BSDMAABNORMAL 0x01
+#define BSCMDABNORMAL 0x02
+#define BSPARITY 0x04
+#define BSSTATUSERROR 0x08
+#define BSTIMEOUT 0x10
+#define BSREQSENSE 0x20
+#define BSSELTIMEOUT 0x40
+#define BSFATALIO 0x80
+#define BSMSGERROR 0x100
+#define BSTRYRECOV 0x200
+#define BSABNORMAL 0x400
+#define BSTARGETBUSY 0x800
+
+#define BSERRORBITS "\020\014busy\013abnormal\012retry\011msgerr\010fatal\007seltimeout\006sense\005timeout\004statuserr\003parity\002cmderr\001dmaerr"
+
+/* ccb & targ_info flags & cmd flags*/
+#define BSREAD 0x0001
+#define BSSAT 0x0002
+#define BSLINK 0x0004
+#define BSERROROK 0x0008
+#define BSSMIT 0x0010
+#define BSDISC 0x1000
+#define BSFORCEIOPOLL 0x2000
+
+#define BSCASTAT 0x01000000
+#define BSSENSECCB 0x02000000
+#define BSQUEUED 0x04000000
+#define BSALTBUF 0x08000000
+#define BSITSDONE 0x10000000
+#define BSNEXUS 0x20000000
+
+#define BSCFLAGSMASK (0xffff)
+
+struct ccb {
+ TAILQ_ENTRY(ccb) ccb_chain;
+
+ struct scsi_xfer *xs; /* upper drivers info */
+
+ u_int lun; /* lun */
+
+ u_int flags; /* control flags */
+
+ int rcnt; /* retry counter of this ccb */
+
+ u_int error; /* recorded error */
+
+ /*****************************************
+ * scsi cmd & data
+ *****************************************/
+ u_int8_t *cmd; /* scsi cmd */
+ int cmdlen;
+
+ u_int8_t *data; /* scsi data */
+ int datalen;
+
+ u_int8_t msgout[MAXMSGLEN]; /* scsi msgout */
+ u_int msgoutlen;
+
+ /*****************************************
+ * timeout counter
+ *****************************************/
+ int tc;
+ int tcmax;
+};
+
+GENERIC_CCB_ASSERT(bs, ccb)
+
+/* target info */
+struct targ_info {
+ TAILQ_ENTRY(targ_info) ti_tchain; /* targ_info link */
+
+ TAILQ_ENTRY(targ_info) ti_wchain; /* wait link */
+
+ struct bs_softc *ti_bsc; /* our controller */
+ u_int ti_id; /* scsi id */
+ u_int ti_lun; /* current lun */
+
+ struct ccbtab ti_ctab, ti_bctab; /* ccb */
+
+#define BS_TARG_NULL 0
+#define BS_TARG_CTRL 1
+#define BS_TARG_START 2
+#define BS_TARG_SYNCH 3
+#define BS_TARG_RDY 4
+ int ti_state; /* target state */
+
+ u_int ti_cfgflags; /* target cfg flags */
+
+ u_int ti_flags; /* flags */
+ u_int ti_mflags; /* flags masks */
+
+ u_int ti_error; /* error flags */
+ u_int ti_herrcnt; /* hardware err retry counter */
+
+ /*****************************************
+ * scsi phase data
+ *****************************************/
+ struct sc_p ti_scsp; /* saved scsi data pointer */
+
+ enum scsi_phase ti_phase; /* scsi phase */
+ enum scsi_phase ti_ophase; /* previous scsi phase */
+
+ u_int8_t ti_status; /* status in */
+
+ u_int8_t ti_msgin[MAXMSGLEN]; /* msgin buffer */
+ int ti_msginptr;
+
+ u_int8_t ti_msgout; /* last msgout byte */
+ u_int8_t ti_emsgout; /* last msgout byte */
+ u_int ti_omsgoutlen; /* for retry msgout */
+
+ struct syncdata ti_syncmax; /* synch data (scsi) */
+ struct syncdata ti_syncnow;
+ u_int8_t ti_sync; /* synch val (chip) */
+
+ /*****************************************
+ * bounce buffer & smit data pointer
+ *****************************************/
+ u_int8_t *bounce_phys;
+ u_int8_t *bounce_addr;
+ u_int bounce_size;
+
+ u_int8_t *sm_vaddr;
+
+ /*****************************************
+ * target inq data
+ *****************************************/
+ u_int8_t targ_type;
+ u_int8_t targ_support;
+
+ /*****************************************
+ * generic scsi cmd buffer for this target
+ *****************************************/
+ u_int8_t scsi_cmd[12];
+ struct scsi_sense_data sense;
+};
+
+TAILQ_HEAD(titab, targ_info);
+struct bshw;
+
+struct bs_softc {
+ /*****************************************
+ * OS depend header
+ *****************************************/
+ OS_DEPEND_DEVICE_HEADER
+
+ OS_DEPEND_SCSI_HEADER
+
+ OS_DEPEND_MISC_HEADER
+
+ /*****************************************
+ * target link
+ *****************************************/
+ struct targ_info *sc_ti[NTARGETS];
+ u_int sc_openf;
+
+ struct titab sc_sttab;
+ struct titab sc_titab;
+
+ /*****************************************
+ * current scsi phase
+ *****************************************/
+ struct targ_info *sc_nexus; /* current active nexus */
+
+ enum scsi_phase sc_msgphase; /* scsi phase pointed by msg */
+
+ struct targ_info *sc_selwait; /* selection assert */
+
+ u_int sc_dtgnum; /* disconnected target */
+
+ /*****************************************
+ * current scsi data pointer
+ *****************************************/
+ struct sc_p sc_p; /* scsi data pointer */
+
+ int sc_dmadir; /* dma direction */
+
+ int sm_tdatalen; /* smit data transfer bytes */
+
+ /*****************************************
+ * parameter
+ *****************************************/
+ u_int sc_retry; /* max retry count */
+
+#define BSDMATRANSFER 0x01
+#define BSDMASTART 0x02
+#define BSSMITSTART 0x04
+#define BSUNDERRESET 0x08
+#define BSRESET 0x10
+#define BSSTARTTIMEOUT 0x20
+#define BSPOLLDONE 0x100
+#define BSJOBDONE 0x200
+#define BSBSMODE 0x400
+#define BSINACTIVE 0x800
+ volatile int sc_flags; /* host flags */
+
+#define BSC_NULL 0
+#define BSC_BOOTUP 1
+#define BSC_TARG_CHECK 2
+#define BSC_RDY 3
+ int sc_hstate; /* host state */
+
+ /*****************************************
+ * polling misc
+ *****************************************/
+ u_int sc_wc; /* weight count */
+
+ int sc_poll;
+ struct ccb *sc_outccb;
+
+ /*****************************************
+ * wd33c93 chip depend section
+ *****************************************/
+ u_int sc_cfgflags; /* hardware cfg flags */
+
+ struct bshw *sc_hw; /* hw selection */
+
+ u_int8_t *sm_vaddr; /* smit buffer */
+
+ u_int sc_RSTdelay;
+
+ int sc_hwlock; /* hardware lock count */
+
+ int sc_iobase; /* iobase for FreeBSD */
+ u_int32_t sc_irqmasks; /* irq */
+
+ u_int sc_dmachan; /* dma channel */
+ u_int8_t sc_busstat; /* scsi bus status register */
+ u_int8_t sc_hostid; /* host scsi id */
+ u_int8_t sc_cspeed; /* chip clock rate */
+ u_int8_t sc_membank; /* memory back (NEC) register */
+
+ /*****************************************
+ * our name
+ *****************************************/
+#define BS_DVNAME_LEN 16
+ u_char sc_dvname[BS_DVNAME_LEN];
+};
+
+/*************************************************
+ * debug
+ *************************************************/
+#ifdef BS_STATICS
+struct bs_statics {
+ u_int select;
+ u_int select_miss_in_assert;
+ u_int select_miss_by_reselect;
+ u_int select_miss;
+ u_int select_win;
+ u_int selected;
+ u_int disconnected;
+ u_int reselect;
+};
+
+extern struct bs_statics bs_statics[NTARGETS];
+extern u_int bs_linkcmd_count[];
+extern u_int bs_bounce_used[];
+#endif /* BS_STATICS */
+
+#ifdef BS_DEBUG_ROUTINE
+#ifndef DDB
+#define Debugger() panic("should call debugger here (bs.c)")
+#endif /* DDB */
+#ifdef BS_DEBUG
+extern int bs_debug_flag;
+#endif /* BS_DEBUG */
+#endif /* BS_DEBUG_ROUTINE */
+
+/*************************************************
+ * Function declare
+ *************************************************/
+int bs_scsi_cmd_internal __P((struct ccb *, u_int));
+struct ccb *bscmddone __P((struct targ_info *));
+int bscmdstart __P((struct targ_info *, int));
+int bs_scsi_cmd_poll __P((struct targ_info *, struct ccb *));
+int bs_sequencer __P((struct bs_softc *));
+void bs_poll_timeout __P((struct bs_softc *, char *));
+
+/*************************************************
+ * XXX
+ *************************************************/
+/* misc error */
+#define NOTARGET -2
+#define HASERROR -1
+
+/* XXX: use scsi_message.h */
+/* status */
+#define ST_GOOD 0x00
+#define ST_CHKCOND 0x02
+#define ST_MET 0x04
+#define ST_BUSY 0x08
+#define ST_INTERGOOD 0x10
+#define ST_INTERMET 0x14
+#define ST_CONFLICT 0x18
+#define ST_QUEFULL 0x28
+#define ST_UNK 0xff
+
+/* message */
+#define MSG_COMP 0x00
+#define MSG_EXTEND 0x01
+
+#define MKMSG_EXTEND(XLEN, XCODE) ((((u_int)(XLEN)) << NBBY) | ((u_int)(XCODE)))
+#define MSG_EXTEND_MDPCODE 0x00
+#define MSG_EXTEND_MDPLEN 0x05
+#define MSG_EXTEND_SYNCHCODE 0x01
+#define MSG_EXTEND_SYNCHLEN 0x03
+#define MSG_EXTEND_WIDECODE 0x03
+#define MSG_EXTEND_WIDELEN 0x02
+
+#define MSG_SAVESP 0x02
+#define MSG_RESTORESP 0x03
+#define MSG_DISCON 0x04
+#define MSG_I_ERROR 0x05
+#define MSG_ABORT 0x06
+#define MSG_REJECT 0x07
+#define MSG_NOOP 0x08
+#define MSG_PARITY 0x09
+#define MSG_LCOMP 0x0a
+#define MSG_LCOMP_F 0x0b
+#define MSG_RESET 0x0c
diff --git a/sys/i386/isa/bs/ccbque.h b/sys/i386/isa/bs/ccbque.h
new file mode 100644
index 0000000..d2c4cfc
--- /dev/null
+++ b/sys/i386/isa/bs/ccbque.h
@@ -0,0 +1,130 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Common command control queue funcs.
+ * Written by N. Honda.
+ */
+
+#ifndef _CCBQUE_H_
+#define _CCBQUE_H_
+
+/* (I) structure and prototype */
+#define GENERIC_CCB_ASSERT(DEV, CCBTYPE) \
+TAILQ_HEAD(CCBTYPE##tab, CCBTYPE); \
+struct CCBTYPE##que { \
+ struct CCBTYPE##tab CCBTYPE##tab; \
+ int count; \
+ int maxccb; \
+}; \
+void DEV##_init_ccbque __P((int)); \
+struct CCBTYPE *DEV##_get_ccb __P((int)); \
+void DEV##_free_ccb __P((struct CCBTYPE *));
+
+/* (II) static allocated memory */
+#define GENERIC_CCB_STATIC_ALLOC(DEV, CCBTYPE) \
+static struct CCBTYPE##que CCBTYPE##que;
+
+/* (III) functions */
+#define GENERIC_CCB(DEV, CCBTYPE, CHAIN) \
+ \
+void \
+DEV##_init_ccbque(count) \
+ int count; \
+{ \
+ if (CCBTYPE##que.maxccb == 0) \
+ TAILQ_INIT(&CCBTYPE##que.CCBTYPE##tab) \
+ CCBTYPE##que.maxccb += count; \
+} \
+ \
+struct CCBTYPE * \
+DEV##_get_ccb(flags) \
+ int flags; \
+{ \
+ struct CCBTYPE *cb; \
+ int s = splbio(); \
+ \
+ do \
+ { \
+ if (CCBTYPE##que.count > CCBTYPE##que.maxccb) \
+ { \
+ if (flags) \
+ { \
+ cb = NULL; \
+ goto done; \
+ } \
+ else \
+ { \
+ tsleep((caddr_t) &CCBTYPE##que.count, \
+ PRIBIO, "ccbwait", 0); \
+ continue; \
+ } \
+ } \
+ \
+ if (cb = CCBTYPE##que.CCBTYPE##tab.tqh_first) \
+ { \
+ TAILQ_REMOVE(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN)\
+ break; \
+ } \
+ else \
+ { \
+ if (cb = malloc(sizeof(*cb), M_DEVBUF, M_NOWAIT))\
+ { \
+ bzero(cb, sizeof(*cb)); \
+ break; \
+ } \
+ else if (flags) \
+ goto done; \
+ \
+ tsleep((caddr_t) &CCBTYPE##que.count, \
+ PRIBIO, "ccbwait", 0); \
+ } \
+ } \
+ while (1); \
+ CCBTYPE##que.count ++; \
+ \
+done: \
+ splx(s); \
+ return cb; \
+} \
+ \
+void \
+DEV##_free_ccb(cb) \
+ struct CCBTYPE *cb; \
+{ \
+ int s = splbio(); \
+ \
+ TAILQ_INSERT_TAIL(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN) \
+ CCBTYPE##que.count --; \
+ \
+ if (CCBTYPE##que.count == CCBTYPE##que.maxccb) \
+ wakeup ((caddr_t) &CCBTYPE##que.count); \
+ splx(s); \
+}
+#endif /* !_CCBQUE_H_ */
diff --git a/sys/i386/isa/bs/dvcfg.h b/sys/i386/isa/bs/dvcfg.h
new file mode 100644
index 0000000..f092117
--- /dev/null
+++ b/sys/i386/isa/bs/dvcfg.h
@@ -0,0 +1,64 @@
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1996 NetBSD/pc98 porting staff.
+ * 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.
+ */
+/*
+ * Copyright (c) 1996 Naofumi HONDA. All rights reserved.
+ */
+
+#ifndef _I386_DVCFG_H_
+#define _I386_DVCFG_H_
+
+typedef void *dvcfg_hw_t;
+
+struct dvcfg_hwsel {
+ int cfg_max;
+
+ dvcfg_hw_t *cfg_sel;
+};
+
+#define DVCFG_MAJOR(dvcfg) (((u_int)(dvcfg)) >> 16)
+#define DVCFG_MINOR(dvcfg) (((u_int)(dvcfg)) & 0xffff)
+
+#define DVCFG_MKCFG(major, minor) ((((u_int)(major)) << 16) | ((minor) & 0xffff))
+
+#define DVCFG_HWSEL_SZ(array) (sizeof(array) / sizeof(dvcfg_hw_t))
+
+static inline dvcfg_hw_t dvcfg_hw __P((struct dvcfg_hwsel *, u_int));
+
+static inline dvcfg_hw_t
+dvcfg_hw(selp, num)
+ struct dvcfg_hwsel *selp;
+ u_int num;
+{
+
+ return ((num >= selp->cfg_max) ? NULL : selp->cfg_sel[num]);
+}
+
+#define DVCFG_HW(SELP, NUM) dvcfg_hw((SELP), (NUM))
+#endif /* _I386_DVCFG_H_ */
diff --git a/sys/i386/isa/ic/wd33c93.h b/sys/i386/isa/ic/wd33c93.h
index f1aa7f9..e8ba4aa 100644
--- a/sys/i386/isa/ic/wd33c93.h
+++ b/sys/i386/isa/ic/wd33c93.h
@@ -1,127 +1,155 @@
/*
- * PC9801 SCSI I/F (PC-9801-55)
- * modified for PC9801 by A.Kojima
- * Kyoto University Microcomputer Club (KMC)
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1996 NetBSD/pc98 porting staff.
+ * Copyright (c) 1996 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.
*/
-/* I/O address */
-
-/* WD33C93 */
-#define SCSI_ADR_REG 0xcc0 /* write Address Register */
-#define SCSI_AUX_REG 0xcc0 /* read Aux. Status Register */
-#define SCSI_CTL_REG 0xcc2 /* read/write Control Registers */
-
-/* Port */
-#define SCSI_STAT_RD 0xcc4 /* read Status Read */
-#define SCSI_CMD_WRT 0xcc4 /* write Command Write */
-
-#if 0 /* H98 extended mode */
-/* WD33C93 */
-#define SCSI_ADR_REG 0xee0 /* write Address Register */
-#define SCSI_AUX_REG 0xee0 /* read Control Register */
-#define SCSI_CTL_REG 0xee2 /* read/write Registers */
-
-/* Port */
-#define SCSI_STAT_RD 0xee4 /* read Status Read */
-#define SCSI_CMD_WRT 0xee4 /* write Command Write */
-#endif
-
-/****************************************************************/
-
-/* WD33C93 Registers */
-#define REG_OWN_ID 0x00 /* Own ID */
-#define REG_CONTROL 0x01 /* Control */
-#define REG_TIMEOUT_PERIOD 0x02 /* Timeout Period */
-#define REG_TOTAL_SECTORS 0x03 /* Total Sectors */
-#define REG_TOTAL_HEADS 0x04 /* Total Heads */
-#define REG_TOTAL_CYL_H 0x05 /* Total Cylinders (MSB) */
-#define REG_TOTAL_CYL_L 0x06 /* Total Cylinders (LSB) */
-#define REG_LOG_SECTOR_HH 0x07 /* Logical Address (MSB) */
-#define REG_LOG_SECTOR_HL 0x08 /* Logical Address */
-#define REG_LOG_SECTOR_LH 0x09 /* Logical Address */
-#define REG_LOG_SECTOR_LL 0x0a /* Logical Address (LSB) */
-#define REG_SECTOR_NUMBER 0x0b /* Sector Number */
-#define REG_HEAD_NUMBER 0x0c /* Head Number */
-#define REG_CYL_NUMBER_H 0x0d /* Cylinder Number (MSB) */
-#define REG_CYL_NUMBER_L 0x0e /* Cylinder Number (LSB) */
-#define REG_TARGET_LUN 0x0f /* Target LUN */
-#define REG_CMD_PHASE 0x10 /* Command Phase */
-#define REG_SYNC_TFR 0x11 /* Synchronous Transfer */
-#define REG_TFR_COUNT_H 0x12 /* Transfer Count (MSB) */
-#define REG_TFR_COUNT_M 0x13 /* Transfer Count */
-#define REG_TFR_COUNT_L 0x14 /* Transfer Count (LSB) */
-#define REG_DST_ID 0x15 /* Destination ID */
-#define REG_SRC_ID 0x16 /* Source ID */
-#define REG_SCSI_STATUS 0x17 /* SCSI Status (Read Only) */
-#define REG_COMMAND 0x18 /* Command */
-#define REG_DATA 0x19 /* Data */
-
-/* PC98 only */
-#define REG_MEM_BANK 0x30 /* Memory Bank */
-#define REG_MEM_WIN 0x31 /* Memery Window */
-#define REG_RESERVED1 0x32 /* NEC Reserved 1 */
-#define REG_RESET_INT 0x33 /* Reset/Int */
-#define REG_RESERVED2 0x34 /* NEC Reserved 2 */
-
-/****************************************************************/
-
-/* WD33C93 Commands */
-#define CMD_RESET 0x00 /* Reset */
-#define CMD_ABORT 0x01 /* Abort */
-#define CMD_ASSERT_ATN 0x02 /* Assert ATN */
-#define CMD_NEGATE_ATN 0x03 /* Negate ATN */
-#define CMD_DISCONNECT 0x04 /* Disconnect */
-#define CMD_RESELECT 0x05 /* Reselect */
-#define CMD_SELECT_ATN 0x06 /* Select with ATN */
-#define CMD_SELECT_NO_ATN 0x07 /* Select without ATN */
-#define CMD_SELECT_ATN_TFR 0x08 /* Select with ATN and Transfer */
-#define CMD_SELECT_NO_ATN_TFR 0x09 /* Select without ATN and Transfer */
-#define CMD_RESELECT_RCV_DATA 0x0a /* Reselect and Recieve Data */
-#define CMD_RESELECT_SEND_DATA 0x0b /* Reselect and Send Data */
-#define CMD_WAIT_SELECT_RCV 0x0c /* Wait for Select and Recieve */
-#define CMD_RCV_CMD 0x10 /* Recieve Command */
-#define CMD_RCV_DATA 0x11 /* Recieve Data */
-#define CMD_RCV_MSG_OUT 0x12 /* Recieve Message Info Out*/
-#define CMD_RCV_UNSP_INFO_OUT 0x13 /* Recieve Unspecified Info Out */
-#define CMD_SEND_STATUS 0x14 /* Send Status */
-#define CMD_SEND_DATA 0x15 /* Send Data */
-#define CMD_SEND_MSG_IN 0x16 /* Send Message In */
-#define CMD_SEND_UNSP_INFO_IN 0x17 /* Send Unspecified Info In */
-#define CMD_TRANSLATE_ADDRESS 0x18 /* Translate Address */
-#define CMD_TFR_INFO 0x20 /* Transfer Info */
-#define CMD_TFR_PAD 0x21 /* Transfer Pad */
-#define CMD_SBT_SFX 0x80 /* single byte suffix */
-
-/* WD33C93 bus status register (lower nibble) */
-#define STAT_DATAOUT 0x08 /* Data out phase */
-#define STAT_DATAIN 0x09 /* Data in phase */
-#define STAT_CMDOUT 0x0a /* Command out phase */
-#define STAT_STATIN 0x0b /* Status in phase */
-#define STAT_MSGOUT 0x0e /* Message out phase */
-#define STAT_MSGIN 0x0f /* Message in phase */
-
-/* SCSI Status byte */
-#define SS_GOOD 0x00 /* Good status */
-#define SS_CHKCOND 0x02
-#define SS_MET 0x04
-#define SS_BUSY 0x08
-#define SS_INTERGOOD 0x10
-#define SS_INTERMET 0x14
-#define SS_CONFLICT 0x18
-
-/* SCSI message system */
-#define MSG_COMPLETE 0x00 /* Command complete message */
-#define MSG_EXTEND 0x01 /* Extend message */
-#define MSG_SAVEPTR 0x02 /* Save data pointer message */
-#define MSG_RESTORE 0x03 /* Restore data pointer message */
-#define MSG_DISCON 0x04 /* Disconnect message */
-#define MSG_INIERROR 0x05
-#define MSG_ABORT 0x06
-#define MSG_REJECT 0x07
-#define MSG_NOP 0x08
-#define MSG_PARERROR 0x09
-#define MSG_LCOMPLETE 0x0a
-#define MSG_LCOMPLETEF 0x0b
-#define MSG_DEVRESET 0x0c
-#define MSG_IDENTIFY 0x80 /* Identify message */
+#ifndef _WD33C93REG_H_
+#define _WD33C93REG_H_
+/* wd33c93 register */
+#define wd3s_oid 0x00
+#define IDR_FS_15_20 0x80
+#define IDR_FS_12_15 0x40
+#define IDR_FS_8_10 0x00
+#define IDR_EHP 0x10
+#define IDR_EAF 0x08
+#define IDR_IDM 0x07
+
+#define wd3s_ctrl 0x01
+#define CR_DMA 0x80
+#define CR_DMAD 0x40
+#define CR_HLT_HOST_PARITY 0x10
+#define CR_DIS_INT 0x08
+#define CR_IDIS_INT 0x04
+#define CR_HLT_ATN 0x02
+#define CR_HLT_BUS_PARITY 0x01
+#define CR_DEFAULT (CR_DIS_INT | CR_IDIS_INT)
+#define CR_DEFAULT_HP (CR_DEFAULT | CR_HLT_BUS_PARITY)
+
+#define wd3s_tout 0x02
+#define wd3s_cdb 0x03
+#define wd3s_lun 0x0f
+#define wd3s_cph 0x10
+#define wd3s_synch 0x11
+#define wd3s_cnt 0x12
+#define wd3s_did 0x15
+
+#define wd3s_sid 0x16
+#define SIDR_RESEL 0x80
+#define SIDR_SEL 0x40
+#define SIDR_VALID 0x08
+#define SIDR_IDM 0x07
+
+#define wd3s_stat 0x17
+
+#define BSR_CM 0xf0
+#define BSR_CMDCPL 0x10
+#define BSR_CMDABT 0x20
+#define BSR_CMDERR 0x40
+#define BSR_CMDREQ 0x80
+
+#define BSR_SM 0x0f
+#define BSR_PM 0x07
+#define BSR_PHVALID 0x08
+#define BSR_IOR 0x01
+#define BSR_DATAOUT 0x00
+#define BSR_DATAIN 0x01
+#define BSR_CMDOUT 0x02
+#define BSR_STATIN 0x03
+#define BSR_UNSPINFO0 0x04
+#define BSR_UNSPINFO1 0x05
+#define BSR_MSGOUT 0x06
+#define BSR_MSGIN 0x07
+
+#define BSR_SELECTED 0x11
+#define BSR_SATFIN 0x16
+#define BSR_ACKREQ 0x20
+#define BSR_SATSDP 0x21
+#define BSR_RESEL 0x80
+#define BSR_DISC 0x85
+
+#define wd3s_cmd 0x18
+#define wd3s_data 0x19
+#define wd3s_qtag 0x1a
+
+#define wd3s_mbank 0x30
+#define MBR_RST 0x02
+#define MBR_IEN 0x04
+
+#define wd3s_mwin 0x31
+#define wd3s_auxc 0x33
+#define AUXCR_HIDM 0x07
+#define AUXCR_INTM 0x38
+#define AUXCR_RRST 0x80
+
+/* status port */
+#define STR_INT 0x80
+#define STR_LCI 0x40
+#define STR_BSY 0x20
+#define STR_CIP 0x10
+#define STR_PE 0x02
+#define STR_DBR 0x01
+#define STR_BUSY 0xf0
+
+/* cmd port */
+#define CMDP_DMES 0x01
+#define CMDP_DMER 0x02
+#define CMDP_TCMS 0x04
+#define CMDP_TCMR 0x08
+#define CMDP_TCIR 0x10
+
+/* wd33c93 chip cmds */
+#define WD3S_SBT 0x80
+#define WD3S_RESET 0x00
+#define WD3S_ABORT 0x01
+#define WD3S_ASSERT_ATN 0x02
+#define WD3S_NEGATE_ACK 0x03
+#define WD3S_DISCONNECT 0x04
+#define WD3S_RESELECT 0x05
+#define WD3S_SELECT_ATN 0x06
+#define WD3S_SELECT_NO_ATN 0x07
+#define WD3S_SELECT_ATN_TFR 0x08
+#define WD3S_SELECT_NO_ATN_TFR 0x09
+#define WD3S_RESELECT_RCV_DATA 0x0a
+#define WD3S_RESELECT_SEND_DATA 0x0b
+#define WD3S_WAIT_SELECT_RCV 0x0c
+#define WD3S_CMD_COMPSEQ 0x0d
+#define WD3S_SEND_DISC_MSG 0x0e
+#define WD3S_SET_IDI 0x0f
+#define WD3S_RCV_CMD 0x10
+#define WD3S_RCV_DATA 0x11
+#define WD3S_RCV_MSG_OUT 0x12
+#define WD3S_RCV_UNSP_INFO_OUT 0x13
+#define WD3S_SEND_STATUS 0x14
+#define WD3S_SEND_DATA 0x15
+#define WD3S_SEND_MSG_IN 0x16
+#define WD3S_SEND_UNSP_INFO_IN 0x17
+#define WD3S_TRANSLATE_ADDRESS 0x18
+#define WD3S_TFR_INFO 0x20
+
+#endif /* !_WD33C93REG_H_ */
diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC
index 69b5064..65af27f 100644
--- a/sys/pc98/conf/GENERIC
+++ b/sys/pc98/conf/GENERIC
@@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
-# $Id: GENERIC98,v 1.8 1996/10/30 22:39:29 asami Exp $
+# $Id: GENERIC98,v 1.9 1996/11/14 08:46:11 asami Exp $
# GENERIC98 -- Generic PC98 machine with WD/SBIC55 disks
@@ -58,12 +58,6 @@ options COM_MULTIPORT
#options SUSP_HLT # CPU enters suspend mode when HALT
#options "DISABLE_5X86_LSSER" # Load-Store reordering enable
#
-# sbic55.c.new
-#
-#options SCSI_SYNC # synchronous transfer mode
-#options FORCE_BUSMASTER
-#options "HA55BS_ID=0"
-#
# IBM-PC HDD support
#options COMPAT_ATDISK
#
@@ -100,13 +94,24 @@ device wcd0 #IDE CD-ROM
# for any number of installed devices.
controller ncr0
controller ahc0
-options "AHC_FORCE_PIO" # Some motherboards choke on MemI/O,
- # so use PIO in the ahc driver in the
- # generic kernel.
-controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 vector sbicintr
-# sbic55.c.new
-#controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0xff vector sbicintr
+#
+# WD33C93 SCSI card (55/92 like board)
+#
+
+options BS_TARG_SAFEMODE
+
+# PC-9801-92
+controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0 vector bsintr
+# SC-98
+# controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x10000 vector bsintr
+# HA-55BS2 and later
+#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x20000 vector bsintr
+# ELECOM type
+#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x30000 vector bsintr
+# SMIT
+#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 iomem 0xdd000 iosiz 0x1000 flags 0x40000 vector bsintr
+
controller aic0 at isa? port 0x1840 bio irq 5 flags 0x10000 vector aicintr
controller scbus0
diff --git a/sys/pc98/conf/GENERIC98 b/sys/pc98/conf/GENERIC98
index 69b5064..65af27f 100644
--- a/sys/pc98/conf/GENERIC98
+++ b/sys/pc98/conf/GENERIC98
@@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
-# $Id: GENERIC98,v 1.8 1996/10/30 22:39:29 asami Exp $
+# $Id: GENERIC98,v 1.9 1996/11/14 08:46:11 asami Exp $
# GENERIC98 -- Generic PC98 machine with WD/SBIC55 disks
@@ -58,12 +58,6 @@ options COM_MULTIPORT
#options SUSP_HLT # CPU enters suspend mode when HALT
#options "DISABLE_5X86_LSSER" # Load-Store reordering enable
#
-# sbic55.c.new
-#
-#options SCSI_SYNC # synchronous transfer mode
-#options FORCE_BUSMASTER
-#options "HA55BS_ID=0"
-#
# IBM-PC HDD support
#options COMPAT_ATDISK
#
@@ -100,13 +94,24 @@ device wcd0 #IDE CD-ROM
# for any number of installed devices.
controller ncr0
controller ahc0
-options "AHC_FORCE_PIO" # Some motherboards choke on MemI/O,
- # so use PIO in the ahc driver in the
- # generic kernel.
-controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 vector sbicintr
-# sbic55.c.new
-#controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0xff vector sbicintr
+#
+# WD33C93 SCSI card (55/92 like board)
+#
+
+options BS_TARG_SAFEMODE
+
+# PC-9801-92
+controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0 vector bsintr
+# SC-98
+# controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x10000 vector bsintr
+# HA-55BS2 and later
+#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x20000 vector bsintr
+# ELECOM type
+#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x30000 vector bsintr
+# SMIT
+#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 iomem 0xdd000 iosiz 0x1000 flags 0x40000 vector bsintr
+
controller aic0 at isa? port 0x1840 bio irq 5 flags 0x10000 vector aicintr
controller scbus0
diff --git a/sys/pc98/pc98/sbic55.c b/sys/pc98/pc98/sbic55.c
deleted file mode 100644
index 2bcaf17..0000000
--- a/sys/pc98/pc98/sbic55.c
+++ /dev/null
@@ -1,917 +0,0 @@
-/*
- * Julian SCSI driver for PC-9801 based on aha1542.c
- *
- * Copyright (c) by Yoshio Kimura
- * 05/14/1994
- */
-
-#include <sys/types.h>
-#include "sbic.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-
-#include <machine/clock.h>
-#include <machine/cpu.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
-#include <pc98/pc98/pc98.h>
-#include <i386/isa/isa_device.h>
-#include <i386/isa/icu.h>
-#include <i386/isa/ic/i8237.h>
-#include <pc98/pc98/scsireg.h>
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-
-#include <sys/kernel.h>
-
-/************************** board definitions *******************************/
-
-/*
- * I/O Port Interface
- */
-
-#define SBIC_BASE sbic->sbic_base
-#define SBIC_AUX_REG (SBIC_BASE + 0) /* auxiliary status(R) */
-#define SBIC_ADR_REG (SBIC_BASE + 0) /* address(W) */
-#define SBIC_CTL_REG (SBIC_BASE + 2) /* control(R/W) */
-#define SBIC_STA_REG (SBIC_BASE + 4) /* status(R/W) */
-
-/*
- * Register Access Interface
- */
-
-#define SBIC_asr(val) (val) = inb(SBIC_AUX_REG)
-#define GET_SBIC_REG(regno, val) { \
- outb(SBIC_ADR_REG, (regno)); \
- (val) = inb(SBIC_CTL_REG); \
- }
-#define SET_SBIC_REG(regno, val) { \
- outb(SBIC_ADR_REG, (regno)); \
- outb(SBIC_CTL_REG, (val)); \
- }
-#define SET_SCSI_CMD(cmd, cmdlen) { \
- int n; \
- u_char *cmds = (u_char *)(cmd); \
- SET_SBIC_REG(SBIC_cdbsize, (cmdlen)); \
- for (n = 0; n < (cmdlen); n++) { \
- SET_SBIC_REG(SBIC_cdb1 + n, cmds[n]); \
- } \
- }
-#define SET_XFER_LEN(val) { \
- SET_SBIC_REG(SBIC_count_hi, ((val) & 0xff0000) >> 16); \
- SET_SBIC_REG(SBIC_count_med, ((val) & 0x00ff00) >> 8); \
- SET_SBIC_REG(SBIC_count_lo, (val) & 0x0000ff); \
- }
-#define SBIC_ENABLE_INT() { \
- int tmp; \
- GET_SBIC_REG(SBIC_bank, tmp); \
- SET_SBIC_REG(SBIC_bank, tmp | 0x04); \
- }
-#define SBIC_DISABLE_INT() { \
- int tmp; \
- GET_SBIC_REG(SBIC_bank, tmp); \
- SET_SBIC_REG(SBIC_bank, tmp & 0xfb); \
- }
-#define SBIC_DMA_ENABLE() outb(SBIC_STA_REG, 1)
-
-#define INT3 0
-#define INT5 1
-#define INT6 2
-#define INT9 3
-#define INT12 4
-#define INT13 5
-
-#define SBIC_NSEG 17
-#define SBIC_ID 7
-#define MAXSIMUL 8
-#define SBIC_RESET_TIMEOUT 2000 /* time to wait for reset */
-
-extern short dmapageport[];
-
-
-struct sbic_ccb {
- u_char target;
- u_char lun;
- u_char status;
- u_char message;
- int datalen;
- int sense_addr;
- int sense_len;
- u_char scsi_cmdlen;
- struct scsi_generic scsi_cmd;
- struct scsi_xfer *xfer;
- struct scat_gather {
- int seg_addr;
- int seg_len;
- } scat_gath[SBIC_NSEG];
- int seg;
- int use_seg;
- int xs_flags;
- int flags;
-#define CCB_FREE 0x00
-#define CCB_ACTIVE 0x01
-#define CCB_ABORT 0x40
-#define CCB_SENSE 0x80
-#define CCB_BOUNCE 0x100
-};
-
-struct sbic_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char :5;
-};
-/*********************************** end of board definitions***************/
-
-#define KVTOPHYS(x) vtophys(x)
-#define SBIC_DMA_PAGES SBIC_NSEG
-
-#define PAGESIZ 4096
-#define ALLWAYS_BOUNCE
-
-#ifdef ALLWAYS_BOUNCE
-static vm_offset_t sbic_bounce;
-#endif
-
-#ifdef SBICDEBUG
-static int sbic_debug = 1;
-#endif
-
-struct sbic_data {
- short sbic_base; /* base port for each board */
- struct sbic_ccb sbic_ccb[MAXSIMUL];
- int top; /* ccb queue top */
- int bottom; /* ccb queue end */
- int active; /* number of active ccb */
- int free; /* number of free ccb */
- int unit;
- int sbic_int; /* our irq level */
- int sbic_dma; /* our DMA req channel */
- int sbic_scsi_dev; /* our scsi bus address */
- struct scsi_link sc_link; /* prototype for subdevs */
-};
-
-struct sbic_data *sbicdata[NSBIC];;
-
-static struct sbic_ccb *sbic_get_ccb(struct sbic_data *, int);
-static int sbicprobe(struct isa_device *);
-static void sbic_done(struct sbic_data *, struct sbic_ccb *);
-static int sbicattach(struct isa_device *);
-static int32_t sbic_scsi_cmd(struct scsi_xfer *xs);
-static u_int32_t sbic_adapter_info(int);
-static void sbicminphys(struct buf *);
-static void sbic_free_ccb(struct sbic_data *, struct sbic_ccb *, int);
-static int sbic_init(int);
-static int xfer_addr_check(int, struct sbic_ccb *);
-static int sbic_poll(struct sbic_data *, struct sbic_ccb *);
-static void start_scsi(struct sbic_data *, struct sbic_ccb *);
-static void dataphase(struct sbic_data *, struct sbic_ccb *);
-static void sbic_request_sense(struct sbic_data *, struct sbic_ccb *);
-static void sbic_dmastart(int, int, unsigned, unsigned);
-static void sbic_dmadone(int, int, unsigned, unsigned);
-
-static struct scsi_adapter sbic_switch = {
- sbic_scsi_cmd,
- sbicminphys,
- 0,
- 0,
- sbic_adapter_info,
- "sbic",
- { 0, 0 }
-};
-
-/* the below structure is so we have a default dev struct for out link struct */
-static struct scsi_device sbic_dev = {
- NULL, /* Use default error handler */
- NULL, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "sbic",
- 0,
- { 0, 0 }
-};
-
-struct isa_driver sbicdriver = {
- sbicprobe,
- sbicattach,
- "sbic"
-};
-
-static int sbicunit = 0;
-
-/*
- * Check if the device can be found at the port given
- * and if so, set it up ready for further work
- * as an argument, takes the isa_device structure from
- * autoconf.c
- */
-static int
-sbicprobe(struct isa_device *dev)
-{
- int unit = sbicunit;
- struct sbic_data *sbic;
-
- /*
- * find unit and check we have that many defined
- */
- if (unit >= NSBIC) {
- printf("sbic: unit number (%d) to high\n", unit);
- return(0);
- }
- dev->id_unit = unit;
-
- /*
- * a quick safety check so we can be sleazy later
- */
- if (sizeof(struct sbic_data) > PAGESIZ) {
- printf("sbic struct > pagesize\n");
- return(0);
- }
- /*
- * Allocate a storage area for us
- */
- if (sbicdata[unit]) {
- printf("sbic%d: memory already allocated\n", unit);
- return(0);
- }
- sbic = malloc(sizeof(struct sbic_data), M_TEMP, M_NOWAIT);
- if (!sbic) {
- printf("sbic%d: cannot malloc!\n", unit);
- return(0);
- }
- bzero(sbic, sizeof(struct sbic_data));
- sbicdata[unit] = sbic;
- sbic->sbic_base = dev->id_iobase;
-
-#ifdef ALLWAYS_BOUNCE
- /*
- * allocate bounce buffer for sense data
- */
-#ifdef EPSON_BOUNCEDMA
-#define PC98_RAMEND 0xf00000
-#else
-#define PC98_RAMEND RAM_END
-#endif
-
- /* try malloc() first. */
- sbic_bounce = (vm_offset_t)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
- if (sbic_bounce != NULL) {
- if (vtophys(sbic_bounce) >= PC98_RAMEND) {
- free(buf, M_DEVBUF);
- sbic_bounce = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
- M_NOWAIT,
- 0ul, PC98_RAMEND, 1ul,
- 0x10000ul);
- }
- }
- if (sbic_bounce == NULL)
- panic("Can't allocate bounce buffer.");
-#endif
-
- /*
- * Try initialize a unit at this location
- * sets up dma, loads sbic_init[unit]
- */
- if (sbic_init(unit) != 0) {
- sbicdata[unit] = NULL;
- free(sbic, M_TEMP);
- return(0);
- }
- /*
- * If it's there, put in it's interrupt vectors
- */
- dev->id_irq = (1 << sbic->sbic_int);
- dev->id_drq = sbic->sbic_dma;
- sbicunit++;
- return(5);
-}
-
-/*
- * Attach all the sub-devices we can find.
- */
-static int
-sbicattach(struct isa_device *dev)
-{
- int unit = dev->id_unit;
- struct sbic_data *sbic = sbicdata[unit];
- struct scsibus_data *scbus;
-
- /*
- * fill in the prototype scsi_link
- */
- sbic->sc_link.adapter_unit = unit;
- sbic->sc_link.adapter_targ = sbic->sbic_scsi_dev;
- sbic->sc_link.adapter_softc = sbic;
- sbic->sc_link.adapter = &sbic_switch;
- sbic->sc_link.device = &sbic_dev;
- sbic->sc_link.flags = SDEV_BOUNCE;
-
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = scsi_alloc_bus();
- if(!scbus)
- return 0;
- scbus->adapter_link = &sbic->sc_link;
-
- /*
- * ask the adapter what subunits are present
- */
- scsi_attachdevs(scbus);
-
- return 1;
-}
-
-/*
- * Return some information to the caller about
- * the adapter and it's capabilities
- */
-static u_int32_t
-sbic_adapter_info(int unit)
-{
- return(1); /* 1 outstanding request at a time per device */
-}
-
-/*
- * Catch an interrupt from the adapter
- */
-void
-sbicintr(int unit)
-{
- struct sbic_ccb *ccb;
- struct sbic_data *sbic = sbicdata[unit];
- u_char asr, host_stat, cmd_phase;
- u_char *cmd;
- int i, seg, phys;
-
-#ifdef SBICDEBUG
- printf("sbicintr");
-#endif /* SBICDEBUG */
-
- SBIC_asr(asr);
- /* drop spurious interrupts */
- if (!(asr & SBIC_ASR_INT))
- return;
- GET_SBIC_REG(SBIC_csr, host_stat);
- GET_SBIC_REG(SBIC_cmd_phase, cmd_phase);
-
- ccb = &sbic->sbic_ccb[sbic->top];
- seg = ccb->seg;
-
- switch(host_stat) {
- case SBIC_CSR_XFERRED | SBIC_MCI_DATA_OUT: /* data phase start */
- case SBIC_CSR_MIS_1 | SBIC_MCI_DATA_OUT: /* data phase continue */
- case SBIC_CSR_XFERRED | SBIC_MCI_DATA_IN:
- case SBIC_CSR_MIS_1 | SBIC_MCI_DATA_IN:
- dataphase(sbic, ccb);
- return;
- case SBIC_CSR_MIS_1 | SBIC_MCI_STATUS: /* status phase start */
- case SBIC_CSR_XFERRED | SBIC_MCI_STATUS: /* status phase start */
- SET_XFER_LEN(0);
- SET_SBIC_REG(SBIC_cmd_phase, 0x46);
- SET_SBIC_REG(SBIC_cmd, SBIC_CMD_SEL_XFER);
- return;
- case SBIC_CSR_S_XFERRED:
- phys = KVTOPHYS(ccb->sense_addr);
- if (ccb->flags & CCB_SENSE) {
- sbic_dmadone(B_READ, phys,
- ccb->sense_len, sbic->sbic_dma);
- } else {
- if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_IN)) {
- sbic_dmadone(B_READ,
- ccb->scat_gath[seg - 1].seg_addr,
- ccb->scat_gath[seg - 1].seg_len,
- sbic->sbic_dma);
- }
- if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_OUT)) {
- sbic_dmadone(B_WRITE,
- ccb->scat_gath[seg - 1].seg_addr,
- ccb->scat_gath[seg - 1].seg_len,
- sbic->sbic_dma);
- }
- }
- GET_SBIC_REG(SBIC_tlun, ccb->status);
- ccb->status &= 0x1f;
- switch(ccb->status) {
- case SCSI_CHECK:
- ccb->flags |= CCB_SENSE;
- ccb->xfer->error = XS_SENSE;
- sbic_request_sense(sbic, ccb);
- return;
- case SCSI_BUSY:
- ccb->xfer->error = XS_BUSY;
- break;
- default:
- break;
- }
- sbic_done(sbic, ccb);
- break;
-
- case SBIC_CSR_SEL_TIMEO: /* selection timeout */
- ccb->xfer->error = XS_TIMEOUT;
- sbic_done(sbic, ccb);
- break;
-
- default:
- printf("sbic%d:%d:%d -- ", unit, ccb->target, ccb->lun);
- printf("host: %x interrupt occured\n", host_stat);
- panic("Unsupported interrupts. check intr code\n");
- break;
- }
- return;
-}
-
-/*
- * A ccb is put onto the free list.
- */
-static void
-sbic_free_ccb(struct sbic_data *sbic, struct sbic_ccb *ccb, int flags)
-{
- unsigned opri = 0;
-
- if (!(flags & SCSI_NOMASK))
- opri = splbio();
- if (ccb = &sbic->sbic_ccb[sbic->top])
- sbic->top = ++sbic->top % MAXSIMUL;
- else
- sbic->bottom = (--sbic->bottom + MAXSIMUL) % MAXSIMUL;
- sbic->active--;
- sbic->free++;
- ccb->flags = CCB_FREE;
- if (sbic->free)
- wakeup((caddr_t)&sbic->free);
- if (!(flags & SCSI_NOMASK))
- splx(opri);
-}
-
-/*
- * Get a free ccb
- */
-static struct sbic_ccb *
-sbic_get_ccb(struct sbic_data *sbic, int flags)
-{
- unsigned opri = 0;
- struct sbic_ccb *rc;
-
- if (!(flags & SCSI_NOMASK))
- opri = splbio();
- /*
- * If we can and have to, sleep waiting for one to come free
- */
- while((!sbic->free) && (!(flags & SCSI_NOSLEEP)))
- tsleep((caddr_t)&sbic->free, PRIBIO, "sbicccb", 0);
- if (sbic->free) {
- rc = &sbic->sbic_ccb[sbic->bottom];
- sbic->free--;
- sbic->active++;
- sbic->bottom = ++sbic->bottom % MAXSIMUL;
- rc->flags = CCB_ACTIVE;
- } else
- rc = (struct sbic_ccb *)0;
- if (!(flags & SCSI_NOMASK))
- splx(opri);
- return(rc);
-}
-
-/*
- * We have a ccb which has been processed by the
- * adapter, now we lock to see how the operation
- * went. Wake up the owner if waiting
- */
-static void
-sbic_done(struct sbic_data *sbic, struct sbic_ccb *ccb)
-{
- struct scsi_xfer *xs = ccb->xfer;
- unsigned opri;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("sbic_done\n"));
- if (!(xs->flags & INUSE)) {
- printf("sbic%d: exiting but not in use!\n", sbic->unit);
- Debugger("sbic55");
- }
- if ((!xs->error) || (xs->flags & SCSI_ERR_OK))
- xs->resid = 0;
-
- xs->flags |= ITSDONE;
-#ifdef ALLWAYS_BOUNCE
- bcopy((char *)ccb->sense_addr, (char *)&xs->sense, ccb->sense_len);
-#else
- if(ccb->flags & CCB_BOUNCE)
- bcopy((char *)ccb->sense_addr,
- (char *)&xs->sense, ccb->sense_len);
-#endif
- sbic_free_ccb(sbic, ccb, xs->flags);
- if(sbic->active) {
- opri = splbio();
- SBIC_ENABLE_INT();
- start_scsi(sbic, &sbic->sbic_ccb[sbic->top]);
- splx(opri);
- }
- scsi_done(xs);
-}
-
-/*
- * Start the board, ready for normal operation
- */
-static int
-sbic_init(int unit)
-{
- struct sbic_data *sbic = sbicdata[unit];
- struct sbic_config conf;
- int i, asr, csr, tmp;
-
- SBIC_asr(asr); /* dummy read */
- GET_SBIC_REG(SBIC_csr, csr);
- SBIC_DISABLE_INT();
-
- SET_SBIC_REG(SBIC_myid, SBIC_ID_FS_16_20 | SBIC_ID);
- SET_SBIC_REG(SBIC_cmd, SBIC_CMD_RESET);
- for (i = SBIC_RESET_TIMEOUT; i; i--) {
- SBIC_asr(asr);
- if ((asr != 0xff) && (asr & SBIC_ASR_INT)) {
- GET_SBIC_REG(SBIC_csr, csr);
- if (csr == SBIC_CSR_RESET)
- break;
- }
- DELAY(1); /* calibrated in msec */
- }
- if (i == 0) {
-#ifdef SBICDEBUG
- if (sbic_debug)
- printf("sbic_init: No answer from sbic board\n");
-#endif
- return(ENXIO);
- }
-
- conf.chan = (inb(SBIC_STA_REG) & 0x03);
- GET_SBIC_REG(SBIC_int, tmp);
- conf.intr = (tmp >> 3) & 0x07;
- conf.scsi_dev = tmp & 0x07;
- sbic->sbic_dma = conf.chan;
- sbic->sbic_scsi_dev = conf.scsi_dev;
- switch(conf.intr) {
- case INT3:
- sbic->sbic_int = 3;
- break;
- case INT5:
- sbic->sbic_int = 5;
- break;
- case INT6:
- sbic->sbic_int = 6;
- break;
- case INT9:
- sbic->sbic_int = 9;
- break;
- case INT12:
- sbic->sbic_int = 12;
- break;
- case INT13:
- sbic->sbic_int = 13;
- break;
- default:
- printf("illegal int jumpter setting\n");
- return(EIO);
- }
-
- SET_SBIC_REG(SBIC_rselid, 0);
-#if 1
- SET_SBIC_REG(SBIC_timeo, 0x80);
-#else
- SET_SBIC_REG(SBIC_timeo, 0xa0);
-#endif
- SET_SBIC_REG(SBIC_control, SBIC_CTL_EDI);
- SET_SBIC_REG(SBIC_syn, 0);
- SBIC_ENABLE_INT();
- /*
- * ccb queue initialize
- */
- for (i = 0; i < MAXSIMUL; i++) {
- sbic->sbic_ccb[i].flags = CCB_FREE;
- }
- sbic->top = sbic->bottom = sbic->active = 0;
- sbic->free = MAXSIMUL;
- /*
- * Note that wa are going and return (to probe)
- */
- return(0);
-}
-
-static void
-sbicminphys(struct buf *bp)
-{
-/* sbic seems to explode with 17 segs (64k may require 17 segs) */
- if (bp->b_bcount > ((SBIC_NSEG - 1) *PAGESIZ))
- bp->b_bcount = ((SBIC_NSEG - 1) * PAGESIZ);
-}
-
-/*
- * start a scsi operation given the command and
- * the data address. Also needs the unit, target
- * and lu
- */
-static int32_t
-sbic_scsi_cmd(struct scsi_xfer *xs)
-{
- struct scsi_link *sc_link = xs->sc_link;
- int unit = sc_link->adapter_unit;
- struct sbic_data *sbic = sc_link->adapter_softc;
- struct sbic_ccb *ccb;
- int s, i, retval, flags;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("sbic_scsi_cmd\n"));
- flags = xs->flags;
- if (!(ccb = sbic_get_ccb(sbic, flags))) {
- xs->error = XS_DRIVER_STUFFUP;
- return(TRY_AGAIN_LATER);
- }
- ccb->xfer = xs;
- ccb->target = xs->sc_link->target;
- ccb->lun = xs->sc_link->lun;
- ccb->xs_flags = xs->flags;
- ccb->scsi_cmdlen = xs->cmdlen;
- ccb->datalen = xs->datalen;
- ccb->sense_len = sizeof(xs->sense);
-#ifdef ALLWAYS_BOUNCE
- ccb->sense_addr = (int)(sbic_bounce);
-#else
- ccb->sense_addr = (int)&xs->sense;
-#endif
- ccb->seg = 0;
-
- if (retval = xfer_addr_check(unit, ccb)) {
- xs->error = XS_DRIVER_STUFFUP;
- sbic_free_ccb(sbic, ccb, flags);
- return(retval);
- }
- if (!(flags & SCSI_RESET)) {
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmdlen);
- ccb->scsi_cmd.bytes[0] |= ((ccb->lun << 5) & 0xe0);
- }
- if (!(flags & SCSI_NOMASK)) {
- if (sbic->active == 1) {
- s = splbio();
- SBIC_ENABLE_INT();
- start_scsi(sbic, ccb);
- splx(s);
- }
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("sent\n"));
- return(SUCCESSFULLY_QUEUED);
- }
- SBIC_DISABLE_INT();
- start_scsi(sbic, ccb);
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd sent, waiting\n"));
- return(sbic_poll(sbic, ccb));
-}
-
-static int
-sbic_poll(struct sbic_data *sbic, struct sbic_ccb *ccb)
-{
- int count, asr, done = 0;
-
- count = ccb->xfer->timeout * 1000;
- while(count) {
- SBIC_asr(asr);
- if ((asr != 0xff) && (asr & SBIC_ASR_INT)) {
- sbicintr(sbic->unit);
- }
- if (ccb->xfer->flags & ITSDONE) {
- break;
- }
- DELAY(1);
- count--;
- }
- if (!count) panic("sbic scsi timeout!!");
- if (ccb->xfer->error) return(HAD_ERROR);
- return(COMPLETE);
-}
-
-static int
-xfer_addr_check(int unit, struct sbic_ccb *ccb)
-{
- struct iovec *iovp;
- struct scat_gather *sg;
- struct scsi_xfer *xs;
- int thiskv, thisphys, nextphys;
- int bytes_this_page, bytes_this_seg;
- int datalen, flags;
-
- xs = ccb->xfer;
- flags = ccb->xs_flags;
- if ((xs->datalen) && (!(flags & SCSI_RESET))) {
- sg = ccb->scat_gath;
- ccb->use_seg = 0;
- if (flags & SCSI_DATA_UIO) {
- iovp = ((struct uio *)xs->data)->uio_iov;
- datalen = ((struct uio *)xs->data)->uio_iovcnt;
- while((datalen) && (ccb->use_seg < SBIC_NSEG)) {
- sg->seg_addr = KVTOPHYS((int)iovp->iov_base);
- sg->seg_len = iovp->iov_len;
- SC_DEBUGN(xs->sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)"
- ,iovp->iov_len
- ,iovp->iov_base));
- sg++;
- iovp++;
- ccb->use_seg++;
- datalen++;
- }
- } else {
- /*
- * Set up scatter gather block
- */
- SC_DEBUG(xs->sc_link, SDEV_DB4,
- ("%d @0x%x:- ", xs->datalen, xs->data));
- datalen = xs->datalen;
- thiskv = (int)xs->data;
- thisphys = KVTOPHYS(thiskv);
- while((datalen) && (ccb->use_seg < SBIC_NSEG)) {
- bytes_this_seg = 0;
- sg->seg_addr = thisphys;
- SC_DEBUGN(xs->sc_link, SDEV_DB4,
- ("0x%x", thisphys));
- nextphys = thisphys;
- while((datalen) && (thisphys == nextphys)) {
- if (thisphys > 0xFFFFFF) {
- printf("sbic%d: DMA beyond"
- " end of PC98\n", unit);
- xs->error = XS_DRIVER_STUFFUP;
- return(HAD_ERROR);
- }
- nextphys = (thisphys & (~(PAGESIZ - 1)))
- + PAGESIZ;
- bytes_this_page = nextphys - thisphys;
- bytes_this_page = min(bytes_this_page,
- datalen);
- bytes_this_seg += bytes_this_page;
- datalen -= bytes_this_page;
- thiskv = (thiskv & (~(PAGESIZ - 1)))
- + PAGESIZ;
- if (datalen)
- thisphys = KVTOPHYS(thiskv);
- }
- SC_DEBUGN(xs->sc_link, SDEV_DB4,
- ("(0x%x)", bytes_this_seg));
- sg->seg_len = bytes_this_seg;
- sg++;
- ccb->use_seg++;
- }
- }
- SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
- if (datalen) {
- printf("sbic%d: sbic_scsi_cmd, more than %d DMA segs\n",
- unit, SBIC_NSEG);
- xs->error = XS_DRIVER_STUFFUP;
- return(HAD_ERROR);
- }
- } else {
- ccb->scat_gath[0].seg_len = 0;
- }
- return(0);
-}
-
-static void
-start_scsi(struct sbic_data *sbic, struct sbic_ccb *ccb)
-{
- if (ccb->xs_flags & SCSI_RESET) {
- SET_SBIC_REG(SBIC_cmd, SBIC_CMD_RESET);
- return;
- }
-
- if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_IN))
- sbic_dmastart(B_READ, ccb->scat_gath[0].seg_addr,
- ccb->scat_gath[0].seg_len, sbic->sbic_dma);
- if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_OUT))
- sbic_dmastart(B_WRITE, ccb->scat_gath[0].seg_addr,
- ccb->scat_gath[0].seg_len, sbic->sbic_dma);
- SET_SCSI_CMD(&ccb->scsi_cmd, ccb->scsi_cmdlen);
- SET_XFER_LEN(ccb->scat_gath[0].seg_len);
- SET_SBIC_REG(SBIC_selid, ccb->target);
- SET_SBIC_REG(SBIC_tlun, ccb->lun);
- SBIC_DMA_ENABLE();
- SET_SBIC_REG(SBIC_control, SBIC_CTL_DMA | SBIC_CTL_EDI);
- SET_SBIC_REG(SBIC_cmd, SBIC_CMD_SEL_XFER);
- ccb->seg++;
- return;
-}
-
-static void
-dataphase(struct sbic_data *sbic, struct sbic_ccb *ccb)
-{
- int seg = ccb->seg, tmp;
-
- if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_IN)) {
- sbic_dmadone(B_READ, ccb->scat_gath[seg - 1].seg_addr,
- ccb->scat_gath[seg - 1].seg_len, sbic->sbic_dma);
- sbic_dmastart(B_READ, ccb->scat_gath[seg].seg_addr,
- ccb->scat_gath[seg].seg_len, sbic->sbic_dma);
- }
- if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_OUT)) {
- sbic_dmadone(B_WRITE, ccb->scat_gath[seg - 1].seg_addr,
- ccb->scat_gath[seg - 1].seg_len, sbic->sbic_dma);
- sbic_dmastart(B_WRITE, ccb->scat_gath[seg].seg_addr,
- ccb->scat_gath[seg].seg_len, sbic->sbic_dma);
- }
- SBIC_DMA_ENABLE();
- SET_SBIC_REG(SBIC_control, SBIC_CTL_DMA | SBIC_CTL_EDI);
- SET_XFER_LEN(ccb->scat_gath[seg].seg_len);
- SET_SBIC_REG(SBIC_cmd, SBIC_CMD_XFER_INFO);
- ccb->seg++;
- return;
-}
-
-static void
-sbic_request_sense(struct sbic_data *sbic, struct sbic_ccb *ccb)
-{
- int phys, len;
- unsigned chan;
- u_char cmd[6] = { 3, 0, 0, 0, 0, 0 };
-
- cmd[1] |= ((ccb->lun << 5) & 0xe0);
-
- chan = sbic->sbic_dma;
- len = ccb->sense_len;
-#ifndef ALLWAYS_BOUNCE
- if(isa_dmarangecheck((caddr_t)ccb->sense_addr,len)) {
- ccb->sense_addr = (int)(sbic_bounce);
- ccb->flags |= CCB_BOUNCE;
- }
-#endif
- phys = KVTOPHYS(ccb->sense_addr);
- sbic_dmastart(B_READ, phys, len, chan);
-
- SET_SCSI_CMD(cmd, 6);
- SET_XFER_LEN(ccb->sense_len);
- SET_SBIC_REG(SBIC_selid, ccb->target);
- SET_SBIC_REG(SBIC_tlun, ccb->lun);
- SBIC_DMA_ENABLE();
- SET_SBIC_REG(SBIC_control, SBIC_CTL_DMA | SBIC_CTL_EDI);
- SET_SBIC_REG(SBIC_cmd, SBIC_CMD_SEL_XFER);
- return;
-}
-
-
-static void
-sbic_dmastart(int flags, int phys, unsigned nbytes, unsigned chan)
-{
- int modeport, waport, mskport;
- caddr_t newaddr;
- int s;
-
- if (chan > 3 || nbytes > (1<<16))
- panic("sbic_dmastart: impossible request");
-
- s = splbio(); /* mask on */
-
-#ifdef CYRIX_5X86
- asm("wbinvd"); /* wbinvd (WB cache flush) */
-#endif
-
- /* mask channel */
- mskport = IO_DMA + 0x14; /* 0x15 */
- outb(mskport, chan & 3 | 0x04);
-
- /* set dma channel mode, and reset address ff */
- modeport = IO_DMA + 0x16; /* 0x17 */
- if (flags & B_READ) {
- outb(modeport, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3));
- } else {
- outb(modeport, DMA37MD_SINGLE|DMA37MD_READ|(chan&3));
- }
- outb(modeport + 1*2, 0); /* 0x19 (clear byte pointer) */
-
- /* send start address */
- waport = IO_DMA + (chan<<2); /* 0x1, 0x5, 0x9, 0xd */
- outb(waport, phys);
- outb(waport, phys>>8);
- outb(dmapageport[chan], phys>>16);
-
- /* send count */
- outb(waport + 2, --nbytes); /* 0x3, 0x7, 0xb, 0xf */
- outb(waport + 2, nbytes>>8);
-
- /* unmask channel */
- mskport = IO_DMA + 0x14; /* 0x15 */
- outb(mskport, chan & 3);
-
- splx(s); /* mask off */
-}
-
-static void
-sbic_dmadone(int flags, int addr, unsigned nbytes, unsigned chan)
-{
-#if defined(CYRIX_486DLC) || defined(IBM_486SLC)
- if (flags & B_READ) {
- /* cache flush only after reading 92/12/9 by A.Kojima */
- asm(" .byte 0x0f,0x08"); /* invd (cache flush) */
- }
-#endif
-}
diff --git a/sys/pc98/pc98/sbic55.c.new b/sys/pc98/pc98/sbic55.c.new
deleted file mode 100644
index 5dc9091..0000000
--- a/sys/pc98/pc98/sbic55.c.new
+++ /dev/null
@@ -1,1745 +0,0 @@
-/* $NetBSD: sbic.c,v 1.10 1995/02/12 19:19:20 chopps Exp $ */
-
-/*
- * Copyright (c) 1994 Christian E. Hopps
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Van Jacobson of Lawrence Berkeley Laboratory.
- *
- * 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
- *
- * @(#)scsi.c 7.5 (Berkeley) 5/4/91
- */
-/*
- * Ported to PC-9801 by Yoshio Kimura, 1994
- * last update 09/25/1994
- */
-
-/*
- * AMIGA AMD 33C93 scsi adaptor driver
- */
-
-#include "sbic.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/device.h>
-#include <sys/disklabel.h>
-#include <sys/dkstat.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-
-#include <machine/clock.h>
-#include <machine/cpu.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
-#include <i386/isa/icu.h>
-#include <pc98/pc98/pc98.h>
-#include <i386/isa/isa_device.h>
-#include <i386/isa/ic/i8237.h>
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-
-#include <pc98/pc98/sbicreg.h>
-#include <pc98/pc98/sbicvar.h>
-
-extern short dmapageport[];
-
-/*
- * SCSI delays
- * In u-seconds, primarily for state changes on the SPC.
- */
-#define SBIC_CMD_WAIT 50000 /* wait per step of 'immediate' cmds */
-#define SBIC_DATA_WAIT 50000 /* wait per data in/out step */
-#define SBIC_INIT_WAIT 50000 /* wait per step (both) during init */
-#define SBIC_RESET_TIMEOUT 2000
-
-#define SBIC_WAIT(sbic, until, timeo) sbicwait(sbic, until, timeo, __LINE__)
-#define SBIC_ENABLE_INT(iobase) { \
- u_char tmp; \
- GET_SBIC_mem_bank(iobase, tmp); \
- SET_SBIC_mem_bank(iobase, tmp | 0x04);\
- }
-#define SBIC_DISABLE_INT(iobase) { \
- u_char tmp; \
- GET_SBIC_mem_bank(iobase, tmp); \
- SET_SBIC_mem_bank(iobase, tmp & 0xfb); \
- }
-
-#define INT0 0
-#define INT1 1
-#define INT2 2
-#define INT3 3
-#define INT5 5
-#define INT6 6
-
-static struct sbic_softc *sbicdata[NSBIC];
-
-#define KVTOPHYS(x) vtophys(x)
-
-static int sbicprobe __P((struct isa_device *));
-static int sbicattach __P((struct isa_device *));
-
-static u_int32_t sbic_adapter_info __P((int));
-static int sbic_find __P((struct sbic_softc *));
-static int32_t sbic_scsi_cmd __P((struct scsi_xfer *));
-static int sbicicmd __P((struct sbic_softc *,
- int, int, void *, int, void *, int,u_char));
-static int sbicgo __P((struct sbic_softc *, struct scsi_xfer *));
-static int sbicdmaok __P((struct sbic_softc *, struct scsi_xfer *));
-static int sbicgetsense __P((struct sbic_softc *, struct scsi_xfer *));
-static int sbicwait __P((struct sbic_softc *, char, int , int));
-static int sbicselectbus __P((struct sbic_softc *, u_char, u_char, u_char));
-static int sbicxfstart __P((struct sbic_softc *, int, u_char, int));
-static int sbicxfout __P((struct sbic_softc *, int, void *, int));
-static int sbicfromscsiperiod __P((struct sbic_softc *, int));
-static int sbictoscsiperiod __P((struct sbic_softc *, int));
-static void sbicminphys __P((struct buf *));
-static void sbicxfin __P((struct sbic_softc *, int, void *));
-static void sbicxfdone __P((struct sbic_softc *, int));
-static void sbicabort __P((struct sbic_softc *, char *));
-static void sbicerror __P((struct sbic_softc *, u_char));
-static void sbicreset __P((struct sbic_softc *));
-static void sbicsetdelay __P((int));
-static void sbic_scsidone __P((struct sbic_softc *, int));
-static void sbic_donextcmd __P((struct sbic_softc *));
-static void sbic_dmastart __P((struct sbic_softc *));
-static void sbic_dmastop __P((struct sbic_softc *));
-
-/*
- * Synch xfer parameters, and timing conversions
- */
-static int sbic_min_period = SBIC_SYN_MIN_PERIOD; /* in cycles = f(ICLK,FSn) */
-static int sbic_max_offset = SBIC_SYN_MAX_OFFSET; /* pure number */
-
-static int sbic_cmd_wait = SBIC_CMD_WAIT;
-static int sbic_data_wait = SBIC_DATA_WAIT;
-static int sbic_init_wait = SBIC_INIT_WAIT;
-
-/*
- * was broken before.. now if you want this you get it for all drives
- * on sbic controllers.
- */
-#ifdef SCSI_SYNC
-static int sbic_inhibit_sync = 0;
-#else
-static int sbic_inhibit_sync = 1;
-#endif
-
-static int sbic_force_async_flag = 0;
-
-#ifdef SC98BUSMASTER
-static int sc98busmaster = 0;
-#endif
-
-#ifdef DEBUG
-#define QPRINTF(a) if (sbic_debug > 1) printf a
-int sbic_debug = 0;
-int sync_debug = 0;
-int sbic_dma_debug = 0;
-#else
-#define QPRINTF(a)
-#endif
-
-static
-struct scsi_adapter sbic_switch = {
- sbic_scsi_cmd,
- sbicminphys,
- 0,
- 0,
- sbic_adapter_info,
- "sbic"
- , { 0, 0 }
-};
-
-/* the below structure is so we have a default dev struct for out link struct */
-static
-struct scsi_device sbic_dev = {
- NULL, /* Use default error handler */
- NULL, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "sbic",
- 0
- , { 0, 0 }
-};
-
-struct isa_driver sbicdriver = {
- sbicprobe,
- sbicattach,
- "sbic"
-};
-
-static int sbicunit = 0;
-
-/*
- * Check if the device can be found at the port given
- * and if so, set ip up ready for further work
- * as an argument, takes the pc98_device structure from
- * autoconf.c
- */
-static int
-sbicprobe(dev)
- struct isa_device *dev;
-{
- int unit = sbicunit;
- struct sbic_softc *sbic;
-
-#define SBICFLAGS
-# ifdef SBICFLAGS
- sbic_force_async_flag = dev->id_flags;
-# else
- sbic_force_async_flag = 0;
-# endif
- if (unit >= NSBIC) {
- printf("sbic%d: unit number too high\n", unit);
- return 0;
- }
- dev->id_unit = unit;
- /*
- * Allocate a storage area for us
- */
- if (sbicdata[unit]) {
- printf("sbic%d: memory already allocated\n", unit);
- return 0;
- }
- sbic = malloc(sizeof(struct sbic_softc), M_TEMP, M_NOWAIT);
- if (!sbic) {
- printf("sbic%d: cannot malloc!\n", unit);
- return 0;
- }
- bzero(sbic, sizeof(struct sbic_softc));
- sbicdata[unit] = sbic;
- sbic->sc_base = dev->id_iobase;
-
- if (sbic_find(sbic) != 0) {
- sbicdata[unit] = NULL;
- free(sbic, M_TEMP);
- return 0;
- }
-
- dev->id_irq = sbic->sc_int;
- dev->id_drq = sbic->sc_dma;
- sbicunit++;
- return 5;
-}
-
-
-/*
- * Attach all the sub-devices we can find
- */
-static int
-sbicattach(dev)
- struct isa_device *dev;
-{
- int unit = dev->id_unit;
- struct sbic_softc *sbic = sbicdata[unit];
- struct scsibus_data *scbus;
-#if defined(SC98BUSMASTER) || defined(FORCE_BUSMASTER)
- int a;
- int i;
-#endif
-
-#ifdef FORCE_BUSMASTER
- sbic_read_reg(sbic->sc_base, 0x37, a);
- /* set busmaster flag */
- sbic_write_reg(sbic->sc_base, 0x37, a | 0x08);
- printf("sbic%d: set busmaster flag\n", unit);
-#if defined(HA55BS_ID) && defined(SCSI_SYNC)
- sbic_read_reg(sbic->sc_base, 0x60 + HA55BS_ID, a);
- for (i = 0; i < 7; i++) {
- if (sbic_force_async_flag & 1 << i) {
- sbic_write_reg(sbic->sc_base, 0x60 + i, a);
- printf("sbic%d: set transfer rate (ID %d)\n",
- unit, i);
- }
- }
- sbic_force_async_flag = 0;
-#endif
-#endif
-
-#ifdef SC98BUSMASTER
- sbic_read_reg(sbic->sc_base, 0x37, a);
- if (a & 0x08) {
- printf("sbic%d: busmaster enable\n", unit);
- sc98busmaster = 1;
- }
-#endif
- /*
- * fill in the prototype scsi_link.
- */
- sbic->sc_link.adapter_unit = unit;
- sbic->sc_link.adapter_softc = sbic;
- sbic->sc_link.adapter_targ = sbic->sc_scsi_dev;
- sbic->sc_link.adapter = &sbic_switch;
- sbic->sc_link.device = &sbic_dev;
- sbic->sc_link.flags = SDEV_BOUNCE;
- TAILQ_INIT(&sbic->sc_xslist);
-
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = scsi_alloc_bus();
- if(!scbus)
- return 0;
- scbus->adapter_link = &sbic->sc_link;
-
- /*
- * ask the adapter what subunits are present
- */
- scsi_attachdevs(scbus);
-
- return 1;
-}
-
-/*
- * Find the board and find its irq/drq
- */
-static int
-sbic_find(sbic)
- struct sbic_softc *sbic;
-{
- int intr, my_id, asr, csr;
- volatile int i, sts;
-
- GET_SBIC_asr(sbic->sc_base, asr); /* dummy read */
- GET_SBIC_csr(sbic->sc_base, csr);
- SBIC_DISABLE_INT(sbic->sc_base);
-
- GET_SBIC_myid(sbic->sc_base, my_id);
- switch(my_id & 0xc0) {
- case SBIC_ID_FS_8_10:
- sbic->sc_clkfreq = 100;
- break;
- case SBIC_ID_FS_12_15:
- sbic->sc_clkfreq = 150;
- break;
- case SBIC_ID_FS_16_20:
- sbic->sc_clkfreq = 200;
- break;
- }
- sbic->sc_scsi_dev = my_id & SBIC_ID_MASK;
- my_id &= 0xc7;
- my_id |= SBIC_ID_EAF;
- /*
- * reset board, If it doesn't respond, assume
- * that it's not there.. good for the probe
- */
- SET_SBIC_myid(sbic->sc_base, my_id);
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_RESET);
- DELAY(10);
- SBIC_WAIT(sbic, SBIC_ASR_INT, 0);
- GET_SBIC_csr(sbic->sc_base, csr);
- if (csr != SBIC_CSR_RESET_AM)
- return(ENXIO);
-
- sbic->sc_dma = inb(sbic->sc_base + 4) & 0x03;
- outb(sbic->sc_base, SBIC_reset_int);
- intr = (inb(sbic->sc_base + 2) >> 3) & 0x07;
- switch(intr) {
- case INT0:
- sbic->sc_int = IRQ3;
- break;
- case INT1:
- sbic->sc_int = IRQ5;
- break;
- case INT2:
- sbic->sc_int = IRQ6;
- break;
- case INT3:
- sbic->sc_int = IRQ9;
- break;
- case INT5:
- sbic->sc_int = IRQ12;
- break;
- case INT6:
- sbic->sc_int = IRQ13;
- break;
- default:
- printf("illegal int jumper setting\n");
- return(EIO);
- }
- SET_SBIC_control(sbic->sc_base, SBIC_CTL_EDI | SBIC_CTL_IDI
- | SBIC_MACHINE_DMA_MODE);
- SET_SBIC_rselid(sbic->sc_base, 0);
- SET_SBIC_syn(sbic->sc_base, 0); /* asynch for now */
-
- sbic->sc_flags = SBICF_ALIVE;
- return 0;
-}
-
-/*
- * default minphys routine for sbic based controllers
- */
-static void
-sbicminphys(bp)
- struct buf *bp;
-{
- if (bp->b_bcount > ((SBIC_NSEG - 1) << PAGE_SHIFT))
- bp->b_bcount = ((SBIC_NSEG - 1) << PAGE_SHIFT);
-}
-
-/*
- * must be used
- */
-static u_int32_t
-sbic_adapter_info(unit)
- int unit;
-{
- /*
- * one request at a time please
- */
- return(1);
-}
-
-/*
- * used by specific sbic controller
- *
- * it appears that the higher level code does nothing with LUN's
- * so I will too. I could plug it in, however so could they
- * in scsi_scsi_cmd().
- */
-static int32_t
-sbic_scsi_cmd(xs)
- struct scsi_xfer *xs;
-{
- struct sbic_pending *pendp;
- struct sbic_softc *sbic;
- struct scsi_link *sc_link;
- int flags, s;
- int unit;
-
- sc_link = xs->sc_link;
- unit = sc_link->adapter_unit;
- sbic = sc_link->adapter_softc;
- flags = xs->flags;
-
- if (flags & SCSI_DATA_UIO)
- panic("sbic: scsi data uio requested");
-
- if (sbic->sc_xs && flags & SCSI_NOMASK)
- panic("sbic_scsi_cmd: busy");
-
- s = splbio();
- pendp = &sbic->sc_xsstore[sc_link->target][sc_link->lun];
- if (pendp->xs) {
- splx(s);
- return(TRY_AGAIN_LATER);
- }
-
- if (sbic->sc_xs) {
- pendp->xs = xs;
- TAILQ_INSERT_TAIL(&sbic->sc_xslist, pendp, link);
- splx(s);
- return(SUCCESSFULLY_QUEUED);
- }
- pendp->xs = NULL;
- sbic->sc_xs = xs;
- splx(s);
-
- /*
- * nothing is pending do it now.
- */
- sbic_donextcmd(sbic);
-
- if (flags & SCSI_NOMASK)
- return(COMPLETE);
- return(SUCCESSFULLY_QUEUED);
-}
-
-/*
- * entered with sbic->sc_xs pointing to the next xfer to perform
- */
-static void
-sbic_donextcmd(sbic)
- struct sbic_softc *sbic;
-{
- struct scsi_xfer *xs;
- struct scsi_link *sc_link;
- int flags, phase, stat;
-
- xs = sbic->sc_xs;
- sc_link = xs->sc_link;
- flags = xs->flags;
-
- if (flags & SCSI_DATA_IN)
- phase = DATA_IN_PHASE;
- else if (flags & SCSI_DATA_OUT)
- phase = DATA_OUT_PHASE;
- else
- phase = STATUS_PHASE;
-
- if (flags & SCSI_RESET)
- sbicreset(sbic);
-
- sbic->sc_stat[0] = -1;
- xs->cmd->bytes[0] |= sc_link->lun << 5;
- if (phase == STATUS_PHASE || flags & SCSI_NOMASK ||
- sbicdmaok(sbic, xs) == 0)
- stat = sbicicmd(sbic, sc_link->target, sc_link->lun, xs->cmd,
- xs->cmdlen, xs->data, xs->datalen, phase);
- else if (sbicgo(sbic, xs) == 0)
- return;
- else
- stat = sbic->sc_stat[0];
-
- sbic_scsidone(sbic, stat);
-}
-
-static void
-sbic_scsidone(sbic, stat)
- struct sbic_softc *sbic;
- int stat;
-{
- struct sbic_pending *pendp;
- struct scsi_xfer *xs;
- int s, donext;
-
- xs = sbic->sc_xs;
-#ifdef DIAGNOSTIC
- if (xs == NULL)
- panic("sbic_scsidone");
-#endif
- /*
- * is this right?
- */
- xs->status = stat;
-
- if (stat == 0)
- xs->resid = 0;
- else {
- switch(stat) {
- case SCSI_CHECK:
- if (stat = sbicgetsense(sbic, xs))
- goto bad_sense;
- xs->error = XS_SENSE;
- break;
- case SCSI_BUSY:
- xs->error = XS_BUSY;
- break;
- bad_sense:
- default:
- xs->error = XS_DRIVER_STUFFUP;
- QPRINTF(("sbic_scsicmd() bad %x\n", stat));
- break;
- }
- }
- xs->flags |= ITSDONE;
-
- /*
- * grab next command before scsi_done()
- * this way no single device can hog scsi resources.
- */
- s = splbio();
- pendp = sbic->sc_xslist.tqh_first;
- if (pendp == NULL) {
- donext = 0;
- sbic->sc_xs = NULL;
- } else {
- donext = 1;
- TAILQ_REMOVE(&sbic->sc_xslist, pendp, link);
- sbic->sc_xs = pendp->xs;
- pendp->xs = NULL;
- }
- splx(s);
- scsi_done(xs);
-
- if (donext)
- sbic_donextcmd(sbic);
-}
-
-static int
-sbicgetsense(sbic, xs)
- struct sbic_softc *sbic;
- struct scsi_xfer *xs;
-{
- struct scsi_sense rqs;
- struct scsi_link *sc_link;
- int stat;
-
- sc_link = xs->sc_link;
-
- rqs.op_code = REQUEST_SENSE;
- rqs.byte2 = sc_link->lun << 5;
-#ifdef not_yet
- rqs.length = xs->req_sense_length ? xs->req_sense_length :
- sizeof(xs->sense);
-#else
- rqs.length = sizeof(xs->sense);
-#endif
-
- rqs.unused[0] = rqs.unused[1] = rqs.control = 0;
-
- return(sbicicmd(sbic, sc_link->target, sc_link->lun, &rqs,
- sizeof(rqs), &xs->sense, rqs.length, DATA_IN_PHASE));
-}
-
-static int
-sbicdmaok(sbic, xs)
- struct sbic_softc *sbic;
- struct scsi_xfer *xs;
-{
- int va, phys, priorpage = 0, endva, length;
-
- va = (int)xs->data;
- length = xs->datalen;
- endva = round_page(va + length);
-
- for (; va < endva; va += PAGE_SIZE) {
- phys = trunc_page(pmap_extract(kernel_pmap, va));
- if (phys == 0)
- panic("sbicdmaok: no physical page present");
- if (phys >= (1 << 24))
- return 0;
- priorpage = phys;
- }
- return 1;
-}
-
-static int
-sbicwait(sbic, until, timeo, line)
- struct sbic_softc *sbic;
- char until;
- int timeo;
- int line;
-{
- u_char val;
- int csr;
-
- if (timeo == 0)
- timeo = 1000000; /* some large value.. */
-
- GET_SBIC_asr(sbic->sc_base,val);
- while ((val & until) == 0) {
- if (timeo-- == 0) {
- GET_SBIC_csr(sbic->sc_base, csr);
- printf("sbicwait TIMEO @%d with asr=x%x csr=x%x\n",
- line, val, csr);
- break;
- }
- DELAY(1);
- GET_SBIC_asr(sbic->sc_base,val);
- }
- return(val);
-}
-
-static void
-sbicabort(sbic, where)
- struct sbic_softc *sbic;
- char *where;
-{
- u_char csr, asr;
-
- GET_SBIC_csr(sbic->sc_base, csr);
- GET_SBIC_asr(sbic->sc_base, asr);
-
- printf ("sbic%d: abort %s: csr = 0x%02x, asr = 0x%02x\n",
- sbic->sc_link.adapter_unit, where, csr, asr);
-
- if (sbic->sc_flags & SBICF_SELECTED) {
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_ABORT);
- WAIT_CIP(sbic->sc_base);
-
- GET_SBIC_asr(sbic->sc_base, asr);
- if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) {
- /* ok, get more drastic.. */
-
- SET_SBIC_cmd (sbic->sc_base, SBIC_CMD_RESET);
- DELAY(25);
- SBIC_WAIT(sbic, SBIC_ASR_INT, 0);
- /* clears interrupt also */
- GET_SBIC_csr (sbic->sc_base, csr);
-
- sbic->sc_flags &= ~SBICF_SELECTED;
- return;
- }
-
- do {
- SBIC_WAIT (sbic, SBIC_ASR_INT, 0);
- GET_SBIC_csr (sbic->sc_base, csr);
- } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
- && (csr != SBIC_CSR_CMD_INVALID));
-
- /* lets just hope it worked.. */
- sbic->sc_flags &= ~SBICF_SELECTED;
- }
-}
-
-/*
- * XXX Set/reset long delays.
- *
- * if delay == 0, reset default delays
- * if delay < 0, set both delays to default long initialization values
- * if delay > 0, set both delays to this value
- *
- * Used when a devices is expected to respond slowly (e.g. during
- * initialization).
- */
-static void
-sbicsetdelay(del)
- int del;
-{
- static int saved_cmd_wait, saved_data_wait;
-
- if (del) {
- saved_cmd_wait = sbic_cmd_wait;
- saved_data_wait = sbic_data_wait;
- if (del > 0)
- sbic_cmd_wait = sbic_data_wait = del;
- else
- sbic_cmd_wait = sbic_data_wait = sbic_init_wait;
- } else {
- sbic_cmd_wait = saved_cmd_wait;
- sbic_data_wait = saved_data_wait;
- }
-}
-
-void
-sbicreset(sbic)
- struct sbic_softc *sbic;
-{
- u_int i, s;
- u_char my_id, csr;
-
- if (sbic->sc_flags & SBICF_ALIVE)
- sbicabort(sbic, "reset");
-
- s = splbio();
- /* preserve our ID for now */
- GET_SBIC_myid (sbic->sc_base, my_id);
- my_id &= SBIC_ID_MASK;
-
- if (sbic->sc_clkfreq < 110)
- my_id |= SBIC_ID_FS_8_10;
- else if (sbic->sc_clkfreq < 160)
- my_id |= SBIC_ID_FS_12_15;
- else if (sbic->sc_clkfreq < 210)
- my_id |= SBIC_ID_FS_16_20;
-
- my_id |= SBIC_ID_EAF /*| SBIC_ID_EHP*/ ;
-
- SET_SBIC_myid(sbic->sc_base, my_id);
-
- /*
- * Disable interrupts (in dmainit) then reset the chip
- */
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_RESET);
- DELAY(25);
- SBIC_WAIT(sbic, SBIC_ASR_INT, 0);
- GET_SBIC_csr(sbic->sc_base, csr); /* clears interrupt also */
-
- /*
- * Set up various chip parameters
- */
- SET_SBIC_control(sbic->sc_base, SBIC_CTL_EDI | SBIC_CTL_IDI
- | SBIC_MACHINE_DMA_MODE);
- /*
- * don't allow (re)selection (SBIC_RID_ES)
- * until we can handle target mode!!
- */
- SET_SBIC_rselid(sbic->sc_base, 0);
- SET_SBIC_syn(sbic->sc_base, 0); /* asynch for now */
-
- /*
- * anything else was zeroed by reset
- */
- splx(s);
-
- sbic->sc_flags |= SBICF_ALIVE;
- sbic->sc_flags &= ~SBICF_SELECTED;
-}
-
-static void
-sbicerror(sbic, csr)
- struct sbic_softc *sbic;
- u_char csr;
-{
- struct scsi_xfer *xs;
-
- xs = sbic->sc_xs;
-
-#ifdef DIAGNOSTIC
- if (xs == NULL)
- panic("sbicerror");
-#endif
- if (xs->flags & SCSI_SILENT)
- return;
-
- printf("sbic%d: ", sbic->sc_link.adapter_unit);
- printf("csr == 0x%02x\n", csr); /* XXX */
-}
-
-/*
- * select the bus, return when selected or error.
- */
-static int
-sbicselectbus(sbic, target, lun, our_addr)
- struct sbic_softc *sbic;
- u_char target, lun, our_addr;
-{
- u_char asr, csr, id;
-
- QPRINTF(("sbicselectbus %d\n", target));
-
- /*
- * if we're already selected, return (XXXX panic maybe?)
- */
- if (sbic->sc_flags & SBICF_SELECTED)
- return(1);
-
- /*
- * issue select
- */
- SBIC_TC_PUT(sbic->sc_base, 0);
- SET_SBIC_selid(sbic->sc_base, target);
- SET_SBIC_timeo(sbic->sc_base, SBIC_TIMEOUT(250,sbic->sc_clkfreq));
-
- /*
- * set sync or async
- */
- if (sbic->sc_sync[target].state == SYNC_DONE)
- SET_SBIC_syn(sbic->sc_base, SBIC_SYN (sbic->sc_sync[target].offset,
- sbic->sc_sync[target].period));
- else
- SET_SBIC_syn(sbic->sc_base, SBIC_SYN (0, sbic_min_period));
-
- SET_SBIC_cmd(sbic->sc_base, sbic_inhibit_sync ? SBIC_CMD_SEL : SBIC_CMD_SEL_ATN);
-
- /*
- * wait for select (merged from seperate function may need
- * cleanup)
- */
- WAIT_CIP(sbic->sc_base);
- do {
- SBIC_WAIT(sbic, SBIC_ASR_INT, 0);
- GET_SBIC_csr (sbic->sc_base, csr);
- QPRINTF(("%02x ", csr));
- } while (csr != (SBIC_CSR_MIS_2|MESG_OUT_PHASE)
- && csr != (SBIC_CSR_MIS_2|CMD_PHASE) && csr != SBIC_CSR_SEL_TIMEO);
-
- if (csr == (SBIC_CSR_MIS_2|CMD_PHASE))
- sbic->sc_flags |= SBICF_SELECTED; /* device ignored ATN */
- else if (csr == (SBIC_CSR_MIS_2|MESG_OUT_PHASE)) {
- /*
- * Send identify message
- * (SCSI-2 requires an identify msg (?))
- */
- GET_SBIC_selid(sbic->sc_base, id);
-
- /*
- * handle drives that don't want to be asked
- * whether to go sync at all.
- */
- if ((sbic_force_async_flag & (1 << id)) || (sbic_inhibit_sync && sbic->sc_sync[id].state == SYNC_START)) {
-#ifdef DEBUG
- if (sync_debug)
- printf("Forcing target %d asynchronous.\n", id);
-#endif
- sbic->sc_sync[id].offset = 0;
- sbic->sc_sync[id].period = sbic_min_period;
- sbic->sc_sync[id].state = SYNC_DONE;
- }
-
-
- if (sbic->sc_sync[id].state != SYNC_START)
- SEND_BYTE (sbic, MSG_IDENTIFY | lun);
- else {
- /*
- * try to initiate a sync transfer.
- * So compose the sync message we're going
- * to send to the target
- */
-
-#ifdef DEBUG
- if (sync_debug)
- printf("Sending sync request to target %d ... ",
- id);
-#endif
- /*
- * setup scsi message sync message request
- */
- sbic->sc_msg[0] = MSG_IDENTIFY | lun;
- sbic->sc_msg[1] = MSG_EXT_MESSAGE;
- sbic->sc_msg[2] = 3;
- sbic->sc_msg[3] = MSG_SYNC_REQ;
- sbic->sc_msg[4] = sbictoscsiperiod(sbic,
- sbic_min_period);
- sbic->sc_msg[5] = sbic_max_offset;
-
- if (sbicxfstart(sbic, 6, MESG_OUT_PHASE, sbic_cmd_wait))
- sbicxfout(sbic, 6, sbic->sc_msg, MESG_OUT_PHASE);
-
- sbic->sc_sync[id].state = SYNC_SENT;
-#ifdef DEBUG
- if (sync_debug)
- printf ("sent\n");
-#endif
- }
-
- SBIC_WAIT (sbic, SBIC_ASR_INT, 0);
- GET_SBIC_csr (sbic->sc_base, csr);
- QPRINTF(("[%02x]", csr));
-#ifdef DEBUG
- if (sync_debug && sbic->sc_sync[id].state == SYNC_SENT)
- printf("csr-result of last msgout: 0x%x\n", csr);
-#endif
-
- if (csr != SBIC_CSR_SEL_TIMEO)
- sbic->sc_flags |= SBICF_SELECTED;
- }
-
- QPRINTF(("\n"));
-
- return(csr == SBIC_CSR_SEL_TIMEO);
-}
-
-static int
-sbicxfstart(sbic, len, phase, wait)
- struct sbic_softc *sbic;
- int len, wait;
- u_char phase;
-{
- u_char id;
-
- if (phase == DATA_IN_PHASE || phase == MESG_IN_PHASE) {
- GET_SBIC_selid (sbic->sc_base, id);
- id |= SBIC_SID_FROM_SCSI;
- SET_SBIC_selid (sbic->sc_base, id);
- SBIC_TC_PUT (sbic->sc_base, (unsigned)len);
- } else if (phase == DATA_OUT_PHASE || phase == MESG_OUT_PHASE
- || phase == CMD_PHASE)
- SBIC_TC_PUT (sbic->sc_base, (unsigned)len);
- else
- SBIC_TC_PUT (sbic->sc_base, 0);
- QPRINTF(("sbicxfstart %d, %d, %d\n", len, phase, wait));
-
- return(1);
-}
-
-static int
-sbicxfout(sbic, len, bp, phase)
- struct sbic_softc *sbic;
- int len;
- void *bp;
- int phase;
-{
- u_char orig_csr, csr, asr, *buf;
- int wait;
-
- buf = bp;
- wait = sbic_data_wait;
-
- QPRINTF(("sbicxfout {%d} %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x\n", len, buf[0], buf[1], buf[2],
- buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]));
-
- GET_SBIC_csr (sbic->sc_base, orig_csr);
-
- /*
- * sigh.. WD-PROTO strikes again.. sending the command in one go
- * causes the chip to lock up if talking to certain (misbehaving?)
- * targets. Anyway, this procedure should work for all targets, but
- * it's slightly slower due to the overhead
- */
- WAIT_CIP (sbic->sc_base);
- SET_SBIC_cmd (sbic->sc_base, SBIC_CMD_XFER_INFO);
- for (;len > 0; len--) {
- GET_SBIC_asr (sbic->sc_base, asr);
- while ((asr & SBIC_ASR_DBR) == 0) {
- if ((asr & SBIC_ASR_INT) || --wait < 0) {
-#ifdef DEBUG
- if (sbic_debug)
- printf("sbicxfout fail: l%d i%x w%d\n",
- len, asr, wait);
-#endif
- return (len);
- }
- DELAY(1);
- GET_SBIC_asr (sbic->sc_base, asr);
- }
-
- SET_SBIC_data (sbic->sc_base, *buf);
- buf++;
- }
-
- QPRINTF(("sbicxfout done\n"));
- /*
- * this leaves with one csr to be read
- */
- return(0);
-}
-
-static void
-sbicxfin(sbic, len, bp)
- struct sbic_softc *sbic;
- int len;
- void *bp;
-{
- int wait;
- u_char *obp, *buf;
- u_char orig_csr, csr, asr;
-
- wait = sbic_data_wait;
- obp = bp;
- buf = bp;
-
- GET_SBIC_csr (sbic->sc_base, orig_csr);
-
- QPRINTF(("sbicxfin %d, csr=%02x\n", len, orig_csr));
-
- WAIT_CIP (sbic->sc_base);
- SET_SBIC_cmd (sbic->sc_base, SBIC_CMD_XFER_INFO);
- for (;len > 0; len--) {
- GET_SBIC_asr (sbic->sc_base, asr);
- while ((asr & SBIC_ASR_DBR) == 0) {
- if ((asr & SBIC_ASR_INT) || --wait < 0) {
-#ifdef DEBUG
- if (sbic_debug)
- printf("sbicxfin fail: l%d i%x w%d\n",
- len, asr, wait);
-#endif
- return;
- }
-
- DELAY(1);
- GET_SBIC_asr (sbic->sc_base, asr);
- }
-
- GET_SBIC_data (sbic->sc_base, *buf);
- buf++;
- }
-
- QPRINTF(("sbicxfin {%d} %02x %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
- obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
-
- /* this leaves with one csr to be read */
-}
-
-
-/*
- * SCSI 'immediate' command: issue a command to some SCSI device
- * and get back an 'immediate' response (i.e., do programmed xfer
- * to get the response data). 'cbuf' is a buffer containing a scsi
- * command of length clen bytes. 'buf' is a buffer of length 'len'
- * bytes for data. The transfer direction is determined by the device
- * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the
- * command must supply no data. 'xferphase' is the bus phase the
- * caller expects to happen after the command is issued. It should
- * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE.
- */
-static int
-sbicicmd(sbic, target, lun, cbuf, clen, buf, len, xferphase)
- struct sbic_softc *sbic;
- int target, lun;
- void *cbuf, *buf;
- int clen, len;
- u_char xferphase;
-{
- u_char phase, csr, asr;
- int wait;
-
- /*
- * set the sbic into non-DMA mode
- */
- SET_SBIC_control(sbic->sc_base, SBIC_CTL_EDI | SBIC_CTL_IDI);
-
-retry_selection:
- /*
- * select the SCSI bus (it's an error if bus isn't free)
- */
- if (sbicselectbus(sbic, target, lun, sbic->sc_scsi_dev))
- return(-1);
- /*
- * Wait for a phase change (or error) then let the device sequence
- * us through the various SCSI phases.
- */
- sbic->sc_stat[0] = 0xff;
- sbic->sc_msg[0] = 0xff;
- phase = CMD_PHASE;
-
-new_phase:
- wait = sbic_cmd_wait;
-
- GET_SBIC_csr (sbic->sc_base, csr);
- QPRINTF((">CSR:%02x<", csr));
-
- /*
- * requesting some new phase
- */
- if ((csr != 0xff) && (csr & 0xf0) && (csr & 0x08))
- phase = csr & PHASE;
- else if ((csr == SBIC_CSR_DISC) || (csr == SBIC_CSR_DISC_1)
- || (csr == SBIC_CSR_S_XFERRED)) {
- sbic->sc_flags &= ~SBICF_SELECTED;
- GET_SBIC_cmd_phase (sbic->sc_base, phase);
- if (phase == 0x60)
- GET_SBIC_tlun (sbic->sc_base, sbic->sc_stat[0]);
- else
- return(-1);
- goto out;
- } else {
- sbicerror(sbic, csr);
- goto abort;
- }
-
- switch (phase) {
- case CMD_PHASE:
- if (sbicxfstart (sbic, clen, phase, wait))
- if (sbicxfout (sbic, clen, cbuf, phase))
- goto abort;
- phase = xferphase;
- break;
- case DATA_IN_PHASE:
- if (len <= 0)
- goto abort;
- wait = sbic_data_wait;
- if (sbicxfstart(sbic, len, phase, wait))
- sbicxfin(sbic, len, buf);
- phase = STATUS_PHASE;
- break;
- case MESG_IN_PHASE:
- if (sbicxfstart(sbic, sizeof(sbic->sc_msg), phase, wait) == 0)
- break;
- sbic->sc_msg[0] = 0xff;
- sbicxfin(sbic, sizeof(sbic->sc_msg), sbic->sc_msg);
- /*
- * get the command completion interrupt, or we
- * can't send a new command (LCI)
- */
- SBIC_WAIT(sbic, SBIC_ASR_INT, wait);
- GET_SBIC_csr(sbic->sc_base, csr);
-#ifdef DEBUG
- if (sync_debug)
- printf("msgin done csr 0x%x\n", csr);
-#endif
- /*
- * test whether this is a reply to our sync
- * request
- */
- if (sbic->sc_msg[0] == MSG_EXT_MESSAGE && sbic->sc_msg[1] == 3
- && sbic->sc_msg[2] == MSG_SYNC_REQ) {
-
- sbic->sc_sync[target].period = sbicfromscsiperiod(sbic,
- sbic->sc_msg[3]);
- sbic->sc_sync[target].offset = sbic->sc_msg[4];
- sbic->sc_sync[target].state = SYNC_DONE;
- SET_SBIC_syn(sbic->sc_base, SBIC_SYN(sbic->sc_sync[target].offset,
- sbic->sc_sync[target].period));
- /* ACK the message */
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_CLR_ACK);
- WAIT_CIP(sbic->sc_base);
- phase = CMD_PHASE; /* or whatever */
- printf("sbic%d: target %d now synchronous,"
- " period=%dns, offset=%d.\n",
- sbic->sc_link.adapter_unit, target, sbic->sc_msg[3] * 4,
- sbic->sc_msg[4]);
- } else if (sbic->sc_msg[0] == MSG_REJECT
- && sbic->sc_sync[target].state == SYNC_SENT) {
-#ifdef DEBUG
- if (sync_debug)
- printf("target %d rejected sync, going async\n",
- target);
-#endif
- sbic->sc_sync[target].period = sbic_min_period;
- sbic->sc_sync[target].offset = 0;
- sbic->sc_sync[target].state = SYNC_DONE;
- SET_SBIC_syn(sbic->sc_base, SBIC_SYN(sbic->sc_sync[target].offset,
- sbic->sc_sync[target].period));
- /* ACK the message */
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_CLR_ACK);
- WAIT_CIP(sbic->sc_base);
- phase = CMD_PHASE; /* or whatever */
- } else if (sbic->sc_msg[0] == MSG_REJECT) {
- /*
- * we'll never REJECt a REJECT message..
- */
- /* ACK the message */
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_CLR_ACK);
- WAIT_CIP(sbic->sc_base);
- phase = CMD_PHASE; /* or whatever */
- } else if (sbic->sc_msg[0] == MSG_CMD_COMPLETE
- || sbic->sc_msg[0] == 0xff) {
- /* !! KLUDGE ALERT !! quite a few drives don't seem to
- * really like the current way of sending the
- * sync-handshake together with the ident-message, and
- * they react by sending command-complete and
- * disconnecting right after returning the valid sync
- * handshake. So, all I can do is reselect the drive,
- * and hope it won't disconnect again. I don't think
- * this is valid behavior, but I can't help fixing a
- * problem that apparently exists.
- *
- * Note: we should not get here on `normal' command
- * completion, as that condition is handled by the
- * high-level sel&xfer resume command used to walk
- * thru status/cc-phase.
- */
-
-#ifdef DEBUG
- if (sync_debug)
- printf ("GOT CMD-COMPLETE! %d acting weird.."
- " waiting for disconnect...\n", target);
-#endif
- /* ACK the message */
- SET_SBIC_cmd (sbic->sc_base, SBIC_CMD_CLR_ACK);
- WAIT_CIP(sbic->sc_base);
-
- /* wait for disconnect */
- while (csr != SBIC_CSR_DISC &&
- csr != SBIC_CSR_DISC_1) {
- DELAY(1);
- GET_SBIC_csr(sbic->sc_base, csr);
- }
-#ifdef DEBUG
- if (sync_debug)
- printf ("ok.\nRetrying selection.\n");
-#endif
- sbic->sc_flags &= ~SBICF_SELECTED;
- goto retry_selection;
- } else {
-#ifdef DEBUG
- if (sbic_debug || sync_debug)
- printf ("Rejecting message 0x%02x\n",
- sbic->sc_msg[0]);
-#endif
- /* prepare to reject the message, NACK */
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_SET_ATN);
- WAIT_CIP(sbic->sc_base);
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_CLR_ACK);
- WAIT_CIP(sbic->sc_base);
- phase = MESG_OUT_PHASE;
- }
- break;
-
- case MESG_OUT_PHASE:
-#ifdef DEBUG
- if (sync_debug)
- printf ("sending REJECT msg to last msg.\n");
-#endif
- /*
- * should only get here on reject,
- * since it's always US that
- * initiate a sync transfer
- */
- SEND_BYTE(sbic, MSG_REJECT);
- phase = STATUS_PHASE;
- break;
- case DATA_OUT_PHASE:
- if (len <= 0)
- goto abort;
- wait = sbic_data_wait;
- if (sbicxfstart(sbic, len, phase, wait))
- if (sbicxfout (sbic, len, buf, phase))
- goto abort;
- phase = STATUS_PHASE;
- break;
- case STATUS_PHASE:
- /*
- * the sbic does the status/cmd-complete reading ok,
- * so do this with its hi-level commands.
- */
- SBIC_TC_PUT(sbic->sc_base, 0);
- SET_SBIC_cmd_phase(sbic->sc_base, 0x46);
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_SEL_ATN_XFER);
- phase = BUS_FREE_PHASE;
- break;
- case BUS_FREE_PHASE:
- goto out;
- default:
- printf("sbic%d: unexpected phase %d in icmd from %d\n",
- sbic->sc_link.adapter_unit, phase, target);
- goto abort;
- }
-
- /*
- * make sure the last command was taken,
- * ie. we're not hunting after an ignored command..
- */
- GET_SBIC_asr(sbic->sc_base, asr);
- if (asr & SBIC_ASR_LCI)
- goto abort;
-
- /* tapes may take a loooong time.. */
- while (asr & SBIC_ASR_BSY) {
- DELAY(1);
- GET_SBIC_asr(sbic->sc_base, asr);
- }
-
- /*
- * wait for last command to complete
- */
- SBIC_WAIT (sbic, SBIC_ASR_INT, wait);
-
- /*
- * do it again
- */
- goto new_phase;
-abort:
- sbicabort(sbic, "icmd");
-out:
- QPRINTF(("=STS:%02x=", sbic->sc_stat[0]));
- return(sbic->sc_stat[0]);
-}
-
-/*
- * Finish SCSI xfer command: After the completion interrupt from
- * a read/write operation, sequence through the final phases in
- * programmed i/o. This routine is a lot like sbicicmd except we
- * skip (and don't allow) the select, cmd out and data in/out phases.
- */
-static void
-sbicxfdone(sbic, target)
- struct sbic_softc *sbic;
- int target;
-{
- u_char phase, csr;
- int s;
-
- QPRINTF(("{"));
- s = splbio();
-
- /*
- * have the sbic complete on its own
- */
- SBIC_TC_PUT(sbic->sc_base, 0);
- SET_SBIC_cmd_phase(sbic->sc_base, 0x46);
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_SEL_ATN_XFER);
-
- do {
- SBIC_WAIT (sbic, SBIC_ASR_INT, 0);
- GET_SBIC_csr (sbic->sc_base, csr);
- QPRINTF(("%02x:", csr));
- } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
- && (csr != SBIC_CSR_S_XFERRED));
-
- sbic->sc_flags &= ~SBICF_SELECTED;
-
- GET_SBIC_cmd_phase (sbic->sc_base, phase);
- QPRINTF(("}%02x", phase));
- if (phase == 0x60)
- GET_SBIC_tlun(sbic->sc_base, sbic->sc_stat[0]);
- else
- sbicerror(sbic, csr);
-
- QPRINTF(("=STS:%02x=\n", sbic->sc_stat[0]));
- splx(s);
-}
-
-static int
-sbicgo(sbic, xs)
- struct sbic_softc *sbic;
- struct scsi_xfer *xs;
-{
- int i, target, len, wait;
- int seg, thiskv, thisphys, nextphys, datalen;
- int bytes_this_seg, bytes_this_page;
- u_char phase, csr, asr, cmd;
- struct dma_chain *sg;
-
- target = xs->sc_link->target;
- datalen = xs->datalen;
- thiskv = (int)xs->data;
-
- /*
- * set the sbic into DMA mode
- */
- SET_SBIC_control(sbic->sc_base, SBIC_CTL_EDI | SBIC_CTL_IDI |
- SBIC_MACHINE_DMA_MODE);
-
- /*
- * select the SCSI bus (it's an error if bus isn't free)
- */
- if (sbicselectbus(sbic, target, xs->sc_link->lun,
- sbic->sc_scsi_dev)) {
- sbic_dmastop(sbic);
- SBIC_DISABLE_INT(sbic->sc_base);
- return(-1);
- }
-
- /*
- * Wait for a phase change (or error) then let the device
- * sequence us through command phase (we may have to take
- * a msg in/out before doing the command). If the disk has
- * to do a seek, it may be a long time until we get a change
- * to data phase so, in the absense of an explicit phase
- * change, we assume data phase will be coming up and tell
- * the SPC to start a transfer whenever it does. We'll get
- * a service required interrupt later if this assumption is
- * wrong. Otherwise we'll get a service required int when
- * the transfer changes to status phase.
- */
- phase = CMD_PHASE;
-
-new_phase:
- wait = sbic_cmd_wait;
- switch (phase) {
- case CMD_PHASE:
- if (sbicxfstart(sbic, xs->cmdlen, phase, wait))
- if (sbicxfout(sbic, xs->cmdlen, xs->cmd, phase))
- goto abort;
- break;
- case MESG_IN_PHASE:
- if (sbicxfstart(sbic, sizeof(sbic->sc_msg), phase, wait) == 0)
- break;
-
- sbicxfin(sbic, sizeof(sbic->sc_msg), sbic->sc_msg);
- /*
- * prepare to reject any mesgin,
- * no matter what it might be..
- */
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_SET_ATN);
- WAIT_CIP(sbic->sc_base);
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_CLR_ACK);
- phase = MESG_OUT_PHASE;
- break;
- case MESG_OUT_PHASE:
- SEND_BYTE(sbic, MSG_REJECT);
- phase = STATUS_PHASE;
- break;
- case DATA_IN_PHASE:
- case DATA_OUT_PHASE:
- goto out;
- /*
- * status phase can happen, if the issued read/write command
- * is illegal (for example, reading after EOT on tape) and the
- * device doesn't even go to data in/out phase. So handle this
- * here normally, instead of going thru abort-handling.
- */
- case STATUS_PHASE:
- sbic_dmastop(sbic);
- SBIC_DISABLE_INT(sbic->sc_base);
- sbicxfdone(sbic, target);
- sbic->sc_flags &= ~(SBICF_INDMA | SBICF_BBUF);
- sbic_scsidone(sbic, sbic->sc_stat[0]);
- return(0);
- default:
- printf("sbic%d: unexpected phase %d in go from %d\n", phase,
- sbic->sc_link.adapter_unit, target);
- goto abort;
- }
-
- /*
- * make sure the last command was taken,
- * ie. we're not hunting after an ignored command..
- */
- GET_SBIC_asr(sbic->sc_base, asr);
- if (asr & SBIC_ASR_LCI)
- goto abort;
-
- /*
- * tapes may take a loooong time..
- */
- while (asr & SBIC_ASR_BSY) {
- DELAY(1);
- GET_SBIC_asr(sbic->sc_base, asr);
- }
-
- if (wait <= 0)
- goto abort;
-
- /*
- * wait for last command to complete
- */
- SBIC_WAIT(sbic, SBIC_ASR_INT, wait);
-
- GET_SBIC_csr(sbic->sc_base, csr);
- QPRINTF((">CSR:%02x<", csr));
-
- /*
- * requesting some new phase
- */
- if ((csr != 0xff) && (csr & 0xf0) && (csr & 0x08))
- phase = csr & PHASE;
- else {
- sbicerror(sbic, csr);
- goto abort;
- }
- /*
- * start again with for new phase
- */
- goto new_phase;
-out:
- /*
- * Build the DMA chain
- */
- thisphys = KVTOPHYS(thiskv);
- seg = 0;
- sg = sbic->sc_chain;
- while((datalen) && (seg < SBIC_NSEG)) {
- bytes_this_seg = 0;
- sg->dc_addr = thisphys;
- nextphys = thisphys;
- while((datalen) && (thisphys == nextphys)) {
- nextphys = (thisphys & ~PAGE_MASK) + PAGE_SIZE;
- bytes_this_page = nextphys - thisphys;
- bytes_this_page = min(bytes_this_page, datalen);
- bytes_this_seg += bytes_this_page;
- datalen -= bytes_this_page;
- thiskv = (thiskv & ~PAGE_MASK) + PAGE_SIZE;
- if (datalen)
- thisphys = KVTOPHYS(thiskv);
- }
- sg->dc_count = bytes_this_seg;
- sg++;
- seg++;
- }
- sbic->sc_cur = sbic->sc_chain;
- sbic->sc_last = --sg;
-
-#ifdef DEBUG
- if (sbic_dma_debug) {
- for (sg = sbic->sc_chain; sg <= sbic->sc_last; sg++)
- printf("\n %d: %d@%x", sg-sbic->sc_chain,
- sg->dc_count, sg->dc_addr);
- printf("Total: %d ", xs->datalen);
- }
-#endif
-
- sbic_dmastart(sbic);
- SBIC_ENABLE_INT(sbic->sc_base);
- SBIC_TC_PUT(sbic->sc_base, (unsigned)sbic->sc_cur->dc_count);
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_XFER_INFO);
-
- return(0);
-
-abort:
- sbicabort(sbic, "go");
- sbic_dmastop(sbic);
- SBIC_DISABLE_INT(sbic->sc_base);
- return(-1);
-}
-
-
-void
-sbicintr(unit)
- int unit;
-{
- struct sbic_softc *sbic = sbicdata[unit];
- u_char asr, csr;
- int i;
-
- /*
- * pending interrupt?
- */
- GET_SBIC_asr (sbic->sc_base, asr);
- if ((asr & SBIC_ASR_INT) == 0)
- return;
- GET_SBIC_csr(sbic->sc_base, csr);
- QPRINTF(("[0x%x]", csr));
-
- if (csr == (SBIC_CSR_XFERRED|STATUS_PHASE)
- || csr == (SBIC_CSR_MIS|STATUS_PHASE)
- || csr == (SBIC_CSR_MIS_1|STATUS_PHASE)
- || csr == (SBIC_CSR_MIS_2|STATUS_PHASE)) {
- /*
- * this should be the normal i/o completion case.
- * get the status & cmd complete msg then let the
- * device driver look at what happened.
- */
- sbic_dmastop(sbic);
- SBIC_DISABLE_INT(sbic->sc_base);
- sbicxfdone(sbic, sbic->sc_xs->sc_link->target);
- /*
- * check for overlapping cache line, flush if so
- */
- sbic->sc_flags &= ~(SBICF_INDMA | SBICF_BBUF | SBICF_DCFLUSH);
- sbic_scsidone(sbic, sbic->sc_stat[0]);
- } else if (csr == (SBIC_CSR_XFERRED|DATA_OUT_PHASE)
- || csr == (SBIC_CSR_XFERRED|DATA_IN_PHASE)
- || csr == (SBIC_CSR_MIS|DATA_OUT_PHASE)
- || csr == (SBIC_CSR_MIS|DATA_IN_PHASE)
- || csr == (SBIC_CSR_MIS_1|DATA_OUT_PHASE)
- || csr == (SBIC_CSR_MIS_1|DATA_IN_PHASE)
- || csr == (SBIC_CSR_MIS_2|DATA_OUT_PHASE)
- || csr == (SBIC_CSR_MIS_2|DATA_IN_PHASE)) {
- /*
- * do scatter-gather dma
- * hacking the controller chip, ouch..
- */
- /*
- * set next dma addr and dec count
- */
- sbic_dmastop(sbic);
- ++sbic->sc_cur; /* advance to next segment */
- sbic_dmastart(sbic);
- SBIC_TC_PUT(sbic->sc_base, (unsigned)sbic->sc_cur->dc_count);
- SET_SBIC_cmd(sbic->sc_base, SBIC_CMD_XFER_INFO);
- } else {
- /*
- * Something unexpected happened -- deal with it.
- */
- sbic_dmastop(sbic);
- sbicerror(sbic, csr);
- sbicabort(sbic, "intr");
- if (sbic->sc_flags & SBICF_INDMA) {
- /*
- * check for overlapping cache line, flush if so
- */
- sbic->sc_flags &=
- ~(SBICF_INDMA | SBICF_BBUF | SBICF_DCFLUSH);
- SBIC_DISABLE_INT(sbic->sc_base);
- sbic_scsidone(sbic, -1);
- }
- }
- return;
-}
-
-static int
-sbictoscsiperiod(sbic, a)
- struct sbic_softc *sbic;
- int a;
-{
- unsigned int fs;
-
- /*
- * cycle = DIV / (2*CLK)
- * DIV = FS+2
- * best we can do is 200ns at 20Mhz, 2 cycles
- */
-
- GET_SBIC_myid(sbic->sc_base,fs);
- fs = (fs >>6) + 2; /* DIV */
- fs = (fs * 10000) / (sbic->sc_clkfreq<<1); /* Cycle, in ns */
- if (a < 2) a = 8; /* map to Cycles */
- return ((fs*a)>>2); /* in 4 ns units */
-}
-
-static int
-sbicfromscsiperiod(sbic, p)
- struct sbic_softc *sbic;
- int p;
-{
- register unsigned int fs, ret;
-
- /* Just the inverse of the above */
-
- GET_SBIC_myid(sbic->sc_base,fs);
- fs = (fs >>6) + 2; /* DIV */
- fs = (fs * 10000) / (sbic->sc_clkfreq<<1); /* Cycle, in ns */
-
- ret = p << 2; /* in ns units */
- ret = ret / fs; /* in Cycles */
- if (ret < sbic_min_period)
- return(sbic_min_period);
-
- /* verify rounding */
- if (sbictoscsiperiod(sbic, ret) < p)
- ret++;
- return (ret >= 8) ? 0 : ret;
-}
-
-#define DMA_SMSK (IO_DMA + 0x14)
-#define DMA_MODE (IO_DMA + 0x16)
-#define DMA_FFC (IO_DMA + 0x18)
-
-#define DMA37SM_CLEAR 0x00
-#define DMA37SM_SET 0x04
-
-#define DMA_CHN(c) (IO_DMA + ((c) << 2))
-
-static void
-sbic_dmastart(sbic)
- struct sbic_softc *sbic;
-{
- int waport;
-
-#ifdef CYRIX_5X86
- /* Cyrix 5x86 */
- asm("wbinvd"); /* wbinvd (WB cache flush) */
-#endif
-
-#ifdef SC98BUSMASTER
- if (sc98busmaster) {
- sbic_write_reg(sbic->sc_base, 0x73, 0x32);
- sbic_write_reg(sbic->sc_base, 0x74, 0x23);
- }
-#endif
-
- /* mask channel */
- outb(DMA_SMSK, sbic->sc_dma | DMA37SM_SET);
-
- /* set dma channel mode, and reset address ff */
- if (sbic->sc_xs->flags & SCSI_DATA_IN)
- outb(DMA_MODE, sbic->sc_dma | DMA37MD_SINGLE | DMA37MD_WRITE);
- else
- outb(DMA_MODE, sbic->sc_dma | DMA37MD_SINGLE | DMA37MD_READ);
- outb(DMA_FFC, 0);
-
- /* send start address */
- waport = DMA_CHN(sbic->sc_dma);
- outb(waport, sbic->sc_cur->dc_addr);
- outb(waport, sbic->sc_cur->dc_addr>>8);
- outb(dmapageport[sbic->sc_dma], sbic->sc_cur->dc_addr>>16);
-
- /* send count */
- outb(waport + 2, sbic->sc_cur->dc_count - 1);
- outb(waport + 2, (sbic->sc_cur->dc_count-1)>>8);
-
- /* unmask channel */
- outb(DMA_SMSK, sbic->sc_dma | DMA37SM_CLEAR);
-
- /* SCSI DMA enable */
- outb(sbic->sc_base + 4, 1);
-}
-
-static void
-sbic_dmastop(sbic)
- struct sbic_softc *sbic;
-{
-#if defined(CYRIX_486DLC) || defined(IBM_486SLC)
- if (sbic->sc_xs->flags & SCSI_DATA_IN) {
- /* cache flush only after reading 92/12/9 by A.Kojima */
- asm(" .byte 0x0f,0x08"); /* invd (cache flush) */
- }
-#endif
- /* mask channel */
- outb(DMA_SMSK, DMA37SM_SET | sbic->sc_dma);
-
- /* SCSI DMA disable */
- outb(sbic->sc_base + 4, 2);
-
-#ifdef SC98BUSMASTER
- if (sc98busmaster) {
- sbic_write_reg(sbic->sc_base, 0x73, 0x43);
- sbic_write_reg(sbic->sc_base, 0x74, 0x34);
- }
-#endif
-}
diff --git a/sys/pc98/pc98/sbicreg.h b/sys/pc98/pc98/sbicreg.h
deleted file mode 100644
index e71a535..0000000
--- a/sys/pc98/pc98/sbicreg.h
+++ /dev/null
@@ -1,429 +0,0 @@
-/* $NetBSD: sbicreg.h,v 1.2 1994/10/26 02:04:40 cgd Exp $ */
-
-/*
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Van Jacobson of Lawrence Berkeley Laboratory.
- *
- * 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
- *
- * @(#)scsireg.h 7.3 (Berkeley) 2/5/91
- */
-/*
- * Ported to PC-9801 by Yoshio Kimura, 1994
- * last update 09/24/1994
- */
-
-/*
- * AMD AM33C93A SCSI interface hardware description.
- *
- * Using parts of the Mach scsi driver for the 33C93
- */
-
-#define SBIC_myid 0
-#define SBIC_cdbsize 0
-#define SBIC_control 1
-#define SBIC_timeo 2
-#define SBIC_cdb1 3
-#define SBIC_tsecs 3
-#define SBIC_cdb2 4
-#define SBIC_theads 4
-#define SBIC_cdb3 5
-#define SBIC_tcyl_hi 5
-#define SBIC_cdb4 6
-#define SBIC_tcyl_lo 6
-#define SBIC_cdb5 7
-#define SBIC_addr_hi 7
-#define SBIC_cdb6 8
-#define SBIC_addr_2 8
-#define SBIC_cdb7 9
-#define SBIC_addr_3 9
-#define SBIC_cdb8 10
-#define SBIC_addr_lo 10
-#define SBIC_cdb9 11
-#define SBIC_secno 11
-#define SBIC_cdb10 12
-#define SBIC_headno 12
-#define SBIC_cdb11 13
-#define SBIC_cylno_hi 13
-#define SBIC_cdb12 14
-#define SBIC_cylno_lo 14
-#define SBIC_tlun 15
-#define SBIC_cmd_phase 16
-#define SBIC_syn 17
-#define SBIC_count_hi 18
-#define SBIC_count_med 19
-#define SBIC_count_lo 20
-#define SBIC_selid 21
-#define SBIC_rselid 22
-#define SBIC_csr 23
-#define SBIC_cmd 24
-#define SBIC_data 25
-#define SBIC_mem_bank 48
-#define SBIC_mem_win 49
-#define SBIC_reserved1 50
-#define SBIC_reset_int 51
-#define SBIC_reserved2 52
-#define SBIC_reserved3 53
-/* sbic_asr is addressed directly */
-
-/*
- * Register defines
- */
-
-/*
- * Auxiliary Status Register
- */
-
-#define SBIC_ASR_INT 0x80 /* Interrupt pending */
-#define SBIC_ASR_LCI 0x40 /* Last command ignored */
-#define SBIC_ASR_BSY 0x20 /* Busy, only cmd/data/asr readable */
-#define SBIC_ASR_CIP 0x10 /* Busy, cmd unavail also */
-#define SBIC_ASR_xxx 0x0c
-#define SBIC_ASR_PE 0x02 /* Parity error (even) */
-#define SBIC_ASR_DBR 0x01 /* Data Buffer Ready */
-
-/*
- * My ID register, and/or CDB Size
- */
-
-#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */
- /* 11 Mhz is invalid */
-#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */
-#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */
-#define SBIC_ID_EHP 0x10 /* Enable host parity */
-#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */
-#define SBIC_ID_MASK 0x07
-#define SBIC_ID_CBDSIZE_MASK 0x0f /* if unk SCSI cmd group */
-
-/*
- * Control register
- */
-
-#define SBIC_CTL_DMA 0x80 /* Single byte dma */
-#define SBIC_CTL_DBA_DMA 0x40 /* direct buffer acces (bus master)*/
-#define SBIC_CTL_BURST_DMA 0x20 /* continuous mode (8237) */
-#define SBIC_CTL_NO_DMA 0x00 /* Programmed I/O */
-#define SBIC_CTL_HHP 0x10 /* Halt on host parity error */
-#define SBIC_CTL_EDI 0x08 /* Ending disconnect interrupt */
-#define SBIC_CTL_IDI 0x04 /* Intermediate disconnect interrupt*/
-#define SBIC_CTL_HA 0x02 /* Halt on ATN */
-#define SBIC_CTL_HSP 0x01 /* Halt on SCSI parity error */
-
-/*
- * Timeout period register
- * [val in msecs, input clk in 0.1 Mhz]
- */
-
-#define SBIC_TIMEOUT(val,clk) ((((val) * (clk)) / 800) + 1)
-
-/*
- * CDBn registers, note that
- * cdb11 is used for status byte in target mode (send-status-and-cc)
- * cdb12 sez if linked command complete, and w/flag if so
- */
-
-/*
- * Target LUN register
- * [holds target status when select-and-xfer]
- */
-
-#define SBIC_TLUN_VALID 0x80 /* did we receive an Identify msg */
-#define SBIC_TLUN_DOK 0x40 /* Disconnect OK */
-#define SBIC_TLUN_xxx 0x38
-#define SBIC_TLUN_MASK 0x07
-
-/*
- * Command Phase register
- */
-
-#define SBIC_CPH_MASK 0x7f /* values/restarts are cmd specific */
-#define SBIC_CPH(p) ((p) & SBIC_CPH_MASK)
-
-/*
- * FIFO register
- */
-
-#define SBIC_FIFO_DEEP 12
-
-/*
- * maximum possible size in TC registers. Since this is 24 bit, it's easy
- */
-#define SBIC_TC_MAX ((1 << 24) - 1)
-
-/*
- * Synchronous xfer register
- */
-
-#define SBIC_SYN_OFF_MASK 0x0f
-#define SBIC_SYN_MAX_OFFSET SBIC_FIFO_DEEP
-#define SBIC_SYN_PER_MASK 0x70
-#define SBIC_SYN_MIN_PERIOD 2 /* upto 8, encoded as 0 */
-
-#define SBIC_SYN(o,p) \
- (((o) & SBIC_SYN_OFF_MASK) | (((p) << 4) & SBIC_SYN_PER_MASK))
-
-/*
- * Transfer count register
- * optimal access macros depend on addressing
- */
-
-/*
- * Destination ID (selid) register
- */
-
-#define SBIC_SID_SCC 0x80 /* Select command chaining (tgt) */
-#define SBIC_SID_DPD 0x40 /* Data phase direction (inittor) */
-#define SBIC_SID_FROM_SCSI 0x40
-#define SBIC_SID_TO_SCSI 0x00
-#define SBIC_SID_xxx 0x38
-#define SBIC_SID_IDMASK 0x07
-
-/*
- * Source ID (rselid) register
- */
-
-#define SBIC_RID_ER 0x80 /* Enable reselection */
-#define SBIC_RID_ES 0x40 /* Enable selection */
-#define SBIC_RID_DSP 0x20 /* Disable select parity */
-#define SBIC_RID_SIV 0x08 /* Source ID valid */
-#define SBIC_RID_MASK 0x07
-
-/*
- * Status register
- */
-
-#define SBIC_CSR_CAUSE 0xf0
-#define SBIC_CSR_RESET 0x00 /* chip was reset */
-#define SBIC_CSR_CMD_DONE 0x10 /* cmd completed */
-#define SBIC_CSR_CMD_STOPPED 0x20 /* interrupted or abrted*/
-#define SBIC_CSR_CMD_ERR 0x40 /* end with error */
-#define SBIC_CSR_BUS_SERVICE 0x80 /* REQ pending on the bus */
-
-
-#define SBIC_CSR_QUALIFIER 0x0f
-/* Reset State Interrupts */
-#define SBIC_CSR_RESET 0x00 /* reset w/advanced features*/
-#define SBIC_CSR_RESET_AM 0x01 /* reset w/advanced features*/
-/* Successful Completion Interrupts */
-#define SBIC_CSR_TARGET 0x10 /* reselect complete */
-#define SBIC_CSR_INITIATOR 0x11 /* select complete */
-#define SBIC_CSR_WO_ATN 0x13 /* tgt mode completion */
-#define SBIC_CSR_W_ATN 0x14 /* ditto */
-#define SBIC_CSR_XLATED 0x15 /* translate address cmd */
-#define SBIC_CSR_S_XFERRED 0x16 /* initiator mode completion*/
-#define SBIC_CSR_XFERRED 0x18 /* phase in low bits */
-/* Paused or Aborted Interrupts */
-#define SBIC_CSR_MSGIN_W_ACK 0x20 /* (I) msgin, ACK asserted*/
-#define SBIC_CSR_SDP 0x21 /* (I) SDP msg received */
-#define SBIC_CSR_SEL_ABRT 0x22 /* sel/resel aborted */
-#define SBIC_CSR_XFR_PAUSED 0x23 /* (T) no ATN */
-#define SBIC_CSR_XFR_PAUSED_ATN 0x24 /* (T) ATN is asserted */
-#define SBIC_CSR_RSLT_AM 0x27 /* (I) lost selection (AM) */
-#define SBIC_CSR_MIS 0x28 /* (I) xfer aborted, ph mis */
-/* Terminated Interrupts */
-#define SBIC_CSR_CMD_INVALID 0x40
-#define SBIC_CSR_DISC 0x41 /* (I) tgt disconnected */
-#define SBIC_CSR_SEL_TIMEO 0x42
-#define SBIC_CSR_PE 0x43 /* parity error */
-#define SBIC_CSR_PE_ATN 0x44 /* ditto, ATN is asserted */
-#define SBIC_CSR_XLATE_TOOBIG 0x45
-#define SBIC_CSR_RSLT_NOAM 0x46 /* (I) lost sel, no AM mode */
-#define SBIC_CSR_BAD_STATUS 0x47 /* status byte was nok */
-#define SBIC_CSR_MIS_1 0x48 /* ph mis, see low bits */
-/* Service Required Interrupts */
-#define SBIC_CSR_RSLT_NI 0x80 /* reselected, no ify msg */
-#define SBIC_CSR_RSLT_IFY 0x81 /* ditto, AM mode, got ify */
-#define SBIC_CSR_SLT 0x82 /* selected, no ATN */
-#define SBIC_CSR_SLT_ATN 0x83 /* selected with ATN */
-#define SBIC_CSR_ATN 0x84 /* (T) ATN asserted */
-#define SBIC_CSR_DISC_1 0x85 /* (I) bus is free */
-#define SBIC_CSR_UNK_GROUP 0x87 /* strange CDB1 */
-#define SBIC_CSR_MIS_2 0x88 /* (I) ph mis, see low bits */
-
-#define SBIC_PHASE(csr) SCSI_PHASE(csr)
-
-/*
- * Command register (command codes)
- */
-
-#define SBIC_CMD_SBT 0x80 /* Single byte xfer qualifier */
-#define SBIC_CMD_MASK 0x7f
-
- /* Miscellaneous */
-#define SBIC_CMD_RESET 0x00 /* (DTI) lev I */
-#define SBIC_CMD_ABORT 0x01 /* (DTI) lev I */
-#define SBIC_CMD_DISC 0x04 /* ( TI) lev I */
-#define SBIC_CMD_SSCC 0x0d /* ( TI) lev I */
-#define SBIC_CMD_SET_IDI 0x0f /* (DTI) lev I */
-#define SBIC_CMD_XLATE 0x18 /* (DT ) lev II */
-
- /* Initiator state */
-#define SBIC_CMD_SET_ATN 0x02 /* ( I) lev I */
-#define SBIC_CMD_CLR_ACK 0x03 /* ( I) lev I */
-#define SBIC_CMD_XFER_PAD 0x19 /* ( I) lev II */
-#define SBIC_CMD_XFER_INFO 0x20 /* ( I) lev II */
-
- /* Target state */
-#define SBIC_CMD_SND_DISC 0x0e /* ( T ) lev II */
-#define SBIC_CMD_RCV_CMD 0x10 /* ( T ) lev II */
-#define SBIC_CMD_RCV_DATA 0x11 /* ( T ) lev II */
-#define SBIC_CMD_RCV_MSG_OUT 0x12 /* ( T ) lev II */
-#define SBIC_CMD_RCV 0x13 /* ( T ) lev II */
-#define SBIC_CMD_SND_STATUS 0x14 /* ( T ) lev II */
-#define SBIC_CMD_SND_DATA 0x15 /* ( T ) lev II */
-#define SBIC_CMD_SND_MSG_IN 0x16 /* ( T ) lev II */
-#define SBIC_CMD_SND 0x17 /* ( T ) lev II */
-
- /* Disconnected state */
-#define SBIC_CMD_RESELECT 0x05 /* (D ) lev II */
-#define SBIC_CMD_SEL_ATN 0x06 /* (D ) lev II */
-#define SBIC_CMD_SEL 0x07 /* (D ) lev II */
-#define SBIC_CMD_SEL_ATN_XFER 0x08 /* (D I) lev II */
-#define SBIC_CMD_SEL_XFER 0x09 /* (D I) lev II */
-#define SBIC_CMD_RESELECT_RECV 0x0a /* (DT ) lev II */
-#define SBIC_CMD_RESELECT_SEND 0x0b /* (DT ) lev II */
-#define SBIC_CMD_WAIT_SEL_RECV 0x0c /* (DT ) lev II */
-
-/* approximate, but we won't do SBT on selects */
-#define sbic_isa_select(cmd) (((cmd) > 0x5) && ((cmd) < 0xa))
-
-#define SBIC_MACHINE_DMA_MODE SBIC_CTL_DMA
-
-#define sbic_read_reg(iobase,regno,val) do { \
- outb(iobase, (regno)); \
- (val) = inb((iobase) + 2); \
- } while (0)
-
-#define sbic_write_reg(iobase,regno,val) do { \
- outb(iobase, (regno)); \
- outb((iobase) + 2, (val)); \
- } while (0)
-
-#define SET_SBIC_myid(iobase,val) sbic_write_reg(iobase,SBIC_myid,val)
-#define GET_SBIC_myid(iobase,val) sbic_read_reg(iobase,SBIC_myid,val)
-#define SET_SBIC_cdbsize(iobase,val) sbic_write_reg(iobase,SBIC_cdbsize,val)
-#define GET_SBIC_cdbsize(iobase,val) sbic_read_reg(iobase,SBIC_cdbsize,val)
-#define SET_SBIC_control(iobase,val) sbic_write_reg(iobase,SBIC_control,val)
-#define GET_SBIC_control(iobase,val) sbic_read_reg(iobase,SBIC_control,val)
-#define SET_SBIC_timeo(iobase,val) sbic_write_reg(iobase,SBIC_timeo,val)
-#define GET_SBIC_timeo(iobase,val) sbic_read_reg(iobase,SBIC_timeo,val)
-#define SET_SBIC_cdb1(iobase,val) sbic_write_reg(iobase,SBIC_cdb1,val)
-#define GET_SBIC_cdb1(iobase,val) sbic_read_reg(iobase,SBIC_cdb1,val)
-#define SET_SBIC_cdb2(iobase,val) sbic_write_reg(iobase,SBIC_cdb2,val)
-#define GET_SBIC_cdb2(iobase,val) sbic_read_reg(iobase,SBIC_cdb2,val)
-#define SET_SBIC_cdb3(iobase,val) sbic_write_reg(iobase,SBIC_cdb3,val)
-#define GET_SBIC_cdb3(iobase,val) sbic_read_reg(iobase,SBIC_cdb3,val)
-#define SET_SBIC_cdb4(iobase,val) sbic_write_reg(iobase,SBIC_cdb4,val)
-#define GET_SBIC_cdb4(iobase,val) sbic_read_reg(iobase,SBIC_cdb4,val)
-#define SET_SBIC_cdb5(iobase,val) sbic_write_reg(iobase,SBIC_cdb5,val)
-#define GET_SBIC_cdb5(iobase,val) sbic_read_reg(iobase,SBIC_cdb5,val)
-#define SET_SBIC_cdb6(iobase,val) sbic_write_reg(iobase,SBIC_cdb6,val)
-#define GET_SBIC_cdb6(iobase,val) sbic_read_reg(iobase,SBIC_cdb6,val)
-#define SET_SBIC_cdb7(iobase,val) sbic_write_reg(iobase,SBIC_cdb7,val)
-#define GET_SBIC_cdb7(iobase,val) sbic_read_reg(iobase,SBIC_cdb7,val)
-#define SET_SBIC_cdb8(iobase,val) sbic_write_reg(iobase,SBIC_cdb8,val)
-#define GET_SBIC_cdb8(iobase,val) sbic_read_reg(iobase,SBIC_cdb8,val)
-#define SET_SBIC_cdb9(iobase,val) sbic_write_reg(iobase,SBIC_cdb9,val)
-#define GET_SBIC_cdb9(iobase,val) sbic_read_reg(iobase,SBIC_cdb9,val)
-#define SET_SBIC_cdb10(iobase,val) sbic_write_reg(iobase,SBIC_cdb10,val)
-#define GET_SBIC_cdb10(iobase,val) sbic_read_reg(iobase,SBIC_cdb10,val)
-#define SET_SBIC_cdb11(iobase,val) sbic_write_reg(iobase,SBIC_cdb11,val)
-#define GET_SBIC_cdb11(iobase,val) sbic_read_reg(iobase,SBIC_cdb11,val)
-#define SET_SBIC_cdb12(iobase,val) sbic_write_reg(iobase,SBIC_cdb12,val)
-#define GET_SBIC_cdb12(iobase,val) sbic_read_reg(iobase,SBIC_cdb12,val)
-#define SET_SBIC_tlun(iobase,val) sbic_write_reg(iobase,SBIC_tlun,val)
-#define GET_SBIC_tlun(iobase,val) sbic_read_reg(iobase,SBIC_tlun,val)
-#define SET_SBIC_cmd_phase(iobase,val) sbic_write_reg(iobase,SBIC_cmd_phase,val)
-#define GET_SBIC_cmd_phase(iobase,val) sbic_read_reg(iobase,SBIC_cmd_phase,val)
-#define SET_SBIC_syn(iobase,val) sbic_write_reg(iobase,SBIC_syn,val)
-#define GET_SBIC_syn(iobase,val) sbic_read_reg(iobase,SBIC_syn,val)
-#define SET_SBIC_count_hi(iobase,val) sbic_write_reg(iobase,SBIC_count_hi,val)
-#define GET_SBIC_count_hi(iobase,val) sbic_read_reg(iobase,SBIC_count_hi,val)
-#define SET_SBIC_count_med(iobase,val) sbic_write_reg(iobase,SBIC_count_med,val)
-#define GET_SBIC_count_med(iobase,val) sbic_read_reg(iobase,SBIC_count_med,val)
-#define SET_SBIC_count_lo(iobase,val) sbic_write_reg(iobase,SBIC_count_lo,val)
-#define GET_SBIC_count_lo(iobase,val) sbic_read_reg(iobase,SBIC_count_lo,val)
-#define SET_SBIC_selid(iobase,val) sbic_write_reg(iobase,SBIC_selid,val)
-#define GET_SBIC_selid(iobase,val) sbic_read_reg(iobase,SBIC_selid,val)
-#define SET_SBIC_rselid(iobase,val) sbic_write_reg(iobase,SBIC_rselid,val)
-#define GET_SBIC_rselid(iobase,val) sbic_read_reg(iobase,SBIC_rselid,val)
-#define SET_SBIC_csr(iobase,val) sbic_write_reg(iobase,SBIC_csr,val)
-#define GET_SBIC_csr(iobase,val) sbic_read_reg(iobase,SBIC_csr,val)
-#define SET_SBIC_cmd(iobase,val) sbic_write_reg(iobase,SBIC_cmd,val)
-#define GET_SBIC_cmd(iobase,val) sbic_read_reg(iobase,SBIC_cmd,val)
-#define SET_SBIC_data(iobase,val) sbic_write_reg(iobase,SBIC_data,val)
-#define GET_SBIC_data(iobase,val) sbic_read_reg(iobase,SBIC_data,val)
-#define SET_SBIC_mem_bank(iobase,val) sbic_write_reg(iobase,SBIC_mem_bank,val)
-#define GET_SBIC_mem_bank(iobase,val) sbic_read_reg(iobase,SBIC_mem_bank,val)
-#define GET_SBIC_mem_win(iobase,val) sbic_read_reg(iobase,SBIC_mem_win,val)
-#define GET_SBIC_reset_int(iobase,val) sbic_read_reg(iobase,SBIC_reset_int,val)
-
-#define SBIC_TC_PUT(iobase,val) do { \
- sbic_write_reg(iobase,SBIC_count_hi,((val)>>16)); \
- outb((iobase) + 2, ((val)>>8)); \
- outb((iobase) + 2, (val)); \
-} while (0)
-#define SBIC_TC_GET(iobase,val) do { \
- sbic_read_reg(iobase,SBIC_count_hi,(val)); \
- (val) = ((val)<<8) | inb((iobase) + 2); \
- (val) = ((val)<<8) | inb((iobase) + 2); \
-} while (0)
-
-#define SBIC_LOAD_COMMAND(iobase,cmd,cmdsize) do { \
- int n=(cmdsize)-1; \
- char *ptr = (char*)(cmd); \
- sbic_write_reg(iobase,SBIC_cdb1,*ptr++); \
- while (n-- > 0) outb((iobase) + 2, *ptr++); \
-} while (0)
-
-#define GET_SBIC_asr(iobase,val) (val) = inb(iobase)
-
-#define WAIT_CIP(iobase) do { \
- while (inb(iobase) & SBIC_ASR_CIP) \
- ; \
-} while (0)
-
-/* transmit a byte in programmed I/O mode */
-#define SEND_BYTE(iobase,ch) do { \
- WAIT_CIP((iobase)->sc_base); \
- SET_SBIC_cmd((iobase)->sc_base, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
- SBIC_WAIT(iobase, SBIC_ASR_DBR, 0); \
- SET_SBIC_data((iobase)->sc_base, ch); \
- } while (0)
-
-/* receive a byte in programmed I/O mode */
-#define RECV_BYTE(iobase,ch) do { \
- WAIT_CIP((iobase)->sc_base); \
- SET_SBIC_cmd((iobase)->sc_base, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
- SBIC_WAIT(iobase, SBIC_ASR_DBR, 0); \
- GET_SBIC_data((iobase)->sc_base, ch); \
- } while (0)
diff --git a/sys/pc98/pc98/sbicvar.h b/sys/pc98/pc98/sbicvar.h
deleted file mode 100644
index d4de02c..0000000
--- a/sys/pc98/pc98/sbicvar.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* $NetBSD: sbicvar.h,v 1.5 1995/02/12 19:19:21 chopps Exp $ */
-
-/*
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Van Jacobson of Lawrence Berkeley Laboratory.
- *
- * 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
- *
- * @(#)scsivar.h 7.1 (Berkeley) 5/8/90
- */
-/*
- * Ported to PC-9801 by Yoshio Kimura, 1994
- * last update 09/23/1994
- */
-#ifndef _SBICVAR_H_
-#define _SBICVAR_H_
-
-/*
- * The largest single request will be MAXPHYS bytes which will require
- * at most MAXPHYS/PAGE_SIZE+1 chain elements to describe, i.e. if none of
- * the buffer pages are physically contiguous (MAXPHYS/PAGE_SIZE) and the
- * buffer is not page aligned (+1).
- */
-#define SBIC_NSEG 17
-
-struct dma_chain {
- int dc_count;
- int dc_addr;
-};
-
-struct sbic_pending {
- TAILQ_ENTRY(sbic_pending) link;
- struct scsi_xfer *xs;
-};
-
-struct sbic_softc {
-#ifndef __FreeBSD__
- struct device sc_dev;
- struct pc98dev sc_id;
- struct intrhand sc_ih;
-#endif
-
-#ifdef __FreeBSD__
- int unit; /* unit number */
-#endif
- u_short sc_base;
- u_short sc_int;
- u_short sc_dma;
- int sc_scsi_dev;
- u_long sc_clkfreq;
-
- struct target_sync {
- u_char state;
- u_char period;
- u_char offset;
- } sc_sync[8];
- struct scsi_link sc_link; /* proto for sub devices */
- TAILQ_HEAD(,sbic_pending) sc_xslist; /* LIFO */
- struct sbic_pending sc_xsstore[8][8]; /* one for every unit */
- struct scsi_xfer *sc_xs; /* transfer from high level code */
- u_char sc_flags;
- u_char sc_stat[2];
- u_char sc_msg[7];
- struct dma_chain sc_chain[SBIC_NSEG];
- struct dma_chain *sc_cur;
- struct dma_chain *sc_last;
-};
-
-/* sc_flags */
-#define SBICF_ALIVE 0x01 /* controller initialized */
-#define SBICF_DCFLUSH 0x02 /* need flush for overlap after dma finishes */
-#define SBICF_SELECTED 0x04 /* bus is in selected state. */
-#define SBICF_BADDMA 0x10 /* controller can only DMA to ztwobus space */
-#define SBICF_BBUF 0x20 /* DMA input needs to be copied from bounce */
-#define SBICF_INTR 0x40 /* SBICF interrupt expected */
-#define SBICF_INDMA 0x80 /* not used yet, DMA I/O in progress */
-
-/* sync states */
-#define SYNC_START 0 /* no sync handshake started */
-#define SYNC_SENT 1 /* we sent sync request, no answer yet */
-#define SYNC_DONE 2 /* target accepted our (or inferior) settings,
- or it rejected the request and we stay async */
-#ifdef DEBUG
-#define DDB_FOLLOW 0x04
-#define DDB_IO 0x08
-#endif
-
-#define PHASE 0x07 /* mask for psns/pctl phase */
-#define DATA_OUT_PHASE 0x00
-#define DATA_IN_PHASE 0x01
-#define CMD_PHASE 0x02
-#define STATUS_PHASE 0x03
-#define BUS_FREE_PHASE 0x04
-#define ARB_SEL_PHASE 0x05 /* Fuji chip combines arbitration with sel. */
-#define MESG_OUT_PHASE 0x06
-#define MESG_IN_PHASE 0x07
-
-#define MSG_CMD_COMPLETE 0x00
-#define MSG_EXT_MESSAGE 0x01
-#define MSG_SAVE_DATA_PTR 0x02
-#define MSG_RESTORE_PTR 0x03
-#define MSG_DISCONNECT 0x04
-#define MSG_INIT_DETECT_ERROR 0x05
-#define MSG_ABORT 0x06
-#define MSG_REJECT 0x07
-#define MSG_NOOP 0x08
-#define MSG_PARITY_ERROR 0x09
-#define MSG_BUS_DEVICE_RESET 0x0C
-#define MSG_IDENTIFY 0x80
-#define MSG_IDENTIFY_DR 0xc0 /* (disconnect/reconnect allowed) */
-#define MSG_SYNC_REQ 0x01
-
-
-#define STS_CHECKCOND 0x02 /* Check Condition (ie., read sense) */
-#define STS_CONDMET 0x04 /* Condition Met (ie., search worked) */
-#define STS_BUSY 0x08
-#define STS_INTERMED 0x10 /* Intermediate status sent */
-#define STS_EXT 0x80 /* Extended status valid */
-
-/*
- * XXXX
- */
-struct scsi_fmt_cdb {
- int len; /* cdb length (in bytes) */
- u_char cdb[28]; /* cdb to use on next read/write */
-};
-
-#endif /* _SBICVAR_H_ */
diff --git a/sys/pc98/pc98/scsireg.h b/sys/pc98/pc98/scsireg.h
deleted file mode 100644
index cefe741..0000000
--- a/sys/pc98/pc98/scsireg.h
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Van Jacobson of Lawrence Berkeley Laboratory.
- *
- * 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
- *
- * @(#)scsireg.h 7.3 (Berkeley) 2/5/91
- */
-
-/*
- * AMD AM33C93A SCSI interface hardware description.
- *
- * Using parts of the Mach scsi driver for the 33C93
- */
-
-#define SBIC_myid 0
-#define SBIC_cdbsize 0
-#define SBIC_control 1
-#define SBIC_timeo 2
-#define SBIC_cdb1 3
-#define SBIC_tsecs 3
-#define SBIC_cdb2 4
-#define SBIC_theads 4
-#define SBIC_cdb3 5
-#define SBIC_tcyl_hi 5
-#define SBIC_cdb4 6
-#define SBIC_tcyl_lo 6
-#define SBIC_cdb5 7
-#define SBIC_addr_hi 7
-#define SBIC_cdb6 8
-#define SBIC_addr_2 8
-#define SBIC_cdb7 9
-#define SBIC_addr_3 9
-#define SBIC_cdb8 10
-#define SBIC_addr_lo 10
-#define SBIC_cdb9 11
-#define SBIC_secno 11
-#define SBIC_cdb10 12
-#define SBIC_headno 12
-#define SBIC_cdb11 13
-#define SBIC_cylno_hi 13
-#define SBIC_cdb12 14
-#define SBIC_cylno_lo 14
-#define SBIC_tlun 15
-#define SBIC_cmd_phase 16
-#define SBIC_syn 17
-#define SBIC_count_hi 18
-#define SBIC_count_med 19
-#define SBIC_count_lo 20
-#define SBIC_selid 21
-#define SBIC_rselid 22
-#define SBIC_csr 23
-#define SBIC_cmd 24
-#define SBIC_data 25
-#define SBIC_bank 48
-#define SBIC_window 49
-#define SBIC_int 51
-/* sbic_asr is addressed directly */
-
-/*
- * Register defines
- */
-
-/*
- * Auxiliary Status Register
- */
-
-#define SBIC_ASR_INT 0x80 /* Interrupt pending */
-#define SBIC_ASR_LCI 0x40 /* Last command ignored */
-#define SBIC_ASR_BSY 0x20 /* Busy, only cmd/data/asr readable */
-#define SBIC_ASR_CIP 0x10 /* Busy, cmd unavail also */
-#define SBIC_ASR_xxx 0x0c
-#define SBIC_ASR_PE 0x02 /* Parity error (even) */
-#define SBIC_ASR_DBR 0x01 /* Data Buffer Ready */
-
-/*
- * My ID register, and/or CDB Size
- */
-
-#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */
- /* 11 Mhz is invalid */
-#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */
-#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */
-#define SBIC_ID_EHP 0x10 /* Enable host parity */
-#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */
-#define SBIC_ID_MASK 0x07
-#define SBIC_ID_CBDSIZE_MASK 0x0f /* if unk SCSI cmd group */
-
-/*
- * Control register
- */
-
-#define SBIC_CTL_DMA 0x80 /* Single byte dma */
-#define SBIC_CTL_DBA_DMA 0x40 /* direct buffer acces (bus master)*/
-#define SBIC_CTL_BURST_DMA 0x20 /* continuous mode (8237) */
-#define SBIC_CTL_NO_DMA 0x00 /* Programmed I/O */
-#define SBIC_CTL_HHP 0x10 /* Halt on host parity error */
-#define SBIC_CTL_EDI 0x08 /* Ending disconnect interrupt */
-#define SBIC_CTL_IDI 0x04 /* Intermediate disconnect interrupt*/
-#define SBIC_CTL_HA 0x02 /* Halt on ATN */
-#define SBIC_CTL_HSP 0x01 /* Halt on SCSI parity error */
-
-/*
- * Timeout period register
- * [val in msecs, input clk in Mhz]
- */
-
-#define SBIC_TIMEOUT(val,clk) ((((val)*(clk))/80)+1)
-
-/*
- * CDBn registers, note that
- * cdb11 is used for status byte in target mode (send-status-and-cc)
- * cdb12 sez if linked command complete, and w/flag if so
- */
-
-/*
- * Target LUN register
- * [holds target status when select-and-xfer]
- */
-
-#define SBIC_TLUN_VALID 0x80 /* did we receive an Identify msg */
-#define SBIC_TLUN_DOK 0x40 /* Disconnect OK */
-#define SBIC_TLUN_xxx 0x38
-#define SBIC_TLUN_MASK 0x07
-
-/*
- * Command Phase register
- */
-
-#define SBIC_CPH_MASK 0x7f /* values/restarts are cmd specific */
-#define SBIC_CPH(p) ((p)&SBIC_CPH_MASK)
-
-/*
- * FIFO register
- */
-
-#define SBIC_FIFO_DEEP 12
-
-/*
- * Synchronous xfer register
- */
-
-#define SBIC_SYN_OFF_MASK 0x0f
-#define SBIC_SYN_MAX_OFFSET (SBIC_FIFO_DEEP-1)
-#define SBIC_SYN_PER_MASK 0x70
-#define SBIC_SYN_MIN_PERIOD 2 /* upto 8, encoded as 0 */
-
-#define SBIC_SYN(o,p) (((o)&SBIC_SYN_OFF_MASK)|(((p)<<4)&SBIC_SYN_PER_MASK))
-
-/*
- * Transfer count register
- * optimal access macros depend on addressing
- */
-
-/*
- * Destination ID (selid) register
- */
-
-#define SBIC_SID_SCC 0x80 /* Select command chaining (tgt) */
-#define SBIC_SID_DPD 0x40 /* Data phase direction (inittor) */
-# define SBIC_SID_FROM_SCSI 0x40
-# define SBIC_SID_TO_SCSI 0x00
-#define SBIC_SID_xxx 0x38
-#define SBIC_SID_IDMASK 0x07
-
-/*
- * Source ID (rselid) register
- */
-
-#define SBIC_RID_ER 0x80 /* Enable reselection */
-#define SBIC_RID_ES 0x40 /* Enable selection */
-#define SBIC_RID_DSP 0x20 /* Disable select parity */
-#define SBIC_RID_SIV 0x08 /* Source ID valid */
-#define SBIC_RID_MASK 0x07
-
-/*
- * Status register
- */
-
-#define SBIC_CSR_CAUSE 0xf0
-# define SBIC_CSR_RESET 0x00 /* chip was reset */
-# define SBIC_CSR_CMD_DONE 0x10 /* cmd completed */
-# define SBIC_CSR_CMD_STOPPED 0x20 /* interrupted or abrted*/
-# define SBIC_CSR_CMD_ERR 0x40 /* end with error */
-# define SBIC_CSR_BUS_SERVICE 0x80 /* REQ pending on the bus */
-
-#define SBIC_CSR_QUALIFIER 0x0f
-
- /* Reset State Interrupts */
-# define SBIC_CSR_RESET 0x00 /* reset w/advanced features*/
-# define SBIC_CSR_RESET_AM 0x01 /* reset w/advanced features*/
-
- /* Successful Completion Interrupts */
-# define SBIC_CSR_TARGET 0x10 /* reselect complete */
-# define SBIC_CSR_INITIATOR 0x11 /* select complete */
-# define SBIC_CSR_WO_ATN 0x13 /* tgt mode completion */
-# define SBIC_CSR_W_ATN 0x14 /* ditto */
-# define SBIC_CSR_XLATED 0x15 /* translate address cmd */
-# define SBIC_CSR_S_XFERRED 0x16 /* initiator mode completion*/
-# define SBIC_CSR_XFERRED 0x18 /* phase in low bits */
-
- /* Paused or Aborted Interrupts */
-# define SBIC_CSR_MSGIN_W_ACK 0x20 /* (I) msgin, ACK asserted*/
-# define SBIC_CSR_SDP 0x21 /* (I) SDP msg received */
-# define SBIC_CSR_SEL_ABRT 0x22 /* sel/resel aborted */
-# define SBIC_CSR_XFR_PAUSED 0x23 /* (T) no ATN */
-# define SBIC_CSR_XFR_PAUSED_ATN 0x24 /* (T) ATN is asserted */
-# define SBIC_CSR_RSLT_AM 0x27 /* (I) lost selection (AM) */
-# define SBIC_CSR_MIS 0x28 /* (I) xfer aborted, ph mis */
-
- /* Terminated Interrupts */
-# define SBIC_CSR_CMD_INVALID 0x40
-# define SBIC_CSR_DISC 0x41 /* (I) tgt disconnected */
-# define SBIC_CSR_SEL_TIMEO 0x42
-# define SBIC_CSR_PE 0x43 /* parity error */
-# define SBIC_CSR_PE_ATN 0x44 /* ditto, ATN is asserted */
-# define SBIC_CSR_XLATE_TOOBIG 0x45
-# define SBIC_CSR_RSLT_NOAM 0x46 /* (I) lost sel, no AM mode */
-# define SBIC_CSR_BAD_STATUS 0x47 /* status byte was nok */
-# define SBIC_CSR_MIS_1 0x48 /* ph mis, see low bits */
-
-# define SBIC_MCI_DATA_OUT 0x00 /* Data Out phase */
-# define SBIC_MCI_DATA_IN 0x01 /* Data In phase */
-# define SBIC_MCI_CMD 0x02 /* Command phase */
-# define SBIC_MCI_STATUS 0x03 /* Status phase */
-# define SBIC_MCI_INFO_OUT 0x04 /* Unspecified Info Out phase */
-# define SBIC_MCI_INFO_IN 0x05 /* Unspecified Info In phase */
-# define SBIC_MCI_MES_OUT 0x06 /* Message Out phase */
-# define SBIC_MCI_MES_IN 0x07 /* Message In phase */
-
- /* Service Required Interrupts */
-# define SBIC_CSR_RSLT_NI 0x80 /* reselected, no ify msg */
-# define SBIC_CSR_RSLT_IFY 0x81 /* ditto, AM mode, got ify */
-# define SBIC_CSR_SLT 0x82 /* selected, no ATN */
-# define SBIC_CSR_SLT_ATN 0x83 /* selected with ATN */
-# define SBIC_CSR_ATN 0x84 /* (T) ATN asserted */
-# define SBIC_CSR_DISC_1 0x85 /* (I) bus is free */
-# define SBIC_CSR_UNK_GROUP 0x87 /* strange CDB1 */
-# define SBIC_CSR_MIS_2 0x88 /* (I) ph mis, see low bits */
-
-#define SBIC_PHASE(csr) SCSI_PHASE(csr)
-
-/*
- * Command register (command codes)
- */
-
-#define SBIC_CMD_SBT 0x80 /* Single byte xfer qualifier */
-#define SBIC_CMD_MASK 0x7f
-
- /* Miscellaneous */
-#define SBIC_CMD_RESET 0x00 /* (DTI) lev I */
-#define SBIC_CMD_ABORT 0x01 /* (DTI) lev I */
-#define SBIC_CMD_DISC 0x04 /* ( TI) lev I */
-#define SBIC_CMD_SSCC 0x0d /* ( TI) lev I */
-#define SBIC_CMD_SET_IDI 0x0f /* (DTI) lev I */
-#define SBIC_CMD_XLATE 0x18 /* (DT ) lev II */
-
- /* Initiator state */
-#define SBIC_CMD_SET_ATN 0x02 /* ( I) lev I */
-#define SBIC_CMD_CLR_ACK 0x03 /* ( I) lev I */
-#define SBIC_CMD_XFER_PAD 0x19 /* ( I) lev II */
-#define SBIC_CMD_XFER_INFO 0x20 /* ( I) lev II */
-
- /* Target state */
-#define SBIC_CMD_SND_DISC 0x0e /* ( T ) lev II */
-#define SBIC_CMD_RCV_CMD 0x10 /* ( T ) lev II */
-#define SBIC_CMD_RCV_DATA 0x11 /* ( T ) lev II */
-#define SBIC_CMD_RCV_MSG_OUT 0x12 /* ( T ) lev II */
-#define SBIC_CMD_RCV 0x13 /* ( T ) lev II */
-#define SBIC_CMD_SND_STATUS 0x14 /* ( T ) lev II */
-#define SBIC_CMD_SND_DATA 0x15 /* ( T ) lev II */
-#define SBIC_CMD_SND_MSG_IN 0x16 /* ( T ) lev II */
-#define SBIC_CMD_SND 0x17 /* ( T ) lev II */
-
- /* Disconnected state */
-#define SBIC_CMD_RESELECT 0x05 /* (D ) lev II */
-#define SBIC_CMD_SEL_ATN 0x06 /* (D ) lev II */
-#define SBIC_CMD_SEL 0x07 /* (D ) lev II */
-#define SBIC_CMD_SEL_ATN_XFER 0x08 /* (D I) lev II */
-#define SBIC_CMD_SEL_XFER 0x09 /* (D I) lev II */
-#define SBIC_CMD_RESELECT_RECV 0x0a /* (DT ) lev II */
-#define SBIC_CMD_RESELECT_SEND 0x0b /* (DT ) lev II */
-#define SBIC_CMD_WAIT_SEL_RECV 0x0c /* (DT ) lev II */
OpenPOWER on IntegriCloud