summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2013-05-19 20:32:48 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2013-05-19 20:32:48 +0000
commit07bd41b83415369e1deeada2064264b06714ddf7 (patch)
tree92078e37953a3b7ebf4da6ca7545634528194e3d /sys
parent4a6a74a895682a2441836a68f259ca70b8283a24 (diff)
Switch mvme68k to MI wdsc(4) driver. Tested on MVME147.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/mvme68k/conf/files.mvme68k5
-rw-r--r--sys/arch/mvme68k/dev/dmavar.h43
-rw-r--r--sys/arch/mvme68k/dev/i82586.h286
-rw-r--r--sys/arch/mvme68k/dev/sbic.c2678
-rw-r--r--sys/arch/mvme68k/dev/sbicreg.h433
-rw-r--r--sys/arch/mvme68k/dev/sbicvar.h201
-rw-r--r--sys/arch/mvme68k/dev/wdsc.c499
7 files changed, 330 insertions, 3815 deletions
diff --git a/sys/arch/mvme68k/conf/files.mvme68k b/sys/arch/mvme68k/conf/files.mvme68k
index 3964a0b648f..07df830a9d6 100644
--- a/sys/arch/mvme68k/conf/files.mvme68k
+++ b/sys/arch/mvme68k/conf/files.mvme68k
@@ -1,4 +1,4 @@
-# $OpenBSD: files.mvme68k,v 1.35 2010/12/06 20:10:18 jasper Exp $
+# $OpenBSD: files.mvme68k,v 1.36 2013/05/19 20:32:47 miod Exp $
# config file for mvme68k
@@ -72,9 +72,8 @@ file arch/mvme68k/dev/if_ie.c ie
include "scsi/files.scsi"
-device wdsc: scsi
+device wdsc: wd33c93, scsi
attach wdsc at pcc
-file arch/mvme68k/dev/sbic.c wdsc
file arch/mvme68k/dev/wdsc.c wdsc
device ipic {manu = -1, prod = -1, [vec = -1], [ipl = 0]}
diff --git a/sys/arch/mvme68k/dev/dmavar.h b/sys/arch/mvme68k/dev/dmavar.h
deleted file mode 100644
index bc0368be1c4..00000000000
--- a/sys/arch/mvme68k/dev/dmavar.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* $OpenBSD: dmavar.h,v 1.4 2003/06/02 23:27:50 millert Exp $ */
-
-/*
- * Copyright (c) 1982, 1990 The Regents of the University of California.
- * 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. 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.
- *
- * @(#)dmavar.h 7.2 (Berkeley) 11/4/90
- */
-
-/* dmago flags */
-#define DMAGO_READ 0x08 /* transfer is a read */
-#define DMAGO_NOINT 0x80 /* don't interrupt on completion */
-
-#ifdef _KERNEL
-typedef void (*dmafree_t) (void *dev);
-typedef int (*dmago_t) (void *dev, char *, int, int);
-typedef int (*dmanext_t) (void *dev);
-typedef void (*dmastop_t) (void *dev);
-#endif
diff --git a/sys/arch/mvme68k/dev/i82586.h b/sys/arch/mvme68k/dev/i82586.h
deleted file mode 100644
index 7674f6b5e97..00000000000
--- a/sys/arch/mvme68k/dev/i82586.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/* $OpenBSD: i82586.h,v 1.4 2003/06/02 05:09:14 deraadt Exp $ */
-
-/*-
- * Copyright (c) 1995 Theo de Raadt
- * Copyright (c) 1992, University of Vermont and State Agricultural College.
- * Copyright (c) 1992, Garrett A. Wollman.
- * 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * Vermont and State Agricultural College and Garrett A. Wollman.
- * 4. Neither the name of the University nor the name of the author
- * 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 UNIVERSITY OR 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.
- */
-
-/*
- * Intel 82586 Ethernet chip
- * Register, bit, and structure definitions.
- *
- * Written by GAW with reference to the Clarkson Packet Driver code for this
- * chip written by Russ Nelson and others.
- *
- * Sun support added by Charles D. Cranor, 25-Oct-94
- */
-
-struct ie_en_addr {
- u_char data[6];
-};
-
-/*
- * This is the master configuration block. It tells the hardware where all
- * the rest of the stuff is.
- */
-struct ie_sys_conf_ptr {
- u_char mbz1[3]; /* must be zero */
- u_char ie_bus_use; /* true if 8-bit only */
- u_char mbz2[4]; /* must be zero */
- caddr_t ie_iscp_ptr; /* 24-bit physaddr of ISCP */
-};
-
-/*
- * The tells the hardware where all the rest of the stuff is, too.
- * FIXME: some of these should be re-commented after we figure out their
- * REAL function.
- */
-struct ie_int_sys_conf_ptr {
- u_char mbz1[1];
- u_char ie_busy; /* zeroed after init */
- u_short ie_scb_offset; /* 16-bit physaddr of next struct */
- caddr_t ie_base; /* 24-bit physaddr for all 16-bit vars */
-};
-
-/*
- * This FINALLY tells the hardware what to do and where to put it.
- */
-struct ie_sys_ctl_block {
- u_short ie_status; /* status word */
- u_short ie_command; /* command word */
- u_short ie_command_list; /* 16-pointer to command block list */
- u_short ie_recv_list; /* 16-pointer to receive frame list */
- u_short ie_err_crc; /* CRC errors */
- u_short ie_err_align; /* Alignment errors */
- u_short ie_err_resource; /* Resource errors */
- u_short ie_err_overrun; /* Overrun errors */
-};
-
-/* Command values */
-#define IE_RU_COMMAND SWAP(0x0070) /* mask for RU command */
-#define IE_RU_NOP SWAP(0) /* for completeness */
-#define IE_RU_START SWAP(0x0010) /* start receive unit command */
-#define IE_RU_ENABLE SWAP(0x0020) /* enable receiver command */
-#define IE_RU_DISABLE SWAP(0x0030) /* disable receiver command */
-#define IE_RU_ABORT SWAP(0x0040) /* abort current receive operation */
-
-#define IE_CU_COMMAND SWAP(0x0700) /* mask for CU command */
-#define IE_CU_NOP SWAP(0) /* included for completeness */
-#define IE_CU_START SWAP(0x0100) /* do-command command */
-#define IE_CU_RESUME SWAP(0x0200) /* resume a suspended cmd list */
-#define IE_CU_STOP SWAP(0x0300) /* SUSPEND was already taken */
-#define IE_CU_ABORT SWAP(0x0400) /* abort current command */
-
-#define IE_ACK_COMMAND SWAP(0xf000) /* mask for ACK command */
-#define IE_ACK_CX SWAP(0x8000) /* ack IE_ST_DONE */
-#define IE_ACK_FR SWAP(0x4000) /* ack IE_ST_RECV */
-#define IE_ACK_CNA SWAP(0x2000) /* ack IE_ST_ALLDONE */
-#define IE_ACK_RNR SWAP(0x1000) /* ack IE_ST_RNR */
-
-#define IE_ACTION_COMMAND(x) (((x) & IE_CU_COMMAND) == IE_CU_START)
- /* is this command an action command? */
-
-/* Status values */
-#define IE_ST_WHENCE SWAP(0xf000) /* mask for cause of interrupt */
-#define IE_ST_DONE SWAP(0x8000) /* command with I bit completed */
-#define IE_ST_RECV SWAP(0x4000) /* frame received */
-#define IE_ST_ALLDONE SWAP(0x2000) /* all commands completed */
-#define IE_ST_RNR SWAP(0x1000) /* receive not ready */
-
-#define IE_CU_STATUS SWAP(0x700) /* mask for command unit status */
-#define IE_CU_ACTIVE SWAP(0x200) /* command unit is active */
-#define IE_CU_SUSPEND SWAP(0x100) /* command unit is suspended */
-
-#define IE_RU_STATUS SWAP(0x70) /* mask for receiver unit status */
-#define IE_RU_SUSPEND SWAP(0x10) /* receiver is suspended */
-#define IE_RU_NOSPACE SWAP(0x20) /* receiver has no resources */
-#define IE_RU_READY SWAP(0x40) /* reveiver is ready */
-
-/*
- * This is filled in partially by the chip, partially by us.
- */
-struct ie_recv_frame_desc {
- u_short ie_fd_status; /* status for this frame */
- u_short ie_fd_last; /* end of frame list flag */
- u_short ie_fd_next; /* 16-pointer to next RFD */
- u_short ie_fd_buf_desc; /* 16-pointer to list of buffer desc's */
- struct ie_en_addr dest; /* destination ether */
- struct ie_en_addr src; /* source ether */
- u_short ie_length; /* 802 length/Ether type */
- u_short mbz; /* must be zero */
-};
-
-#define IE_FD_LAST SWAP(0x8000) /* last rfd in list */
-#define IE_FD_SUSP SWAP(0x4000) /* suspend RU after receipt */
-
-#define IE_FD_COMPLETE SWAP(0x8000) /* frame is complete */
-#define IE_FD_BUSY SWAP(0x4000) /* frame is busy */
-#define IE_FD_OK SWAP(0x2000) /* frame is bad */
-#define IE_FD_RNR SWAP(0x0200) /* receiver out of resources here */
-
-/*
- * linked list of buffers...
- */
-struct ie_recv_buf_desc {
- u_short ie_rbd_actual; /* status for this buffer */
- u_short ie_rbd_next; /* 16-pointer to next RBD */
- caddr_t ie_rbd_buffer; /* 24-pointer to buffer for this RBD */
- u_short ie_rbd_length; /* length of the buffer */
- u_short mbz; /* must be zero */
-};
-
-#define IE_RBD_LAST SWAP(0x8000) /* last buffer */
-#define IE_RBD_USED SWAP(0x4000) /* this buffer has data */
-/*
- * All commands share this in common.
- */
-struct ie_cmd_common {
- u_short ie_cmd_status; /* status of this command */
- u_short ie_cmd_cmd; /* command word */
- u_short ie_cmd_link; /* link to next command */
-};
-
-#define IE_STAT_COMPL SWAP(0x8000) /* command is completed */
-#define IE_STAT_BUSY SWAP(0x4000) /* command is running now */
-#define IE_STAT_OK SWAP(0x2000) /* command completed successfully */
-#define IE_STAT_ABORT SWAP(0x1000) /* command was aborted */
-
-
-#define IE_CMD_NOP SWAP(0x0000) /* NOP */
-#define IE_CMD_IASETUP SWAP(0x0001) /* initial address setup */
-#define IE_CMD_CONFIG SWAP(0x0002) /* configure command */
-#define IE_CMD_MCAST SWAP(0x0003) /* multicast setup command */
-#define IE_CMD_XMIT SWAP(0x0004) /* transmit command */
-#define IE_CMD_TDR SWAP(0x0005) /* time-domain reflectometer command */
-#define IE_CMD_DUMP SWAP(0x0006) /* dump command */
-#define IE_CMD_DIAGNOSE SWAP(0x0007) /* diagnostics command */
-
-#define IE_CMD_LAST SWAP(0x8000) /* this is the last command in the list */
-#define IE_CMD_SUSPEND SWAP(0x4000) /* suspend CU after this command */
-#define IE_CMD_INTR SWAP(0x2000) /* post an interrupt after completion */
-
-/*
- * This is the command to transmit a frame.
- */
-struct ie_xmit_cmd {
- struct ie_cmd_common com; /* common part */
-#define ie_xmit_status com.ie_cmd_status
-
- u_short ie_xmit_desc; /* 16-pointer to buffer descriptor */
- struct ie_en_addr ie_xmit_addr; /* destination address */
-
- u_short ie_xmit_length; /* 802.3 length/Ether type field */
-};
-
-#define IE_XS_MAXCOLL SWAP(0x000f) /* number of collisions during transmit */
-#define IE_XS_EXCMAX SWAP(0x0020) /* exceeded maximum number of collisions */
-#define IE_XS_SQE SWAP(0x0040) /* SQE positive */
-#define IE_XS_DEFERRED SWAP(0x0080) /* transmission deferred */
-#define IE_XS_UNDERRUN SWAP(0x0100) /* DMA underrun */
-#define IE_XS_LOSTCTS SWAP(0x0200) /* Lost CTS */
-#define IE_XS_NOCARRIER SWAP(0x0400) /* No Carrier */
-
-/*
- * This is a buffer descriptor for a frame to be transmitted.
- */
-
-struct ie_xmit_buf {
- u_short ie_xmit_flags; /* see below */
- u_short ie_xmit_next; /* 16-pointer to next desc. */
- caddr_t ie_xmit_buf; /* 24-pointer to the actual buffer */
-};
-
-#define IE_XMIT_LAST SWAP(0x8000) /* this TBD is the last one */
-/* The rest of the `flags' word is actually the length. */
-
-/*
- * Multicast setup command.
- */
-
-#define MAXMCAST 250 /* must fit in transmit buffer */
-
-struct ie_mcast_cmd {
- struct ie_cmd_common com; /* common part */
-#define ie_mcast_status com.ie_cmd_status
-
- u_short ie_mcast_bytes; /* size (in bytes) of multicast addresses */
- struct ie_en_addr ie_mcast_addrs[MAXMCAST + 1]; /* space for them */
-};
-
-/*
- * Time Domain Reflectometer command.
- */
-
-struct ie_tdr_cmd {
- struct ie_cmd_common com; /* common part */
-#define ie_tdr_status com.ie_cmd_status
-
- u_short ie_tdr_time; /* error bits and time */
-};
-
-#define IE_TDR_SUCCESS SWAP(0x8000) /* TDR succeeded without error */
-#define IE_TDR_XCVR SWAP(0x4000) /* detected a transceiver problem */
-#define IE_TDR_OPEN SWAP(0x2000) /* detected an open */
-#define IE_TDR_SHORT SWAP(0x1000) /* TDR detected a short */
-#define IE_TDR_TIME SWAP(0x07ff) /* mask for reflection time */
-
-/*
- * Initial Address Setup command
- */
-struct ie_iasetup_cmd {
- struct ie_cmd_common com;
-#define ie_iasetup_status com.ie_cmd_status
-
- struct ie_en_addr ie_address;
-};
-
-/*
- * Configuration command
- */
-struct ie_config_cmd {
- struct ie_cmd_common com; /* common part */
-#define ie_config_status com.ie_cmd_status
-
- u_char ie_config_count; /* byte count (0x0c) */
- u_char ie_fifo; /* fifo (8) */
- u_char ie_save_bad; /* save bad frames (0x40) */
- u_char ie_addr_len; /* address length (0x2e) (AL-LOC == 1) */
- u_char ie_priority; /* priority and backoff (0x0) */
- u_char ie_ifs; /* inter-frame spacing (0x60) */
- u_char ie_slot_low; /* slot time, LSB (0x0) */
- u_char ie_slot_high; /* slot time, MSN, and retries (0xf2) */
- u_char ie_promisc; /* 1 if promiscuous, else 0 */
- u_char ie_crs_cdt; /* CSMA/CD parameters (0x0) */
- u_char ie_min_len; /* min frame length (0x40) */
- u_char ie_junk; /* stuff for 82596 (0xff) */
-};
diff --git a/sys/arch/mvme68k/dev/sbic.c b/sys/arch/mvme68k/dev/sbic.c
deleted file mode 100644
index baf80c6b4a7..00000000000
--- a/sys/arch/mvme68k/dev/sbic.c
+++ /dev/null
@@ -1,2678 +0,0 @@
-/* $OpenBSD: sbic.c,v 1.29 2010/11/18 21:13:19 miod Exp $ */
-/* $NetBSD: sbic.c,v 1.2 1996/04/23 16:32:54 chuck Exp $ */
-
-/*
- * Changes Copyright (c) 1996 Steve Woodford
- * Original 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. 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
- */
-
-/*
- * Steve Woodford (SCW), Apr, 1996
- * MVME147S WD33C93 Scsi Bus Interface Controller driver,
- *
- * Basically a de-loused and tidied up version of the Amiga AMD 33C93 driver.
- *
- * The original driver used features which required at least a WD33C93A
- * chip. The '147 has the original WD33C93 chip (no 'A' suffix).
- *
- * This version of the driver is pretty well generic, so should work with
- * any flavour of WD33C93 chip.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/device.h>
-#include <sys/kernel.h> /* For hz */
-#include <sys/disklabel.h>
-#include <sys/buf.h>
-#include <sys/queue.h>
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-#include <uvm/uvm_extern.h>
-#include <mvme68k/dev/dmavar.h>
-#include <mvme68k/dev/sbicreg.h>
-#include <mvme68k/dev/sbicvar.h>
-#include <machine/autoconf.h>
-#include <mvme68k/dev/pccreg.h>
-
-
-/*
- * Since I can't find this in any other header files
- */
-#define SCSI_PHASE(reg) (reg&0x07)
-
-/*
- * 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 */
-
-/*
- * Convenience macro for waiting for a particular sbic event
- */
-#define SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__)
-
-int sbicicmd(struct sbic_softc *, void *, int, void *, int);
-int sbicgo(struct sbic_softc *, struct scsi_xfer *);
-int sbicdmaok(struct sbic_softc *, struct scsi_xfer *);
-int sbicwait(sbic_regmap_p, u_char, int , int);
-int sbiccheckdmap(void *, u_long, u_long);
-u_char sbicselectbus(struct sbic_softc *);
-int sbicxfout(sbic_regmap_p, int, void *);
-int sbicxfin(sbic_regmap_p, int, void *);
-int sbicfromscsiperiod(struct sbic_softc *, int);
-int sbictoscsiperiod(struct sbic_softc *, int);
-int sbicintr(struct sbic_softc *);
-int sbicpoll(struct sbic_softc *);
-int sbicnextstate(struct sbic_softc *, u_char, u_char);
-int sbicmsgin(struct sbic_softc *);
-int sbicabort(struct sbic_softc *, char *);
-void sbicxfdone(struct sbic_softc *);
-void sbicerror(struct sbic_softc *,u_char);
-void sbicreset(struct sbic_softc *);
-void sbic_scsidone(struct sbic_acb *, int);
-void sbic_sched(struct sbic_softc *);
-void sbic_save_ptrs(struct sbic_softc *);
-void sbic_load_ptrs(struct sbic_softc *);
-void sbicinit(struct sbic_softc *);
-
-/*
- * Synch xfer parameters, and timing conversions
- */
-int sbic_min_period = SBIC_SYN_MIN_PERIOD; /* in cycles = f(ICLK,FSn) */
-int sbic_max_offset = SBIC_SYN_MAX_OFFSET; /* pure number */
-int sbic_cmd_wait = SBIC_CMD_WAIT;
-int sbic_data_wait = SBIC_DATA_WAIT;
-int sbic_init_wait = SBIC_INIT_WAIT;
-
-/*
- * was broken before.. now if you want this you get it for all drives
- * on sbic controllers.
- */
-u_char sbic_inhibit_sync[8];
-int sbic_enable_reselect = 1; /* Allow Disconnect / Reselect */
-int sbic_no_dma = 0; /* Use PIO transfers instead of DMA */
-int sbic_parallel_operations = 1; /* Allow command queues */
-
-/*
- * Some useful stuff for debugging purposes
- */
-#ifdef DEBUG
-int sbicdma_ops = 0; /* total DMA operations */
-int sbicdma_hits = 0; /* number of DMA chains that were contiguous */
-int sbicdma_misses = 0; /* number of DMA chains that were not contiguous */
-int sbicdma_saves = 0;
-
-#define QPRINTF(a) if (sbic_debug > 1) printf a
-
-int sbic_debug = 0; /* Debug all chip related things */
-int sync_debug = 0; /* Debug all Synchronous Scsi related things */
-int reselect_debug = 0; /* Debug all reselection related things */
-int report_sense = 0; /* Always print Sense information */
-int data_pointer_debug = 0; /* Debug Data Pointer related things */
-
-void sbictimeout(struct sbic_softc *dev);
-
-#else
-#define QPRINTF(a) /* */
-#endif
-
-/*
- * Save DMA pointers. Take into account partial transfer. Shut down DMA.
- */
-void
-sbic_save_ptrs(dev)
- struct sbic_softc *dev;
-{
- sbic_regmap_p regs;
- struct sbic_acb* acb;
- int count,
- asr,
- s;
-
- /*
- * Only need to save pointers if DMA was active...
- */
- if ( dev->sc_cur == NULL || (dev->sc_flags & SBICF_INDMA) == 0 )
- return;
-
- regs = dev->sc_sbicp;
-
- s = splbio();
-
- /*
- * Wait until WD chip is idle
- */
- do {
- GET_SBIC_asr(regs, asr);
- if( asr & SBIC_ASR_DBR ) {
- printf("sbic_save_ptrs: asr %02x canceled!\n", asr);
- splx(s);
- return;
- }
- } while( asr & (SBIC_ASR_BSY|SBIC_ASR_CIP) );
-
-
- /*
- * Save important state.
- * must be done before dmastop
- */
- acb = dev->sc_nexus;
- acb->sc_dmacmd = dev->sc_dmacmd;
-
- /*
- * Fetch the residual count
- */
- SBIC_TC_GET(regs, count);
-
- /*
- * Shut down DMA
- */
- dev->sc_dmastop(dev);
-
- /*
- * No longer in DMA
- */
- dev->sc_flags &= ~SBICF_INDMA;
-
- /*
- * Ensure the WD chip is back in polled I/O mode, with nothing to
- * transfer.
- */
- SBIC_TC_PUT(regs, 0);
- SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
-
- /*
- * Update current count...
- */
- acb->sc_tcnt = count;
-
- /*
- * Work out how many bytes were actually transferred
- */
- count = dev->sc_tcnt - count;
- dev->sc_tcnt = acb->sc_tcnt;
-
- /*
- * Fixup partial xfers
- */
- acb->sc_kv.dc_addr += count;
- acb->sc_kv.dc_count -= count;
- acb->sc_pa.dc_addr += count;
- acb->sc_pa.dc_count -= count >> 1;
-
-#ifdef DEBUG
- if ( data_pointer_debug )
- printf("save at (%x,%x):%x\n",
- dev->sc_cur->dc_addr, dev->sc_cur->dc_count,count);
- sbicdma_saves++;
-#endif
-
- splx(s);
-}
-
-
-/*
- * DOES NOT RESTART DMA!!!
- */
-void
-sbic_load_ptrs(dev)
- struct sbic_softc *dev;
-{
- struct sbic_acb *acb = dev->sc_nexus;
- int s;
-
- if ( acb->sc_kv.dc_count == 0 ) {
- /*
- * No data to xfer
- */
- return;
- }
-
- s = splbio();
-
- /*
- * Reset the Scatter-Gather chain
- */
- dev->sc_last = dev->sc_cur = &acb->sc_pa;
-
- /*
- * Restore the Transfer Count and DMA specific data
- */
- dev->sc_tcnt = acb->sc_tcnt;
- dev->sc_dmacmd = acb->sc_dmacmd;
-
-#ifdef DEBUG
- sbicdma_ops++;
-#endif
-
- /*
- * Need to fixup new segment?
- */
- if ( dev->sc_tcnt == 0 ) {
- /*
- * sc_tcnt == 0 implies end of segment
- */
- char *vaddr, *paddr;
- int count;
-
- /*
- * do kvm to pa mappings
- */
- vaddr = acb->sc_kv.dc_addr;
- paddr = acb->sc_pa.dc_addr = (char *)kvtop((vaddr_t)vaddr);
-
- for (count = (NBPG - ((int)vaddr & PGOFSET));
- count < acb->sc_kv.dc_count &&
- (char *)kvtop((vaddr_t)vaddr + count + 4) == paddr + count + 4;
- count += NBPG)
- ; /* Do nothing */
-
- /*
- * If it's all contiguous...
- */
- if ( count > acb->sc_kv.dc_count ) {
- count = acb->sc_kv.dc_count;
-#ifdef DEBUG
- sbicdma_hits++;
-#endif
- }
-#ifdef DEBUG
- else
- sbicdma_misses++;
-#endif
-
- acb->sc_tcnt = count;
- acb->sc_pa.dc_count = count >> 1;
-
-#ifdef DEBUG
- if ( data_pointer_debug )
- printf("DMA recalc:kv(%x,%x)pa(%x,%x)\n", acb->sc_kv.dc_addr,
- acb->sc_kv.dc_count,
- acb->sc_pa.dc_addr,
- acb->sc_tcnt);
-#endif
-
- }
-
- splx(s);
-}
-
-/*
- * 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().
- */
-void
-sbic_scsicmd(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *slp = xs->sc_link;
- struct sbic_softc *dev = slp->adapter_softc;
- struct sbic_acb *acb;
- int flags = xs->flags,
- s;
-
- if ( dev->sc_nexus && (flags & SCSI_POLL) )
- panic("sbic_scsicmd: busy");
-
- s = splbio();
-
- if ( (acb = TAILQ_FIRST(&dev->free_list)) != NULL )
- TAILQ_REMOVE(&dev->free_list, acb, chain);
-
- splx(s);
-
- if ( acb == NULL ) {
-#ifdef DEBUG
- printf("sbic_scsicmd: unable to queue request for target %d\n",
- slp->target);
-#ifdef DDB
- Debugger();
-#endif
-#endif
- xs->error = XS_NO_CCB;
- scsi_done(xs);
- return;
- }
-
- if ( flags & SCSI_DATA_IN )
- acb->flags = ACB_ACTIVE | ACB_DATAIN;
- else
- acb->flags = ACB_ACTIVE;
-
- acb->xs = xs;
- acb->clen = xs->cmdlen;
- acb->sc_kv.dc_addr = xs->data;
- acb->sc_kv.dc_count = xs->datalen;
- acb->pa_addr = xs->data ? (char *)kvtop((vaddr_t)xs->data) : 0;
- bcopy(xs->cmd, &acb->cmd, xs->cmdlen);
-
- if ( flags & SCSI_POLL ) {
- /*
- * This has major side effects -- it locks up the machine
- */
- int stat;
-
- s = splbio();
-
- dev->sc_flags |= SBICF_ICMD;
-
- do {
- /*
- * If we already had a nexus, while away the time until idle...
- * This is likely only to happen if a reselection occurs between
- * here and our earlier check for ICMD && sc_nexus (which would
- * have resulted in a panic() had it been true).
- */
- while ( dev->sc_nexus )
- sbicpoll(dev);
-
- /*
- * Fix up the new nexus
- */
- dev->sc_nexus = acb;
- dev->sc_xs = xs;
- dev->target = slp->target;
- dev->lun = slp->lun;
-
- stat = sbicicmd(dev, &acb->cmd, acb->clen,
- acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
-
- } while ( dev->sc_nexus != acb );
-
- sbic_scsidone(acb, stat);
-
- splx(s);
-
- return;
- }
-
- s = splbio();
- TAILQ_INSERT_TAIL(&dev->ready_list, acb, chain);
-
- /*
- * If nothing is active, try to start it now.
- */
- if ( dev->sc_nexus == NULL )
- sbic_sched(dev);
-
- splx(s);
-}
-
-/*
- * attempt to start the next available command
- */
-void
-sbic_sched(dev)
- struct sbic_softc *dev;
-{
- struct scsi_xfer *xs;
- struct scsi_link *slp = NULL; /* Gag the compiler */
- struct sbic_acb *acb;
- int flags,
- stat;
-
- /*
- * XXXSCW
- * I'll keep this test here, even though I can't see any obvious way
- * in which sbic_sched() could be called with sc_nexus non NULL
- */
- if ( dev->sc_nexus )
- return; /* a command is current active */
-
- /*
- * Loop through the ready list looking for work to do...
- */
- TAILQ_FOREACH(acb, &dev->ready_list, chain) {
- int i, j;
-
- slp = acb->xs->sc_link;
- i = slp->target;
- j = 1 << slp->lun;
-
- /*
- * We've found a potential command, but is the target/lun busy?
- */
- if ( (dev->sc_tinfo[i].lubusy & j) == 0 ) {
- /*
- * Nope, it's not busy, so we can use it.
- */
- dev->sc_tinfo[i].lubusy |= j;
- TAILQ_REMOVE(&dev->ready_list, acb, chain);
- dev->sc_nexus = acb;
- acb->sc_pa.dc_addr = acb->pa_addr; /* XXXX check */
- break;
- }
- }
-
- if ( acb == NULL ) {
- QPRINTF(("sbicsched: no work\n"));
- return; /* did not find an available command */
- }
-
-#ifdef DEBUG
- if ( data_pointer_debug > 1 )
- printf("sbic_sched(%d,%d)\n", slp->target, slp->lun);
-#endif
-
- dev->sc_xs = xs = acb->xs;
- flags = xs->flags;
-
- if ( flags & SCSI_RESET )
- sbicreset(dev);
-
- dev->sc_stat[0] = -1;
- dev->target = slp->target;
- dev->lun = slp->lun;
-
- if ( flags & SCSI_POLL || (!sbic_parallel_operations &&
- (sbicdmaok(dev, xs) == 0)) )
- stat = sbicicmd(dev, &acb->cmd, acb->clen,
- acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
- else
- if ( sbicgo(dev, xs) == 0 )
- return;
- else
- stat = dev->sc_stat[0];
-
- sbic_scsidone(acb, stat);
-}
-
-void
-sbic_scsidone(acb, stat)
- struct sbic_acb *acb;
- int stat;
-{
- struct scsi_xfer *xs = acb->xs;
- struct scsi_link *slp = xs->sc_link;
- struct sbic_softc *dev = slp->adapter_softc;
- int dosched = 0;
-
-#ifdef DIAGNOSTIC
- if ( acb == NULL || xs == NULL ) {
- printf("sbic_scsidone -- (%d,%d) no scsi_xfer\n", dev->target, dev->lun);
-#ifdef DDB
- Debugger();
-#endif
- return;
- }
-#endif
-
- /*
- * is this right?
- */
- xs->status = stat;
-
-#ifdef DEBUG
- if ( data_pointer_debug > 1 )
- printf("scsidone: (%d,%d)->(%d,%d)%02x\n", slp->target, slp->lun,
- dev->target, dev->lun, stat);
-
- if ( xs->sc_link->target == dev->sc_link.adapter_target )
- panic("target == hostid");
-#endif
-
- if ( xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE) == 0 ) {
-
- if ( stat == SCSI_CHECK ) {
- /*
- * Schedule a REQUEST SENSE
- */
- struct scsi_sense *ss = (void *)&acb->cmd;
-
-#ifdef DEBUG
- if ( report_sense )
- printf("sbic_scsidone: autosense %02x targ %d lun %d",
- acb->cmd.opcode, slp->target, slp->lun);
-#endif
-
- bzero(ss, sizeof(*ss));
-
- ss->opcode = REQUEST_SENSE;
- ss->byte2 = slp->lun << 5;
- ss->length = sizeof(struct scsi_sense_data);
-
- acb->clen = sizeof(*ss);
- acb->sc_kv.dc_addr = (char *)&xs->sense;
- acb->sc_kv.dc_count = sizeof(struct scsi_sense_data);
- acb->pa_addr = (char *)kvtop((vaddr_t)&xs->sense); /* XXX check */
- acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN;
-
- TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain);
-
- dev->sc_tinfo[slp->target].lubusy &= ~(1 << slp->lun);
- dev->sc_tinfo[slp->target].senses++;
-
- if ( dev->sc_nexus == acb ) {
- dev->sc_nexus = NULL;
- dev->sc_xs = NULL;
- sbic_sched(dev);
- }
- return;
- }
- }
-
- if ( xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE) != 0 ) {
-
- xs->error = XS_SENSE;
-
-#ifdef DEBUG
- if (report_sense)
- printf(" => %02x\n", xs->sense.flags);
-#endif
-
- } else {
- xs->resid = 0; /* XXXX */
- }
-
- /*
- * Remove the ACB from whatever queue it's on. We have to do a bit of
- * a hack to figure out which queue it's on. Note that it is *not*
- * necessary to cdr down the ready queue, but we must cdr down the
- * nexus queue and see if it's there, so we can mark the unit as no
- * longer busy. This code is sickening, but it works.
- */
- if ( acb == dev->sc_nexus ) {
-
- dev->sc_nexus = NULL;
- dev->sc_xs = NULL;
-
- dev->sc_tinfo[slp->target].lubusy &= ~(1 << slp->lun);
-
- if ( !TAILQ_EMPTY(&dev->ready_list) )
- dosched = 1; /* start next command */
-
- } else
- if (TAILQ_LAST(&dev->ready_list, acb_list) == TAILQ_NEXT(acb, chain)) {
-
- TAILQ_REMOVE(&dev->ready_list, acb, chain);
-
- } else {
-
- register struct sbic_acb *a;
-
- TAILQ_FOREACH(a, &dev->nexus_list, chain) {
- if ( a == acb ) {
- TAILQ_REMOVE(&dev->nexus_list, acb, chain);
- dev->sc_tinfo[slp->target].lubusy &= ~(1 << slp->lun);
- break;
- }
- }
-
- if ( a )
- ;
- else if ( TAILQ_NEXT(acb, chain) != NULL) {
- TAILQ_REMOVE(&dev->ready_list, acb, chain);
- } else {
- printf("%s: can't find matching acb\n", dev->sc_dev.dv_xname);
-#ifdef DDB
- Debugger();
-#endif
- }
- }
-
- /*
- * Put it on the free list.
- */
- acb->flags = ACB_FREE;
- TAILQ_INSERT_HEAD(&dev->free_list, acb, chain);
-
- dev->sc_tinfo[slp->target].cmds++;
-
- scsi_done(xs);
-
- if ( dosched )
- sbic_sched(dev);
-}
-
-int
-sbicdmaok(dev, xs)
- struct sbic_softc *dev;
- struct scsi_xfer *xs;
-{
- if ( sbic_no_dma || xs->datalen & 0x03 || (int)xs->data & 0x03)
- return(0);
-
- /*
- * controller supports dma to any addresses?
- */
- if ( (dev->sc_flags & SBICF_BADDMA) == 0 )
- return(1);
-
- /*
- * this address is ok for dma?
- */
- if ( sbiccheckdmap(xs->data, xs->datalen, dev->sc_dmamask) == 0 )
- return(1);
-
- return(0);
-}
-
-int
-sbicwait(regs, until, timeo, line)
- sbic_regmap_p regs;
- u_char until;
- int timeo;
- int line;
-{
- u_char val;
-
- if ( timeo == 0 )
- timeo = 1000000; /* some large value.. */
-
- GET_SBIC_asr(regs, val);
-
- while ( (val & until) == 0 ) {
-
- if ( timeo-- == 0 ) {
- int csr;
- GET_SBIC_csr(regs, csr);
- printf("sbicwait TIMEO @%d with asr=x%x csr=x%x\n", line, val, csr);
-#if defined(DDB) && defined(DEBUG)
- Debugger();
-#endif
- return(val); /* Maybe I should abort */
- break;
- }
-
- DELAY(1);
- GET_SBIC_asr(regs, val);
- }
-
- return(val);
-}
-
-int
-sbicabort(dev, where)
- struct sbic_softc *dev;
- char *where;
-{
- sbic_regmap_p regs = dev->sc_sbicp;
- u_char csr,
- asr;
-
- GET_SBIC_asr(regs, asr);
- GET_SBIC_csr(regs, csr);
-
- printf ("%s: abort %s: csr = 0x%02x, asr = 0x%02x\n",
- dev->sc_dev.dv_xname, where, csr, asr);
-
- /*
- * Clean up chip itself
- */
- if ( dev->sc_flags & SBICF_SELECTED ) {
-
- while ( asr & SBIC_ASR_DBR ) {
- /*
- * sbic is jammed w/data. need to clear it
- * But we don't know what direction it needs to go
- */
- GET_SBIC_data(regs, asr);
- printf("%s: abort %s: clearing data buffer 0x%02x\n",
- dev->sc_dev.dv_xname, where, asr);
- GET_SBIC_asr(regs, asr);
- if ( asr & SBIC_ASR_DBR ) /* Not the read direction, then */
- SET_SBIC_data(regs, asr);
- GET_SBIC_asr(regs, asr);
- }
-
- WAIT_CIP(regs);
-
- printf("%s: sbicabort - sending ABORT command\n", dev->sc_dev.dv_xname);
- SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
- WAIT_CIP(regs);
-
- GET_SBIC_asr(regs, asr);
-
- if ( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI) ) {
- /*
- * ok, get more drastic..
- */
- printf("%s: sbicabort - asr %x, trying to reset\n",
- dev->sc_dev.dv_xname, asr);
- sbicreset(dev);
- dev->sc_flags &= ~SBICF_SELECTED;
- return SBIC_STATE_ERROR;
- }
-
- printf("%s: sbicabort - sending DISC command\n", dev->sc_dev.dv_xname);
- SET_SBIC_cmd(regs, SBIC_CMD_DISC);
-
- do {
- SBIC_WAIT (regs, SBIC_ASR_INT, 0);
- GET_SBIC_asr(regs, asr);
- GET_SBIC_csr (regs, csr);
- QPRINTF(("csr: 0x%02x, asr: 0x%02x\n", csr, asr));
- } while ( (csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) &&
- (csr != SBIC_CSR_CMD_INVALID) );
-
- /*
- * lets just hope it worked..
- */
- dev->sc_flags &= ~SBICF_SELECTED;
- }
-
- return SBIC_STATE_ERROR;
-}
-
-
-/*
- * Initialize driver-private structures
- */
-void
-sbicinit(dev)
- struct sbic_softc *dev;
-{
- u_int i;
-
- extern u_long scsi_nosync;
- extern int shift_nosync;
-
- if ( (dev->sc_flags & SBICF_ALIVE) == 0 ) {
-
- struct sbic_acb *acb;
-
- TAILQ_INIT(&dev->ready_list);
- TAILQ_INIT(&dev->nexus_list);
- TAILQ_INIT(&dev->free_list);
-
- dev->sc_nexus = NULL;
- dev->sc_xs = NULL;
-
- acb = dev->sc_acb;
- bzero(acb, sizeof(dev->sc_acb));
-
- for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
- TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
- acb++;
- }
-
- bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo));
-
-#ifdef DEBUG
- /*
- * make sure timeout is really not needed
- */
- timeout((void *)sbictimeout, dev, 30 * hz);
-#endif
-
- } else
- panic("sbic: reinitializing driver!");
-
- dev->sc_flags |= SBICF_ALIVE;
- dev->sc_flags &= ~SBICF_SELECTED;
-
- /*
- * initialize inhibit array
- */
- if ( scsi_nosync ) {
-
- u_int inhibit_sync = (scsi_nosync >> shift_nosync) & 0xff;
-
- shift_nosync += 8;
-
-#ifdef DEBUG
- if ( inhibit_sync )
- printf("%s: Inhibiting synchronous transfer %02x\n",
- dev->sc_dev.dv_xname, inhibit_sync);
-#endif
- for (i = 0; i < 8; ++i) {
- if ( inhibit_sync & (1 << i) )
- sbic_inhibit_sync[i] = 1;
- }
- }
-
- sbicreset(dev);
-}
-
-void
-sbicreset(dev)
- struct sbic_softc *dev;
-{
- sbic_regmap_p regs = dev->sc_sbicp;
- u_int my_id,
- s;
- u_char csr;
-
- s = splbio();
-
- my_id = dev->sc_link.adapter_target & SBIC_ID_MASK;
-
- if (dev->sc_clkfreq < 110)
- my_id |= SBIC_ID_FS_8_10;
- else if (dev->sc_clkfreq < 160)
- my_id |= SBIC_ID_FS_12_15;
- else if (dev->sc_clkfreq < 210)
- my_id |= SBIC_ID_FS_16_20;
-
- SET_SBIC_myid(regs, my_id);
-
- /*
- * Reset the chip
- */
- SET_SBIC_cmd(regs, SBIC_CMD_RESET);
- DELAY(25);
-
- SBIC_WAIT(regs, SBIC_ASR_INT, 0);
- GET_SBIC_csr(regs, csr); /* clears interrupt also */
-
- /*
- * Set up various chip parameters
- */
- SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
-
- /*
- * don't allow Selection (SBIC_RID_ES)
- * until we can handle target mode!!
- */
- SET_SBIC_rselid(regs, SBIC_RID_ER);
-
- /*
- * Asynchronous for now
- */
- SET_SBIC_syn(regs, 0);
-
- /*
- * Anything else was zeroed by reset
- */
- splx(s);
-
- dev->sc_flags &= ~SBICF_SELECTED;
-}
-
-void
-sbicerror(dev, csr)
- struct sbic_softc *dev;
- u_char csr;
-{
- struct scsi_xfer *xs = dev->sc_xs;
-
-#ifdef DIAGNOSTIC
- if ( xs == NULL )
- panic("sbicerror: dev->sc_xs == NULL");
-#endif
-
- if ( xs->flags & SCSI_SILENT )
- return;
-
- printf("%s: csr == 0x%02x\n", dev->sc_dev.dv_xname, csr);
-}
-
-/*
- * select the bus, return when selected or error.
- *
- * Returns the current CSR following selection and optionally MSG out phase.
- * i.e. the returned CSR *should* indicate CMD phase...
- * If the return value is 0, some error happened.
- */
-u_char
-sbicselectbus(dev)
- struct sbic_softc *dev;
-{
- sbic_regmap_p regs = dev->sc_sbicp;
- u_char target = dev->target,
- lun = dev->lun,
- asr,
- csr,
- id;
-
- /*
- * if we're already selected, return (XXXX panic maybe?)
- */
- if ( dev->sc_flags & SBICF_SELECTED )
- return(0);
-
- QPRINTF(("sbicselectbus %d: ", target));
-
- /*
- * issue select
- */
- SET_SBIC_selid(regs, target);
- SET_SBIC_timeo(regs, SBIC_TIMEOUT(250, dev->sc_clkfreq));
-
- GET_SBIC_asr(regs, asr);
-
- if ( asr & (SBIC_ASR_INT|SBIC_ASR_BSY) ) {
- /*
- * This means we got ourselves reselected upon
- */
- QPRINTF(("WD busy (reselect?)\n"));
- return 0;
- }
-
- SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN);
-
- /*
- * wait for select (merged from separate function may need
- * cleanup)
- */
- WAIT_CIP(regs);
-
- do {
-
- asr = SBIC_WAIT(regs, SBIC_ASR_INT | SBIC_ASR_LCI, 0);
-
- if ( asr & SBIC_ASR_LCI ) {
- QPRINTF(("late LCI: asr %02x\n", asr));
- return 0;
- }
-
- /*
- * Clear interrupt
- */
- GET_SBIC_csr (regs, csr);
-
- QPRINTF(("%02x ", csr));
-
- /*
- * Reselected from under our feet?
- */
- if ( csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY ) {
- QPRINTF(("got reselected, asr %02x\n", asr));
- /*
- * We need to handle this now so we don't lock up later
- */
- sbicnextstate(dev, csr, asr);
-
- return 0;
- }
-
- /*
- * Whoops!
- */
- if ( csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN ) {
- panic("sbicselectbus: target issued select!");
- return 0;
- }
-
- } while (csr != (SBIC_CSR_MIS_2 | MESG_OUT_PHASE) &&
- csr != (SBIC_CSR_MIS_2 | CMD_PHASE) &&
- csr != SBIC_CSR_SEL_TIMEO);
-
- /*
- * Anyone at home?
- */
- if ( csr == SBIC_CSR_SEL_TIMEO ) {
- dev->sc_xs->error = XS_SELTIMEOUT;
- QPRINTF(("Selection Timeout\n"));
- return 0;
- }
-
- QPRINTF(("Selection Complete\n"));
-
- /*
- * Assume we're now selected
- */
- GET_SBIC_selid(regs, id);
- dev->target = id;
- dev->lun = lun;
- dev->sc_flags |= SBICF_SELECTED;
-
- /*
- * Enable (or not) reselection
- * XXXSCW This is probably not necessary since we don't use use the
- * Select-and-Xfer-with-ATN command to initiate a selection...
- */
- if ( !sbic_enable_reselect && TAILQ_EMPTY(&dev->nexus_list))
- SET_SBIC_rselid (regs, 0);
- else
- SET_SBIC_rselid (regs, SBIC_RID_ER);
-
- /*
- * We only really need to do anything when the target goes to MSG out
- * If the device ignored ATN, it's probably old and brain-dead,
- * but we'll try to support it anyhow.
- * If it doesn't support message out, it definitely doesn't
- * support synchronous transfers, so no point in even asking...
- */
- if ( csr == (SBIC_CSR_MIS_2 | MESG_OUT_PHASE) ) {
- /*
- * Send identify message (SCSI-2 requires an identify msg)
- */
- if ( sbic_inhibit_sync[id] && dev->sc_sync[id].state == SYNC_START ) {
- /*
- * Handle drives that don't want to be asked
- * whether to go sync at all.
- */
- dev->sc_sync[id].offset = 0;
- dev->sc_sync[id].period = sbic_min_period;
- dev->sc_sync[id].state = SYNC_DONE;
- }
-
- /*
- * Do we need to negotiate Synchronous Xfers for this target?
- */
- if ( dev->sc_sync[id].state != SYNC_START ) {
- /*
- * Nope, we've already negotiated.
- * Now see if we should allow the target to disconnect/reselect...
- */
- if ( dev->sc_xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD ||
- !sbic_enable_reselect )
- SEND_BYTE (regs, MSG_IDENTIFY | lun);
- else
- SEND_BYTE (regs, MSG_IDENTIFY_DR | 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("\nSending sync request to target %d ... ", id);
-#endif
- /*
- * setup scsi message sync message request
- */
- dev->sc_msg[0] = MSG_IDENTIFY | lun;
- dev->sc_msg[1] = MSG_EXT_MESSAGE;
- dev->sc_msg[2] = 3;
- dev->sc_msg[3] = MSG_SYNC_REQ;
- dev->sc_msg[4] = sbictoscsiperiod(dev, sbic_min_period);
- dev->sc_msg[5] = sbic_max_offset;
-
- sbicxfout(regs, 6, dev->sc_msg);
-
- dev->sc_sync[id].state = SYNC_SENT;
-#ifdef DEBUG
- if ( sync_debug )
- printf ("sent\n");
-#endif
- }
-
- /*
- * There's one interrupt still to come: the change to CMD phase...
- */
- SBIC_WAIT(regs, SBIC_ASR_INT , 0);
- GET_SBIC_csr(regs, csr);
- }
-
- /*
- * set sync or async
- */
- if ( dev->sc_sync[target].state == SYNC_DONE ) {
-#ifdef DEBUG
- if ( sync_debug )
- printf("select(%d): sync reg = 0x%02x\n", target,
- SBIC_SYN(dev->sc_sync[target].offset,
- dev->sc_sync[target].period));
-#endif
- SET_SBIC_syn(regs, SBIC_SYN(dev->sc_sync[target].offset,
- dev->sc_sync[target].period));
- } else {
-#ifdef DEBUG
- if ( sync_debug )
- printf("select(%d): sync reg = 0x%02x\n", target,
- SBIC_SYN(0,sbic_min_period));
-#endif
- SET_SBIC_syn(regs, SBIC_SYN(0, sbic_min_period));
- }
-
- return csr;
-}
-
-/*
- * Information Transfer *to* a Scsi Target.
- *
- * Note: Don't expect there to be an interrupt immediately after all
- * the data is transferred out. The WD spec sheet says that the Transfer-
- * Info command for non-MSG_IN phases only completes when the target
- * next asserts 'REQ'. That is, when the SCSI bus changes to a new state.
- *
- * This can have a nasty effect on commands which take a relatively long
- * time to complete, for example a START/STOP unit command may remain in
- * CMD phase until the disk has spun up. Only then will the target change
- * to STATUS phase. This is really only a problem for immediate commands
- * since we don't allow disconnection for them (yet).
- */
-int
-sbicxfout(regs, len, bp)
- sbic_regmap_p regs;
- int len;
- void *bp;
-{
- int wait = sbic_data_wait;
- u_char asr,
- *buf = bp;
-
- 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]));
-
- /*
- * 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 (regs);
-
- SBIC_TC_PUT (regs, 0);
- SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
- SBIC_TC_PUT (regs, (unsigned)len);
- SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
-
- /*
- * Loop for each byte transferred
- */
- do {
-
- GET_SBIC_asr (regs, asr);
-
- if ( asr & SBIC_ASR_DBR ) {
- if ( len ) {
- SET_SBIC_data (regs, *buf);
- buf++;
- len--;
- } else {
- SET_SBIC_data (regs, 0);
- }
- wait = sbic_data_wait;
- }
-
- } while ( len && (asr & SBIC_ASR_INT) == 0 && wait-- > 0 );
-
-#ifdef DEBUG
- QPRINTF(("sbicxfout done: %d bytes remaining (wait:%d)\n", len, wait));
-#endif
-
- /*
- * Normally, an interrupt will be pending when this routing returns.
- */
- return(len);
-}
-
-/*
- * Information Transfer *from* a Scsi Target
- * returns # bytes left to read
- */
-int
-sbicxfin(regs, len, bp)
- sbic_regmap_p regs;
- int len;
- void *bp;
-{
- int wait = sbic_data_wait;
- u_char *buf = bp;
- u_char asr;
-#ifdef DEBUG
- u_char *obp = bp;
-#endif
-
- WAIT_CIP (regs);
-
- SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
- SBIC_TC_PUT (regs, (unsigned)len);
- SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
-
- /*
- * Loop for each byte transferred
- */
- do {
-
- GET_SBIC_asr (regs, asr);
-
- if ( asr & SBIC_ASR_DBR ) {
- if ( len ) {
- GET_SBIC_data (regs, *buf);
- buf++;
- len--;
- } else {
- u_char foo;
- GET_SBIC_data (regs, foo);
- }
- wait = sbic_data_wait;
- }
-
- } while ( (asr & SBIC_ASR_INT) == 0 && wait-- > 0 );
-
- 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]));
-
- SBIC_TC_PUT (regs, 0);
-
- /*
- * this leaves with one csr to be read
- */
- return len;
-}
-
-/*
- * 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.
- *
- * Note that although this routine looks like it can handle disconnect/
- * reselect, the fact is that it can't. There is still some work to be
- * done to clean this lot up.
- */
-int
-sbicicmd(dev, cbuf, clen, buf, len)
- struct sbic_softc *dev;
- void *cbuf,
- *buf;
- int clen,
- len;
-{
- sbic_regmap_p regs = dev->sc_sbicp;
- struct sbic_acb *acb = dev->sc_nexus;
- u_char csr,
- asr;
- int still_busy = SBIC_STATE_RUNNING;
-#ifdef DEBUG
- int counter = 0;
-#endif
-
- /*
- * Make sure pointers are OK
- */
- dev->sc_last = dev->sc_cur = &acb->sc_pa;
- dev->sc_tcnt = acb->sc_tcnt = 0;
-
- acb->sc_dmacmd = 0;
- acb->sc_pa.dc_count = 0; /* No DMA */
- acb->sc_kv.dc_addr = buf;
- acb->sc_kv.dc_count = len;
-
-#ifdef DEBUG
- if ( data_pointer_debug > 1 )
- printf("sbicicmd(%d,%d):%d\n", dev->target, dev->lun, acb->sc_kv.dc_count);
-#endif
-
- /*
- * set the sbic into non-DMA mode
- */
- SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
-
- dev->sc_stat[0] = 0xff;
- dev->sc_msg[0] = 0xff;
-
- /*
- * We're stealing the SCSI bus
- */
- dev->sc_flags |= SBICF_ICMD;
-
- do {
- GET_SBIC_asr (regs, asr);
-
- /*
- * select the SCSI bus (it's an error if bus isn't free)
- */
- if ( (dev->sc_flags & SBICF_SELECTED) == 0 &&
- still_busy != SBIC_STATE_DISCONNECT ) {
- if ( (csr = sbicselectbus(dev)) == 0 ) {
- dev->sc_flags &= ~SBICF_ICMD;
- return(-1);
- }
- } else
- if ( (asr & (SBIC_ASR_BSY | SBIC_ASR_INT)) == SBIC_ASR_INT )
- GET_SBIC_csr(regs, csr);
- else
- csr = 0;
-
- if ( csr ) {
-
- QPRINTF((">ASR:0x%02x CSR:0x%02x< ", asr, csr));
-
- switch ( csr ) {
-
- case SBIC_CSR_S_XFERRED:
- case SBIC_CSR_DISC:
- case SBIC_CSR_DISC_1:
- {
- u_char phase;
-
- dev->sc_flags &= ~SBICF_SELECTED;
- GET_SBIC_cmd_phase (regs, phase);
-
- if ( phase == 0x60 ) {
- GET_SBIC_tlun (regs, dev->sc_stat[0]);
- still_busy = SBIC_STATE_DONE; /* done */
- } else {
-#ifdef DEBUG
- if ( reselect_debug > 1 )
- printf("sbicicmd: handling disconnect\n");
-#endif
- still_busy = SBIC_STATE_DISCONNECT;
- }
- }
- break;
-
- case SBIC_CSR_XFERRED | CMD_PHASE:
- case SBIC_CSR_MIS | CMD_PHASE:
- case SBIC_CSR_MIS_1 | CMD_PHASE:
- case SBIC_CSR_MIS_2 | CMD_PHASE:
- {
- if ( sbicxfout(regs, clen, cbuf) )
- still_busy = sbicabort(dev, "icmd sending cmd");
- }
- break;
-
- case SBIC_CSR_XFERRED | STATUS_PHASE:
- case SBIC_CSR_MIS | STATUS_PHASE:
- case SBIC_CSR_MIS_1 | STATUS_PHASE:
- case SBIC_CSR_MIS_2 | STATUS_PHASE:
- {
- /*
- * The sbic does the status/cmd-complete reading ok,
- * so do this with its hi-level commands.
- */
-#ifdef DEBUG
- if ( sbic_debug )
- printf("SBICICMD status phase (bsy=%d)\n", still_busy);
-#endif
- SET_SBIC_cmd_phase(regs, 0x46);
- SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
- }
- break;
-
- default:
- {
- still_busy = sbicnextstate(dev, csr, asr);
- }
- break;
- }
-
- /*
- * make sure the last command was taken,
- * ie. we're not hunting after an ignored command..
- */
- GET_SBIC_asr(regs, asr);
-
- /*
- * tapes may take a loooong time..
- */
- while (asr & SBIC_ASR_BSY ) {
-
- if ( asr & SBIC_ASR_DBR ) {
- int i;
-
- printf("sbicicmd: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n", csr,asr);
-#ifdef DDB
- Debugger();
-#endif
- /*
- * SBIC is jammed
- * DUNNO which direction
- * Try old direction
- */
- GET_SBIC_data(regs, i);
- GET_SBIC_asr(regs, asr);
-
- if ( asr & SBIC_ASR_DBR ) /* Wants us to write */
- SET_SBIC_data(regs, i);
- }
-
- GET_SBIC_asr(regs, asr);
- }
- }
-
- /*
- * wait for last command to complete
- */
- if ( asr & SBIC_ASR_LCI ) {
- printf("sbicicmd: last command ignored\n");
- }
- else
- if ( still_busy >= SBIC_STATE_RUNNING ) /* Bsy */
- SBIC_WAIT (regs, SBIC_ASR_INT, sbic_cmd_wait);
-
- /*
- * do it again
- */
- } while ( still_busy >= SBIC_STATE_RUNNING && dev->sc_stat[0] == 0xff );
-
- /*
- * Sometimes we need to do an extra read of the CSR
- */
- GET_SBIC_csr(regs, csr);
-
-#ifdef DEBUG
- if ( data_pointer_debug > 1 )
- printf("sbicicmd done(%d,%d):%d =%d=\n", dev->target, dev->lun,
- acb->sc_kv.dc_count,
- dev->sc_stat[0]);
-#endif
-
- dev->sc_flags &= ~SBICF_ICMD;
-
- return(dev->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.
- */
-void
-sbicxfdone(dev)
- struct sbic_softc *dev;
-{
- sbic_regmap_p regs = dev->sc_sbicp;
- u_char phase,
- csr;
- int s;
-
- QPRINTF(("{"));
- s = splbio();
-
- /*
- * have the sbic complete on its own
- */
- SBIC_TC_PUT(regs, 0);
- SET_SBIC_cmd_phase(regs, 0x46);
- SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
-
- do {
-
- SBIC_WAIT (regs, SBIC_ASR_INT, 0);
- GET_SBIC_csr (regs, csr);
- QPRINTF(("%02x:", csr));
-
- } while ( (csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) &&
- (csr != SBIC_CSR_S_XFERRED));
-
- dev->sc_flags &= ~SBICF_SELECTED;
-
- GET_SBIC_cmd_phase (regs, phase);
- QPRINTF(("}%02x", phase));
-
- if ( phase == 0x60 )
- GET_SBIC_tlun(regs, dev->sc_stat[0]);
- else
- sbicerror(dev, csr);
-
- QPRINTF(("=STS:%02x=\n", dev->sc_stat[0]));
-
- splx(s);
-}
-
-/*
- * No DMA chains
- */
-int
-sbicgo(dev, xs)
- struct sbic_softc *dev;
- struct scsi_xfer *xs;
-{
- struct sbic_acb *acb = dev->sc_nexus;
- sbic_regmap_p regs = dev->sc_sbicp;
- int i,
- dmaflags,
- count,
- usedma;
- u_char csr,
- asr,
- *addr;
-
- dev->target = xs->sc_link->target;
- dev->lun = xs->sc_link->lun;
-
- usedma = sbicdmaok(dev, xs);
-
-#ifdef DEBUG
- if ( data_pointer_debug > 1 )
- printf("sbicgo(%d,%d): usedma=%d\n", dev->target, dev->lun, usedma);
-#endif
-
- /*
- * select the SCSI bus (it's an error if bus isn't free)
- */
- if ( (csr = sbicselectbus(dev)) == 0 )
- return(0); /* Not done: needs to be rescheduled */
-
- dev->sc_stat[0] = 0xff;
-
- /*
- * Calculate DMA chains now
- */
- if ( acb->flags & ACB_DATAIN )
- dmaflags = DMAGO_READ;
- else
- dmaflags = 0;
-
- addr = acb->sc_kv.dc_addr;
- count = acb->sc_kv.dc_count;
-
- if ( count && ((char *)kvtop((vaddr_t)addr) != acb->sc_pa.dc_addr) ) {
- printf("sbic: DMA buffer mapping changed %p->%lx\n",
- acb->sc_pa.dc_addr, kvtop((vaddr_t)addr));
-#ifdef DDB
- Debugger();
-#endif
- }
-
-#ifdef DEBUG
- ++sbicdma_ops; /* count total DMA operations */
-#endif
-
- /*
- * Allocate the DMA chain
- * Mark end of segment...
- */
- acb->sc_tcnt = dev->sc_tcnt = 0;
- acb->sc_pa.dc_count = 0;
-
- sbic_load_ptrs(dev);
-
- /*
- * Enable interrupts but don't do any DMA
- * enintr() also enables interrupts for the sbic
- */
- dev->sc_enintr(dev);
-
- if ( usedma ) {
- dev->sc_tcnt = dev->sc_dmago(dev, acb->sc_pa.dc_addr,
- acb->sc_pa.dc_count, dmaflags);
-#ifdef DEBUG
- dev->sc_dmatimo = dev->sc_tcnt ? 1 : 0;
-#endif
- } else
- dev->sc_dmacmd = 0; /* Don't use DMA */
-
- acb->sc_dmacmd = dev->sc_dmacmd;
-
-#ifdef DEBUG
- if ( data_pointer_debug > 1 ) {
- printf("sbicgo dmago:%d(%x:%x) dmacmd=0x%02x\n", dev->target,
- dev->sc_cur->dc_addr,
- dev->sc_tcnt,
- dev->sc_dmacmd);
- }
-#endif
-
- /*
- * Lets cycle a while then let the interrupt handler take over.
- */
- GET_SBIC_asr(regs, asr);
-
- do {
-
- QPRINTF(("go "));
-
- /*
- * Handle the new phase
- */
- i = sbicnextstate(dev, csr, asr);
-#if 0
- WAIT_CIP(regs);
-#endif
- if ( i == SBIC_STATE_RUNNING ) {
- GET_SBIC_asr(regs, asr);
-
- if ( asr & SBIC_ASR_LCI )
- printf("sbicgo: LCI asr:%02x csr:%02x\n", asr, csr);
-
- if ( asr & SBIC_ASR_INT )
- GET_SBIC_csr(regs, csr);
- }
-
- } while ( i == SBIC_STATE_RUNNING && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) );
-
- if ( i == SBIC_STATE_DONE ) {
- if ( dev->sc_stat[0] == 0xff )
-#if 0
- printf("sbicgo: done & stat = 0xff\n");
-#else
- ;
-#endif
- else
- return 1; /* Did we really finish that fast? */
- }
-
- return 0;
-}
-
-
-int
-sbicintr(dev)
- struct sbic_softc *dev;
-{
- sbic_regmap_p regs = dev->sc_sbicp;
- u_char asr,
- csr;
- int i;
-
- /*
- * pending interrupt?
- */
- GET_SBIC_asr (regs, asr);
- if ( (asr & SBIC_ASR_INT) == 0 )
- return(0);
-
- GET_SBIC_csr(regs, csr);
-
- do {
-
- QPRINTF(("intr[0x%x]", csr));
-
- i = sbicnextstate(dev, csr, asr);
-#if 0
- WAIT_CIP(regs);
-#endif
- if ( i == SBIC_STATE_RUNNING ) {
- GET_SBIC_asr(regs, asr);
-
- if ( asr & SBIC_ASR_LCI )
- printf("sbicgo: LCI asr:%02x csr:%02x\n", asr, csr);
-
- if ( asr & SBIC_ASR_INT )
- GET_SBIC_csr(regs, csr);
- }
-
- } while ( i == SBIC_STATE_RUNNING && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) );
-
- QPRINTF(("intr done. state=%d, asr=0x%02x\n", i, asr));
-
- return(1);
-}
-
-/*
- * Run commands and wait for disconnect.
- * This is only ever called when a command is in progress, when we
- * want to busy wait for it to finish.
- */
-int
-sbicpoll(dev)
- struct sbic_softc *dev;
-{
- sbic_regmap_p regs = dev->sc_sbicp;
- u_char asr,
- csr = 0;
- int i;
-
- /*
- * Wait for the next interrupt
- */
- SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
-
- do {
- GET_SBIC_asr (regs, asr);
-
- if ( asr & SBIC_ASR_INT )
- GET_SBIC_csr(regs, csr);
-
- QPRINTF(("poll[0x%x]", csr));
-
- /*
- * Handle it
- */
- i = sbicnextstate(dev, csr, asr);
-
- WAIT_CIP(regs);
- GET_SBIC_asr(regs, asr);
-
- /*
- * tapes may take a loooong time..
- */
- while ( asr & SBIC_ASR_BSY ) {
- u_char z = 0;
-
- if ( asr & SBIC_ASR_DBR ) {
- printf("sbipoll: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n", csr,asr);
-#ifdef DDB
- Debugger();
-#endif
- /*
- * SBIC is jammed
- * DUNNO which direction
- * Try old direction
- */
- GET_SBIC_data(regs, z);
- GET_SBIC_asr(regs, asr);
-
- if ( asr & SBIC_ASR_DBR ) /* Wants us to write */
- SET_SBIC_data(regs, z);
- }
-
- GET_SBIC_asr(regs, asr);
- }
-
- if ( asr & SBIC_ASR_LCI )
- printf("sbicpoll: LCI asr:%02x csr:%02x\n", asr,csr);
- else
- if ( i == SBIC_STATE_RUNNING ) /* BSY */
- SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
-
- } while ( i == SBIC_STATE_RUNNING );
-
- return(1);
-}
-
-/*
- * Handle a single msgin
- */
-int
-sbicmsgin(dev)
- struct sbic_softc *dev;
-{
- sbic_regmap_p regs = dev->sc_sbicp;
- int recvlen = 1;
- u_char asr,
- csr,
- *tmpaddr,
- *msgaddr;
-
- tmpaddr = msgaddr = dev->sc_msg;
-
- tmpaddr[0] = 0xff;
- tmpaddr[1] = 0xff;
-
- GET_SBIC_asr(regs, asr);
-
-#ifdef DEBUG
- if ( reselect_debug > 1 )
- printf("sbicmsgin asr=%02x\n", asr);
-#endif
-
- GET_SBIC_selid (regs, csr);
- SET_SBIC_selid (regs, csr | SBIC_SID_FROM_SCSI);
-
- SBIC_TC_PUT(regs, 0);
- SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
-
- do {
- while( recvlen-- ) {
-
- /*
- * Fetch the next byte of the message
- */
- RECV_BYTE(regs, *tmpaddr);
-
- /*
- * get the command completion interrupt, or we
- * can't send a new command (LCI)
- */
- SBIC_WAIT(regs, SBIC_ASR_INT, 0);
- GET_SBIC_csr(regs, csr);
-
-#ifdef DEBUG
- if ( reselect_debug > 1 )
- printf("sbicmsgin: got %02x csr %02x\n", *tmpaddr, csr);
-#endif
-
- tmpaddr++;
-
- if ( recvlen ) {
- /*
- * Clear ACK, and wait for the interrupt for the next byte
- */
- SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
- SBIC_WAIT(regs, SBIC_ASR_INT, 0);
- GET_SBIC_csr(regs, csr);
- }
- }
-
- if ( msgaddr[0] == 0xff ) {
- printf("sbicmsgin: sbic swallowed our message\n");
- break;
- }
-
-#ifdef DEBUG
- if ( sync_debug ) {
- GET_SBIC_asr(regs, asr);
- printf("msgin done csr 0x%x asr 0x%x msg 0x%x\n", csr, asr, msgaddr[0]);
- }
-#endif
- /*
- * test whether this is a reply to our sync
- * request
- */
- if ( MSG_ISIDENTIFY(msgaddr[0]) ) {
-
- /*
- * Got IFFY msg -- ack it
- */
- QPRINTF(("IFFY"));
-
- } else
- if ( msgaddr[0] == MSG_REJECT &&
- dev->sc_sync[dev->target].state == SYNC_SENT) {
-
- /*
- * Target probably rejected our Sync negotiation.
- */
- QPRINTF(("REJECT of SYN"));
-
-#ifdef DEBUG
- if ( sync_debug )
- printf("target %d rejected sync, going async\n", dev->target);
-#endif
-
- dev->sc_sync[dev->target].period = sbic_min_period;
- dev->sc_sync[dev->target].offset = 0;
- dev->sc_sync[dev->target].state = SYNC_DONE;
- SET_SBIC_syn(regs, SBIC_SYN(dev->sc_sync[dev->target].offset,
- dev->sc_sync[dev->target].period));
-
- } else
- if ( msgaddr[0] == MSG_REJECT ) {
-
- /*
- * we'll never REJECt a REJECT message..
- */
- QPRINTF(("REJECT"));
-
- } else
- if ( msgaddr[0] == MSG_SAVE_DATA_PTR ) {
-
- /*
- * don't reject this either.
- */
- QPRINTF(("MSG_SAVE_DATA_PTR"));
-
- } else
- if ( msgaddr[0] == MSG_RESTORE_PTR ) {
-
- /*
- * don't reject this either.
- */
- QPRINTF(("MSG_RESTORE_PTR"));
-
- } else
- if ( msgaddr[0] == MSG_DISCONNECT ) {
-
- /*
- * Target is disconnecting...
- */
- QPRINTF(("DISCONNECT"));
-
-#ifdef DEBUG
- if ( reselect_debug > 1 && msgaddr[0] == MSG_DISCONNECT )
- printf("sbicmsgin: got disconnect msg %s\n",
- (dev->sc_flags & SBICF_ICMD) ? "rejecting" : "");
-#endif
-
- if ( dev->sc_flags & SBICF_ICMD ) {
- /*
- * We're in immediate mode. Prevent disconnects.
- * prepare to reject the message, NACK
- */
- SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
- WAIT_CIP(regs);
- }
-
- } else
- if ( msgaddr[0] == MSG_CMD_COMPLETE ) {
-
- /*
- * !! 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.
- */
- QPRINTF(("CMD_COMPLETE"));
-
-#ifdef DEBUG
- if ( sync_debug )
- printf ("GOT MSG %d! target %d acting weird.."
- " waiting for disconnect...\n", msgaddr[0], dev->target);
-#endif
-
- /*
- * Check to see if sbic is handling this
- */
- GET_SBIC_asr(regs, asr);
-
- /*
- * XXXSCW: I'm not convinced of this, we haven't negated ACK yet...
- */
- if ( asr & SBIC_ASR_BSY )
- return SBIC_STATE_RUNNING;
-
- /*
- * Let's try this: Assume it works and set status to 00
- */
- dev->sc_stat[0] = 0;
-
- } else
- if ( msgaddr[0] == MSG_EXT_MESSAGE && tmpaddr == &(msgaddr[1]) ) {
-
- /*
- * Target is sending us an extended message. We'll assume it's
- * the response to our Sync. negotiation.
- */
- QPRINTF(("ExtMSG\n"));
-
- /*
- * Read in whole extended message. First, negate ACK to accept
- * the MSG_EXT_MESSAGE byte...
- */
- SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
-
- /*
- * Wait for the interrupt for the next byte (length)
- */
- SBIC_WAIT(regs, SBIC_ASR_INT, 0);
- GET_SBIC_csr(regs, csr);
-
-#ifdef DEBUG
- QPRINTF(("CLR ACK csr %02x\n", csr));
-#endif
-
- /*
- * Read the length byte
- */
- RECV_BYTE(regs, *tmpaddr);
-
- /*
- * Wait for command completion IRQ
- */
- SBIC_WAIT(regs, SBIC_ASR_INT, 0);
- GET_SBIC_csr(regs, csr);
-
- /*
- * Reload the loop counter
- */
- recvlen = *tmpaddr++;
-
- QPRINTF(("Recving ext msg, csr %02x len %02x\n", csr, recvlen));
-
- } else
- if ( msgaddr[0] == MSG_EXT_MESSAGE && msgaddr[1] == 3 &&
- msgaddr[2] == MSG_SYNC_REQ ) {
-
- /*
- * We've received the complete Extended Message Sync. Request...
- */
- QPRINTF(("SYN"));
-
- /*
- * Compute the required Transfer Period for the WD chip...
- */
- dev->sc_sync[dev->target].period = sbicfromscsiperiod(dev, msgaddr[3]);
- dev->sc_sync[dev->target].offset = msgaddr[4];
- dev->sc_sync[dev->target].state = SYNC_DONE;
-
- /*
- * Put the WD chip in synchronous mode
- */
- SET_SBIC_syn(regs, SBIC_SYN(dev->sc_sync[dev->target].offset,
- dev->sc_sync[dev->target].period));
-#ifdef DEBUG
- if ( sync_debug )
- printf("msgin(%d): sync reg = 0x%02x\n", dev->target,
- SBIC_SYN(dev->sc_sync[dev->target].offset,
- dev->sc_sync[dev->target].period));
-#endif
-
- printf("%s: target %d now synchronous, period=%dns, offset=%d.\n",
- dev->sc_dev.dv_xname, dev->target,
- msgaddr[3] * 4, msgaddr[4]);
-
- } else {
-
- /*
- * We don't support whatever this message is...
- */
-#ifdef DEBUG
- if ( sbic_debug || sync_debug )
- printf ("sbicmsgin: Rejecting message 0x%02x\n", msgaddr[0]);
-#endif
-
- /*
- * prepare to reject the message, NACK
- */
- SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
- WAIT_CIP(regs);
- }
-
- /*
- * Negate ACK to complete the transfer
- */
- SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
-
- /*
- * Wait for the interrupt for the next byte, or phase change.
- * Only read the CSR if we have more data to transfer.
- * XXXSCW: We should really verify that we're still in MSG IN phase
- * before blindly going back around this loop, but that would mean
- * we read the CSR... <sigh>
- */
- SBIC_WAIT(regs, SBIC_ASR_INT, 0);
- if ( recvlen > 0 )
- GET_SBIC_csr(regs, csr);
-
- } while ( recvlen > 0 );
-
- /*
- * Should still have one CSR to read
- */
- return SBIC_STATE_RUNNING;
-}
-
-
-/*
- * sbicnextstate()
- * return:
- * SBIC_STATE_DONE == done
- * SBIC_STATE_RUNNING == working
- * SBIC_STATE_DISCONNECT == disconnected
- * SBIC_STATE_ERROR == error
- */
-int
-sbicnextstate(dev, csr, asr)
- struct sbic_softc *dev;
- u_char csr,
- asr;
-{
- sbic_regmap_p regs = dev->sc_sbicp;
- struct sbic_acb *acb = dev->sc_nexus;
-
- QPRINTF(("next[%02x,%02x]: ",asr,csr));
-
- switch (csr) {
-
- case SBIC_CSR_XFERRED | CMD_PHASE:
- case SBIC_CSR_MIS | CMD_PHASE:
- case SBIC_CSR_MIS_1 | CMD_PHASE:
- case SBIC_CSR_MIS_2 | CMD_PHASE:
- {
- if ( sbicxfout(regs, acb->clen, &acb->cmd) )
- goto abort;
- }
- break;
-
- case SBIC_CSR_XFERRED | STATUS_PHASE:
- case SBIC_CSR_MIS | STATUS_PHASE:
- case SBIC_CSR_MIS_1 | STATUS_PHASE:
- case SBIC_CSR_MIS_2 | STATUS_PHASE:
- {
- SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
-
- /*
- * this should be the normal i/o completion case.
- * get the status & cmd complete msg then let the
- * device driver look at what happened.
- */
- sbicxfdone(dev);
-
-#ifdef DEBUG
- dev->sc_dmatimo = 0;
- if ( data_pointer_debug > 1 )
- printf("next dmastop: %d(%x:%x)\n", dev->target,
- dev->sc_cur->dc_addr,
- dev->sc_tcnt);
-#endif
- /*
- * Stop the DMA chip
- */
- dev->sc_dmastop(dev);
-
- dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH);
-
- /*
- * Indicate to the upper layers that the command is done
- */
- sbic_scsidone(acb, dev->sc_stat[0]);
-
- return SBIC_STATE_DONE;
- }
-
- case SBIC_CSR_XFERRED | DATA_OUT_PHASE:
- case SBIC_CSR_XFERRED | DATA_IN_PHASE:
- case SBIC_CSR_MIS | DATA_OUT_PHASE:
- case SBIC_CSR_MIS | DATA_IN_PHASE:
- case SBIC_CSR_MIS_1 | DATA_OUT_PHASE:
- case SBIC_CSR_MIS_1 | DATA_IN_PHASE:
- case SBIC_CSR_MIS_2 | DATA_OUT_PHASE:
- case SBIC_CSR_MIS_2 | DATA_IN_PHASE:
- {
- /*
- * Verify that we expected to transfer data...
- */
- if ( acb->sc_kv.dc_count <= 0 ) {
- printf("next: DATA phase with xfer count == %d, asr:0x%02x csr:0x%02x\n",
- acb->sc_kv.dc_count, asr, csr);
- goto abort;
- }
-
- /*
- * Should we transfer using PIO or DMA ?
- */
- if ( dev->sc_xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD ||
- acb->sc_dmacmd == 0 ) {
-
- /*
- * Do PIO transfer
- */
- int i;
-
-#ifdef DEBUG
- if ( data_pointer_debug > 1 )
- printf("next PIO: %d(%x:%x)\n", dev->target,
- acb->sc_kv.dc_addr,
- acb->sc_kv.dc_count);
-#endif
-
- if ( SBIC_PHASE(csr) == DATA_IN_PHASE )
- /*
- * data in
- */
- i = sbicxfin(regs, acb->sc_kv.dc_count,
- acb->sc_kv.dc_addr);
- else
- /*
- * data out
- */
- i = sbicxfout(regs, acb->sc_kv.dc_count,
- acb->sc_kv.dc_addr);
-
- acb->sc_kv.dc_addr += (acb->sc_kv.dc_count - i);
- acb->sc_kv.dc_count = i;
-
- /*
- * Update current count...
- */
- acb->sc_tcnt = dev->sc_tcnt = i;
-
- dev->sc_flags &= ~SBICF_INDMA;
-
- } else {
-
- /*
- * Do DMA transfer
- * set next dma addr and dec count
- */
- sbic_save_ptrs(dev);
- sbic_load_ptrs(dev);
-
- SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI |
- SBIC_MACHINE_DMA_MODE);
-
-#ifdef DEBUG
- dev->sc_dmatimo = 1;
- if ( data_pointer_debug > 1 )
- printf("next DMA: %d(%x:%x)\n", dev->target,
- dev->sc_cur->dc_addr,
- dev->sc_tcnt);
-#endif
- /*
- * Start the DMA chip going
- */
- dev->sc_tcnt = dev->sc_dmanext(dev);
-
- /*
- * Tell the WD chip how much to transfer this time around
- */
- SBIC_TC_PUT(regs, (unsigned)dev->sc_tcnt);
-
- /*
- * Start the transfer
- */
- SET_SBIC_cmd(regs, SBIC_CMD_XFER_INFO);
-
- /*
- * Indicate that we're in DMA mode
- */
- dev->sc_flags |= SBICF_INDMA;
- }
- }
- break;
-
- case SBIC_CSR_XFERRED | MESG_IN_PHASE:
- case SBIC_CSR_MIS | MESG_IN_PHASE:
- case SBIC_CSR_MIS_1 | MESG_IN_PHASE:
- case SBIC_CSR_MIS_2 | MESG_IN_PHASE:
- {
- sbic_save_ptrs(dev);
-
- /*
- * Handle a single message in...
- */
- return sbicmsgin(dev);
- }
-
- case SBIC_CSR_MSGIN_W_ACK:
- {
- /*
- * We should never see this since it's handled in 'sbicmsgin()'
- * but just for the sake of paranoia...
- */
- SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); /* Dunno what I'm ACKing */
- printf("Acking unknown msgin CSR:%02x",csr);
- }
- break;
-
- case SBIC_CSR_XFERRED | MESG_OUT_PHASE:
- case SBIC_CSR_MIS | MESG_OUT_PHASE:
- case SBIC_CSR_MIS_1 | MESG_OUT_PHASE:
- case SBIC_CSR_MIS_2 | MESG_OUT_PHASE:
- {
- /*
- * We only ever handle a message out phase here for sending a
- * REJECT message.
- */
- sbic_save_ptrs(dev);
-
-#ifdef DEBUG
- if (sync_debug)
- printf ("sending REJECT msg to last msg.\n");
-#endif
-
- SEND_BYTE(regs, MSG_REJECT);
- WAIT_CIP(regs);
- }
- break;
-
- case SBIC_CSR_DISC:
- case SBIC_CSR_DISC_1:
- {
- /*
- * Try to schedule another target
- */
- sbic_save_ptrs(dev);
-
- dev->sc_flags &= ~SBICF_SELECTED;
-
-#ifdef DEBUG
- if ( reselect_debug > 1 )
- printf("sbicnext target %d disconnected\n", dev->target);
-#endif
-
- TAILQ_INSERT_HEAD(&dev->nexus_list, acb, chain);
-
- ++dev->sc_tinfo[dev->target].dconns;
-
- dev->sc_nexus = NULL;
- dev->sc_xs = NULL;
-
- if ( acb->xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD ||
- !sbic_parallel_operations )
- return SBIC_STATE_DISCONNECT;
-
- QPRINTF(("sbicnext: calling sbic_sched\n"));
-
- sbic_sched(dev);
-
- QPRINTF(("sbicnext: sbic_sched returned\n"));
-
- return SBIC_STATE_DISCONNECT;
- }
-
- case SBIC_CSR_RSLT_NI:
- case SBIC_CSR_RSLT_IFY:
- {
- /*
- * A reselection.
- * Note that since we don't enable Advanced Features (assuming
- * the WD chip is at least the 'A' revision), we're only ever
- * likely to see the 'SBIC_CSR_RSLT_NI' status. But for the
- * hell of it, we'll handle it anyway, for all the extra code
- * it needs...
- */
- u_char newtarget,
- newlun;
-
- GET_SBIC_rselid(regs, newtarget);
-
- /*
- * check SBIC_RID_SIV?
- */
- newtarget &= SBIC_RID_MASK;
-
- if ( csr == SBIC_CSR_RSLT_IFY ) {
-
- /*
- * Read Identify msg to avoid lockup
- */
- GET_SBIC_data(regs, newlun);
- WAIT_CIP(regs);
- newlun &= SBIC_TLUN_MASK;
-
- } else {
-
- /*
- * Need to read Identify message the hard way, assuming
- * the target even sends us one...
- */
- for (newlun = 255; newlun; --newlun) {
- GET_SBIC_asr(regs, asr);
- if (asr & SBIC_ASR_INT)
- break;
- delay(10);
- }
-
- /*
- * If we didn't get an interrupt, somethink's up
- */
- if ( (asr & SBIC_ASR_INT) == 0 ) {
- printf("%s: Reselect without identify? asr %x\n",
- dev->sc_dev.dv_xname, asr);
- newlun = 0; /* XXXX */
- } else {
- /*
- * We got an interrupt, verify that it's a change to
- * message in phase, and if so read the message.
- */
- GET_SBIC_csr(regs,csr);
-
- if (csr == (SBIC_CSR_MIS | MESG_IN_PHASE) ||
- csr == (SBIC_CSR_MIS_1 | MESG_IN_PHASE) ||
- csr == (SBIC_CSR_MIS_2 | MESG_IN_PHASE)) {
- /*
- * Yup, gone to message in. Fetch the target LUN
- */
- sbicmsgin(dev);
- newlun = dev->sc_msg[0] & 0x07;
-
- } else {
- /*
- * Whoops! Target didn't go to message in phase!!
- */
- printf("RSLT_NI - not MESG_IN_PHASE %x\n", csr);
- newlun = 0; /* XXXSCW */
- }
- }
- }
-
- /*
- * Ok, we have the identity of the reselecting target.
- */
-#ifdef DEBUG
- if ( reselect_debug > 1 ||
- (reselect_debug && csr == SBIC_CSR_RSLT_NI) ) {
- printf("sbicnext: reselect %s from targ %d lun %d\n",
- csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget, newlun);
- }
-#endif
-
- if ( dev->sc_nexus ) {
- /*
- * Whoops! We've been reselected with an command in progress!
- * The best we can do is to put the current command back on the
- * ready list and hope for the best.
- */
-#ifdef DEBUG
- if ( reselect_debug > 1 ) {
- printf("%s: reselect %s with active command\n",
- dev->sc_dev.dv_xname,
- csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY");
- }
-#endif
-
- TAILQ_INSERT_HEAD(&dev->ready_list, dev->sc_nexus, chain);
-
- dev->sc_tinfo[dev->target].lubusy &= ~(1 << dev->lun);
-
- dev->sc_nexus = NULL;
- dev->sc_xs = NULL;
- }
-
- /*
- * Reload sync values for this target
- */
- if ( dev->sc_sync[newtarget].state == SYNC_DONE )
- SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[newtarget].offset,
- dev->sc_sync[newtarget].period));
- else
- SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
-
- /*
- * Loop through the nexus list until we find the saved entry
- * for the reselecting target...
- */
- TAILQ_FOREACH(acb, &dev->nexus_list, chain) {
-
- if ( acb->xs->sc_link->target == newtarget &&
- acb->xs->sc_link->lun == newlun) {
- /*
- * We've found the saved entry. Dequeue it, and
- * make it current again.
- */
- TAILQ_REMOVE(&dev->nexus_list, acb, chain);
-
- dev->sc_nexus = acb;
- dev->sc_xs = acb->xs;
- dev->sc_flags |= SBICF_SELECTED;
- dev->target = newtarget;
- dev->lun = newlun;
- break;
- }
- }
-
- if ( acb == NULL ) {
- printf("%s: reselect %s targ %d not in nexus_list %p\n",
- dev->sc_dev.dv_xname,
- csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget,
- &TAILQ_FIRST(&dev->nexus_list));
- panic("bad reselect in sbic");
- }
-
- if ( csr == SBIC_CSR_RSLT_IFY )
- SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
- }
- break;
-
- default:
- abort:
- {
- /*
- * Something unexpected happened -- deal with it.
- */
- printf("next: aborting asr 0x%02x csr 0x%02x\n", asr, csr);
-
-#ifdef DDB
- Debugger();
-#endif
-
-#ifdef DEBUG
- dev->sc_dmatimo = 0;
- if ( data_pointer_debug > 1 )
- printf("next dmastop: %d(%x:%x)\n", dev->target,
- dev->sc_cur->dc_addr,
- dev->sc_tcnt);
-#endif
-
- dev->sc_dmastop(dev);
- SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
- if ( dev->sc_xs ) sbicerror(dev, csr);
- sbicabort(dev, "next");
-
- if ( dev->sc_flags & SBICF_INDMA ) {
- dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH);
-
-#ifdef DEBUG
- dev->sc_dmatimo = 0;
- if ( data_pointer_debug > 1 )
- printf("next dmastop: %d(%x:%x)\n", dev->target,
- dev->sc_cur->dc_addr,
- dev->sc_tcnt);
-#endif
- sbic_scsidone(acb, -1);
- }
-
- return SBIC_STATE_ERROR;
- }
- }
-
- return(SBIC_STATE_RUNNING);
-}
-
-
-/*
- * Check if DMA can not be used with specified buffer
- */
-int
-sbiccheckdmap(bp, len, mask)
- void *bp;
- u_long len,
- mask;
-{
- u_char *buffer;
- u_long phy_buf;
- u_long phy_len;
-
- buffer = bp;
-
- if ( len == 0 )
- return(1);
-
- while ( len ) {
-
- phy_buf = kvtop((vaddr_t)buffer);
- phy_len = NBPG - ((int) buffer & PGOFSET);
-
- if ( len < phy_len )
- phy_len = len;
-
- if ( phy_buf & mask )
- return(1);
-
- buffer += phy_len;
- len -= phy_len;
- }
-
- return(0);
-}
-
-int
-sbictoscsiperiod(dev, a)
- struct sbic_softc *dev;
- 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(dev->sc_sbicp, fs);
-
- fs = (fs >> 6) + 2; /* DIV */
-
- fs = (fs * 10000) / (dev->sc_clkfreq << 1); /* Cycle, in ns */
-
- if ( a < 2 )
- a = 8; /* map to Cycles */
-
- return ( (fs * a) >> 2 ); /* in 4 ns units */
-}
-
-int
-sbicfromscsiperiod(dev, p)
- struct sbic_softc *dev;
- int p;
-{
- unsigned fs,
- ret;
-
- /*
- * Just the inverse of the above
- */
- GET_SBIC_myid(dev->sc_sbicp, fs);
-
- fs = (fs >> 6) + 2; /* DIV */
-
- fs = (fs * 10000) / (dev->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(dev, ret) < p )
- ret++;
-
- return( (ret >= 8) ? 0 : ret );
-}
-
-#ifdef DEBUG
-void
-sbictimeout(dev)
- struct sbic_softc *dev;
-{
- int s,
- asr;
-
- s = splbio();
-
- if ( dev->sc_dmatimo ) {
-
- if ( dev->sc_dmatimo > 1 ) {
-
- printf("%s: dma timeout #%d\n", dev->sc_dev.dv_xname,
- dev->sc_dmatimo - 1);
-
- GET_SBIC_asr(dev->sc_sbicp, asr);
-
- if ( asr & SBIC_ASR_INT ) {
- /*
- * We need to service a missed IRQ
- */
- sbicintr(dev);
- } else {
- (void) sbicabort(dev, "timeout");
- splx(s);
- return;
- }
- }
-
- dev->sc_dmatimo++;
- }
-
- splx(s);
-
- timeout((void *)sbictimeout, dev, 30 * hz);
-}
-#endif
diff --git a/sys/arch/mvme68k/dev/sbicreg.h b/sys/arch/mvme68k/dev/sbicreg.h
deleted file mode 100644
index 854664d71a7..00000000000
--- a/sys/arch/mvme68k/dev/sbicreg.h
+++ /dev/null
@@ -1,433 +0,0 @@
-/* $OpenBSD: sbicreg.h,v 1.6 2003/06/02 23:27:50 millert 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. 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
- */
-
-/*
- * WD33C93 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
-/* 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 says 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 PAD(n) char n;
-#define SBIC_MACHINE_DMA_MODE SBIC_CTL_DMA
-
-typedef struct {
- volatile unsigned char sbic_asr; /* r : Aux Status Register */
-#define sbic_address sbic_asr /* w : desired register no */
- volatile unsigned char sbic_value; /* rw: register value */
-} sbic_padded_ind_regmap_t;
-typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p;
-
-#define sbic_read_reg(regs,regno,val) \
- do { \
- (regs)->sbic_address = (regno); \
- (val) = (regs)->sbic_value; \
- } while (0)
-
-#define sbic_write_reg(regs,regno,val) \
- do { \
- (regs)->sbic_address = (regno); \
- (regs)->sbic_value = (val); \
- } while (0)
-
-#define SET_SBIC_myid(regs,val) sbic_write_reg(regs,SBIC_myid,val)
-#define GET_SBIC_myid(regs,val) sbic_read_reg(regs,SBIC_myid,val)
-#define SET_SBIC_cdbsize(regs,val) sbic_write_reg(regs,SBIC_cdbsize,val)
-#define GET_SBIC_cdbsize(regs,val) sbic_read_reg(regs,SBIC_cdbsize,val)
-#define SET_SBIC_control(regs,val) sbic_write_reg(regs,SBIC_control,val)
-#define GET_SBIC_control(regs,val) sbic_read_reg(regs,SBIC_control,val)
-#define SET_SBIC_timeo(regs,val) sbic_write_reg(regs,SBIC_timeo,val)
-#define GET_SBIC_timeo(regs,val) sbic_read_reg(regs,SBIC_timeo,val)
-#define SET_SBIC_cdb1(regs,val) sbic_write_reg(regs,SBIC_cdb1,val)
-#define GET_SBIC_cdb1(regs,val) sbic_read_reg(regs,SBIC_cdb1,val)
-#define SET_SBIC_cdb2(regs,val) sbic_write_reg(regs,SBIC_cdb2,val)
-#define GET_SBIC_cdb2(regs,val) sbic_read_reg(regs,SBIC_cdb2,val)
-#define SET_SBIC_cdb3(regs,val) sbic_write_reg(regs,SBIC_cdb3,val)
-#define GET_SBIC_cdb3(regs,val) sbic_read_reg(regs,SBIC_cdb3,val)
-#define SET_SBIC_cdb4(regs,val) sbic_write_reg(regs,SBIC_cdb4,val)
-#define GET_SBIC_cdb4(regs,val) sbic_read_reg(regs,SBIC_cdb4,val)
-#define SET_SBIC_cdb5(regs,val) sbic_write_reg(regs,SBIC_cdb5,val)
-#define GET_SBIC_cdb5(regs,val) sbic_read_reg(regs,SBIC_cdb5,val)
-#define SET_SBIC_cdb6(regs,val) sbic_write_reg(regs,SBIC_cdb6,val)
-#define GET_SBIC_cdb6(regs,val) sbic_read_reg(regs,SBIC_cdb6,val)
-#define SET_SBIC_cdb7(regs,val) sbic_write_reg(regs,SBIC_cdb7,val)
-#define GET_SBIC_cdb7(regs,val) sbic_read_reg(regs,SBIC_cdb7,val)
-#define SET_SBIC_cdb8(regs,val) sbic_write_reg(regs,SBIC_cdb8,val)
-#define GET_SBIC_cdb8(regs,val) sbic_read_reg(regs,SBIC_cdb8,val)
-#define SET_SBIC_cdb9(regs,val) sbic_write_reg(regs,SBIC_cdb9,val)
-#define GET_SBIC_cdb9(regs,val) sbic_read_reg(regs,SBIC_cdb9,val)
-#define SET_SBIC_cdb10(regs,val) sbic_write_reg(regs,SBIC_cdb10,val)
-#define GET_SBIC_cdb10(regs,val) sbic_read_reg(regs,SBIC_cdb10,val)
-#define SET_SBIC_cdb11(regs,val) sbic_write_reg(regs,SBIC_cdb11,val)
-#define GET_SBIC_cdb11(regs,val) sbic_read_reg(regs,SBIC_cdb11,val)
-#define SET_SBIC_cdb12(regs,val) sbic_write_reg(regs,SBIC_cdb12,val)
-#define GET_SBIC_cdb12(regs,val) sbic_read_reg(regs,SBIC_cdb12,val)
-#define SET_SBIC_tlun(regs,val) sbic_write_reg(regs,SBIC_tlun,val)
-#define GET_SBIC_tlun(regs,val) sbic_read_reg(regs,SBIC_tlun,val)
-#define SET_SBIC_cmd_phase(regs,val) sbic_write_reg(regs,SBIC_cmd_phase,val)
-#define GET_SBIC_cmd_phase(regs,val) sbic_read_reg(regs,SBIC_cmd_phase,val)
-#define SET_SBIC_syn(regs,val) sbic_write_reg(regs,SBIC_syn,val)
-#define GET_SBIC_syn(regs,val) sbic_read_reg(regs,SBIC_syn,val)
-#define SET_SBIC_count_hi(regs,val) sbic_write_reg(regs,SBIC_count_hi,val)
-#define GET_SBIC_count_hi(regs,val) sbic_read_reg(regs,SBIC_count_hi,val)
-#define SET_SBIC_count_med(regs,val) sbic_write_reg(regs,SBIC_count_med,val)
-#define GET_SBIC_count_med(regs,val) sbic_read_reg(regs,SBIC_count_med,val)
-#define SET_SBIC_count_lo(regs,val) sbic_write_reg(regs,SBIC_count_lo,val)
-#define GET_SBIC_count_lo(regs,val) sbic_read_reg(regs,SBIC_count_lo,val)
-#define SET_SBIC_selid(regs,val) sbic_write_reg(regs,SBIC_selid,val)
-#define GET_SBIC_selid(regs,val) sbic_read_reg(regs,SBIC_selid,val)
-#define SET_SBIC_rselid(regs,val) sbic_write_reg(regs,SBIC_rselid,val)
-#define GET_SBIC_rselid(regs,val) sbic_read_reg(regs,SBIC_rselid,val)
-#define SET_SBIC_csr(regs,val) sbic_write_reg(regs,SBIC_csr,val)
-#define GET_SBIC_csr(regs,val) sbic_read_reg(regs,SBIC_csr,val)
-#define SET_SBIC_cmd(regs,val) sbic_write_reg(regs,SBIC_cmd,val)
-#define GET_SBIC_cmd(regs,val) sbic_read_reg(regs,SBIC_cmd,val)
-#define SET_SBIC_data(regs,val) sbic_write_reg(regs,SBIC_data,val)
-#define GET_SBIC_data(regs,val) sbic_read_reg(regs,SBIC_data,val)
-
-#define SBIC_TC_PUT(regs,val) \
- do { \
- sbic_write_reg(regs,SBIC_count_hi,((val)>>16)); \
- (regs)->sbic_value = (val)>>8; \
- (regs)->sbic_value = (val); \
- } while (0)
-
-#define SBIC_TC_GET(regs,val) \
- do { \
- sbic_read_reg(regs,SBIC_count_hi,(val)); \
- (val) = ((val)<<8) | (regs)->sbic_value; \
- (val) = ((val)<<8) | (regs)->sbic_value; \
- } while (0)
-
-#define SBIC_LOAD_COMMAND(regs,cmd,cmdsize) \
- do { \
- int n = (cmdsize) - 1; \
- char *ptr = (char *)(cmd); \
- sbic_write_reg(regs, SBIC_cdb1, *ptr++); \
- while(n-- > 0) (regs)->sbic_value = *ptr++; \
- } while (0)
-
-#define GET_SBIC_asr(regs,val) (val) = (regs)->sbic_asr
-
-#define WAIT_CIP(regs) \
- do { \
- while ((regs)->sbic_asr & SBIC_ASR_CIP) \
- ; \
- } while (0)
-
-/*
- * transmit a byte in programmed I/O mode
- **/
-#define SEND_BYTE(regs, ch) \
- do { \
- WAIT_CIP(regs); \
- SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
- SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \
- SET_SBIC_data(regs, ch); \
- } while (0)
-
-/*
- * receive a byte in programmed I/O mode
- */
-#define RECV_BYTE(regs, ch) \
- do { \
- WAIT_CIP(regs); \
- SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
- SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \
- GET_SBIC_data(regs, ch); \
- } while (0)
-
diff --git a/sys/arch/mvme68k/dev/sbicvar.h b/sys/arch/mvme68k/dev/sbicvar.h
deleted file mode 100644
index 6d740e28d03..00000000000
--- a/sys/arch/mvme68k/dev/sbicvar.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/* $OpenBSD: sbicvar.h,v 1.10 2013/01/16 18:06:46 miod 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. 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
- */
-#ifndef _SBICVAR_H_
-#define _SBICVAR_H_
-#include <sys/malloc.h>
-
-
-/*
- * DMA chains are used for Scatter-Gather DMA.
- */
-struct dma_chain {
- int dc_count;
- char *dc_addr;
-};
-
-/*
- * ACB. Holds additional information for each SCSI command Comments: We
- * need a separate scsi command block because we may need to overwrite it
- * with a request sense command. Basicly, we refrain from fiddling with
- * the scsi_xfer struct (except do the expected updating of return values).
- * We'll generally update: xs->{flags,resid,error,sense,status} and
- * occasionally xs->retries.
- */
-struct sbic_acb {
- TAILQ_ENTRY(sbic_acb) chain;
- struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */
- int flags; /* Status */
-#define ACB_FREE 0x00
-#define ACB_ACTIVE 0x01
-#define ACB_DONE 0x04
-#define ACB_CHKSENSE 0x08
-#define ACB_BBUF 0x10 /* DMA input needs to be copied from bounce */
-#define ACB_DATAIN 0x20 /* DMA direction flag */
-
- struct scsi_generic cmd; /* SCSI command block */
- int clen;
- struct dma_chain sc_kv; /* Virtual address of whole DMA */
- struct dma_chain sc_pa; /* Physical address of DMA segment */
- u_long sc_tcnt; /* number of bytes for this DMA */
- u_short sc_dmacmd; /* Internal data for this DMA */
- char *pa_addr; /* XXXX initial phys addr */
-};
-
-/*
- * Some info about each (possible) target on the SCSI bus. This should
- * probably have been a "per target+lunit" structure, but we'll leave it at
- * this for now. Is there a way to reliably hook it up to sc->fordriver??
- */
-struct sbic_tinfo {
- int cmds; /* #commands processed */
- int dconns; /* #disconnects */
- int senses; /* #request sense commands sent */
- int lubusy; /* What local units/subr. are busy? */
-};
-
-struct sbic_softc {
- struct device sc_dev;
- struct intrhand sc_dmaih;
- struct intrhand sc_sbicih;
- struct target_sync {
- u_char state;
- u_char period;
- u_char offset;
- } sc_sync[8];
- u_char target; /* Currently active target */
- u_char lun;
- struct scsi_link sc_link; /* proto for sub devices */
- sbic_regmap_p sc_sbicp; /* the SBIC */
- int sc_ipl;
-
- /* Lists of command blocks */
- TAILQ_HEAD(acb_list, sbic_acb) free_list,
- ready_list,
- nexus_list;
-
- struct sbic_acb *sc_nexus; /* current command */
- struct sbic_acb sc_acb[8]; /* the real command blocks */
- struct sbic_tinfo sc_tinfo[8];
-
- struct scsi_xfer *sc_xs; /* transfer from high level code */
- u_char sc_flags;
- u_char sc_stat[2];
- u_char sc_msg[7];
- u_long sc_clkfreq;
- u_long sc_tcnt; /* number of bytes transferred */
- u_short sc_dmacmd; /* used by dma drivers */
- u_long sc_dmamask; /* dma valid mem mask */
-#ifdef DEBUG
- u_short sc_dmatimo; /* dma timeout */
-#endif
- struct dma_chain *sc_cur;
- struct dma_chain *sc_last;
- int (*sc_dmago)(struct sbic_softc *, char *, int, int);
- int (*sc_dmanext)(struct sbic_softc *);
- void (*sc_enintr)(struct sbic_softc *);
- void (*sc_dmastop)(struct sbic_softc *);
-};
-
-/*
- * 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_ICMD 0x08 /* Immediate command in execution */
-#define SBICF_BADDMA 0x10 /* controller can only DMA to ztwobus space */
-#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 */
-
-#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 MSG_ISIDENTIFY(x) ((x) & MSG_IDENTIFY)
-
-
-#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 */
-
-
-/*
- * States returned by our state machine
- */
-
-#define SBIC_STATE_ERROR -1
-#define SBIC_STATE_DONE 0
-#define SBIC_STATE_RUNNING 1
-#define SBIC_STATE_DISCONNECT 2
-
-
-struct buf;
-struct scsi_xfer;
-
-void sbic_scsicmd(struct scsi_xfer *);
-
-#endif /* _SBICVAR_H_ */
diff --git a/sys/arch/mvme68k/dev/wdsc.c b/sys/arch/mvme68k/dev/wdsc.c
index 229470ca055..1fa476ba926 100644
--- a/sys/arch/mvme68k/dev/wdsc.c
+++ b/sys/arch/mvme68k/dev/wdsc.c
@@ -1,6 +1,56 @@
-/* $OpenBSD: wdsc.c,v 1.17 2010/06/28 18:31:01 krw Exp $ */
+/* $OpenBSD: wdsc.c,v 1.18 2013/05/19 20:32:47 miod Exp $ */
/*
+ * Copyright (c) 2013 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (c) 2001 Wayne Knowles
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Wayne Knowles
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+/*
* Copyright (c) 1996 Steve Woodford
* Copyright (c) 1982, 1990 The Regents of the University of California.
* All rights reserved.
@@ -31,251 +81,302 @@
*
* @(#)wdsc.c
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
+
+#include <uvm/uvm_extern.h>
+
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
-#include <mvme68k/dev/dmavar.h>
-#include <mvme68k/dev/sbicreg.h>
-#include <mvme68k/dev/sbicvar.h>
-#include <mvme68k/dev/wdscreg.h>
+
#include <machine/autoconf.h>
-#include <mvme68k/dev/pccreg.h>
-void wdscattach(struct device *, struct device *, void *);
-int wdscmatch(struct device *, struct cfdata *, void *);
+#include <mvme68k/dev/pccreg.h>
+#include <mvme68k/dev/wdscreg.h>
-void wdsc_enintr(struct sbic_softc *);
-int wdsc_dmago(struct sbic_softc *, char *, int, int);
-int wdsc_dmanext(struct sbic_softc *);
-void wdsc_dmastop(struct sbic_softc *);
-int wdsc_dmaintr(void *);
-int wdsc_scsiintr(void *);
+#include <dev/ic/wd33c93reg.h>
+#include <dev/ic/wd33c93var.h>
-extern void sbicinit(struct sbic_softc *);
-extern int sbicintr(struct sbic_softc *);
+struct dma_table_entry {
+ uint32_t dc_paddr;
+ uint32_t dc_cnt;
+};
-struct scsi_adapter wdsc_scsiswitch = {
- sbic_scsicmd,
- scsi_minphys,
- 0, /* no lun support */
- 0, /* no lun support */
+struct wdsc_softc {
+ struct wd33c93_softc sc_wd33c93;
+ bus_dma_tag_t sc_dmat;
+ bus_dmamap_t sc_dmamap;
+ bus_dmamap_t sc_tablemap;
+ bus_dma_segment_t sc_tableseg;
+ vaddr_t sc_tableva;
+ struct intrhand sc_dmaih;
+ struct intrhand sc_wdscih;
+ int sc_ipl;
+ int sc_flags;
+#define WDSC_DMA_ACTIVE 0x01
+#define WDSC_DMA_MAPLOADED 0x02
+ u_short sc_dmacmd;
};
-struct cfattach wdsc_ca = {
- sizeof(struct sbic_softc), (cfmatch_t)wdscmatch, wdscattach
+int wdscmatch(struct device *, void *, void *);
+void wdscattach(struct device *, struct device *, void *);
+
+const struct cfattach wdsc_ca = {
+ sizeof(struct wdsc_softc), wdscmatch, wdscattach
};
struct cfdriver wdsc_cd = {
NULL, "wdsc", DV_DULL
};
-/*
- * Define 'scsi_nosync = 0x00' to enable sync SCSI mode.
- * This is untested as yet, use at your own risk...
- */
-u_long scsi_nosync = 0xff;
-int shift_nosync = 0;
+int wdsc_dmasetup(struct wd33c93_softc *, void **, size_t *, int, size_t *);
+int wdsc_dmago(struct wd33c93_softc *);
+void wdsc_dmastop(struct wd33c93_softc *);
+
+int wdsc_alloc_physical(struct wdsc_softc *, bus_dmamap_t *,
+ bus_dma_segment_t *, vaddr_t *, bus_size_t, const char *);
+int wdsc_dmaintr(void *);
+int wdsc_scsiintr(void *);
+
+struct scsi_adapter wdsc_switch = {
+ wd33c93_scsi_cmd,
+ scsi_minphys,
+ NULL,
+ NULL
+};
/*
* Match for SCSI devices on the onboard WD33C93 chip
*/
int
-wdscmatch(pdp, cdp, auxp)
- struct device *pdp;
- struct cfdata *cdp;
- void *auxp;
+wdscmatch(struct device *parent, void *vcf, void *aux)
{
- /*
- * Match everything
- */
- return(1);
-}
+ struct confargs *ca = (struct confargs *)aux;
+ if (strcmp(ca->ca_name, wdsc_cd.cd_name) != 0)
+ return 0;
+ return 1;
+}
/*
* Attach the wdsc driver
*/
void
-wdscattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+wdscattach(struct device *parent, struct device *self, void *aux)
{
- struct sbic_softc *sc = (struct sbic_softc *)self;
- struct confargs *ca = aux;
- struct scsibus_attach_args saa;
+ struct wdsc_softc *wsc = (struct wdsc_softc *)self;
+ struct confargs *ca = (struct confargs *)aux;
+ struct wd33c93_softc *sc = &wsc->sc_wd33c93;
int tmp;
- printf("\n");
-
- sc->sc_enintr = wdsc_enintr;
- sc->sc_dmago = wdsc_dmago;
- sc->sc_dmanext = wdsc_dmanext;
- sc->sc_dmastop = wdsc_dmastop;
- sc->sc_dmacmd = 0;
-
- sc->sc_link.adapter_softc = sc;
- sc->sc_link.adapter_target = 7;
- sc->sc_link.adapter = &wdsc_scsiswitch;
- sc->sc_link.openings = 2;
+ /*
+ * Map address and data registers.
+ */
- sc->sc_sbicp = (sbic_regmap_p)ca->ca_vaddr;
+ sc->sc_regt = ca->ca_iot;
+ if (bus_space_map(ca->ca_iot, ca->ca_paddr + 0, 1, 0,
+ &sc->sc_asr_regh) != 0) {
+ printf(": failed to map asr register\n");
+ return;
+ }
+ if (bus_space_map(ca->ca_iot, ca->ca_paddr + 1, 1, 0,
+ &sc->sc_data_regh) != 0) {
+ printf(": failed to map data register\n");
+ return;
+ }
/*
- * Everything is a valid dma address.
+ * Allocate DMA map for up to MAXPHYS bytes.
*/
- sc->sc_dmamask = 0;
+
+ wsc->sc_dmat = ca->ca_dmat;
+ if (bus_dmamap_create(ca->ca_dmat, MAXPHYS, 1 + atop(MAXPHYS),
+ 0, 0, BUS_DMA_WAITOK, &wsc->sc_dmamap) != 0) {
+ printf(": failed to create dmamap\n");
+ return;
+ }
/*
- * The onboard WD33C93 of the '147 is usually clocked at 10MHz...
- * (We use 10 times this for accuracy in later calculations)
+ * Allocate table walk memory.
*/
- sc->sc_clkfreq = 100;
+ if (wdsc_alloc_physical(wsc, &wsc->sc_tablemap, &wsc->sc_tableseg,
+ &wsc->sc_tableva,
+ sizeof(struct dma_table_entry) * (1 + atop(MAXPHYS)),
+ "dma table") != 0) {
+ bus_dmamap_destroy(ca->ca_dmat, wsc->sc_dmamap);
+ return;
+ }
+
+ printf("\n");
+
+ sc->sc_dmasetup = wdsc_dmasetup;
+ sc->sc_dmago = wdsc_dmago;
+ sc->sc_dmastop = wdsc_dmastop;
+ sc->sc_reset = NULL;
/*
- * Initialize the hardware
+ * The onboard WD33C93 of the MVME147 is usually clocked at 10MHz...
*/
- sbicinit(sc);
+ sc->sc_clkfreq = 100;
+ sc->sc_id = 7;
+ sc->sc_dmamode = SBIC_CTL_DMA;
- sc->sc_ipl = ca->ca_ipl;
+ wsc->sc_dmacmd = 0;
+ wsc->sc_ipl = ca->ca_ipl;
sys_pcc->pcc_sbicirq = ca->ca_ipl | PCC_IRQ_INT;
sys_pcc->pcc_dmairq = ca->ca_ipl | PCC_IRQ_INT;
sys_pcc->pcc_dmacsr = 0;
/*
- * Fix up the interrupts
+ * Register interrupt handlers for DMA and WDSC
*/
- sc->sc_dmaih.ih_fn = wdsc_dmaintr;
- sc->sc_dmaih.ih_arg = sc;
- sc->sc_dmaih.ih_ipl = ca->ca_ipl;
- pccintr_establish(PCCV_DMA, &sc->sc_dmaih, self->dv_xname);
+ wsc->sc_dmaih.ih_fn = wdsc_dmaintr;
+ wsc->sc_dmaih.ih_arg = wsc;
+ wsc->sc_dmaih.ih_ipl = ca->ca_ipl;
+ pccintr_establish(PCCV_DMA, &wsc->sc_dmaih, self->dv_xname);
- sc->sc_sbicih.ih_fn = wdsc_scsiintr;
- sc->sc_sbicih.ih_arg = sc;
- sc->sc_sbicih.ih_ipl = ca->ca_ipl;
- pccintr_establish(PCCV_SBIC, &sc->sc_sbicih, self->dv_xname);
-
- sys_pcc->pcc_sbicirq = ca->ca_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+ wsc->sc_wdscih.ih_fn = wdsc_scsiintr;
+ wsc->sc_wdscih.ih_arg = wsc;
+ wsc->sc_wdscih.ih_ipl = ca->ca_ipl;
+ pccintr_establish(PCCV_SBIC, &wsc->sc_wdscih, self->dv_xname);
/*
- * Attach all scsi units on us, watching for boot device
+ * Attach all SCSI devices on us, watching for boot device
* (see device_register).
*/
- bzero(&saa, sizeof(saa));
- saa.saa_sc_link = &sc->sc_link;
-
tmp = bootpart;
if (ca->ca_paddr != bootaddr)
bootpart = -1;
- config_found(self, &saa, scsiprint);
+ wd33c93_attach(sc, &wdsc_switch);
bootpart = tmp; /* restore old value */
-}
-/*
- * Enable DMA interrupts
- */
-void
-wdsc_enintr(dev)
- struct sbic_softc *dev;
-{
- dev->sc_flags |= SBICF_INTR;
-
- sys_pcc->pcc_dmairq = dev->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+ sys_pcc->pcc_sbicirq = ca->ca_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
}
/*
* Prime the hardware for a DMA transfer
*/
int
-wdsc_dmago(dev, addr, count, flags)
- struct sbic_softc *dev;
- char *addr;
- int count, flags;
+wdsc_dmasetup(struct wd33c93_softc *sc, void **addr, size_t *len, int datain,
+ size_t *dmasize)
{
- /*
- * Set up the command word based on flags
- */
- if ((flags & DMAGO_READ) == 0)
- dev->sc_dmacmd = DMAC_CSR_ENABLE | DMAC_CSR_WRITE;
- else
- dev->sc_dmacmd = DMAC_CSR_ENABLE;
+ struct wdsc_softc *wsc = (struct wdsc_softc *)sc;
+ int count;
+ int rc;
- dev->sc_flags |= SBICF_INTR;
- dev->sc_tcnt = dev->sc_cur->dc_count << 1;
+ KASSERT((wsc->sc_flags & WDSC_DMA_ACTIVE) == 0);
- /*
- * Prime the hardware.
- * Note, it's probably not necessary to do this here, since dmanext
- * is called just prior to the actual transfer.
- */
- sys_pcc->pcc_dmacsr = 0;
- sys_pcc->pcc_dmairq = dev->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
- sys_pcc->pcc_dmadaddr = (unsigned long)dev->sc_cur->dc_addr;
- sys_pcc->pcc_dmabcnt = (unsigned long)dev->sc_tcnt | (1 << 24);
- sys_pcc->pcc_dmacsr = dev->sc_dmacmd;
+ count = *len;
+ if (count) {
+ KASSERT((wsc->sc_flags & WDSC_DMA_MAPLOADED) == 0);
+
+ if (datain)
+ wsc->sc_dmacmd = DMAC_CSR_ENABLE;
+ else
+ wsc->sc_dmacmd = DMAC_CSR_ENABLE | DMAC_CSR_WRITE;
- return dev->sc_tcnt;
+ rc = bus_dmamap_load(wsc->sc_dmat, wsc->sc_dmamap,
+ *addr, count, NULL, BUS_DMA_NOWAIT);
+ if (rc != 0)
+ panic("%s: bus_dmamap_load failed, rc=%d",
+ sc->sc_dev.dv_xname, rc);
+
+ bus_dmamap_sync(wsc->sc_dmat, wsc->sc_dmamap, 0,
+ wsc->sc_dmamap->dm_mapsize, datain ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+
+ /*
+ * Build dma table, unless transfer fits in one
+ * contiguous chunk
+ */
+ if (wsc->sc_dmamap->dm_nsegs > 1) {
+ struct dma_table_entry *entry;
+ bus_dma_segment_t *seg;
+ int i;
+
+ entry = (struct dma_table_entry *)wsc->sc_tableva;
+ seg = wsc->sc_dmamap->dm_segs;
+ for (i = wsc->sc_dmamap->dm_nsegs; i != 0; i--) {
+ entry->dc_paddr = seg->ds_addr;
+ entry->dc_cnt = seg->ds_len |
+ (FC_SUPERD << 24) | (1UL << 31);
+ seg++;
+ entry++;
+ }
+ (--entry)->dc_cnt &= ~(1UL << 31);
+
+ wsc->sc_dmacmd |= DMAC_CSR_TABLE;
+ }
+
+ wsc->sc_flags |= WDSC_DMA_MAPLOADED;
+ }
+
+ return count;
}
/*
- * Prime the hardware for the next DMA transfer
+ * Trigger a DMA transfer
*/
int
-wdsc_dmanext(dev)
- struct sbic_softc *dev;
+wdsc_dmago(struct wd33c93_softc *sc)
{
- if (dev->sc_cur > dev->sc_last) {
- /*
- * Shouldn't happen !!
- */
- printf("wdsc_dmanext at end !!!\n");
- wdsc_dmastop(dev);
- return 0;
+ struct wdsc_softc *wsc = (struct wdsc_softc *)sc;
+
+ KASSERT((wsc->sc_flags & WDSC_DMA_ACTIVE) == 0);
+ KASSERT((wsc->sc_flags & WDSC_DMA_MAPLOADED));
+
+ wsc->sc_flags |= WDSC_DMA_ACTIVE;
+
+ sys_pcc->pcc_dmacsr = 0;
+ sys_pcc->pcc_dmairq = wsc->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+ if (wsc->sc_dmamap->dm_nsegs > 1) {
+ sys_pcc->pcc_tafcr = FC_SUPERD;
+ sys_pcc->pcc_dmataddr = wsc->sc_tableseg.ds_addr;
+ } else {
+ sys_pcc->pcc_dmadaddr =
+ (unsigned long)wsc->sc_dmamap->dm_segs[0].ds_addr;
+ sys_pcc->pcc_dmabcnt = (FC_SUPERD << 24) |
+ (unsigned long)wsc->sc_dmamap->dm_segs[0].ds_len;
}
+ sys_pcc->pcc_dmacsr = wsc->sc_dmacmd;
- dev->sc_tcnt = dev->sc_cur->dc_count << 1;
-
- /*
- * Load the next DMA address
- */
- sys_pcc->pcc_dmacsr = 0;
- sys_pcc->pcc_dmairq = dev->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
- sys_pcc->pcc_dmadaddr = (unsigned long)dev->sc_cur->dc_addr;
- sys_pcc->pcc_dmabcnt = (unsigned long)dev->sc_tcnt | (1 << 24);
- sys_pcc->pcc_dmacsr = dev->sc_dmacmd;
-
- return dev->sc_tcnt;
+ return wsc->sc_dmamap->dm_mapsize;
}
/*
- * Stop DMA, and disable interrupts
+ * Stop DMA, and disable DMA interrupts
*/
void
-wdsc_dmastop(dev)
- struct sbic_softc *dev;
+wdsc_dmastop(struct wd33c93_softc *sc)
{
- int s;
-
- s = splbio();
+ struct wdsc_softc *wsc = (struct wdsc_softc *)sc;
- sys_pcc->pcc_dmacsr = 0;
- sys_pcc->pcc_dmairq = dev->sc_ipl | PCC_IRQ_INT;
+ if (wsc->sc_flags & WDSC_DMA_ACTIVE) {
+ sys_pcc->pcc_dmacsr = 0;
+ sys_pcc->pcc_dmairq = wsc->sc_ipl | PCC_IRQ_INT;
- splx(s);
+ bus_dmamap_sync(wsc->sc_dmat, wsc->sc_dmamap, 0,
+ wsc->sc_dmamap->dm_mapsize,
+ wsc->sc_dmacmd & DMAC_CSR_WRITE ?
+ BUS_DMASYNC_POSTWRITE : BUS_DMASYNC_POSTREAD);
+ }
+ if (wsc->sc_flags & WDSC_DMA_MAPLOADED)
+ bus_dmamap_unload(wsc->sc_dmat, wsc->sc_dmamap);
+ wsc->sc_flags &= ~(WDSC_DMA_ACTIVE | WDSC_DMA_MAPLOADED);
}
/*
- * Come here following a DMA interrupt
+ * DMA completion interrupt
*/
int
-wdsc_dmaintr(arg)
- void *arg;
+wdsc_dmaintr(void *arg)
{
- struct sbic_softc *dev = (struct sbic_softc *)arg;
- int found = 0;
+ struct wdsc_softc *wsc = (struct wdsc_softc *)arg;
+ int rc = -1;
/*
* Really a DMA interrupt?
@@ -283,28 +384,31 @@ wdsc_dmaintr(arg)
if ((sys_pcc->pcc_dmairq & PCC_IRQ_INT) == 0)
return 0;
- /*
- * Was it a completion interrupt?
- * XXXSCW Note: Support for other DMA interrupts is required, eg. buserr
- */
if (sys_pcc->pcc_dmacsr & DMAC_CSR_DONE) {
- ++found;
-
- sys_pcc->pcc_dmairq = dev->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+ rc = 1;
+ /* acknowledge interrupt... */
+ sys_pcc->pcc_dmairq = wsc->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+ if (sys_pcc->pcc_dmacsr & (DMAC_CSR_TBUSERR | DMAC_CSR_DBUSERR |
+ DMAC_CSR_TSIZE | DMAC_CSR_8BITS)) {
+ printf("%s: DMA error, CSR=%02x\n",
+ wsc->sc_wd33c93.sc_dev.dv_xname,
+ sys_pcc->pcc_dmacsr);
+ }
+ sys_pcc->pcc_dmacsr = 0;
+ sys_pcc->pcc_dmairq = wsc->sc_ipl | PCC_IRQ_INT;
}
- return found;
+ return rc;
}
/*
- * Come here for SCSI interrupts
+ * SCSI interrupt
*/
int
-wdsc_scsiintr(arg)
- void *arg;
+wdsc_scsiintr(void *arg)
{
- struct sbic_softc *dev = (struct sbic_softc *)arg;
- int found;
+ struct wdsc_softc *wsc = (struct wdsc_softc *)arg;
+ int rc;
/*
* Really a SCSI interrupt?
@@ -312,15 +416,68 @@ wdsc_scsiintr(arg)
if ((sys_pcc->pcc_sbicirq & PCC_IRQ_INT) == 0)
return 0;
- /*
- * Go handle it
- */
- found = sbicintr(dev);
+ rc = wd33c93_intr(&wsc->sc_wd33c93);
/*
* Acknowledge and clear the interrupt
*/
- sys_pcc->pcc_sbicirq = dev->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+ sys_pcc->pcc_sbicirq = wsc->sc_ipl | PCC_IRQ_IEN | PCC_IRQ_INT;
+
+ return rc;
+}
+
+/*
+ * Allocate contiguous physical memory.
+ */
+int
+wdsc_alloc_physical(struct wdsc_softc *wsc, bus_dmamap_t *dmamap,
+ bus_dma_segment_t *dmaseg, vaddr_t *va, bus_size_t len, const char *what)
+{
+ int nseg;
+ int rc;
+
+ len = round_page(len);
+
+ rc = bus_dmamem_alloc(wsc->sc_dmat, len, 0, 0, dmaseg, 1, &nseg,
+ BUS_DMA_NOWAIT);
+ if (rc != 0) {
+ printf("%s: unable to allocate %s memory: error %d\n",
+ wsc->sc_wd33c93.sc_dev.dv_xname, what, rc);
+ goto fail1;
+ }
+
+ rc = bus_dmamem_map(wsc->sc_dmat, dmaseg, nseg, len,
+ (caddr_t *)va, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+ if (rc != 0) {
+ printf("%s: unable to map %s memory: error %d\n",
+ wsc->sc_wd33c93.sc_dev.dv_xname, what, rc);
+ goto fail2;
+ }
+
+ rc = bus_dmamap_create(wsc->sc_dmat, len, 1, len, 0,
+ BUS_DMA_NOWAIT /* | BUS_DMA_ALLOCNOW */, dmamap);
+ if (rc != 0) {
+ printf("%s: unable to create %s dma map: error %d\n",
+ wsc->sc_wd33c93.sc_dev.dv_xname, what, rc);
+ goto fail3;
+ }
+
+ rc = bus_dmamap_load(wsc->sc_dmat, *dmamap, (void *)*va, len, NULL,
+ BUS_DMA_NOWAIT);
+ if (rc != 0) {
+ printf("%s: unable to load %s dma map: error %d\n",
+ wsc->sc_wd33c93.sc_dev.dv_xname, what, rc);
+ goto fail4;
+ }
+
+ return 0;
- return found;
+fail4:
+ bus_dmamap_destroy(wsc->sc_dmat, *dmamap);
+fail3:
+ bus_dmamem_unmap(wsc->sc_dmat, (caddr_t)*va, PAGE_SIZE);
+fail2:
+ bus_dmamem_free(wsc->sc_dmat, dmaseg, 1);
+fail1:
+ return rc;
}