diff options
-rw-r--r-- | distrib/sets/lists/man/mi | 2 | ||||
-rw-r--r-- | share/man/man4/Makefile | 4 | ||||
-rw-r--r-- | share/man/man4/man4.sgi/Makefile | 4 | ||||
-rw-r--r-- | share/man/man4/wdsc.4 (renamed from share/man/man4/man4.sgi/wdsc.4) | 10 | ||||
-rw-r--r-- | sys/arch/mvme68k/conf/files.mvme68k | 5 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/dmavar.h | 43 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/i82586.h | 286 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/sbic.c | 2678 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/sbicreg.h | 433 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/sbicvar.h | 201 | ||||
-rw-r--r-- | sys/arch/mvme68k/dev/wdsc.c | 499 |
11 files changed, 341 insertions, 3824 deletions
diff --git a/distrib/sets/lists/man/mi b/distrib/sets/lists/man/mi index 93a4bebfd84..174207c65e8 100644 --- a/distrib/sets/lists/man/mi +++ b/distrib/sets/lists/man/mi @@ -2092,7 +2092,6 @@ ./usr/share/man/man4/sgi/panel.4 ./usr/share/man/man4/sgi/power.4 ./usr/share/man/man4/sgi/sq.4 -./usr/share/man/man4/sgi/wdsc.4 ./usr/share/man/man4/sgi/xbow.4 ./usr/share/man/man4/sgi/xbpci.4 ./usr/share/man/man4/sgi/xbridge.4 @@ -2435,6 +2434,7 @@ ./usr/share/man/man4/wbsio.4 ./usr/share/man/man4/wd.4 ./usr/share/man/man4/wdc.4 +./usr/share/man/man4/wdsc.4 ./usr/share/man/man4/we.4 ./usr/share/man/man4/wi.4 ./usr/share/man/man4/wpi.4 diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 0da50795132..74e10cbb989 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.545 2013/03/15 09:10:52 ratchov Exp $ +# $OpenBSD: Makefile,v 1.546 2013/05/19 20:32:47 miod Exp $ MAN= aac.4 ac97.4 acphy.4 \ acpi.4 acpiac.4 acpiasus.4 acpibat.4 acpibtn.4 acpicpu.4 acpidock.4 \ @@ -69,7 +69,7 @@ MAN= aac.4 ac97.4 acphy.4 \ viapm.4 viasio.4 vic.4 video.4 vio.4 vioblk.4 viomb.4 virtio.4 vlan.4 \ vmt.4 vnd.4 vr.4 \ vscsi.4 vte.4 \ - watchdog.4 wb.4 wbenv.4 wbng.4 wbsd.4 wbsio.4 wd.4 wdc.4 we.4 \ + watchdog.4 wb.4 wbenv.4 wbng.4 wbsd.4 wbsio.4 wd.4 wdc.4 wdsc.4 we.4 \ wi.4 wpi.4 wscons.4 wsdisplay.4 wskbd.4 wsmouse.4 wsmux.4 \ xe.4 xf86.4 xge.4 xl.4 xmphy.4 yds.4 ym.4 zero.4 zyd.4 diff --git a/share/man/man4/man4.sgi/Makefile b/share/man/man4/man4.sgi/Makefile index 887f69724ee..feed458fa00 100644 --- a/share/man/man4/man4.sgi/Makefile +++ b/share/man/man4/man4.sgi/Makefile @@ -1,10 +1,10 @@ -# $OpenBSD: Makefile,v 1.22 2012/04/18 18:01:56 miod Exp $ +# $OpenBSD: Makefile,v 1.23 2013/05/19 20:32:47 miod Exp $ MAN= dpclock.4 dsclock.4 dsrtc.4 gbe.4 gio.4 grtwo.4 hpc.4 iec.4 imc.4 \ impact.4 intro.4 ioc.4 iockbc.4 iof.4 light.4 \ macebus.4 mavb.4 mec.4 mkbc.4 newport.4 odyssey.4 \ owmac.4 owserial.4 panel.4 power.4 \ - sq.4 wdsc.4 xbow.4 xbridge.4 xheart.4 zs.4 + sq.4 xbow.4 xbridge.4 xheart.4 zs.4 MLINKS= macebus.4 macepcibr.4 \ xbridge.4 xbpci.4 \ zs.4 zstty.4 zs.4 zskbd.4 zs.4 zsms.4 diff --git a/share/man/man4/man4.sgi/wdsc.4 b/share/man/man4/wdsc.4 index d96b03f488d..ddc9335489d 100644 --- a/share/man/man4/man4.sgi/wdsc.4 +++ b/share/man/man4/wdsc.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: wdsc.4,v 1.5 2012/03/28 20:44:23 miod Exp $ +.\" $OpenBSD: wdsc.4,v 1.1 2013/05/19 20:32:47 miod Exp $ .\" $NetBSD: wdsc.4,v 1.10 2009/03/09 19:24:30 joerg Exp $ .\" .\" Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -28,14 +28,15 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: March 28 2012 $ -.Dt WDSC 4 sgi +.Dd $Mdocdate: May 19 2013 $ +.Dt WDSC 4 .Os .Sh NAME .Nm wdsc .Nd WD33c93 SCSI controller .Sh SYNOPSIS -.Cd "wdsc* at hpc?" +.Cd "wdsc0 at pcc0 offset 0x4000 ipl 2" Pq mvme68k +.Cd "wdsc* at hpc? " Pq sgi .Sh DESCRIPTION The .Nm @@ -66,4 +67,5 @@ acceptably. .Sh SEE ALSO .Xr hpc 4 , .Xr intro 4 , +.\" .Xr pcc 4 , .Xr scsibus 4 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; } |