summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1998-12-27 13:06:44 +0000
committerphk <phk@FreeBSD.org>1998-12-27 13:06:44 +0000
commita20df1525176cfcc049d8282308a210b2ffe1095 (patch)
treed94f351de920f7eec4bbc420b60864f1738e46a1 /sys
parenteb15c87aad94ce69d22c6cbaf4c91c7678b3f397 (diff)
downloadFreeBSD-src-a20df1525176cfcc049d8282308a210b2ffe1095.zip
FreeBSD-src-a20df1525176cfcc049d8282308a210b2ffe1095.tar.gz
Pre 3.0 branch cleanup casualty #5: nca, sea, wds, uha
No CAM drivers available. If somebody CAMifies one of these, they will be welcome back in the tree
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/conf/GENERIC3
-rw-r--r--sys/conf/NOTES18
-rw-r--r--sys/conf/files.i3866
-rw-r--r--sys/i386/conf/GENERIC3
-rw-r--r--sys/i386/conf/LINT18
-rw-r--r--sys/i386/conf/NOTES18
-rw-r--r--sys/i386/conf/files.i3866
-rw-r--r--sys/i386/isa/ic/ncr53400.h49
-rw-r--r--sys/i386/isa/ic/ncr5380.h90
-rw-r--r--sys/i386/isa/ncr5380.c1539
-rw-r--r--sys/i386/isa/seagate.c1509
-rw-r--r--sys/i386/isa/ultra14f.c1366
-rw-r--r--sys/i386/isa/wd7000.c727
13 files changed, 13 insertions, 5339 deletions
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index de0e261..7519449 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
-# $Id: GENERIC,v 1.135 1998/12/13 23:04:35 n_hibma Exp $
+# $Id: GENERIC,v 1.136 1998/12/27 12:52:45 phk Exp $
machine "i386"
cpu "I386_CPU"
@@ -84,7 +84,6 @@ controller adv0 at isa? port ? cam irq ?
controller adw0
controller bt0 at isa? port ? cam irq ?
controller aha0 at isa? port ? cam irq ?
-#controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5
#controller aic0 at isa? port 0x340 bio irq 11
controller scbus0
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index f7b566b..02cca8b 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.514 1998/12/27 12:44:54 phk Exp $
+# $Id: LINT,v 1.515 1998/12/27 12:52:45 phk Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -886,7 +886,7 @@ device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13
#
#
-# SCSI host adapters: `aha', `aic', `bt', `nca'
+# SCSI host adapters: `aha', `aic', `bt'
#
# adv: All Narrow SCSI bus AdvanSys controllers.
# adw: Second Generation AdvanSys controllers including the ADV940UW.
@@ -894,10 +894,6 @@ device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13
# ahc: Adaptec 274x/284x/294x
# aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!)
# bt: Most Buslogic controllers
-# nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130
-# uha: UltraStor ULTRA 14F/24F/34F
-# sea: Seagate ST01/02 8 bit controller (slow!)
-# wds: Western Digital WD7000 controller (no scatter/gather!).
#
# Note that the order is important in order for Buslogic cards to be
# probed correctly.
@@ -907,17 +903,9 @@ controller bt0 at isa? port "IO_BT0" cam irq ?
controller adv0 at isa? port ? cam irq ?
controller adw0
controller aha0 at isa? port ? cam irq ?
-#!CAM# controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5
#!CAM# controller aic0 at isa? port 0x340 bio irq 11
-#!CAM# controller nca0 at isa? port 0x1f88 bio irq 10
-#!CAM# controller nca1 at isa? port 0x1f84
-#!CAM# controller nca2 at isa? port 0x1f8c
-#!CAM# controller nca3 at isa? port 0x1e88
-#!CAM# controller nca4 at isa? port 0x350 bio irq 5
-
-#!CAM# controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000
-#!CAM# controller wds0 at isa? port 0x350 bio irq 15 drq 6
+
#
# ST-506, ESDI, and IDE hard disks: `wdc' and `wd'
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 40ede78..249a285 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.209 1998/12/27 12:44:55 phk Exp $
+# $Id: files.i386,v 1.210 1998/12/27 12:52:46 phk Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -142,7 +142,6 @@ i386/isa/lpt.c optional lpt device-driver
i386/isa/labpc.c optional labpc device-driver
i386/isa/mcd.c optional mcd device-driver
i386/isa/mse.c optional mse device-driver
-#i386/isa/ncr5380.c optional nca device-driver
i386/isa/npx.c mandatory npx device-driver
i386/isa/pcaudio.c optional pca device-driver
i386/isa/matcd/matcd.c optional matcd device-driver
@@ -158,7 +157,6 @@ i386/isa/random_machdep.c standard
i386/isa/rc.c optional rc device-driver
i386/isa/rp.c optional rp device-driver
i386/isa/scd.c optional scd device-driver
-#i386/isa/seagate.c optional sea device-driver
i386/isa/si.c optional si device-driver
i386/isa/si2_z280.c optional si device-driver
i386/isa/si3_t225.c optional si device-driver
@@ -238,7 +236,6 @@ i386/isa/scvesactl.c optional sc device-driver
i386/isa/videoio.c optional sc device-driver
i386/isa/vesa.c optional sc device-driver
i386/isa/tw.c optional tw device-driver
-#i386/isa/ultra14f.c optional uha device-driver
i386/isa/wd.c optional wdc device-driver
i386/isa/wd.c optional wd device-driver
i386/isa/atapi.c optional atapi device-driver
@@ -246,7 +243,6 @@ i386/isa/atapi-cd.c optional acd device-driver
i386/isa/wcd.c optional wcd device-driver
i386/isa/wfd.c optional wfd device-driver
i386/isa/wst.c optional wst device-driver
-i386/isa/wd7000.c optional wds device-driver
i386/isa/wt.c optional wt device-driver
i386/linux/imgact_linux.c optional compat_linux
i386/linux/linux_dummy.c optional compat_linux
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index de0e261..7519449 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
-# $Id: GENERIC,v 1.135 1998/12/13 23:04:35 n_hibma Exp $
+# $Id: GENERIC,v 1.136 1998/12/27 12:52:45 phk Exp $
machine "i386"
cpu "I386_CPU"
@@ -84,7 +84,6 @@ controller adv0 at isa? port ? cam irq ?
controller adw0
controller bt0 at isa? port ? cam irq ?
controller aha0 at isa? port ? cam irq ?
-#controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5
#controller aic0 at isa? port 0x340 bio irq 11
controller scbus0
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index f7b566b..02cca8b 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.514 1998/12/27 12:44:54 phk Exp $
+# $Id: LINT,v 1.515 1998/12/27 12:52:45 phk Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -886,7 +886,7 @@ device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13
#
#
-# SCSI host adapters: `aha', `aic', `bt', `nca'
+# SCSI host adapters: `aha', `aic', `bt'
#
# adv: All Narrow SCSI bus AdvanSys controllers.
# adw: Second Generation AdvanSys controllers including the ADV940UW.
@@ -894,10 +894,6 @@ device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13
# ahc: Adaptec 274x/284x/294x
# aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!)
# bt: Most Buslogic controllers
-# nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130
-# uha: UltraStor ULTRA 14F/24F/34F
-# sea: Seagate ST01/02 8 bit controller (slow!)
-# wds: Western Digital WD7000 controller (no scatter/gather!).
#
# Note that the order is important in order for Buslogic cards to be
# probed correctly.
@@ -907,17 +903,9 @@ controller bt0 at isa? port "IO_BT0" cam irq ?
controller adv0 at isa? port ? cam irq ?
controller adw0
controller aha0 at isa? port ? cam irq ?
-#!CAM# controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5
#!CAM# controller aic0 at isa? port 0x340 bio irq 11
-#!CAM# controller nca0 at isa? port 0x1f88 bio irq 10
-#!CAM# controller nca1 at isa? port 0x1f84
-#!CAM# controller nca2 at isa? port 0x1f8c
-#!CAM# controller nca3 at isa? port 0x1e88
-#!CAM# controller nca4 at isa? port 0x350 bio irq 5
-
-#!CAM# controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000
-#!CAM# controller wds0 at isa? port 0x350 bio irq 15 drq 6
+
#
# ST-506, ESDI, and IDE hard disks: `wdc' and `wd'
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index f7b566b..02cca8b 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.514 1998/12/27 12:44:54 phk Exp $
+# $Id: LINT,v 1.515 1998/12/27 12:52:45 phk Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -886,7 +886,7 @@ device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13
#
#
-# SCSI host adapters: `aha', `aic', `bt', `nca'
+# SCSI host adapters: `aha', `aic', `bt'
#
# adv: All Narrow SCSI bus AdvanSys controllers.
# adw: Second Generation AdvanSys controllers including the ADV940UW.
@@ -894,10 +894,6 @@ device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13
# ahc: Adaptec 274x/284x/294x
# aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!)
# bt: Most Buslogic controllers
-# nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130
-# uha: UltraStor ULTRA 14F/24F/34F
-# sea: Seagate ST01/02 8 bit controller (slow!)
-# wds: Western Digital WD7000 controller (no scatter/gather!).
#
# Note that the order is important in order for Buslogic cards to be
# probed correctly.
@@ -907,17 +903,9 @@ controller bt0 at isa? port "IO_BT0" cam irq ?
controller adv0 at isa? port ? cam irq ?
controller adw0
controller aha0 at isa? port ? cam irq ?
-#!CAM# controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5
#!CAM# controller aic0 at isa? port 0x340 bio irq 11
-#!CAM# controller nca0 at isa? port 0x1f88 bio irq 10
-#!CAM# controller nca1 at isa? port 0x1f84
-#!CAM# controller nca2 at isa? port 0x1f8c
-#!CAM# controller nca3 at isa? port 0x1e88
-#!CAM# controller nca4 at isa? port 0x350 bio irq 5
-
-#!CAM# controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000
-#!CAM# controller wds0 at isa? port 0x350 bio irq 15 drq 6
+
#
# ST-506, ESDI, and IDE hard disks: `wdc' and `wd'
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index 40ede78..249a285 100644
--- a/sys/i386/conf/files.i386
+++ b/sys/i386/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.209 1998/12/27 12:44:55 phk Exp $
+# $Id: files.i386,v 1.210 1998/12/27 12:52:46 phk Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -142,7 +142,6 @@ i386/isa/lpt.c optional lpt device-driver
i386/isa/labpc.c optional labpc device-driver
i386/isa/mcd.c optional mcd device-driver
i386/isa/mse.c optional mse device-driver
-#i386/isa/ncr5380.c optional nca device-driver
i386/isa/npx.c mandatory npx device-driver
i386/isa/pcaudio.c optional pca device-driver
i386/isa/matcd/matcd.c optional matcd device-driver
@@ -158,7 +157,6 @@ i386/isa/random_machdep.c standard
i386/isa/rc.c optional rc device-driver
i386/isa/rp.c optional rp device-driver
i386/isa/scd.c optional scd device-driver
-#i386/isa/seagate.c optional sea device-driver
i386/isa/si.c optional si device-driver
i386/isa/si2_z280.c optional si device-driver
i386/isa/si3_t225.c optional si device-driver
@@ -238,7 +236,6 @@ i386/isa/scvesactl.c optional sc device-driver
i386/isa/videoio.c optional sc device-driver
i386/isa/vesa.c optional sc device-driver
i386/isa/tw.c optional tw device-driver
-#i386/isa/ultra14f.c optional uha device-driver
i386/isa/wd.c optional wdc device-driver
i386/isa/wd.c optional wd device-driver
i386/isa/atapi.c optional atapi device-driver
@@ -246,7 +243,6 @@ i386/isa/atapi-cd.c optional acd device-driver
i386/isa/wcd.c optional wcd device-driver
i386/isa/wfd.c optional wfd device-driver
i386/isa/wst.c optional wst device-driver
-i386/isa/wd7000.c optional wds device-driver
i386/isa/wt.c optional wt device-driver
i386/linux/imgact_linux.c optional compat_linux
i386/linux/linux_dummy.c optional compat_linux
diff --git a/sys/i386/isa/ic/ncr53400.h b/sys/i386/isa/ic/ncr53400.h
deleted file mode 100644
index 4a60f01..0000000
--- a/sys/i386/isa/ic/ncr53400.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Definitions for 53C400 SCSI-controller chip.
- *
- * Derived from Linux NCR-5380 generic driver sources (by Drew Eckhardt).
- *
- * Copyright (C) 1994 Serge Vakulenko (vak@cronyx.ru)
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _IC_NCR_53C400_H_
-#define _IC_NCR_53C400_H_
-
-#define C400_CSR 0 /* rw - Control and Status Reg. */
-#define CSR_5380_ENABLE 0x80
-#define CSR_TRANSFER_DIRECTION 0x40
-#define CSR_TRANSFER_READY_INTR 0x20
-#define CSR_5380_INTR 0x10
-#define CSR_SHARED_INTR 0x08
-#define CSR_HOST_BUF_NOT_READY 0x04 /* read only */
-#define CSR_SCSI_BUF_READY 0x02 /* read only */
-#define CSR_5380_GATED_IRQ 0x01 /* read only */
-#define CSR_BITS "\20\1irq\2sbrdy\3hbrdy\4shintr\5intr\6tintr\7tdir\10enable"
-
-#define C400_CCR 1 /* rw - Clock Counter Reg. */
-#define C400_HBR 4 /* rw - Host Buffer Reg. */
-
-#define C400_5380_REG_OFFSET 8 /* Offset of 5380 registers. */
-
-#endif /* _IC_NCR_53C400_H_ */
diff --git a/sys/i386/isa/ic/ncr5380.h b/sys/i386/isa/ic/ncr5380.h
deleted file mode 100644
index ce14fec..0000000
--- a/sys/i386/isa/ic/ncr5380.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- * Modified by Serge Vakulenko (vak@cronyx.ru)
- *
- * ncr_5380.h,v 1.2 1994/09/11 20:29:18 phk Exp
- *
- * Definitions for 5380 SCSI-controller chip.
- *
- * Derived from "NCR 53C80 Family SCSI Protocol Controller Data Manual"
- */
-
-#ifndef _IC_NCR_5380_H_
-#define _IC_NCR_5380_H_
-
-#define C80_CSDR 0 /* ro - Current SCSI Data Reg. */
-#define C80_ODR 0 /* wo - Output Data Reg. */
-
-#define C80_ICR 1 /* rw - Initiator Command Reg. */
-#define ICR_ASSERT_RST 0x80
-#define ICR_ARBITRATION_IN_PROGRESS 0x40 /* read only */
-#define ICR_TRI_STATE_MODE 0x40 /* write only */
-#define ICR_LOST_ARBITRATION 0x20 /* read only */
-#define ICR_DIFF_ENABLE 0x20 /* write only */
-#define ICR_ASSERT_ACK 0x10
-#define ICR_ASSERT_BSY 0x08
-#define ICR_ASSERT_SEL 0x04
-#define ICR_ASSERT_ATN 0x02
-#define ICR_ASSERT_DATA_BUS 0x01
-#define ICR_BITS "\20\1dbus\2atn\3sel\4bsy\5ack\6arblost\7arb\10rst"
-
-/*
- * The mask to use when doing read_modify_write on ICR.
- */
-#define ICR_MASK (~(ICR_DIFF_ENABLE | ICR_TRI_STATE_MODE))
-
-#define C80_MR 2 /* rw - Mode Reg. */
-#define MR_BLOCK_MODE_DMA 0x80
-#define MR_TARGET_MODE 0x40
-#define MR_ENABLE_PARITY_CHECKING 0x20
-#define MR_ENABLE_PARITY_INTERRUPT 0x10
-#define MR_ENABLE_EOP_INTERRUPT 0x08
-#define MR_MONITOR_BUSY 0x04
-#define MR_DMA_MODE 0x02
-#define MR_ARBITRATE 0x01
-#define MR_BITS "\20\1arb\2dma\3mbusy\4eopintr\5parintr\6pcheck\7targ\10blk"
-
-#define C80_TCR 3 /* rw - Target Command Reg. */
-#define TCR_LAST_BYTE_SENT 0x80 /* read only */
-#define TCR_ASSERT_REQ 0x08
-#define TCR_ASSERT_MSG 0x04
-#define TCR_ASSERT_CD 0x02
-#define TCR_ASSERT_IO 0x01
-#define TCR_BITS "\20\1i/o\2c/d\3msg\4req\10lastbyte"
-
-#define C80_CSBR 4 /* ro - Current SCSI Bus Status Reg. */
-#define CSBR_RST 0x80
-#define CSBR_BSY 0x40
-#define CSBR_REQ 0x20
-#define CSBR_MSG 0x10
-#define CSBR_CD 0x08
-#define CSBR_IO 0x04
-#define CSBR_SEL 0x02
-#define CSBR_ACK 0x01
-#define CSBR_BITS "\20\1ack\2sel\3i/o\4c/d\5msg\6req\7bsy\10rst"
-
-#define C80_SER 4 /* wo - Select Enable Reg. */
-
-#define C80_BSR 5 /* ro - Bus and Status Reg. */
-#define BSR_END_OF_DMA_XFER 0x80
-#define BSR_DMA_REQUEST 0x40
-#define BSR_PARITY_ERROR 0x20
-#define BSR_INTERRUPT_REQUEST_ACTIVE 0x10
-#define BSR_PHASE_MISMATCH 0x08
-#define BSR_BUSY_ERROR 0x04
-#define BSR_ATN 0x02
-#define BSR_ACK 0x01
-#define BSR_BITS "\20\1ack\2atn\3busyerr\4pherr\5irq\6parerr\7drq\10dend"
-
-#define C80_SDSR 5 /* wo - Start DMA Send Reg. */
-#define C80_IDR 6 /* ro - Input Data Reg. */
-#define C80_SDTR 6 /* wo - Start DMA Target Receive Reg. */
-#define C80_RPIR 7 /* ro - Reset Parity/Interrupt Reg. */
-#define C80_SDIR 7 /* wo - Start DMA Initiator Receive Reg. */
-
-#endif /* _IC_NCR_5380_H_ */
diff --git a/sys/i386/isa/ncr5380.c b/sys/i386/isa/ncr5380.c
deleted file mode 100644
index cb01305..0000000
--- a/sys/i386/isa/ncr5380.c
+++ /dev/null
@@ -1,1539 +0,0 @@
-/*
- * FreeBSD generic NCR-5380/NCR-53C400 SCSI driver
- *
- * Copyright (C) 1994 Serge Vakulenko (vak@cronyx.ru)
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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.
- */
-
-/*
- * Tested on the following hardware:
- * Adapter: Trantor T130
- * Streamer: Archive Viper 150,
- * CD-ROM: NEC CDR-25
- */
-#undef DEBUG
-
-#include "nca.h"
-#if NNCA > 0
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-
-#include <machine/clock.h>
-
-#include <i386/isa/isa_device.h>
-#include <i386/isa/ic/ncr5380.h>
-#include <i386/isa/ic/ncr53400.h>
-
-#include <scsi/scsiconf.h>
-
-#ifdef DEBUG
-# define PRINT(s) printf s
-#else
-# define PRINT(s) /*void*/
-#endif
-
-#define SCB_TABLE_SIZE 8 /* start with 8 scb entries in table */
-#define BLOCK_SIZE 512 /* size of READ/WRITE areas on SCSI card */
-#define HOST_SCSI_ADDR 7 /* address of the adapter on the SCSI bus */
-
-/*
- * Defice config flags
- */
-#define FLAG_NOPARITY 0x01 /* disable SCSI bus parity check */
-
-/*
- * ProAudioSpectrum registers
- */
-#define PAS16_DATA 8 /* Data Register */
-#define PAS16_STAT 9 /* Status Register */
-#define PAS16_STAT_DREQ 0x80 /* Pseudo-DMA ready bit */
-#define PAS16_REG(r) (((r) & 0xc) << 11 | ((r) & 3))
-
-static u_char pas16_irq_magic[] =
- { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 };
-
-/*
- * SCSI bus phases
- */
-#define PHASE_MASK (CSBR_MSG | CSBR_CD | CSBR_IO)
-#define PHASE_DATAOUT 0
-#define PHASE_DATAIN CSBR_IO
-#define PHASE_CMDOUT CSBR_CD
-#define PHASE_STATIN (CSBR_CD | CSBR_IO)
-#define PHASE_MSGOUT (CSBR_MSG | CSBR_CD)
-#define PHASE_MSGIN (CSBR_MSG | CSBR_CD | CSBR_IO)
-#define PHASE_NAME(ph) phase_name[(ph)>>2]
-#define PHASE_TO_TCR(ph) ((ph) >> 2)
-
-static char *phase_name[] = {
- "DATAOUT", "DATAIN", "CMDOUT", "STATIN",
- "Phase4?", "Phase5?", "MSGOUT", "MSGIN",
-};
-
-/*
- * SCSI message codes
- */
-#define MSG_COMMAND_COMPLETE 0x00
-#define MSG_SAVE_POINTERS 0x02
-#define MSG_RESTORE_POINTERS 0x03
-#define MSG_DISCONNECT 0x04
-#define MSG_ABORT 0x06
-#define MSG_MESSAGE_REJECT 0x07
-#define MSG_NOP 0x08
-#define MSG_BUS_DEV_RESET 0x0c
-#define MSG_IDENTIFY(lun) (0xc0 | ((lun) & 0x7))
-#define MSG_ISIDENT(m) ((m) & 0x80)
-
-/*
- * SCSI control block used to keep info about a scsi command
- */
-typedef struct scb {
- int flags; /* status of the instruction */
-#define SCB_FREE 0x00
-#define SCB_ACTIVE 0x01
-#define SCB_ABORTED 0x02
-#define SCB_TIMEOUT 0x04
-#define SCB_ERROR 0x08
-#define SCB_TIMECHK 0x10 /* we have set a timeout on this one */
-#define SCB_SENSE 0x20 /* sensed data available */
-#define SCB_TBUSY 0x40 /* target busy */
- struct scb *next; /* in free list */
- struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
- u_char *data; /* position in data buffer so far */
- int32_t datalen; /* bytes remaining to transfer */
-} scb_t;
-
-typedef enum {
- CTLR_NONE,
- CTLR_NCR_5380,
- CTLR_NCR_53C400,
- CTLR_PAS_16
-} ctlr_t;
-
-/*
- * Data structure describing the target state.
- */
-typedef struct {
- u_char busy; /* mask of busy luns at device target */
- u_long perrcnt; /* counter of target parity errors */
-} target_t;
-
-/*
- * Data structure describing current status of the scsi bus. One for each
- * controller card.
- */
-typedef struct {
- ctlr_t type; /* Seagate or Future Domain */
- char *name; /* adapter name */
-
- /* NCR-5380 controller registers */
- u_short ODR; /* (wo-0) Output Data Register */
- u_short CSDR; /* (ro-0) Current SCSI Data Register */
- u_short ICR; /* (rw-1) Initiator Command Register */
- u_short MR; /* (rw-2) Mode Register */
- u_short TCR; /* (rw-3) Target Command Register */
- u_short SER; /* (wo-4) Select Enable Register */
- u_short CSBR; /* (ro-4) Current SCSI Bus Status Register */
- u_short BSR; /* (ro-5) Bus and Status Register */
- u_short SDSR; /* (wo-5) Start DMA Send Register */
- u_short SDIR; /* (wo-7) Start DMA Initiator Receive Register */
- u_short RPIR; /* (ro-7) Reset Parity/Interrupt Register */
-
- /* NCR-53C400 controller registers */
- u_short CSR; /* (rw-0) Control and Status Register */
- u_short CCR; /* (rw-1) Clock Counter Register */
- u_short HBR; /* (rw-4) Host Buffer Register */
-
- /* ProAudioSpectrum controller registers */
- u_short PDATA; /* (rw) Pseudo-DMA Data Register */
- u_short PSTAT; /* (rw) Pseudo-DMA Status Register */
-
- u_char scsi_addr; /* our scsi address, 0..7 */
- u_char scsi_id; /* our scsi id mask */
- u_char parity; /* parity flag: CMD_EN_PARITY or 0 */
- u_char irq; /* IRQ number used or 0 if no IRQ */
- u_int timeout_active : 1; /* timeout() active (requested) */
-
- struct scsi_link sc_link; /* struct connecting different data */
- scb_t *queue; /* waiting to be issued */
- scb_t *disconnected_queue; /* waiting to reconnect */
-
- int numscb; /* number of scsi control blocks */
- scb_t *free_scb; /* free scb list */
- scb_t scbs[SCB_TABLE_SIZE];
-
- target_t target[8]; /* target state data */
-} adapter_t;
-
-static adapter_t ncadata[NNCA];
-
-#define IS_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy &\
- (1 << (b)->xfer->sc_link->lun))
-#define SET_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy |=\
- (1 << (b)->xfer->sc_link->lun))
-#define CLEAR_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy &=\
- ~(1 << (b)->xfer->sc_link->lun))
-
-/*
- * Wait for condition, given as an boolean expression.
- * Print the message on timeout.
- */
-#define WAITFOR(condition,count,message) {\
- register u_long cnt = count; char *_msg = message;\
- while (cnt-- && ! (condition)) continue;\
- if (cnt == -1 && _msg)\
- printf ("nca: %s timeout\n", _msg); }
-
-static int nca_probe (struct isa_device *dev);
-static int nca_attach (struct isa_device *dev);
-static int32_t nca_scsi_cmd (struct scsi_xfer *xs);
-static u_int32_t nca_adapter_info (int unit);
-static void nca_timeout (void *scb);
-static void ncaminphys (struct buf *bp);
-static void nca_done (adapter_t *z, scb_t *scb);
-static void nca_start (adapter_t *z);
-static void nca_information_transfer (adapter_t *z, scb_t *scb);
-static int nca_poll (adapter_t *z, scb_t *scb);
-static int nca_init (adapter_t *z);
-static ointhand2_t ncaintr;
-static int nca_reselect (adapter_t *z);
-static int nca_select (adapter_t *z, scb_t *scb);
-static int nca_abort (adapter_t *z, scb_t *scb);
-static void nca_send_abort (adapter_t *z);
-static u_char nca_msg_input (adapter_t *z);
-static void nca_tick (void *arg);
-static int nca_sense (adapter_t *z, scb_t *scb);
-static void nca_data_output (adapter_t *z, u_char **pdata, u_long *plen);
-static void nca_data_input (adapter_t *z, u_char **pdata, u_long *plen);
-static void nca_cmd_output (adapter_t *z, u_char *cmd, int cmdlen);
-static void nca_53400_dma_xfer (adapter_t *z, int r, u_char **dat, u_long *len);
-static void nca_pas_dma_xfer (adapter_t *z, int r, u_char **dat, u_long *len);
-
-static struct scsi_adapter nca_switch = {
- nca_scsi_cmd, ncaminphys, 0, 0, nca_adapter_info, "nca", {0},
-};
-static struct scsi_device nca_dev = { NULL, NULL, NULL, NULL, "nca", 0, {0} };
-struct isa_driver ncadriver = { nca_probe, nca_attach, "nca" };
-
-/*
- * Check if the device can be found at the port given and if so,
- * detect the type of board. Set it up ready for further work.
- * Takes the isa_dev structure from autoconf as an argument.
- * Returns 1 if card recognized, 0 if errors.
- */
-int nca_probe (struct isa_device *dev)
-{
- adapter_t *z = &ncadata[dev->id_unit];
- int i;
-
- /* Init fields used by our routines */
- z->parity = (dev->id_flags & FLAG_NOPARITY) ? 0 :
- MR_ENABLE_PARITY_CHECKING;
- z->scsi_addr = HOST_SCSI_ADDR;
- z->scsi_id = 1 << z->scsi_addr;
- z->irq = dev->id_irq ? ffs (dev->id_irq) - 1 : 0;
- z->queue = 0;
- z->disconnected_queue = 0;
- for (i=0; i<8; i++)
- z->target[i].busy = 0;
-
- /* Link up the free list of scbs */
- z->numscb = SCB_TABLE_SIZE;
- z->free_scb = z->scbs;
- for (i=1; i<SCB_TABLE_SIZE; i++)
- z->scbs[i-1].next = z->scbs + i;
- z->scbs[SCB_TABLE_SIZE-1].next = 0;
-
- /* Try NCR 5380. */
- z->type = CTLR_NCR_5380;
- z->name = "NCR-5380";
- z->ODR = dev->id_iobase + C80_ODR;
- z->CSDR = dev->id_iobase + C80_CSDR;
- z->ICR = dev->id_iobase + C80_ICR;
- z->MR = dev->id_iobase + C80_MR;
- z->TCR = dev->id_iobase + C80_TCR;
- z->SER = dev->id_iobase + C80_SER;
- z->CSBR = dev->id_iobase + C80_CSBR;
- z->BSR = dev->id_iobase + C80_BSR;
- z->SDSR = dev->id_iobase + C80_SDSR;
- z->SDIR = dev->id_iobase + C80_SDIR;
- z->RPIR = dev->id_iobase + C80_RPIR;
- z->CSR = 0;
- z->CCR = 0;
- z->HBR = 0;
- z->PDATA = 0;
- z->PSTAT = 0;
- if (nca_init (z) == 0)
- return (8);
-
- /* Try NCR 53C400. */
- z->type = CTLR_NCR_53C400;
- z->name = "NCR-53C400";
- z->ODR = dev->id_iobase + C400_5380_REG_OFFSET + C80_ODR;
- z->CSDR = dev->id_iobase + C400_5380_REG_OFFSET + C80_CSDR;
- z->ICR = dev->id_iobase + C400_5380_REG_OFFSET + C80_ICR;
- z->MR = dev->id_iobase + C400_5380_REG_OFFSET + C80_MR;
- z->TCR = dev->id_iobase + C400_5380_REG_OFFSET + C80_TCR;
- z->SER = dev->id_iobase + C400_5380_REG_OFFSET + C80_SER;
- z->CSBR = dev->id_iobase + C400_5380_REG_OFFSET + C80_CSBR;
- z->BSR = dev->id_iobase + C400_5380_REG_OFFSET + C80_BSR;
- z->SDSR = dev->id_iobase + C400_5380_REG_OFFSET + C80_SDSR;
- z->SDIR = dev->id_iobase + C400_5380_REG_OFFSET + C80_SDIR;
- z->RPIR = dev->id_iobase + C400_5380_REG_OFFSET + C80_RPIR;
- z->CSR = dev->id_iobase + C400_CSR;
- z->CCR = dev->id_iobase + C400_CCR;
- z->HBR = dev->id_iobase + C400_HBR;
- z->PDATA = 0;
- z->PSTAT = 0;
- if (nca_init (z) == 0)
- return (16);
-
- /* Try ProAudioSpectrum-16. */
- z->type = CTLR_PAS_16;
- z->name = "ProAudioSpectrum"; /* changed later */
- z->ODR = dev->id_iobase ^ PAS16_REG (C80_ODR);
- z->CSDR = dev->id_iobase ^ PAS16_REG (C80_CSDR);
- z->ICR = dev->id_iobase ^ PAS16_REG (C80_ICR);
- z->MR = dev->id_iobase ^ PAS16_REG (C80_MR);
- z->TCR = dev->id_iobase ^ PAS16_REG (C80_TCR);
- z->SER = dev->id_iobase ^ PAS16_REG (C80_SER);
- z->CSBR = dev->id_iobase ^ PAS16_REG (C80_CSBR);
- z->BSR = dev->id_iobase ^ PAS16_REG (C80_BSR);
- z->SDSR = dev->id_iobase ^ PAS16_REG (C80_SDSR);
- z->SDIR = dev->id_iobase ^ PAS16_REG (C80_SDIR);
- z->RPIR = dev->id_iobase ^ PAS16_REG (C80_RPIR);
- z->CSR = 0;
- z->CCR = 0;
- z->HBR = 0;
- z->PDATA = dev->id_iobase ^ PAS16_REG (PAS16_DATA);
- z->PSTAT = dev->id_iobase ^ PAS16_REG (PAS16_STAT);
- if (nca_init (z) == 0)
- return (4);
-
- bzero (z, sizeof (*z));
- return (0);
-}
-
-/*
- * Probe the adapter, and if found, reset the board and the scsi bus.
- * Return 0 if the adapter found.
- */
-int nca_init (adapter_t *z)
-{
- int i, c;
-
- if (z->type == CTLR_NCR_53C400) {
- if (inb (z->CSR) == 0xFF)
- return (100);
-
- /* Reset 53C400. */
- outb (z->CSR, CSR_5380_ENABLE);
-
- /* Enable interrupts. */
- outb (z->CSR, z->irq ? CSR_5380_INTR : 0);
- }
-
- if (z->type == CTLR_PAS_16) {
- u_short base = z->PDATA & 0x3FF;
-
- outb (0x9a01, 0xbc + (z-ncadata)); /* unit number */
- outb (0x9a01, base >> 2);
-
- if (inb (base^0x803) == 0xFF)
- return (200);
-
- if (inb (z->CSDR) == 0xFF && inb (z->CSDR^0x2000) == 0xFF &&
- inb (z->CSDR) == 0xFF && inb (z->CSDR^0x2000) == 0xFF &&
- inb (z->CSDR) == 0xFF && inb (z->CSDR^0x2000) == 0xFF &&
- inb (z->CSDR) == 0xFF && inb (z->CSDR^0x2000) == 0xFF)
- return (201);
-
- i = inb (base^0x803);
- outb (base^0x803, i ^ 0xE0);
- c = inb (base^0x803);
- outb (base^0x803, 1);
- if (i != c)
- return (202);
-
- /* Various magic. */
- outb (base^0x4000, 0x30); /* Timeout counter */
- outb (base^0x4001, 0x01); /* Reset TC */
- outb (base^0xbc00, 0x01); /* 1 Wait state */
- outb (base^0x8003, 0x4d); /* sysconfig_4 */
- i = pas16_irq_magic[z->irq];
- if (!i) {
- z->irq = 0;
- } else {
- outb (base^0xf002, i << 4);
- outb (base^0x8003, 0x6d); /* sysconfig_4 */
- }
-
- switch (inb (base^0xEC03) & 0xF) {
- case 6: z->name = "ProAudioSpectrum-Plus"; break;
- case 12: z->name = "ProAudioSpectrum-16D"; break;
- case 14: z->name = "ProAudioSpectrum-CDPC"; break;
- case 15: z->name = "ProAudioSpectrum-16"; break;
- default: return (203);
- }
- }
-
- /* Read RPI port, resetting parity/interrupt state. */
- inb (z->RPIR);
-
- /* Test BSR: parity error, interrupt request and busy loss state
- * should be cleared. */
- if (inb (z->BSR) & (BSR_PARITY_ERROR |
- BSR_INTERRUPT_REQUEST_ACTIVE | BSR_BUSY_ERROR)) {
- PRINT (("nca: invalid bsr[0x%x]=%b\n", z->BSR,
- inb (z->BSR), BSR_BITS));
- return (1);
- }
-
- /* Reset the SCSI bus. */
- outb (z->ICR, ICR_ASSERT_RST);
- outb (z->ODR, 0);
- /* Hold reset for at least 25 microseconds. */
- DELAY (25);
- /* Check that status cleared. */
- if (inb (z->CSBR) != CSBR_RST) {
- PRINT (("nca: invalid csbr[0x%x]=%b\n", z->CSBR,
- inb (z->CSBR), CSBR_BITS));
- outb (z->ICR, 0);
- return (2);
- }
- /* Clear reset. */
- outb (z->ICR, 0);
- /* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */
- DELAY (2);
-
- /* Enable data drivers. */
- outb (z->ICR, ICR_ASSERT_DATA_BUS);
-
- /* Check that data register is writable. */
- for (i=0; i<256; ++i) {
- outb (z->ODR, i);
- DELAY (1);
- if (inb (z->CSDR) != i) {
- PRINT (("nca: ODR[0x%x] not writable: 0x%x should be 0x%x\n",
- z->ODR, inb (z->CSDR), i));
- outb (z->ICR, 0);
- return (3);
- }
- }
-
- /* Disable data drivers. */
- outb (z->ICR, 0);
-
- /* Check that data register is NOT writable. */
- c = inb (z->CSDR);
- for (i=0; i<256; ++i) {
- outb (z->ODR, i);
- DELAY (1);
- if (inb (z->CSDR) != c) {
- PRINT (("nca: ODR[0x%x] writable: 0x%x should be 0x%x\n",
- z->ODR, inb (z->CSDR), c));
- return (4);
- }
- }
-
- /* Initialize the controller. */
- outb (z->MR, z->parity);
- outb (z->TCR, 0);
- outb (z->SER, z->scsi_id);
- return (0);
-}
-
-/*
- * Attach all sub-devices we can find.
- */
-int nca_attach (struct isa_device *dev)
-{
- int unit = dev->id_unit;
- adapter_t *z = &ncadata[unit];
- struct scsibus_data *scbus;
-
- printf ("nca%d: type %s%s\n", unit, z->name,
- (dev->id_flags & FLAG_NOPARITY) ? ", no parity" : "");
-
- dev->id_ointr = ncaintr;
-
- /* fill in the prototype scsi_link */
- z->sc_link.adapter_unit = unit;
- z->sc_link.adapter_targ = z->scsi_addr;
- z->sc_link.adapter_softc = z;
- z->sc_link.adapter = &nca_switch;
- z->sc_link.device = &nca_dev;
-
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = scsi_alloc_bus();
- if(!scbus)
- return 0;
- scbus->adapter_link = &z->sc_link;
-
- /* ask the adapter what subunits are present */
- scsi_attachdevs (scbus);
-
- return (1);
-}
-
-/*
- * Return some information to the caller about
- * the adapter and its capabilities.
- */
-u_int32_t nca_adapter_info (int unit)
-{
- return (1);
-}
-
-void ncaminphys (struct buf *bp)
-{
-}
-
-/*
- * Catch an interrupt from the adaptor.
- */
-static void ncaintr (int unit)
-{
- adapter_t *z = &ncadata[unit];
-
- PRINT (("nca%d: interrupt bsr=%b csbr=%b\n", unit,
- inb (z->BSR), BSR_BITS, inb (z->CSBR), CSBR_BITS));
- nca_start (z);
- /* Reset interrupt state. */
- inb (z->RPIR);
-}
-
-/*
- * This routine is used in the case when we have no IRQ line (z->irq == 0).
- * It is called every timer tick and polls for reconnect from target.
- */
-void nca_tick (void *arg)
-{
- adapter_t *z = arg;
- int x = splbio ();
-
- z->timeout_active = 0;
- nca_start (z);
- /* Reset interrupt state. */
- inb (z->RPIR);
- if (z->disconnected_queue && ! z->timeout_active) {
- timeout (nca_tick, z, 1);
- z->timeout_active = 1;
- }
- splx (x);
-}
-
-/*
- * Start a scsi operation given the command and the data address.
- * Also needs the unit, target and lu. Get a free scb and set it up.
- * Call send_scb. Either start timer or wait until done.
- */
-int32_t nca_scsi_cmd (struct scsi_xfer *xs)
-{
- int unit = xs->sc_link->adapter_unit, flags = xs->flags, x = 0;
- adapter_t *z = (adapter_t *)xs->sc_link->adapter_softc;
- scb_t *scb;
-
- /* PRINT (("nca%d/%d/%d command 0x%x\n", unit, xs->sc_link->target,
- xs->sc_link->lun, xs->cmd->opcode)); */
- if (xs->bp)
- flags |= SCSI_NOSLEEP;
- if (flags & ITSDONE) {
- printf ("nca%d: already done?", unit);
- xs->flags &= ~ITSDONE;
- }
- if (! (flags & INUSE)) {
- printf ("nca%d: not in use?", unit);
- xs->flags |= INUSE;
- }
- if (flags & SCSI_RESET)
- printf ("nca%d: SCSI_RESET not implemented\n", unit);
-
- if (! (flags & SCSI_NOMASK))
- x = splbio ();
-
- /* Get a free scb.
- * If we can and have to, sleep waiting for one to come free. */
- while (! (scb = z->free_scb)) {
- if (flags & SCSI_NOSLEEP) {
- xs->error = XS_DRIVER_STUFFUP;
- if (! (flags & SCSI_NOMASK))
- splx (x);
- return (TRY_AGAIN_LATER);
- }
- tsleep ((caddr_t)&z->free_scb, PRIBIO, "ncascb", 0);
- }
- /* Get scb from free list. */
- z->free_scb = scb->next;
- scb->next = 0;
- scb->flags = SCB_ACTIVE;
-
- /* Put all the arguments for the xfer in the scb */
- scb->xfer = xs;
- scb->datalen = xs->datalen;
- scb->data = xs->data;
-
- /* Setup the scb to contain necessary values.
- * The interesting values can be read from the xs that is saved.
- * I therefore think that the structure can be kept very small.
- * The driver doesn't use DMA so the scatter/gather is not needed? */
- if (! z->queue) {
- scb->next = z->queue;
- z->queue = scb;
- } else {
- scb_t *q;
-
- for (q=z->queue; q->next; q=q->next)
- continue;
- q->next = scb;
- scb->next = 0; /* placed at the end of the queue */
- }
-
- /* Try to send this command to the board. */
- nca_start (z);
-
- /* Usually return SUCCESSFULLY QUEUED. */
- if (! (flags & SCSI_NOMASK)) {
- splx (x);
- if (xs->flags & ITSDONE)
- /* Timeout timer not started, already finished.
- * Tried to return COMPLETE but the machine hanged
- * with this. */
- return (SUCCESSFULLY_QUEUED);
- xs->timeout_ch = timeout (nca_timeout, (caddr_t) scb,
- (xs->timeout * hz) / 1000);
- scb->flags |= SCB_TIMECHK;
- PRINT (("nca%d/%d/%d command queued\n", unit,
- xs->sc_link->target, xs->sc_link->lun));
- return (SUCCESSFULLY_QUEUED);
- }
-
- /* If we can't use interrupts, poll on completion. */
- if (! nca_poll (z, scb)) {
- /* We timed out, so call the timeout handler manually,
- * accounting for the fact that the clock is not running yet
- * by taking out the clock queue entry it makes. */
- nca_timeout ((void*) scb);
-
- /* Because we are polling, take out the timeout entry
- * nca_timeout made. */
- untimeout (nca_timeout, (void*) scb, scb->xfer->timeout_ch);
-
- if (! nca_poll (z, scb))
- /* We timed out again... This is bad. Notice that
- * this time there is no clock queue entry to remove. */
- nca_timeout ((void*) scb);
- }
- /* PRINT (("nca%d/%d/%d command %s\n", unit,
- xs->sc_link->target, xs->sc_link->lun,
- xs->error ? "failed" : "done")); */
- return (xs->error ? HAD_ERROR : COMPLETE);
-}
-
-/*
- * Coroutine that runs as long as more work can be done.
- * Both scsi_cmd() and intr() will try to start it in
- * case it is not running.
- * Always called with interrupts disabled.
- */
-void nca_start (adapter_t *z)
-{
- scb_t *q, *prev;
-again:
- /* First check that if any device has tried
- * a reconnect while we have done other things
- * with interrupts disabled. */
- if (nca_reselect (z))
- goto again;
-
- /* Search through the queue for a command
- * destined for a target that's not busy. */
- for (q=z->queue, prev=0; q; prev=q, q=q->next) {
- /* Attempt to establish an I_T_L nexus here. */
- if (IS_BUSY (z, q) || ! nca_select (z, q))
- continue;
-
- /* Remove the command from the issue queue. */
- if (prev)
- prev->next = q->next;
- else
- z->queue = q->next;
- q->next = 0;
-
- /* We are connected. Do the task. */
- nca_information_transfer (z, q);
- goto again;
- }
-}
-
-void nca_timeout (void *arg)
-{
- scb_t *scb = (scb_t*) arg;
- int unit = scb->xfer->sc_link->adapter_unit;
- adapter_t *z = (adapter_t *)scb->xfer->sc_link->adapter_softc;
- int x = splbio ();
-
- if (! (scb->xfer->flags & SCSI_NOMASK))
- printf ("nca%d/%d/%d (%s%d) timed out\n", unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun,
- scb->xfer->sc_link->device->name,
- scb->xfer->sc_link->dev_unit);
-
- /* If it has been through before, then a previous abort has failed,
- * don't try abort again. */
- if (! (scb->flags & SCB_ABORTED)) {
- nca_abort (z, scb);
- /* 2 seconds for the abort */
- scb->xfer->timeout_ch = timeout (nca_timeout, (caddr_t)scb,
- 2*hz);
- scb->flags |= (SCB_ABORTED | SCB_TIMECHK);
- } else {
- /* abort timed out */
- scb->flags |= SCB_ABORTED;
- scb->xfer->retries = 0;
- nca_done (z, scb);
- }
- splx (x);
-}
-
-static __inline void nca_sendbyte (adapter_t *z, u_char data)
-{
- outb (z->ODR, data);
- outb (z->ICR, ICR_ASSERT_DATA_BUS | ICR_ASSERT_ACK);
- WAITFOR (! (inb (z->CSBR) & CSBR_REQ), 10000, "sendbyte");
- outb (z->ICR, ICR_ASSERT_DATA_BUS);
-}
-
-static __inline u_char nca_recvbyte (adapter_t *z)
-{
- u_char data;
-
- data = inb (z->CSDR);
- outb (z->ICR, ICR_ASSERT_ACK);
- WAITFOR (! (inb (z->CSBR) & CSBR_REQ), 10000, "recvbyte");
- outb (z->ICR, 0);
- return (data);
-}
-
-/*
- * Establish I_T_L or I_T_L_Q nexus for new or existing command
- * including ARBITRATION, SELECTION, and initial message out
- * for IDENTIFY and queue messages.
- * Return 1 if selection succeded.
- */
-int nca_select (adapter_t *z, scb_t *scb)
-{
- /* Set the phase bits to 0, otherwise the NCR5380 won't drive the
- * data bus during SELECTION. */
- outb (z->TCR, 0);
-
- /* Start arbitration. */
- outb (z->ODR, z->scsi_id);
- outb (z->MR, MR_ARBITRATE);
-
- /* Wait for arbitration logic to complete (20 usec) */
- WAITFOR (inb (z->ICR) & ICR_ARBITRATION_IN_PROGRESS, 200, 0);
- if (! (inb (z->ICR) & ICR_ARBITRATION_IN_PROGRESS)) {
- PRINT (("nca%d/%d/%d no arbitration progress, bsr=%b csbr=%b\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun, inb (z->BSR), BSR_BITS,
- inb (z->CSBR), CSBR_BITS));
- outb (z->MR, z->parity);
- return (0);
- }
- DELAY (3);
-
- /* Check for lost arbitration. */
- if ((inb (z->ICR) & ICR_LOST_ARBITRATION) ||
- (inb (z->CSDR) >> 1 >> z->scsi_addr) ||
- (inb (z->ICR) & ICR_LOST_ARBITRATION)) {
- PRINT (("nca%d/%d/%d arbitration lost\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- outb (z->MR, z->parity);
- return (0);
- }
-
- outb (z->ICR, ICR_ASSERT_SEL);
- if (inb (z->ICR) & ICR_LOST_ARBITRATION) {
- PRINT (("nca%d/%d/%d arbitration lost after SEL\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- outb (z->ICR, 0);
- outb (z->MR, z->parity);
- return (0);
- }
- DELAY (2);
-
- /* Start selection, asserting the host and target ID's on the bus. */
- outb (z->SER, 0);
- outb (z->ODR, z->scsi_id | (1 << scb->xfer->sc_link->target));
- outb (z->ICR, ICR_ASSERT_DATA_BUS | ICR_ASSERT_BSY |
- ICR_ASSERT_SEL);
-
- /* Finish arbitration, drop BSY. */
- outb (z->MR, 0);
- outb (z->ICR, ICR_ASSERT_DATA_BUS | ICR_ASSERT_SEL |
- ICR_ASSERT_ATN);
- DELAY (1);
-
- /* The SCSI specification calls for a 250 ms timeout for the actual
- * selection. */
- WAITFOR (inb (z->CSBR) & CSBR_BSY, 100000, 0);
- if (! (inb (z->CSBR) & CSBR_BSY)) {
- /* The target does not respond. Not an error, though. */
- PRINT (("nca%d/%d/%d target does not respond\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- outb (z->ICR, 0);
- outb (z->SER, z->scsi_id);
- outb (z->MR, z->parity);
- scb->flags |= SCB_TIMEOUT;
- return (0);
- }
-
- /* Clear SEL and SCSI id.
- * Wait for start of REQ/ACK handshake. */
- outb (z->ICR, ICR_ASSERT_DATA_BUS | ICR_ASSERT_ATN);
- WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, 0);
- if (! (inb (z->CSBR) & CSBR_REQ)) {
- PRINT (("nca%d/%d/%d timeout waiting for REQ\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- outb (z->ICR, 0);
- outb (z->SER, z->scsi_id);
- outb (z->MR, z->parity);
- scb->flags |= SCB_ERROR;
- return (0);
- }
-
- /* Check for phase mismatch. */
- if ((inb (z->CSBR) & PHASE_MASK) != PHASE_MSGOUT) {
- /* This should not be taken as an error, but more like
- * an unsupported feature!
- * Should set a flag indicating that the target don't support
- * messages, and continue without failure.
- * (THIS IS NOT AN ERROR!) */
- PRINT (("nca%d/%d/%d waiting for MSGOUT: invalid phase %s\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun,
- PHASE_NAME (inb (z->CSBR) & PHASE_MASK)));
- outb (z->ICR, 0);
- outb (z->SER, z->scsi_id);
- outb (z->MR, z->parity);
- scb->flags |= SCB_ERROR;
- return (0);
- }
-
- /* Allow disconnects. */
- outb (z->TCR, PHASE_TO_TCR (PHASE_MSGOUT));
- outb (z->ICR, ICR_ASSERT_DATA_BUS);
- nca_sendbyte (z, MSG_IDENTIFY (scb->xfer->sc_link->lun));
- outb (z->ICR, 0);
- outb (z->SER, z->scsi_id);
- outb (z->MR, z->parity);
-
- SET_BUSY (z, scb);
- return (1);
-}
-
-int nca_reselect (adapter_t *z)
-{
- scb_t *q = 0, *prev = 0;
- u_char msg, target_mask, lun;
-again:
- /* Wait for a device to win the reselection phase. */
- /* Signals this by asserting the I/O signal. */
- if ((inb (z->CSBR) & (CSBR_SEL | CSBR_IO | CSBR_BSY)) !=
- (CSBR_SEL | CSBR_IO))
- return (0);
-
- /* The data bus contains original initiator id ORed with target id. */
- /* See that we really are the initiator. */
- target_mask = inb (z->CSDR);
- if (! (target_mask & z->scsi_id)) {
- PRINT (("nca%d reselect not for me: mask=0x%x, csbr=%b\n",
- z->sc_link.adapter_unit, target_mask,
- inb (z->CSBR), CSBR_BITS));
- goto again;
- }
-
- /* Find target who won. */
- /* Host responds by asserting the BSY signal. */
- /* Target should respond by deasserting the SEL signal. */
- target_mask &= ~z->scsi_id;
- outb (z->ICR, ICR_ASSERT_BSY);
- WAITFOR (! (inb (z->CSBR) & CSBR_SEL), 10000, "SEL deassert");
-
- /* Remove the busy status. */
- /* Target should set the MSGIN phase. */
- outb (z->ICR, 0);
- WAITFOR (inb (z->CSBR) & CSBR_REQ, 10000, "MSGIN");
-
- /* Hope we get an IDENTIFY message. */
- msg = nca_msg_input (z);
- if (MSG_ISIDENT (msg)) {
- /* Find the command corresponding to the I_T_L or I_T_L_Q
- * nexus we just restablished, and remove it from
- * the disconnected queue. */
- lun = (msg & 7);
- for (q=z->disconnected_queue; q; prev=q, q=q->next) {
- if (target_mask != (1 << q->xfer->sc_link->target))
- continue;
- if (lun != q->xfer->sc_link->lun)
- continue;
- if (prev)
- prev->next = q->next;
- else
- z->disconnected_queue = q->next;
- q->next = 0;
- PRINT (("nca%d/%d/%d reselect done\n",
- z->sc_link.adapter_unit,
- ffs (target_mask) - 1, lun));
- nca_information_transfer (z, q);
- WAITFOR (! (inb (z->CSBR) & CSBR_BSY), 100000, "reselect !busy");
- return (1);
- }
- } else
- printf ("nca%d reselect: expecting IDENTIFY, got 0x%x\n",
- z->sc_link.adapter_unit, msg);
-
- /* Since we have an established nexus that we can't
- * do anything with, we must abort it. */
- nca_send_abort (z);
- PRINT (("nca%d reselect aborted\n", z->sc_link.adapter_unit));
- WAITFOR (! (inb (z->CSBR) & CSBR_BSY), 100000, "reselect abort !busy");
- goto again;
-}
-
-/*
- * Send an abort to the target.
- * Return 1 success, 0 on failure.
- * Called on splbio level.
- */
-int nca_abort (adapter_t *z, scb_t *scb)
-{
- scb_t *q, **prev;
-
- /* If the command hasn't been issued yet, we simply remove it
- * from the issue queue. */
- prev = &z->queue;
- for (q=z->queue; q; q=q->next) {
- if (scb == q) {
- (*prev) = q->next;
- q->next = 0;
- return (1);
- }
- prev = &q->next;
- }
-
- /* If the command is currently disconnected from the bus,
- * we reconnect the I_T_L or I_T_L_Q nexus associated with it,
- * go into message out, and send an abort message. */
- for (q=z->disconnected_queue; q; q=q->next) {
- if (scb != q)
- continue;
-
- if (! nca_select (z, scb))
- return (0);
- nca_send_abort (z);
-
- prev = &z->disconnected_queue;
- for (q=z->disconnected_queue; q; q=q->next) {
- if (scb == q) {
- *prev = q->next;
- q->next = 0;
- /* Set some type of error result
- * for the operation. */
- return (1);
- }
- prev = &q->next;
- }
- }
-
- /* Command not found in any queue. */
- return (0);
-}
-
-/*
- * The task accomplished, mark the i/o control block as done.
- * Always called with interrupts disabled.
- */
-void nca_done (adapter_t *z, scb_t *scb)
-{
- struct scsi_xfer *xs = scb->xfer;
-
- if (scb->flags & SCB_TIMECHK)
- untimeout (nca_timeout, (caddr_t) scb, xs->timeout_ch);
-
- /* How much of the buffer was not touched. */
- xs->resid = scb->datalen;
-
- if (scb->flags != SCB_ACTIVE && ! (xs->flags & SCSI_ERR_OK))
- if (scb->flags & (SCB_TIMEOUT | SCB_ABORTED))
- xs->error = XS_TIMEOUT;
- else if (scb->flags & SCB_ERROR)
- xs->error = XS_DRIVER_STUFFUP;
- else if (scb->flags & SCB_TBUSY)
- xs->error = XS_BUSY;
- else if (scb->flags & SCB_SENSE)
- xs->error = XS_SENSE;
-
- xs->flags |= ITSDONE;
-
- /* Free the control block. */
- scb->next = z->free_scb;
- z->free_scb = scb;
- scb->flags = SCB_FREE;
-
- /* If there were none, wake anybody waiting for one to come free,
- * starting with queued entries. */
- if (! scb->next)
- wakeup ((caddr_t) &z->free_scb);
-
- scsi_done (xs);
-}
-
-/*
- * Wait for completion of command in polled mode.
- * Always called with interrupts masked out.
- */
-int nca_poll (adapter_t *z, scb_t *scb)
-{
- int count;
-
- for (count=0; count<30; ++count) {
- DELAY (1000); /* delay for a while */
- nca_start (z); /* retry operation */
- if (scb->xfer->flags & ITSDONE)
- return (1); /* all is done */
- if (scb->flags & SCB_TIMEOUT)
- return (0); /* no target present */
- }
- return (0);
-}
-
-/*
- * Perform NCR-53C400 pseudo-dma data transfer.
- */
-void nca_53400_dma_xfer (adapter_t *z, int read, u_char **pdata, u_long *plen)
-{
- /* Set dma direction. */
- outb (z->CSR, read ? CSR_TRANSFER_DIRECTION : 0);
-
- /* Enable dma mode. */
- outb (z->MR, MR_DMA_MODE | (read ? z->parity : 0));
-
- /* Start dma transfer. */
- outb (read ? z->SDIR : z->SDSR, 0);
-
- /* Set up clock counter. */
- outb (z->CCR, *plen/128);
-
- for (; *plen>=128; *plen-=128, *pdata+=128) {
- /* Wait for 53C400 host buffer ready. */
- WAITFOR (! (inb (z->CSR) & CSR_HOST_BUF_NOT_READY), 100000, 0);
- if (inb (z->CSR) & CSR_HOST_BUF_NOT_READY)
- break;
-
- /* Transfer 128 bytes of data. */
- if (read)
- insw (z->HBR, *pdata, 64);
- else
- outsw (z->HBR, *pdata, 64);
- }
-
- /* Wait for 5380 registers ready. */
- WAITFOR (inb (z->CSR) & CSR_5380_ENABLE, 10000, 0);
- if (! (inb (z->CSR) & CSR_5380_ENABLE)) {
- /* Reset 53C400. */
- PRINT (("nca%d: reset: pseudo-dma incomplete, csr=%b\n",
- z->sc_link.adapter_unit, inb (z->CSR), CSR_BITS));
- outb (z->CSR, CSR_5380_ENABLE);
- outb (z->CSR, 0);
- }
-
- /* Wait for FIFO flush on write. */
- if (! read)
- WAITFOR (inb (z->TCR) & TCR_LAST_BYTE_SENT, 10000, "last byte");
-
- /* Clear dma mode. */
- outb (z->MR, z->parity);
-
- /* Re-enable interrupts. */
- outb (z->CSR, z->irq ? CSR_5380_INTR : 0);
-}
-
-/*
- * Perform PAS-16 pseudo-dma data transfer.
- */
-void nca_pas_dma_xfer (adapter_t *z, int read, u_char **pdata, u_long *plen)
-{
- /* Enable dma mode. */
- outb (z->MR, MR_DMA_MODE | (read ? z->parity : 0));
-
- /* Start dma transfer. */
- outb (read ? z->SDIR : z->SDSR, 0);
-
- for (; *plen>=512; *plen-=512, *pdata+=512) {
- /* Wait for pseudo-DMA request. */
- WAITFOR (inb (z->PSTAT) & PAS16_STAT_DREQ, 10000, "pseudo-dma");
- if (! (inb (z->PSTAT) & PAS16_STAT_DREQ))
- break;
-
- /* Transfer 512 bytes of data. */
- if (read)
- insb (z->PDATA, *pdata, 512);
- else
- outsb (z->PDATA, *pdata, 512);
- }
-
- /* Clear dma mode. */
- outb (z->MR, z->parity);
-}
-
-/*
- * Send data to the target.
- */
-void nca_data_output (adapter_t *z, u_char **pdata, u_long *plen)
-{
- u_char *data = *pdata;
- u_long len = *plen;
-
- outb (z->ICR, ICR_ASSERT_DATA_BUS);
- if (z->type == CTLR_NCR_53C400 && len%128 == 0)
- /* Use NCR-53C400 pseudo-dma for data transfer. */
- nca_53400_dma_xfer (z, 0, &data, &len);
- else if (z->type == CTLR_PAS_16 && len%512 == 0)
- /* Use PAS-16 pseudo-dma for data transfer. */
- nca_pas_dma_xfer (z, 0, &data, &len);
- else
- for (;;) {
- /* Check SCSI bus phase. */
- u_char s = inb (z->CSBR) ^ (CSBR_BSY | PHASE_DATAOUT);
- if (s & (CSBR_BSY | PHASE_MASK))
- break;
-
- /* Wait for REQ. */
- if (! (s & CSBR_REQ))
- continue;
-
- /* Output data. */
- outb (z->ODR, *data++);
-
- /* Assert ACK and wait for REQ deassert,
- * with irqs disabled. */
- disable_intr ();
- outb (z->ICR, ICR_ASSERT_ACK | ICR_ASSERT_DATA_BUS);
- WAITFOR (! (inb (z->CSBR) & CSBR_REQ), 1000, 0);
- enable_intr ();
-
- /* Deassert ACK. */
- outb (z->ICR, ICR_ASSERT_DATA_BUS);
- --len;
- }
- outb (z->ICR, 0);
- PRINT (("nca (DATAOUT) send %ld bytes\n", *plen - len));
- *plen = len;
- *pdata = data;
-}
-
-/*
- * Receive data from the target.
- */
-void nca_data_input (adapter_t *z, u_char **pdata, u_long *plen)
-{
- u_char *data = *pdata;
- u_long len = *plen;
-
- if (z->type == CTLR_NCR_53C400 && len%128 == 0)
- /* Use NCR-53C400 pseudo-dma for data transfer. */
- nca_53400_dma_xfer (z, 1, &data, &len);
- else if (z->type == CTLR_PAS_16 && len%512 == 0)
- /* Use PAS-16 pseudo-dma for data transfer. */
- nca_pas_dma_xfer (z, 1, &data, &len);
- else
- for (;;) {
- /* Check SCSI bus phase. */
- u_char s = inb (z->CSBR) ^ (CSBR_BSY | PHASE_DATAIN);
- if (s & (CSBR_BSY | PHASE_MASK))
- break;
-
- /* Wait for REQ. */
- if (! (s & CSBR_REQ))
- continue;
-
- /* Input data. */
- *data++ = inb (z->CSDR);
-
- /* Assert ACK and wait for REQ deassert,
- * with irqs disabled. */
- disable_intr ();
- outb (z->ICR, ICR_ASSERT_ACK);
- WAITFOR (! (inb (z->CSBR) & CSBR_REQ), 1000, 0);
- enable_intr ();
-
- /* Deassert ACK. */
- outb (z->ICR, 0);
- --len;
- }
- PRINT (("nca (DATAIN) got %ld bytes\n", *plen - len));
- *plen = len;
- *pdata = data;
-}
-
-/*
- * Send the command to the target.
- */
-void nca_cmd_output (adapter_t *z, u_char *cmd, int cmdlen)
-{
- PRINT (("nca%d send command (%d bytes) ", z->sc_link.adapter_unit,
- cmdlen));
-
- outb (z->ICR, ICR_ASSERT_DATA_BUS);
- while (cmdlen) {
- /* Check for target disconnect. */
- u_char sts = inb (z->CSBR);
- if (! (sts & CSBR_BSY))
- break;
-
- /* Check for phase mismatch. */
- if ((sts & PHASE_MASK) != PHASE_CMDOUT) {
- printf ("nca: sending command: invalid phase %s\n",
- PHASE_NAME (sts & PHASE_MASK));
- break;
- }
-
- /* Wait for REQ. */
- if (! (sts & CSBR_REQ))
- continue;
-
- PRINT (("-%x", *cmd));
- nca_sendbyte (z, *cmd++);
- --cmdlen;
- }
- outb (z->ICR, 0);
- PRINT (("\n"));
-}
-
-/*
- * Send the message to the target.
- */
-void nca_send_abort (adapter_t *z)
-{
- u_char sts;
-
- outb (z->ICR, ICR_ASSERT_ATN);
-
- /* Wait for REQ, after which the phase bits will be valid. */
- WAITFOR (inb (z->CSBR) & CSBR_REQ, 1000000, "abort message");
- sts = inb (z->CSBR);
- if (! (sts & CSBR_REQ))
- goto ret;
-
- /* Check for phase mismatch. */
- if ((sts & PHASE_MASK) != PHASE_MSGOUT) {
- printf ("nca: sending MSG_ABORT: invalid phase %s\n",
- PHASE_NAME (sts & PHASE_MASK));
- goto ret;
- }
-
- outb (z->ICR, ICR_ASSERT_DATA_BUS);
- outb (z->TCR, PHASE_TO_TCR (PHASE_MSGOUT));
- nca_sendbyte (z, MSG_ABORT);
-
- PRINT (("nca%d send MSG_ABORT\n", z->sc_link.adapter_unit));
-ret: outb (z->ICR, 0);
-}
-
-/*
- * Get the message from the target.
- * Return the length of the received message.
- */
-u_char nca_msg_input (adapter_t *z)
-{
- u_char sts, msg;
-
- /* Wait for REQ, after which the phase bits will be valid. */
- WAITFOR (inb (z->CSBR) & CSBR_REQ, 1000000, "message input");
- sts = inb (z->CSBR);
- if (! (sts & CSBR_REQ))
- return (MSG_ABORT);
-
- /* Check for phase mismatch.
- * Reached if the target decides that it has finished the transfer. */
- if ((sts & PHASE_MASK) != PHASE_MSGIN) {
- printf ("nca: sending message: invalid phase %s\n",
- PHASE_NAME (sts & PHASE_MASK));
- return (MSG_ABORT);
- }
-
- /* Do actual transfer from SCSI bus to memory. */
- outb (z->TCR, PHASE_TO_TCR (PHASE_MSGIN));
- msg = nca_recvbyte (z);
- PRINT (("nca%d (MSG_INPUT) got 0x%x\n", z->sc_link.adapter_unit, msg));
- return (msg);
-}
-
-/*
- * Send request-sense op to the target.
- * Return 1 success, 0 on failure.
- * Called on splbio level.
- */
-int nca_sense (adapter_t *z, scb_t *scb)
-{
- u_char cmd[6], status, msg, *data;
- u_long len;
-
- /* Wait for target to disconnect. */
- WAITFOR (! (inb (z->CSBR) & CSBR_BSY), 100000, "sense bus free");
- if (inb (z->CSBR) & CSBR_BSY)
- return (0);
-
- /* Select the target again. */
- if (! nca_select (z, scb))
- return (0);
-
- /* Wait for CMDOUT phase. */
- WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, "sense CMDOUT");
- if (! (inb (z->CSBR) & CSBR_REQ) ||
- (inb (z->CSBR) & PHASE_MASK) != PHASE_CMDOUT)
- return (0);
- outb (z->TCR, PHASE_TO_TCR (PHASE_CMDOUT));
-
- /* Send command. */
- len = sizeof (scb->xfer->sense);
- cmd[0] = REQUEST_SENSE;
- cmd[1] = scb->xfer->sc_link->lun << 5;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = len;
- cmd[5] = 0;
- nca_cmd_output (z, cmd, sizeof (cmd));
-
- /* Wait for DATAIN phase. */
- WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, "sense DATAIN");
- if (! (inb (z->CSBR) & CSBR_REQ) ||
- (inb (z->CSBR) & PHASE_MASK) != PHASE_DATAIN)
- return (0);
- outb (z->TCR, PHASE_TO_TCR (PHASE_DATAIN));
-
- data = (u_char*) &scb->xfer->sense;
- nca_data_input (z, &data, &len);
- PRINT (("nca%d sense %x-%x-%x-%x-%x-%x-%x-%x\n",
- z->sc_link.adapter_unit, scb->xfer->sense.error_code,
- scb->xfer->sense.ext.extended.segment,
- scb->xfer->sense.ext.extended.flags,
- scb->xfer->sense.ext.extended.info[0],
- scb->xfer->sense.ext.extended.info[1],
- scb->xfer->sense.ext.extended.info[2],
- scb->xfer->sense.ext.extended.info[3],
- scb->xfer->sense.ext.extended.extra_len));
-
- /* Wait for STATIN phase. */
- WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, "sense STATIN");
- if (! (inb (z->CSBR) & CSBR_REQ) ||
- (inb (z->CSBR) & PHASE_MASK) != PHASE_STATIN)
- return (0);
- outb (z->TCR, PHASE_TO_TCR (PHASE_STATIN));
-
- status = nca_recvbyte (z);
-
- /* Wait for MSGIN phase. */
- WAITFOR (inb (z->CSBR) & CSBR_REQ, 100000, "sense MSGIN");
- if (! (inb (z->CSBR) & CSBR_REQ) ||
- (inb (z->CSBR) & PHASE_MASK) != PHASE_MSGIN)
- return (0);
- outb (z->TCR, PHASE_TO_TCR (PHASE_MSGIN));
-
- msg = nca_recvbyte (z);
-
- if (status != 0 || msg != 0)
- printf ("nca%d: bad sense status=0x%x, msg=0x%x\n",
- z->sc_link.adapter_unit, status, msg);
- return (1);
-}
-
-/*
- * Do the transfer. We know we are connected. Update the flags,
- * call nca_done when task accomplished. Dialog controlled by the target.
- * Always called with interrupts disabled.
- */
-void nca_information_transfer (adapter_t *z, scb_t *scb)
-{
- u_char *data = scb->data; /* current data buffer */
- u_long datalen = scb->datalen; /* current data transfer size */
- register u_char sts;
- u_char msg;
-
- while ((sts = inb (z->CSBR)) & CSBR_BSY) {
- /* We only have a valid SCSI phase when REQ is asserted. */
- if (! (sts & CSBR_REQ))
- continue;
- if (inb (z->BSR) & BSR_PARITY_ERROR) {
- int target = scb->xfer->sc_link->target;
- if (++z->target[target].perrcnt <= 8)
- printf ("nca%d/%d/%d parity error\n",
- z->sc_link.adapter_unit, target,
- scb->xfer->sc_link->lun);
- if (z->target[target].perrcnt == 8)
- printf ("nca%d/%d/%d too many parity errors, not logging any more\n",
- z->sc_link.adapter_unit, target,
- scb->xfer->sc_link->lun);
- /* Clear parity error. */
- inb (z->RPIR);
- }
- outb (z->TCR, PHASE_TO_TCR (sts & PHASE_MASK));
- switch (sts & PHASE_MASK) {
- case PHASE_DATAOUT:
- if (datalen <= 0) {
- printf ("nca%d/%d/%d data length underflow\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun);
- /* send zero byte */
- outb (z->ICR, ICR_ASSERT_DATA_BUS);
- nca_sendbyte (z, 0);
- outb (z->ICR, 0);
- break;
- }
- nca_data_output (z, &data, &datalen);
- break;
- case PHASE_DATAIN:
- if (datalen <= 0) {
- /* Get extra data. Some devices (e.g. CDROMs)
- * use fixed-length blocks (e.g. 2k),
- * even if we need less. */
- PRINT (("@"));
- nca_recvbyte (z);
- break;
- }
- nca_data_input (z, &data, &datalen);
- break;
- case PHASE_CMDOUT:
- nca_cmd_output (z, (u_char*) scb->xfer->cmd,
- scb->xfer->cmdlen);
- break;
- case PHASE_STATIN:
- scb->xfer->status = nca_recvbyte (z);
- PRINT (("nca%d/%d/%d (STATIN) got 0x%x\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun,
- (u_char) scb->xfer->status));
- break;
- case PHASE_MSGOUT:
- /* Send no-op message. */
- outb (z->ICR, ICR_ASSERT_DATA_BUS);
- nca_sendbyte (z, MSG_NOP);
- outb (z->ICR, 0);
- PRINT (("nca%d/%d/%d (MSGOUT) send NOP\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- break;
- case PHASE_MSGIN:
- /* Don't handle multi-byte messages here, because they
- * should not be present here. */
- msg = nca_recvbyte (z);
- PRINT (("nca%d/%d/%d (MSGIN) got 0x%x\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun, msg));
- switch (msg) {
- case MSG_COMMAND_COMPLETE:
- scb->data = data;
- scb->datalen = datalen;
- /* In the case of check-condition status,
- * perform the request-sense op. */
- switch (scb->xfer->status & 0x1e) {
- case SCSI_CHECK:
- if (nca_sense (z, scb))
- scb->flags = SCB_SENSE;
- break;
- case SCSI_BUSY:
- scb->flags = SCB_TBUSY;
- break;
- }
- goto done;
- case MSG_ABORT:
- printf ("nca: command aborted by target\n");
- scb->flags = SCB_ABORTED;
- goto done;
- case MSG_MESSAGE_REJECT:
- printf ("nca: message rejected\n");
- scb->flags = SCB_ABORTED;
- goto done;
- case MSG_DISCONNECT:
- scb->next = z->disconnected_queue;
- z->disconnected_queue = scb;
- if (! z->irq && ! z->timeout_active) {
- timeout (nca_tick, z, 1);
- z->timeout_active = 1;
- }
- PRINT (("nca%d/%d/%d disconnected\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- goto ret;
- case MSG_SAVE_POINTERS:
- scb->data = data;
- scb->datalen = datalen;
- break;
- case MSG_RESTORE_POINTERS:
- data = scb->data;
- datalen = scb->datalen;
- break;
- default:
- printf ("nca%d/%d/%d unknown message: 0x%x\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun, msg);
- break;
- }
- break;
- default:
- printf ("nca: unknown phase: %b\n", sts, CSBR_BITS);
- break;
- }
- }
- printf ("nca%d/%d/%d unexpected target disconnect\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun);
- scb->flags = SCB_ERROR;
-done:
- CLEAR_BUSY (z, scb);
- nca_done (z, scb);
-ret:
- outb (z->ICR, 0);
- outb (z->TCR, 0);
- outb (z->SER, z->scsi_id);
- WAITFOR (! (inb (z->CSBR) & CSBR_BSY), 100000, "xfer bus free");
-}
-#endif /* NNCA */
diff --git a/sys/i386/isa/seagate.c b/sys/i386/isa/seagate.c
deleted file mode 100644
index 30ca28c..0000000
--- a/sys/i386/isa/seagate.c
+++ /dev/null
@@ -1,1509 +0,0 @@
-/*
- * (Free/Net/386)BSD ST01/02, Future Domain TMC-885, TMC-950 SCSI driver for
- * Julians SCSI-code
- *
- * Copyright 1994, Kent Palmkvist (kentp@isy.liu.se)
- * Copyright 1994, Robert Knier (rknier@qgraph.com)
- * Copyright 1992, 1994 Drew Eckhardt (drew@colorado.edu)
- * Copyright 1994, Julian Elischer (julian@tfs.com)
- * Copyright 1994-1995, Serge Vakulenko (vak@cronyx.ru)
- * Copyright 1995 Stephen Hocking (sysseh@devetir.qld.gov.au)
- *
- * Others that has contributed by example code is
- * Glen Overby (overby@cray.com)
- * Tatu Yllnen
- * Brian E Litzinger
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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.
- */
-
-/*
- * kentp 940307 alpha version based on newscsi-03 version of Julians SCSI-code
- * kentp 940314 Added possibility to not use messages
- * rknier 940331 Added fast transfer code
- * rknier 940407 Added assembler coded data transfers
- * vak 941226 New probe algorithm, based on expected behaviour
- * instead of BIOS signatures analysis, better timeout handling,
- * new asm fragments for data input/output, target-dependent
- * delays, device flags, polling mode, generic cleanup
- * vak 950115 Added request-sense ops
- * seh 950701 Fixed up Future Domain TMC-885 problems with disconnects,
- * weird phases and the like. (we could probably investigate
- * what the board's idea of the phases are, but that requires
- * doco that I don't have). Note that it is slower than the
- * 2.0R driver with both SEA_BLINDTRANSFER & SEA_ASSEMBLER
- * defined by a factor of more than 2. I'll look at that later!
- * seh 950712 The performance release 8^). Put in the blind transfer code
- * from the 2.0R source. Don't use it by commenting out the
- * SEA_BLINDTRANSFER below. Note that it only kicks in during
- * DATAOUT or DATAIN and then only when the transfer is a
- * multiple of BLOCK_SIZE bytes (512). Most devices fit into
- * that category, with the possible exception of scanners and
- * some of the older MO drives.
- *
- * $Id: seagate.c,v 1.31 1998/08/11 17:22:42 bde Exp $
- */
-
-/*
- * What should really be done:
- *
- * Restructure interrupt enable/disable code (runs too long with int disabled)
- * Add code to handle Future Domain 840, 841, 880 and 881
- * Add code to use tagged commands in SCSI2
- * Add code to handle slow devices better (sleep if device not disconnecting)
- * Fix unnecessary interrupts
- */
-
-/* Note to users trying to share a disk between DOS and unix:
- * The ST01/02 is a translating host-adapter. It is not giving DOS
- * the same number of heads/tracks/sectors as specified by the disk.
- * It is therefore important to look at what numbers DOS thinks the
- * disk has. Use these to disklabel your disk in an appropriate manner
- *
- * About ST02+IDE coexistence: the original Seagate ST02
- * BIOS cannot coexist with IDE or any other disk controller
- * because it does not share BIOS disk drive numbers (80h, 81h)
- * with others. New probing code allows using ST02 controller
- * without BIOS: just unplug the ST02 BIOS chip from the board.
- *
- * Another problem is the floppy adapter on ST02 which could not be
- * disabled by jumpers. I commonly use ST02 adapter as a cheap solution
- * for atttaching the tape and CD-ROM drives, and an extra floppy controller
- * is just a headache. I found a simple workaround: cutting off
- * the AEN signal (A11 contact on ISA connector). AEN then goes high and
- * disables the floppy adapter port address decoder.
- *
- * I also had a problem with ST02 conflicting with IDE during
- * IDE data write phase. It seems than ST02 makes some noise
- * on /IOW line. The /IOW line is used only for floppy controller
- * part of ST02, and because I don't need it, I cut off the /IOW (contact B13)
- * and it helped. (vak)
- *
- * Tested on the following hardware:
- * Adapter: Seagate ST02
- * Disk: HP D1686
- * Streamers: Archive Viper 150, Wangtek 5525
- * CD-ROMs: Toshiba XM-3401, NEC CDR-25
- *
- * Maximum data rate is about 270-280 kbytes/sec (on 386DX/40).
- * (vak)
- */
-#undef DEBUG
-
-#include "sea.h"
-#if NSEA > 0
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-
-#include <machine/clock.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
-#include <i386/isa/isa_device.h>
-
-#include <scsi/scsiconf.h>
-
-#ifdef DEBUG
-# define PRINT(s) printf s
-#else
-# define PRINT(s) /*void*/
-#endif
-
-#define SCB_TABLE_SIZE 8 /* start with 8 scb entries in table */
-#define BLOCK_SIZE 512 /* size of READ/WRITE areas on SCSI card */
-#define HOST_SCSI_ADDR 7 /* address of the adapter on the SCSI bus */
-#define SEA_BLINDTRANSFER 1 /* for quicker than quick xfers */
-/*
- * Define config flags
- */
-#define FLAG_NOPARITY 0x01 /* disable SCSI bus parity check */
-
-/*
- * Board CONTROL register
- */
-#define CMD_RST 0x01 /* scsi reset */
-#define CMD_SEL 0x02 /* scsi select */
-#define CMD_BSY 0x04 /* scsi busy */
-#define CMD_ATTN 0x08 /* scsi attention */
-#define CMD_START_ARB 0x10 /* start arbitration bit */
-#define CMD_EN_PARITY 0x20 /* enable scsi parity generation */
-#define CMD_INTR 0x40 /* enable scsi interrupts */
-#define CMD_DRVR_ENABLE 0x80 /* scsi enable */
-
-/*
- * Board STATUS register
- */
-#define STAT_BSY 0x01 /* scsi busy */
-#define STAT_MSG 0x02 /* scsi msg */
-#define STAT_IO 0x04 /* scsi I/O */
-#define STAT_CD 0x08 /* scsi C/D */
-#define STAT_REQ 0x10 /* scsi req */
-#define STAT_SEL 0x20 /* scsi select */
-#define STAT_PARITY 0x40 /* parity error bit */
-#define STAT_ARB_CMPL 0x80 /* arbitration complete bit */
-#define STAT_BITS "\20\1bsy\2msg\3i/o\4c/d\5req\6sel\7parity\10arb"
-
-/*
- * SCSI bus phases
- */
-#define PHASE_MASK (STAT_MSG | STAT_CD | STAT_IO)
-#define PHASE_DATAOUT 0
-#define PHASE_DATAIN STAT_IO
-#define PHASE_CMDOUT STAT_CD
-#define PHASE_STATIN (STAT_CD | STAT_IO)
-#define PHASE_MSGOUT (STAT_MSG | STAT_CD)
-#define PHASE_MSGIN (STAT_MSG | STAT_CD | STAT_IO)
-#define PHASE_NAME(ph) phase_name[(ph)>>2]
-
-static char *phase_name[] = {
- "DATAOUT", "Phase1?", "Phase2?", "Phase3?",
- "DATAIN", "Phase5?", "Phase6?", "Phase7?",
- "CMDOUT", "Phase9?", "MSGOUT", "Phase11?",
- "STATIN", "Phase13?", "MSGIN", "Phase15?",
-};
-
-/*
- * SCSI message codes
- */
-#define MSG_COMMAND_COMPLETE 0x00
-#define MSG_SAVE_POINTERS 0x02
-#define MSG_RESTORE_POINTERS 0x03
-#define MSG_DISCONNECT 0x04
-#define MSG_ABORT 0x06
-#define MSG_MESSAGE_REJECT 0x07
-#define MSG_NOP 0x08
-#define MSG_BUS_DEV_RESET 0x0c
-#define MSG_IDENTIFY(lun) (0xc0 | ((lun) & 0x7))
-#define MSG_ISIDENT(m) ((m) & 0x80)
-
-/*
- * SCSI control block used to keep info about a scsi command
- */
-typedef struct scb {
- int flags; /* status of the instruction */
-#define SCB_FREE 0x00
-#define SCB_ACTIVE 0x01
-#define SCB_ABORTED 0x02
-#define SCB_TIMEOUT 0x04
-#define SCB_ERROR 0x08
-#define SCB_TIMECHK 0x10 /* we have set a timeout on this one */
-#define SCB_SENSE 0x20 /* sensed data available */
-#define SCB_TBUSY 0x40 /* target busy */
- struct scb *next; /* in free list */
- struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
- u_char *data; /* position in data buffer so far */
- int32_t datalen; /* bytes remaining to transfer */
-} scb_t;
-
-typedef enum {
- CTLR_NONE,
- CTLR_SEAGATE,
- CTLR_FUTURE_DOMAIN
-} ctlr_t;
-
-/*
- * Flags for waiting for REQ deassert during some SCSI bus phases.
- */
-typedef struct {
- unsigned cmdout1 : 1; /* after CMDOUT[0] byte */
- unsigned cmdout : 1; /* after CMDOUT[1..N] bytes */
- unsigned msgout : 1; /* after MSGOUT byte */
- unsigned statin : 1; /* after STATIN byte */
-} phase_t;
-
-/*
- * Data structure describing the target state.
- */
-typedef struct {
- struct adapter *adapter; /* pointer to the adapter structure */
- u_char busy; /* mask of busy luns at device target */
- u_long perrcnt; /* counter of target parity errors */
- phase_t ndelay; /* "don't delay" flags */
- phase_t init; /* "initialized" flags */
-} target_t;
-
-/*
- * Data structure describing current status of the scsi bus. One for each
- * controller card.
- */
-typedef struct adapter {
- ctlr_t type; /* Seagate or Future Domain */
- char *name; /* adapter name */
- volatile u_char *addr; /* base address for card */
-
- volatile u_char *CONTROL; /* address of control register */
- volatile u_char *STATUS; /* address of status register */
- volatile u_char *DATA; /* address of data register */
-
- u_char scsi_addr; /* our scsi address, 0..7 */
- u_char scsi_id; /* our scsi id mask */
- u_char parity; /* parity flag: CMD_EN_PARITY or 0 */
- u_char irq; /* IRQ number used or 0 if no IRQ */
- u_int timeout_active : 1; /* timeout() active (requested) */
-
- struct scsi_link sc_link; /* struct connecting different data */
- scb_t *queue; /* waiting to be issued */
- scb_t *disconnected_queue; /* waiting to reconnect */
-
- int numscb; /* number of scsi control blocks */
- scb_t *free_scb; /* free scb list */
- scb_t scbs[SCB_TABLE_SIZE];
-
- target_t target[8]; /* target state data */
-} adapter_t;
-
-static adapter_t seadata[NSEA];
-
-#define IS_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy &\
- (1 << (b)->xfer->sc_link->lun))
-#define SET_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy |=\
- (1 << (b)->xfer->sc_link->lun))
-#define CLEAR_BUSY(a,b) ((a)->target[(b)->xfer->sc_link->target].busy &=\
- ~(1 << (b)->xfer->sc_link->lun))
-
-/*
- * Wait for condition, given as an boolean expression.
- * Print the message on timeout.
- */
-#define WAITFOR(condition,message) {\
- register u_long cnt = 100000; char *_msg = message;\
- while (cnt-- && ! (condition)) continue;\
- if (cnt == -1 && _msg)\
- printf ("sea: %s timeout\n", _msg); }
-
-#define WAITFOR10(condition,message) {\
- register u_long cnt = 1000000; char *_msg = message;\
- while (cnt-- && ! (condition)) continue;\
- if (cnt == -1 && _msg)\
- printf ("sea: %s timeout\n", _msg); }
-
-/*
- * Seagate adapter does not support in hardware
- * waiting for REQ deassert after transferring each data byte.
- * We must do it in software.
- * The problem is that some SCSI devices deassert REQ so fast that
- * we can miss it. We the flag for each target sayind if we should (not)
- * wait for REQ deassert. This flag is initialized when the first
- * operation on the target is done.
- * 1) Test if we don't need to wait for REQ deassert (`nodelay' flag).
- * Initially the flag is off, i.e. wait. If the flag is set,
- * go to the step 4.
- * 2) Wait for REQ deassert (call sea_wait_for_req_deassert function).
- * If REQ deassert got, go to the step 4. If REQ did not cleared
- * during timeout period, go to the next step.
- * 3) If `nodelay' flag did not initialized yet (`init' flag),
- * then set `ndelay' flag.
- * 4) Set `init' flag. Done.
- */
-#define WAITREQ(t,op,cnt) {\
- if (! (t)->ndelay.op &&\
- ! sea_wait_for_req_deassert ((t)->adapter, cnt, #op) &&\
- ! (t)->init.op)\
- (t)->ndelay.op = 1;\
- (t)->init.op = 1; }
-
-static int sea_probe (struct isa_device *dev);
-static int sea_detect (adapter_t *z, struct isa_device *dev);
-static int sea_attach (struct isa_device *dev);
-static int32_t sea_scsi_cmd (struct scsi_xfer *xs);
-static u_int32_t sea_adapter_info (int unit);
-static void sea_timeout (void *scb);
-static void seaminphys (struct buf *bp);
-static void sea_done (adapter_t *z, scb_t *scb);
-static void sea_start (adapter_t *z);
-static void sea_information_transfer (adapter_t *z, scb_t *scb);
-static int sea_poll (adapter_t *z, scb_t *scb);
-static int sea_init (adapter_t *z);
-static ointhand2_t seaintr;
-static int sea_reselect (adapter_t *z);
-static int sea_select (volatile adapter_t *z, scb_t *scb);
-static int sea_abort (adapter_t *z, scb_t *scb);
-static void sea_send_abort (adapter_t *z);
-static u_char sea_msg_input (adapter_t *z);
-static void sea_tick (void *arg);
-static int sea_sense (adapter_t *z, scb_t *scb);
-static void sea_data_output (adapter_t *z, u_char **pdata, u_long *plen);
-static void sea_data_input (adapter_t *z, u_char **pdata, u_long *plen);
-static void sea_cmd_output (target_t *z, u_char *cmd, int cmdlen);
-
-static struct scsi_adapter sea_switch = {
- sea_scsi_cmd, seaminphys, 0, 0, sea_adapter_info, "sea", {0},
-};
-static struct scsi_device sea_dev = { NULL, NULL, NULL, NULL, "sea", 0, {0} };
-struct isa_driver seadriver = { sea_probe, sea_attach, "sea" };
-
-/* FD TMC885's can't handle detach & re-attach */
-static int sea_select_cmd = CMD_DRVR_ENABLE | CMD_ATTN;
-
-/*
- * Check if the device can be found at the port given and if so,
- * detect the type of board. Set it up ready for further work.
- * Takes the isa_dev structure from autoconf as an argument.
- * Returns 1 if card recognized, 0 if errors.
- */
-int sea_probe (struct isa_device *dev)
-{
- adapter_t *z = &seadata[dev->id_unit];
- static const int addrtab[] = {
- 0xc8000, 0xca000, 0xcc000, 0xce000, 0xdc000, 0xde000, 0,
- };
- int i;
-
- /* Init fields used by our routines */
- z->parity = (dev->id_flags & FLAG_NOPARITY) ? 0 : CMD_EN_PARITY;
- z->scsi_addr = HOST_SCSI_ADDR;
- z->scsi_id = 1 << z->scsi_addr;
- z->irq = dev->id_irq ? ffs (dev->id_irq) - 1 : 0;
- z->queue = 0;
- z->disconnected_queue = 0;
- for (i=0; i<8; i++) {
- z->target[i].adapter = z;
- z->target[i].busy = 0;
- }
-
- /* Link up the free list of scbs */
- z->numscb = SCB_TABLE_SIZE;
- z->free_scb = z->scbs;
- for (i=1; i<SCB_TABLE_SIZE; i++)
- z->scbs[i-1].next = z->scbs + i;
- z->scbs[SCB_TABLE_SIZE-1].next = 0;
-
- /* Detect the adapter. */
- dev->id_msize = 0x4000;
- if (! dev->id_maddr)
- for (i=0; addrtab[i]; ++i) {
- dev->id_maddr = (u_char*) KERNBASE + addrtab[i];
- if (sea_detect (z, dev))
- return (1);
- }
- else if (sea_detect (z, dev))
- return (1);
-
- bzero (z, sizeof (*z));
- return (0);
-}
-
-int sea_detect (adapter_t *z, struct isa_device *dev)
-{
- z->addr = dev->id_maddr;
-
- /* Try Seagate. */
- z->type = CTLR_SEAGATE;
- z->name = "Seagate ST01/ST02";
- z->CONTROL = z->addr + 0x1a00; /* ST01/ST02 register offsets */
- z->STATUS = z->addr + 0x1a00;
- z->DATA = z->addr + 0x1c00;
- if (sea_init (z) == 0)
- return (1);
-
- /* Try Future Domain. */
- z->type = CTLR_FUTURE_DOMAIN;
- z->name = "Future Domain TMC-885/TMC-950";
- z->CONTROL = z->addr + 0x1c00; /* TMC-885/TMC-950 reg. offsets */
- z->STATUS = z->addr + 0x1c00;
- z->DATA = z->addr + 0x1e00;
- /* FD TMC885's can't handle detach & re-attach */
- sea_select_cmd = CMD_DRVR_ENABLE;
- /* FD TMC-885 is supposed to be at id 6. How strange. */
- z->scsi_addr = HOST_SCSI_ADDR - 1;
- z->scsi_id = 1 << z->scsi_addr;
- if (sea_init (z) == 0)
- return (1);
-
- return (0);
-}
-
-/*
- * Probe the adapter, and if found, reset the board and the scsi bus.
- * Return 0 if the adapter found.
- */
-int sea_init (adapter_t *z)
-{
- volatile u_char *p;
- int i, c;
-
- /* Check that STATUS..STATUS+200h are equal. */
- p = z->STATUS;
- c = *p;
- if (c == 0xff)
- return (2);
- while (++p < z->STATUS+0x200)
- if (*p != c)
- return (3);
-
- /* Check that DATA..DATA+200h are equal. */
- for (p=z->DATA, c= *p++; p<z->DATA+0x200; ++p)
- if (*p != c)
- return (4);
-
- /* Check that addr..addr+1800h are not writable. */
- for (p=z->addr; p<z->addr+0x1800; ++p) {
- c = *p;
- *p = ~c;
- if (*p == ~c) {
- *p = c;
- return (5);
- }
- }
-
- /* Check that addr+1800h..addr+1880h are writable. */
- for (p=z->addr+0x1800; p<z->addr+0x1880; ++p) {
- c = *p;
- *p = 0x55;
- if (*p != 0x55) {
- *p = c;
- return (6);
- }
- *p = 0xaa;
- if (*p != 0xaa) {
- *p = c;
- return (7);
- }
- }
-
- /* Reset the scsi bus (I don't know if this is needed). */
- *z->CONTROL = CMD_RST | CMD_DRVR_ENABLE | z->parity | CMD_INTR;
- /* Hold reset for at least 25 microseconds. */
- DELAY (25);
- /* Check that status cleared. */
- if (*z->STATUS != 0) {
- *z->CONTROL = 0;
- return (8);
- }
-
- /* Check that DATA register is writable. */
- for (i=0; i<256; ++i) {
- *z->DATA = i;
- if (*z->DATA != i) {
- *z->CONTROL = 0;
- return (9);
- }
- }
-
- /* Enable the adapter. */
- *z->CONTROL = CMD_INTR | z->parity;
- /* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */
- DELAY (10);
-
- /* Check that DATA register is NOT writable. */
- c = *z->DATA;
- for (i=0; i<256; ++i) {
- *z->DATA = i;
- if (*z->DATA != c) {
- *z->CONTROL = 0;
- return (10);
- }
- }
-
- return (0);
-}
-
-/*
- * Attach all sub-devices we can find.
- */
-int sea_attach (struct isa_device *dev)
-{
- int unit = dev->id_unit;
- adapter_t *z = &seadata[unit];
- struct scsibus_data *scbus;
-
- printf ("\nsea%d: type %s%s\n", unit, z->name,
- (dev->id_flags & FLAG_NOPARITY) ? ", no parity" : "");
-
- dev->id_ointr = seaintr;
-
- /* fill in the prototype scsi_link */
- z->sc_link.adapter_unit = unit;
- z->sc_link.adapter_targ = z->scsi_addr;
- z->sc_link.adapter_softc = z;
- z->sc_link.adapter = &sea_switch;
- z->sc_link.device = &sea_dev;
-
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = scsi_alloc_bus();
- if(!scbus)
- return 0;
- scbus->adapter_link = &z->sc_link;
-
- /* ask the adapter what subunits are present */
- scsi_attachdevs (scbus);
-
- return (1);
-}
-
-/*
- * Return some information to the caller about
- * the adapter and its capabilities.
- */
-u_int32_t sea_adapter_info (int unit)
-{
- return (1);
-}
-
-void seaminphys (struct buf *bp)
-{
-}
-
-/*
- * Catch an interrupt from the adaptor.
- */
-static void seaintr (int unit)
-{
- adapter_t *z = &seadata[unit];
-
- PRINT (("sea%d: interrupt status=%b\n", unit, *z->STATUS, STAT_BITS));
- sea_start (z);
-}
-
-/*
- * This routine is used in the case when we have no IRQ line (z->irq == 0).
- * It is called every timer tick and polls for reconnect from target.
- */
-void sea_tick (void *arg)
-{
- adapter_t *z = arg;
- int x = splbio ();
-
- z->timeout_active = 0;
- sea_start (z);
- if (z->disconnected_queue && ! z->timeout_active) {
- timeout (sea_tick, z, 1);
- z->timeout_active = 1;
- }
- splx (x);
-}
-
-/*
- * Start a scsi operation given the command and the data address.
- * Also needs the unit, target and lu. Get a free scb and set it up.
- * Call send_scb. Either start timer or wait until done.
- */
-int32_t sea_scsi_cmd (struct scsi_xfer *xs)
-{
- int flags = xs->flags, x = 0;
- adapter_t *z = (adapter_t *)xs->sc_link->adapter_softc;
- scb_t *scb;
-
- PRINT (("sea%d/%d/%d command 0x%x\n", unit, xs->sc_link->target,
- xs->sc_link->lun, xs->cmd->opcode));
- if (xs->bp)
- flags |= SCSI_NOSLEEP;
- if (flags & ITSDONE) {
- printf ("sea%d: already done?", xs->sc_link->adapter_unit);
- xs->flags &= ~ITSDONE;
- }
- if (! (flags & INUSE)) {
- printf ("sea%d: not in use?", xs->sc_link->adapter_unit);
- xs->flags |= INUSE;
- }
- if (flags & SCSI_RESET)
- printf ("sea%d: SCSI_RESET not implemented\n",
- xs->sc_link->adapter_unit);
-
- if (! (flags & SCSI_NOMASK))
- x = splbio ();
-
- /* Get a free scb.
- * If we can and have to, sleep waiting for one to come free. */
- while (! (scb = z->free_scb)) {
- if (flags & SCSI_NOSLEEP) {
- xs->error = XS_DRIVER_STUFFUP;
- if (! (flags & SCSI_NOMASK))
- splx (x);
- return (TRY_AGAIN_LATER);
- }
- tsleep ((caddr_t)&z->free_scb, PRIBIO, "seascb", 0);
- }
- /* Get scb from free list. */
- z->free_scb = scb->next;
- scb->next = 0;
- scb->flags = SCB_ACTIVE;
-
- /* Put all the arguments for the xfer in the scb */
- scb->xfer = xs;
- scb->datalen = xs->datalen;
- scb->data = xs->data;
-
- /* Setup the scb to contain necessary values.
- * The interesting values can be read from the xs that is saved.
- * I therefore think that the structure can be kept very small.
- * The driver doesn't use DMA so the scatter/gather is not needed? */
- if (! z->queue) {
- scb->next = z->queue;
- z->queue = scb;
- } else {
- scb_t *q;
-
- for (q=z->queue; q->next; q=q->next)
- continue;
- q->next = scb;
- scb->next = 0; /* placed at the end of the queue */
- }
-
- /* Try to send this command to the board. */
- sea_start (z);
-
- /* Usually return SUCCESSFULLY QUEUED. */
- if (! (flags & SCSI_NOMASK)) {
- splx (x);
- if (xs->flags & ITSDONE)
- /* Timeout timer not started, already finished.
- * Tried to return COMPLETE but the machine hanged
- * with this. */
- return (SUCCESSFULLY_QUEUED);
- xs->timeout_ch = timeout (sea_timeout, (caddr_t) scb,
- (xs->timeout * hz) / 1000);
- scb->flags |= SCB_TIMECHK;
- PRINT (("sea%d/%d/%d command queued\n",
- xs->sc_link->adapter_unit,
- xs->sc_link->target, xs->sc_link->lun));
- return (SUCCESSFULLY_QUEUED);
- }
-
- /* If we can't use interrupts, poll on completion. */
- if (! sea_poll (z, scb)) {
- /* We timed out, so call the timeout handler manually,
- * accounting for the fact that the clock is not running yet
- * by taking out the clock queue entry it makes. */
- sea_timeout ((void*) scb);
-
- /* Because we are polling, take out the timeout entry
- * sea_timeout made. */
- untimeout (sea_timeout, (void*) scb, xs->timeout_ch);
-
- if (! sea_poll (z, scb))
- /* We timed out again... This is bad. Notice that
- * this time there is no clock queue entry to remove. */
- sea_timeout ((void*) scb);
- }
- PRINT (("sea%d/%d/%d command %s\n", xs->sc_link->adapter_unit,
- xs->sc_link->target, xs->sc_link->lun,
- xs->error ? "failed" : "done"));
- return (xs->error ? HAD_ERROR : COMPLETE);
-}
-
-/*
- * Coroutine that runs as long as more work can be done.
- * Both scsi_cmd() and intr() will try to start it in
- * case it is not running.
- * Always called with interrupts disabled.
- */
-void sea_start (adapter_t *z)
-{
- scb_t *q, *prev;
-again:
- /* First check that if any device has tried
- * a reconnect while we have done other things
- * with interrupts disabled. */
- if (sea_reselect (z))
- goto again;
-
- /* Search through the queue for a command
- * destined for a target that's not busy. */
- for (q=z->queue, prev=0; q; prev=q, q=q->next) {
- /* Attempt to establish an I_T_L nexus here. */
- if (IS_BUSY (z, q) || ! sea_select (z, q))
- continue;
-
- /* Remove the command from the issue queue. */
- if (prev)
- prev->next = q->next;
- else
- z->queue = q->next;
- q->next = 0;
-
- /* We are connected. Do the task. */
- sea_information_transfer (z, q);
- goto again;
- }
-}
-
-void sea_timeout (void *arg)
-{
- scb_t *scb = (scb_t*) arg;
- adapter_t *z = (adapter_t *)scb->xfer->sc_link->adapter_softc;
- int x = splbio ();
-
- if (! (scb->xfer->flags & SCSI_NOMASK))
- printf ("sea%d/%d/%d (%s%d) timed out\n",
- scb->xfer->sc_link->adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun,
- scb->xfer->sc_link->device->name,
- scb->xfer->sc_link->dev_unit);
-
- /* If it has been through before, then a previous abort has failed,
- * don't try abort again. */
- if (! (scb->flags & SCB_ABORTED)) {
- sea_abort (z, scb);
- /* 2 seconds for the abort */
- scb->xfer->timeout_ch = timeout (sea_timeout,
- (caddr_t)scb, 2*hz);
- scb->flags |= (SCB_ABORTED | SCB_TIMECHK);
- } else {
- /* abort timed out */
- scb->flags |= SCB_ABORTED;
- scb->xfer->retries = 0;
- sea_done (z, scb);
- }
- splx (x);
-}
-
-/*
- * Wait until REQ goes down. This is needed for some devices (CDROMs)
- * after every MSGOUT, MSGIN, CMDOUT, STATIN request.
- * Return true if REQ deassert found.
- */
-static __inline int sea_wait_for_req_deassert (adapter_t *z, int cnt, char *msg)
-{
- __asm __volatile ("
- 1: testb $0x10, %2
- jz 2f
- loop 1b
- 2:"
- : "=c" (cnt) /* output */
- : "0" (cnt), "m" (*z->STATUS)); /* input */
- if (! cnt) {
- PRINT (("sea%d (%s) timeout waiting for !REQ\n",
- z->sc_link.adapter_unit, msg));
- return (0);
- }
- /* PRINT (("sea_wait_for_req_deassert %s count=%d\n", msg, cnt)); */
- return (1);
-}
-
-/*
- * Establish I_T_L or I_T_L_Q nexus for new or existing command
- * including ARBITRATION, SELECTION, and initial message out
- * for IDENTIFY and queue messages.
- * Return 1 if selection succeded.
- */
-int sea_select (volatile adapter_t *z, scb_t *scb)
-{
- /* Start arbitration. */
- *z->CONTROL = z->parity | CMD_INTR;
- *z->DATA = z->scsi_id;
- *z->CONTROL = CMD_START_ARB | z->parity;
-
- /* Wait for arbitration to complete. */
- WAITFOR (*z->STATUS & STAT_ARB_CMPL, "arbitration");
- if (! (*z->STATUS & STAT_ARB_CMPL)) {
- if (*z->STATUS & STAT_SEL) {
- printf ("sea: arbitration lost\n");
- scb->flags |= SCB_ERROR;
- } else {
- printf ("sea: arbitration timeout\n");
- scb->flags |= SCB_TIMEOUT;
- }
- *z->CONTROL = CMD_INTR | z->parity;
- return (0);
- }
- DELAY (1);
-
- *z->DATA = (1 << scb->xfer->sc_link->target) | z->scsi_id;
- *z->CONTROL = sea_select_cmd | CMD_SEL | z->parity;
- DELAY (2);
-
- /* Wait for a bsy from target.
- * If the target is not present on the bus, we get
- * the timeout. Don't PRINT any message -- it's not an error. */
- WAITFOR (*z->STATUS & STAT_BSY, 0);
- if (! (*z->STATUS & STAT_BSY)) {
- /* The target does not respond. Not an error, though. */
- PRINT (("sea%d/%d/%d target does not respond\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- *z->CONTROL = CMD_INTR | z->parity;
- scb->flags |= SCB_TIMEOUT;
- return (0);
- }
-
- /* Try to make the target to take a message from us.
- * Should start a MSGOUT phase. */
- *z->CONTROL = sea_select_cmd | z->parity;
- DELAY (15);
- WAITFOR (*z->STATUS & STAT_REQ, 0);
-
- if (z->type == CTLR_FUTURE_DOMAIN)
- *z->CONTROL = CMD_INTR | z->parity | CMD_DRVR_ENABLE;
-
- WAITFOR (*z->STATUS & STAT_REQ, 0);
- if (! (*z->STATUS & STAT_REQ)) {
- PRINT (("sea%d/%d/%d timeout waiting for REQ\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- scb->flags |= SCB_ERROR;
- *z->CONTROL = CMD_INTR | z->parity;
- return (0);
- }
-
- /* Check for phase mismatch. FD 885 always seems to get this wrong! */
- if ((*z->STATUS & PHASE_MASK) != PHASE_MSGOUT && z->type != CTLR_FUTURE_DOMAIN) {
- PRINT (("sea%d/%d/%d waiting for MSGOUT: invalid phase %s\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun,
- PHASE_NAME (*z->STATUS & PHASE_MASK)));
- scb->flags |= SCB_ERROR;
- *z->CONTROL = CMD_INTR | z->parity;
- return (0);
- }
-
- /* Allow disconnects. (except for FD controllers) */
- if (z->type == CTLR_SEAGATE) {
- *z->CONTROL = CMD_DRVR_ENABLE | z->parity;
- *z->DATA = MSG_IDENTIFY (scb->xfer->sc_link->lun);
- WAITREQ (&z->target[scb->xfer->sc_link->target], msgout, 1000);
- }
- *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity;
-
- SET_BUSY (z, scb);
- return (1);
-}
-
-int sea_reselect (adapter_t *z)
-{
- scb_t *q = 0, *prev = 0;
- u_char msg, target_mask, lun;
-again:
- /* Wait for a device to win the reselection phase. */
- /* Signals this by asserting the I/O signal. */
- if ((*z->STATUS & (STAT_SEL | STAT_IO | STAT_BSY)) !=
- (STAT_SEL | STAT_IO))
- return (0);
-
- /* The data bus contains original initiator id ORed with target id. */
- /* See that we really are the initiator. */
- target_mask = *z->DATA;
- if (! (target_mask & z->scsi_id)) {
- PRINT (("sea%d reselect not for me: mask=0x%x, status=%b\n",
- z->sc_link.adapter_unit, target_mask,
- *z->STATUS, STAT_BITS));
- goto again;
- }
-
- /* Find target who won. */
- /* Host responds by asserting the BSY signal. */
- /* Target should respond by deasserting the SEL signal. */
- target_mask &= ~z->scsi_id;
- *z->CONTROL = CMD_DRVR_ENABLE | CMD_BSY | z->parity | CMD_INTR;
- WAITFOR (! (*z->STATUS & STAT_SEL), "reselection acknowledge");
-
- /* Remove the busy status. */
- /* Target should set the MSGIN phase. */
- *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity;
- WAITFOR (*z->STATUS & STAT_REQ, "identify message");
-
- /* Hope we get an IDENTIFY message. */
- msg = sea_msg_input (z);
- if (MSG_ISIDENT (msg)) {
- /* Find the command corresponding to the I_T_L or I_T_L_Q
- * nexus we just restablished, and remove it from
- * the disconnected queue. */
- lun = (msg & 7);
- for (q=z->disconnected_queue; q; prev=q, q=q->next) {
- if (target_mask != (1 << q->xfer->sc_link->target))
- continue;
- if (lun != q->xfer->sc_link->lun)
- continue;
- if (prev)
- prev->next = q->next;
- else
- z->disconnected_queue = q->next;
- q->next = 0;
- PRINT (("sea%d/%d/%d reselect done\n",
- z->sc_link.adapter_unit,
- ffs (target_mask) - 1, lun));
- sea_information_transfer (z, q);
- WAITFOR (! (*z->STATUS & STAT_BSY), "reselect !busy");
- return (1);
- }
- } else
- printf ("sea%d reselect: expecting IDENTIFY, got 0x%x\n",
- z->sc_link.adapter_unit, msg);
-
- /* Since we have an established nexus that we can't
- * do anything with, we must abort it. */
- sea_send_abort (z);
- PRINT (("sea%d reselect aborted\n", z->sc_link.adapter_unit));
- WAITFOR (! (*z->STATUS & STAT_BSY), "bus free after reselect abort");
- goto again;
-}
-
-/*
- * Send an abort to the target.
- * Return 1 success, 0 on failure.
- * Called on splbio level.
- */
-int sea_abort (adapter_t *z, scb_t *scb)
-{
- scb_t *q, **prev;
-
- /* If the command hasn't been issued yet, we simply remove it
- * from the issue queue. */
- prev = &z->queue;
- for (q=z->queue; q; q=q->next) {
- if (scb == q) {
- (*prev) = q->next;
- q->next = 0;
- return (1);
- }
- prev = &q->next;
- }
-
- /* If the command is currently disconnected from the bus,
- * we reconnect the I_T_L or I_T_L_Q nexus associated with it,
- * go into message out, and send an abort message. */
- for (q=z->disconnected_queue; q; q=q->next) {
- if (scb != q)
- continue;
-
- if (! sea_select (z, scb))
- return (0);
- sea_send_abort (z);
-
- prev = &z->disconnected_queue;
- for (q=z->disconnected_queue; q; q=q->next) {
- if (scb == q) {
- *prev = q->next;
- q->next = 0;
- /* Set some type of error result
- * for the operation. */
- return (1);
- }
- prev = &q->next;
- }
- }
-
- /* Command not found in any queue. */
- return (0);
-}
-
-/*
- * The task accomplished, mark the i/o control block as done.
- * Always called with interrupts disabled.
- */
-void sea_done (adapter_t *z, scb_t *scb)
-{
- struct scsi_xfer *xs = scb->xfer;
-
- if (scb->flags & SCB_TIMECHK)
- untimeout (sea_timeout, (caddr_t) scb, xs->timeout_ch);
-
- /* How much of the buffer was not touched. */
- xs->resid = scb->datalen;
-
- if (scb->flags != SCB_ACTIVE && ! (xs->flags & SCSI_ERR_OK))
- if (scb->flags & (SCB_TIMEOUT | SCB_ABORTED))
- xs->error = XS_TIMEOUT;
- else if (scb->flags & SCB_ERROR)
- xs->error = XS_DRIVER_STUFFUP;
- else if (scb->flags & SCB_TBUSY)
- xs->error = XS_BUSY;
- else if (scb->flags & SCB_SENSE)
- xs->error = XS_SENSE;
-
- xs->flags |= ITSDONE;
-
- /* Free the control block. */
- scb->next = z->free_scb;
- z->free_scb = scb;
- scb->flags = SCB_FREE;
-
- /* If there were none, wake anybody waiting for one to come free,
- * starting with queued entries. */
- if (! scb->next)
- wakeup ((caddr_t) &z->free_scb);
-
- scsi_done (xs);
-}
-
-/*
- * Wait for completion of command in polled mode.
- * Always called with interrupts masked out.
- */
-int sea_poll (adapter_t *z, scb_t *scb)
-{
- int count;
-
- for (count=0; count<30; ++count) {
- DELAY (1000); /* delay for a while */
- sea_start (z); /* retry operation */
- if (scb->xfer->flags & ITSDONE)
- return (1); /* all is done */
- if (scb->flags & SCB_TIMEOUT)
- return (0); /* no target present */
- }
- return (0);
-}
-
-/*
- * Send data to the target.
- */
-void sea_data_output (adapter_t *z, u_char **pdata, u_long *plen)
-{
- volatile u_char *data = *pdata;
- volatile u_int len = *plen;
-
-#ifdef SEA_BLINDTRANSFER
- if (len && !(len % BLOCK_SIZE)) {
- while (len) {
- WAITFOR10 (*z->STATUS & STAT_REQ, "blind block read");
- __asm __volatile ("
- shr $2, %%ecx;
- cld;
- rep;
- movsl; " : :
- "D" (z->DATA), "S" (data), "c" (BLOCK_SIZE) :
- "cx", "si", "di" );
- data += BLOCK_SIZE;
- len -= BLOCK_SIZE;
- }
- } else {
-#endif
- __asm __volatile ("cld
- 1: movb (%%ebx), %%al
- xorb $1, %%al
- testb $0xf, %%al
- jnz 2f
- testb $0x10, %%al
- jz 1b
- lodsb
- movb %%al, (%%edi)
- loop 1b
- 2:"
- : "=S" (data), "=c" (len) /* output */
- : "D" (z->DATA), "b" (z->STATUS), /* input */
- "0" (data), "1" (len)
- : "eax", "ebx", "edi"); /* clobbered */
-#ifdef SEA_BLINDTRANSFER
- }
-#endif
- PRINT (("sea (DATAOUT) send %ld bytes\n", *plen - len));
- *plen = len;
- *pdata = (u_char *)data;
-}
-
-/*
- * Receive data from the target.
- */
-void sea_data_input (adapter_t *z, u_char **pdata, u_long *plen)
-{
- volatile u_char *data = *pdata;
- volatile u_int len = *plen;
-
-#ifdef SEA_BLINDTRANSFER
- if (len && !(len % BLOCK_SIZE)) {
- while (len) {
- WAITFOR10 (*z->STATUS & STAT_REQ, "blind block read");
- __asm __volatile ("
- shr $2, %%ecx;
- cld;
- rep;
- movsl; " : :
- "S" (z->DATA), "D" (data), "c" (BLOCK_SIZE) :
- "cx", "si", "di" );
- data += BLOCK_SIZE;
- len -= BLOCK_SIZE;
- }
- } else {
-#endif
- if (len >= 512) {
- __asm __volatile (" cld
- 1: movb (%%esi), %%al
- xorb $5, %%al
- testb $0xf, %%al
- jnz 2f
- testb $0x10, %%al
- jz 1b
- movb (%%ebx), %%al
- stosb
- loop 1b
- 2:"
- : "=D" (data), "=c" (len) /* output */
- : "b" (z->DATA), "S" (z->STATUS),
- "0" (data), "1" (len) /* input */
- : "eax", "ebx", "esi"); /* clobbered */
- } else {
- __asm __volatile (" cld
- 1: movb (%%esi), %%al
- xorb $5, %%al
- testb $0xf, %%al
- jnz 2f
- testb $0x10, %%al
- jz 1b
- movb (%%ebx), %%al
- stosb
- movb $1000, %%al
- 3: testb $0x10, (%%esi)
- jz 4f
- dec %%al
- jnz 3b
- 4: loop 1b
- 2:"
- : "=D" (data), "=c" (len) /* output */
- : "b" (z->DATA), "S" (z->STATUS),
- "0" (data), "1" (len) /* input */
- : "eax", "ebx", "esi"); /* clobbered */
- }
-#ifdef SEA_BLINDTRANSFER
- }
-#endif
- PRINT (("sea (DATAIN) got %ld bytes\n", *plen - len));
- *plen = len;
- *pdata = (u_char *)data;
-}
-
-/*
- * Send the command to the target.
- */
-void sea_cmd_output (target_t *t, u_char *cmd, int cmdlen)
-{
- adapter_t *z = t->adapter;
-
- PRINT (("sea%d send command (%d bytes) ", z->sc_link.adapter_unit,
- cmdlen));
-
- PRINT (("%x", *cmd));
- *z->DATA = *cmd++;
- if (z->type == CTLR_SEAGATE)
- WAITREQ (t, cmdout1, 10000);
- --cmdlen;
-
- while (cmdlen) {
- /* Check for target disconnect. */
- u_char sts = *z->STATUS;
- if (! (sts & STAT_BSY))
- break;
-
- /* Check for phase mismatch. FD 885 seems to get this wrong! */
- if ((sts & PHASE_MASK) != PHASE_CMDOUT && z->type != CTLR_FUTURE_DOMAIN) {
- printf ("sea: sea_cmd_output: invalid phase %s\n",
- PHASE_NAME (sts & PHASE_MASK));
- return;
- }
-
- /* Wait for REQ. */
- if (! (sts & STAT_REQ))
- continue;
-
- PRINT (("-%x", *cmd));
- *z->DATA = *cmd++;
- if (z->type == CTLR_SEAGATE)
- WAITREQ (t, cmdout, 1000);
- --cmdlen;
- }
- PRINT (("\n"));
-}
-
-/*
- * Send the message to the target.
- */
-void sea_send_abort (adapter_t *z)
-{
- u_char sts;
-
- *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | CMD_ATTN | z->parity;
-
- /* Wait for REQ, after which the phase bits will be valid. */
- WAITFOR (*z->STATUS & STAT_REQ, "abort message");
- sts = *z->STATUS;
- if (! (sts & STAT_REQ))
- goto ret;
-
- /* Check for phase mismatch. */
- if ((sts & PHASE_MASK) != PHASE_MSGOUT) {
- printf ("sea: sending MSG_ABORT: invalid phase %s\n",
- PHASE_NAME (sts & PHASE_MASK));
- goto ret;
- }
-
- *z->DATA = MSG_ABORT;
- sea_wait_for_req_deassert (z, 1000, "MSG_OUTPUT");
- PRINT (("sea%d send abort message\n", z->sc_link.adapter_unit));
-ret:
- *z->CONTROL = CMD_INTR | CMD_DRVR_ENABLE | z->parity;
-}
-
-/*
- * Get the message from the target.
- * Return the length of the received message.
- */
-u_char sea_msg_input (adapter_t *z)
-{
- u_char sts, msg;
-
- /* Wait for REQ, after which the phase bits will be valid. */
- WAITFOR (*z->STATUS & STAT_REQ, "message input");
- sts = *z->STATUS;
- if (! (sts & STAT_REQ))
- return (MSG_ABORT);
-
- /* Check for phase mismatch.
- * Reached if the target decides that it has finished the transfer. */
- if ((sts & PHASE_MASK) != PHASE_MSGIN) {
- printf ("sea: sea_msg_input: invalid phase %s\n",
- PHASE_NAME (sts & PHASE_MASK));
- return (MSG_ABORT);
- }
-
- /* Do actual transfer from SCSI bus to/from memory. */
- msg = *z->DATA;
- sea_wait_for_req_deassert (z, 1000, "MSG_INPUT");
- PRINT (("sea%d (MSG_INPUT) got 0x%x\n", z->sc_link.adapter_unit, msg));
- return (msg);
-}
-
-/*
- * Send request-sense op to the target.
- * Return 1 success, 0 on failure.
- * Called on splbio level.
- */
-int sea_sense (adapter_t *z, scb_t *scb)
-{
- u_char cmd[6], status, msg, *data;
- u_long len;
-
- /* Wait for target to disconnect. */
- WAITFOR (! (*z->STATUS & STAT_BSY), "sense bus free");
- if (*z->STATUS & STAT_BSY)
- return (0);
-
- /* Select the target again. */
- if (! sea_select (z, scb))
- return (0);
-
- /* Wait for CMDOUT phase. */
- WAITFOR (*z->STATUS & STAT_REQ, "sense CMDOUT");
- if (! (*z->STATUS & STAT_REQ) ||
- (*z->STATUS & PHASE_MASK) != PHASE_CMDOUT)
- return (0);
-
- /* Send command. */
- len = sizeof (scb->xfer->sense);
- cmd[0] = REQUEST_SENSE;
- cmd[1] = scb->xfer->sc_link->lun << 5;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = len;
- cmd[5] = 0;
- sea_cmd_output (&z->target[scb->xfer->sc_link->target],
- cmd, sizeof (cmd));
-
- /* Wait for DATAIN phase. */
- WAITFOR (*z->STATUS & STAT_REQ, "sense DATAIN");
- if (! (*z->STATUS & STAT_REQ) ||
- (*z->STATUS & PHASE_MASK) != PHASE_DATAIN)
- return (0);
-
- data = (u_char*) &scb->xfer->sense;
- sea_data_input (z, &data, &len);
- PRINT (("sea%d sense %x-%x-%x-%x-%x-%x-%x-%x\n",
- z->sc_link.adapter_unit, scb->xfer->sense.error_code,
- scb->xfer->sense.ext.extended.segment,
- scb->xfer->sense.ext.extended.flags,
- scb->xfer->sense.ext.extended.info[0],
- scb->xfer->sense.ext.extended.info[1],
- scb->xfer->sense.ext.extended.info[2],
- scb->xfer->sense.ext.extended.info[3],
- scb->xfer->sense.ext.extended.extra_len));
-
- /* Wait for STATIN phase. */
- WAITFOR (*z->STATUS & STAT_REQ, "sense STATIN");
- if (! (*z->STATUS & STAT_REQ) ||
- (*z->STATUS & PHASE_MASK) != PHASE_STATIN)
- return (0);
-
- status = *z->DATA;
-
- /* Wait for MSGIN phase. */
- WAITFOR (*z->STATUS & STAT_REQ, "sense MSGIN");
- if (! (*z->STATUS & STAT_REQ) ||
- (*z->STATUS & PHASE_MASK) != PHASE_MSGIN)
- return (0);
-
- msg = *z->DATA;
-
- if (status != 0 || msg != 0)
- printf ("sea%d: bad sense status=0x%x, msg=0x%x\n",
- z->sc_link.adapter_unit, status, msg);
- return (1);
-}
-
-/*
- * Do the transfer. We know we are connected. Update the flags,
- * call sea_done when task accomplished. Dialog controlled by the target.
- * Always called with interrupts disabled.
- */
-void sea_information_transfer (adapter_t *z, scb_t *scb)
-{
- u_char *data = scb->data; /* current data buffer */
- u_long datalen = scb->datalen; /* current data transfer size */
- target_t *t = &z->target[scb->xfer->sc_link->target];
- register u_char sts;
- u_char msg;
-
- while ((sts = *z->STATUS) & STAT_BSY) {
- /* We only have a valid SCSI phase when REQ is asserted. */
- if (! (sts & STAT_REQ))
- continue;
- if (sts & STAT_PARITY) {
- int target = scb->xfer->sc_link->target;
- if (++z->target[target].perrcnt <= 8)
- printf ("sea%d/%d/%d parity error\n",
- z->sc_link.adapter_unit, target,
- scb->xfer->sc_link->lun);
- if (z->target[target].perrcnt == 8)
- printf ("sea%d/%d/%d too many parity errors, not logging any more\n",
- z->sc_link.adapter_unit, target,
- scb->xfer->sc_link->lun);
- }
- switch (sts & PHASE_MASK) {
- case PHASE_DATAOUT:
- if (datalen <= 0) {
- printf ("sea%d/%d/%d data length underflow\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun);
- /* send zero byte */
- *z->DATA = 0;
- break;
- }
- sea_data_output (z, &data, &datalen);
- break;
- case PHASE_DATAIN:
- if (datalen <= 0) {
- /* Get extra data. Some devices (e.g. CDROMs)
- * use fixed-length blocks (e.g. 2k),
- * even if we need less. */
- PRINT (("@"));
- sts = *z->DATA;
- break;
- }
- sea_data_input (z, &data, &datalen);
- break;
- case PHASE_CMDOUT:
- sea_cmd_output (t, (u_char*) scb->xfer->cmd,
- scb->xfer->cmdlen);
- break;
- case PHASE_STATIN:
- scb->xfer->status = *z->DATA;
- if (z->type == CTLR_SEAGATE)
- WAITREQ (t, statin, 2000);
- PRINT (("sea%d/%d/%d (STATIN) got 0x%x\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun,
- (u_char) scb->xfer->status));
- break;
- case PHASE_MSGOUT:
- /* Send no-op message. */
- *z->DATA = MSG_NOP;
- sea_wait_for_req_deassert (z, 1000, "MSGOUT");
- PRINT (("sea%d/%d/%d (MSGOUT) send NOP\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- break;
- case PHASE_MSGIN:
- /* Don't handle multi-byte messages here, because they
- * should not be present here. */
- msg = *z->DATA;
- sea_wait_for_req_deassert (z, 2000, "MSGIN");
- PRINT (("sea%d/%d/%d (MSGIN) got 0x%x\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun, msg));
- switch (msg) {
- case MSG_COMMAND_COMPLETE:
- scb->data = data;
- scb->datalen = datalen;
- /* In the case of check-condition status,
- * perform the request-sense op. */
- switch (scb->xfer->status & 0x1e) {
- case SCSI_CHECK:
- if (sea_sense (z, scb))
- scb->flags = SCB_SENSE;
- break;
- case SCSI_BUSY:
- scb->flags = SCB_TBUSY;
- break;
- }
- goto done;
- case MSG_ABORT:
- printf ("sea: command aborted by target\n");
- scb->flags = SCB_ABORTED;
- goto done;
- case MSG_MESSAGE_REJECT:
- printf ("sea: message rejected\n");
- scb->flags = SCB_ABORTED;
- goto done;
- case MSG_DISCONNECT:
- scb->next = z->disconnected_queue;
- z->disconnected_queue = scb;
- if (! z->irq && ! z->timeout_active) {
- timeout (sea_tick, z, 1);
- z->timeout_active = 1;
- }
- PRINT (("sea%d/%d/%d disconnected\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun));
- goto ret;
- case MSG_SAVE_POINTERS:
- scb->data = data;
- scb->datalen = datalen;
- break;
- case MSG_RESTORE_POINTERS:
- data = scb->data;
- datalen = scb->datalen;
- break;
- default:
- printf ("sea%d/%d/%d unknown message: 0x%x\n",
- z->sc_link.adapter_unit,
- scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun, msg);
- break;
- }
- break;
- default:
- printf ("sea: unknown phase: %b\n", sts, STAT_BITS);
- break;
- }
- }
- printf ("sea%d/%d/%d unexpected target disconnect\n",
- z->sc_link.adapter_unit, scb->xfer->sc_link->target,
- scb->xfer->sc_link->lun);
- scb->flags = SCB_ERROR;
-done:
- CLEAR_BUSY (z, scb);
- sea_done (z, scb);
-ret:
- *z->CONTROL = CMD_INTR | z->parity;
-}
-#endif /* NSEA */
diff --git a/sys/i386/isa/ultra14f.c b/sys/i386/isa/ultra14f.c
deleted file mode 100644
index 1687811..0000000
--- a/sys/i386/isa/ultra14f.c
+++ /dev/null
@@ -1,1366 +0,0 @@
-/*
- * Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu)
- * Slight fixes to timeouts to run with the 34F
- * Thanks to Julian Elischer for advice and help with this port.
- *
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * commenced: Sun Sep 27 18:14:01 PDT 1992
- * slight mod to make work with 34F as well: Wed Jun 2 18:05:48 WST 1993
- *
- * today: Fri Jun 2 17:21:03 EST 1994
- * added 24F support ++sg
- *
- * $Id: ultra14f.c,v 1.61 1998/06/21 15:49:39 bde Exp $
- */
-
-#ifdef KERNEL /* don't laugh.. this compiles to a program too.. look */
-#include "uha.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/kernel.h>
-
-#include <machine/clock.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#include <i386/isa/isa_device.h>
-#endif /*KERNEL */
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-
-/* */
-
-#ifndef KERNEL
-#define NUHA 1
-#endif /*KERNEL */
-
-typedef struct {
- unsigned char addr[4];
-} physaddr;
-typedef struct {
- unsigned char len[4];
-} physlen;
-
-#define KVTOPHYS(x) vtophys(x)
-
-#define UHA_MSCP_MAX 32 /* store up to 32MSCPs at any one time
- * MAX = ?
- */
-#define MSCP_HASH_SIZE 32 /* when we have a physical addr. for
- * a mscp and need to find the mscp in
- * space, look it up in the hash table
- */
-#define MSCP_HASH_SHIFT 9 /* only hash on multiples of 512 */
-#define MSCP_HASH(x) ((((long int)(x))>>MSCP_HASH_SHIFT) % MSCP_HASH_SIZE)
-
-#define UHA_NSEG 33 /* number of dma segments supported */
-
-/************************** board definitions *******************************/
-struct uha_reg
-{
- int id; /* product id reg */
- int type; /* product type reg */
- int ectl; /* EISA expansion control bits */
- int config; /* configuration bits */
- int lmask; /* local doorbell mask reg */
- int lint; /* local doorbell int/stat reg */
- int smask; /* system doorbell mask reg */
- int sint; /* system doorbell int/stat reg */
- int ogmcmd; /* outgoing mail command */
- int ogmptr; /* outgoing mail ptr */
- int icmcmd; /* incoming mail command */
- int icmptr; /* incoming mail ptr */
-};
-
-struct uha_bits
-{
- /* uha_lint (read) */
- unsigned char ldip;
-
- /* uha_lint (write) */
- unsigned char adrst;
- unsigned char sbrst;
- unsigned char asrst;
- unsigned char abort;
- unsigned char ogmint;
-
- /* uha_sint (read) */
- unsigned char sintp;
- unsigned char abort_succ;
- unsigned char abort_fail;
-
- /* uha_sint (write) */
- unsigned char abort_ack;
- unsigned char icm_ack;
-};
-
-
-/*
- * UHA_LINT bits (read)
- */
-
-#define UHA_LDIP 0x80 /* local doorbell int pending */
-#define U24_LDIP 0x02
-
-/*
- * UHA_LINT bits (write)
- */
-
-#define UHA_ADRST 0x40 /* adapter soft reset */
-#define UHA_SBRST 0x20 /* scsi bus reset */
-#define UHA_ASRST 0x60 /* adapter and scsi reset */
-#define UHA_ABORT 0x10 /* abort MSCP */
-#define UHA_OGMINT 0x01 /* tell adapter to get mail */
-#define U24_SBRST 0x40 /* scsi bus reset */
-#define U24_ADRST 0x80 /* adapter soft reset */
-#define U24_ASRST 0xc0 /* adapter and scsi reset */
-#define U24_ABORT 0x10 /* same? */
-#define U24_OGMINT 0x02 /* enable OGM interrupt */
-
-/*
- * UHA_SMASK bits (read)
- */
-
-#define UHA_SINTEN 0x80 /* system doorbell interupt Enabled */
-#define UHA_ABORT_COMPLETE_EN 0x10 /* abort MSCP command complete int Enabled */
-#define UHA_ICM_ENABLED 0x01 /* ICM interrupt enabled */
-
-/*
- * UHA_SMASK bits (write)
- */
-
-#define UHA_ENSINT 0x80 /* enable system doorbell interrupt */
-#define UHA_EN_ABORT_COMPLETE 0x10 /* enable abort MSCP complete int */
-#define UHA_ENICM 0x01 /* enable ICM interrupt */
-
-/*
- * UHA_SINT bits (read)
- */
-
-#define UHA_SINTP 0x80 /* system doorbell int pending */
-#define UHA_ABORT_SUCC 0x10 /* abort MSCP successful */
-#define UHA_ABORT_FAIL 0x18 /* abort MSCP failed */
-#define U24_SINTP 0x02 /* system doorbell int pending */
-#define U24_ABORT_SUCC 0x10 /* same? */
-#define U24_ABORT_FAIL 0x18 /* same? */
-
-/*
- * UHA_SINT bits (write)
- */
-
-#define UHA_ABORT_ACK 0x18 /* acknowledge status and clear */
-#define UHA_ICM_ACK 0x01 /* acknowledge ICM and clear */
-#define U24_ABORT_ACK 0x18 /* same */
-#define U24_ICM_ACK 0x02 /* 24F acknowledge ICM and clear */
-
-/*
- * UHA_CONF1 bits (read only)
- */
-
-#define UHA_DMA_CH5 0x00 /* DMA channel 5 */
-#define UHA_DMA_CH6 0x40 /* 6 */
-#define UHA_DMA_CH7 0x80 /* 7 */
-#define UHA_IRQ15 0x00 /* IRQ 15 */
-#define UHA_IRQ14 0x10 /* 14 */
-#define UHA_IRQ11 0x20 /* 11 */
-#define UHA_IRQ10 0x30 /* 10 */
-
-#define EISA_CONFIG 0x0c80 /* Configuration base port */
-#define EISA_DISABLE 0x01 /* EISA disable bit */
-
-/*
- * ha_status error codes
- */
-
-#define UHA_NO_ERR 0x00 /* No error supposedly */
-#define UHA_SBUS_ABORT_ERR 0x84 /* scsi bus abort error */
-#define UHA_SBUS_TIMEOUT 0x91 /* scsi bus selection timeout */
-#define UHA_SBUS_OVER_UNDER 0x92 /* scsi bus over/underrun */
-#define UHA_BAD_SCSI_CMD 0x96 /* illegal scsi command */
-#define UHA_AUTO_SENSE_ERR 0x9b /* auto request sense err */
-#define UHA_SBUS_RES_ERR 0xa3 /* scsi bus reset error */
-#define UHA_BAD_SG_LIST 0xff /* invalid scatter gath list */
-
-struct uha_dma_seg {
- physaddr addr;
- physlen len;
-};
-
-struct mscp {
- unsigned int opcode:3;
-#define U14_HAC 0x01 /* host adapter command */
-#define U14_TSP 0x02 /* target scsi pass through command */
-#define U14_SDR 0x04 /* scsi device reset */
- unsigned int xdir:2; /* xfer direction */
-#define U14_SDET 0x00 /* determined by scsi command */
-#define U14_SDIN 0x01 /* scsi data in */
-#define U14_SDOUT 0x02 /* scsi data out */
-#define U14_NODATA 0x03 /* no data xfer */
- unsigned int dcn:1; /* disable disconnect for this command */
- unsigned int ca:1; /* cache control */
- unsigned int sgth:1; /* scatter gather flag */
- unsigned int target:3;
- unsigned int chan:2; /* scsi channel (always 0 for 14f) */
- unsigned int lun:3;
- physaddr data;
- physlen datalen;
- physaddr link;
- unsigned char link_id;
- unsigned char sg_num; /*number of scat gath segs */
- /*in s-g list if sg flag is */
- /*set. starts at 1, 8bytes per */
- unsigned char senselen;
- unsigned char cdblen;
- unsigned char cdb[12];
- unsigned char ha_status;
- unsigned char targ_status;
- physaddr sense; /* if 0 no auto sense */
- /*-----------------end of hardware supported fields----------------*/
- struct mscp *next; /* in free list */
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define MSCP_FREE 0
-#define MSCP_ACTIVE 1
-#define MSCP_ABORTED 2
- struct uha_dma_seg uha_dma[UHA_NSEG];
- struct scsi_sense_data mscp_sense;
- struct mscp *nexthash;
- long int hashkey;
-};
-
-static struct uha_data {
- int flags;
-#define UHA_INIT 0x01
-#define UHA_24F 0x02
- int baseport;
- struct mscp *mscphash[MSCP_HASH_SIZE];
- struct mscp *free_mscp;
- int unit;
- int our_id; /* our scsi id */
- int vect;
- int dma;
- int nummscps;
- struct scsi_link sc_link;
- struct uha_reg *ur;
- struct uha_bits *ub;
-} *uhadata[NUHA];
-
-static int uha_abort __P((struct uha_data *uha, struct mscp *mscp));
-static u_int32_t uha_adapter_info __P((int unit));
-static int uha_attach __P((struct isa_device *dev));
-static void uha_done __P((struct uha_data *uha, struct mscp *mscp));
-static void uha_free_mscp __P((struct uha_data *uha, struct mscp *mscp,
- int flags));
-static struct mscp *
- uha_get_mscp __P((struct uha_data *uha, int flags));
-static int uha_init __P((struct uha_data *uha));
-static int uha24_init __P((struct uha_data *uha));
-static ointhand2_t
- uhaintr;
-static void uhaminphys __P((struct buf *bp));
-static struct mscp *
- uha_mscp_phys_kv __P((struct uha_data *uha, long mscp_phys));
-static int uha_poll __P((struct uha_data *uha, int wait));
-#ifdef UHADEBUG
-static void uha_print_active_mscp __P((struct uha_data *uha));
-static void uha_print_mscp __P((struct mscp *mscp));
-#endif
-static int uhaprobe __P((struct isa_device *dev));
-static int32_t uha_scsi_cmd __P((struct scsi_xfer *xs));
-static void uha_send_mbox __P((struct uha_data *uha, struct mscp *mscp));
-static timeout_t
- uha_timeout;
-
-static unsigned long int scratch;
-#define EISA_MAX_SLOTS 16 /* XXX This should go into a comon header */
-static int uha_slot; /* slot last board was found in */
-static int uha_unit;
-#define UHA_SHOWMSCPS 0x01
-#define UHA_SHOWINTS 0x02
-#define UHA_SHOWCMDS 0x04
-#define UHA_SHOWMISC 0x08
-#define FAIL 1
-#define SUCCESS 0
-#define PAGESIZ 4096
-
-#ifdef KERNEL
-struct isa_driver uhadriver =
-{
- uhaprobe,
- uha_attach,
- "uha"
-};
-
-static struct scsi_adapter uha_switch =
-{
- uha_scsi_cmd,
- uhaminphys,
- 0,
- 0,
- uha_adapter_info,
- "uha",
- { 0, 0 }
-};
-
-/* the below structure is so we have a default dev struct for out link struct */
-static struct scsi_device uha_dev =
-{
- NULL, /* Use default error handler */
- NULL, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "uha",
- 0,
- { 0, 0 }
-};
-
-#endif /*KERNEL */
-
-#ifndef KERNEL
-main()
-{
- printf("uha_data is %d bytes\n", sizeof(struct uha_data));
- printf("mscp is %d bytes\n", sizeof(struct mscp));
-}
-
-#else /*KERNEL*/
-/*
- * Function to send a command out through a mailbox
- */
-static void
-uha_send_mbox(struct uha_data *uha, struct mscp *mscp)
-{
- int spincount = 100000; /* 1s should be enough */
- struct uha_reg *ur = uha->ur;
- struct uha_bits *ub = uha->ub;
- int s = splbio();
-
- while (--spincount) {
- if ((inb(ur->lint) & ub->ldip) == 0)
- break;
- DELAY(100);
- }
- if (spincount == 0) {
- printf("uha%d: uha_send_mbox, board is not responding\n",
- uha->unit);
- Debugger("ultra14f");
- }
- outl(ur->ogmptr, KVTOPHYS(mscp));
- if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1);
- outb(ur->lint, ub->ogmint);
- splx(s);
-}
-
-/*
- * Function to send abort to 14f
- */
-int
-uha_abort(struct uha_data *uha, struct mscp *mscp)
-{
- int spincount = 100; /* 1 mSec */
- int abortcount = 200000; /*2 secs */
- struct uha_reg *ur = uha->ur;
- struct uha_bits *ub = uha->ub;
- int s = splbio();
-
- while (--spincount) {
- if ((inb(ur->lint) & ub->ldip) == 0)
- break;
- DELAY(10);
- }
- if (spincount == 0) {
- printf("uha%d: uha_abort, board is not responding\n", uha->unit);
- Debugger("ultra14f");
- }
- outl(ur->ogmptr,KVTOPHYS(mscp));
- if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1);
- outb(ur->lint, ub->abort);
-
- while (--abortcount) {
- if (inb(ur->sint) & ub->abort_fail)
- break;
- DELAY(10);
- }
- if (abortcount == 0) {
- printf("uha%d: uha_abort, board is not responding\n", uha->unit);
- Debugger("ultra14f");
- }
- if ((inb(ur->sint) & 0x10) != 0) {
- outb(ur->sint, ub->abort_ack);
- splx(s);
- return (1);
- } else {
- outb(ur->sint, ub->abort_ack);
- splx(s);
- return (0);
- }
-}
-
-/*
- * Function to poll for command completion when in poll mode.
- *
- * wait = timeout in msec
- */
-static int
-uha_poll(struct uha_data *uha, int wait)
-{
- struct uha_reg *ur = uha->ur;
- struct uha_bits *ub = uha->ub;
- int stport = ur->sint;
-
- while (--wait) {
- if (inb(stport) & ub->sintp)
- break;
- DELAY(1000); /* 1 mSec per loop */
- }
- if (wait == 0) {
- printf("uha%d: uha_poll, board is not responding\n", uha->unit);
- return (EIO);
- }
- uhaintr(uha->unit);
- return (0);
-}
-
-/*
- * Check if the device can be found at the port given and if so, set it up
- * ready for further work as an argument, takes the isa_device structure
- * from autoconf.c
- */
-int
-uhaprobe(dev)
- struct isa_device *dev;
-{
- int unit = uha_unit;
- struct uha_data *uha;
-
- dev->id_unit = unit; /* XXX */
-
- /*
- * find unit and check we have that many defined
- */
- if (unit >= NUHA) {
- printf("uha: unit number (%d) too high\n", unit);
- return (0);
- }
- dev->id_unit = unit;
-
- /*
- * Allocate a storage area for us
- */
- if (uhadata[unit]) {
- printf("uha%d: memory already allocated\n", unit);
- return 0;
- }
- uha = malloc(sizeof(struct uha_data), M_TEMP, M_NOWAIT);
- if (!uha) {
- printf("uha%d: cannot malloc!\n", unit);
- return 0;
- }
- bzero(uha, sizeof(struct uha_data));
-
- uha->ur = malloc(sizeof(struct uha_reg), M_TEMP, M_NOWAIT);
- if (!uha->ur) {
- printf("uha%d: cannot malloc!\n", unit);
- return 0;
- }
- bzero(uha->ur, sizeof(struct uha_reg));
-
- uha->ub = malloc(sizeof(struct uha_bits), M_TEMP, M_NOWAIT);
- if (!uha->ub) {
- printf("uha%d: cannot malloc!\n", unit);
- return 0;
- }
- bzero(uha->ub, sizeof(struct uha_bits));
-
- uhadata[unit] = uha;
- uha->unit = unit;
- uha->baseport = dev->id_iobase;
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads uha->vect
- */
- if (uha_init(uha) != 0 && uha24_init(uha) != 0) {
- uhadata[unit] = NULL;
- free(uha->ur, M_TEMP);
- free(uha->ub, M_TEMP);
- free(uha, M_TEMP);
- return (0);
- }
- /* if it's there put in its interrupt and DRQ vectors */
- dev->id_irq = (1 << uha->vect);
- dev->id_drq = uha->dma;
- dev->id_iobase = uha->baseport;
-
- uha_unit++;
- return (16);
-}
-
-/*
- * Attach all the sub-devices we can find
- */
-int
-uha_attach(dev)
- struct isa_device *dev;
-{
- int unit = dev->id_unit;
- struct uha_data *uha = uhadata[unit];
- struct scsibus_data *scbus;
-
- dev->id_ointr = uhaintr;
-
- /*
- * fill in the prototype scsi_link.
- */
- uha->sc_link.adapter_unit = unit;
- uha->sc_link.adapter_targ = uha->our_id;
- uha->sc_link.adapter_softc = uha;
- uha->sc_link.adapter = &uha_switch;
- uha->sc_link.device = &uha_dev;
- uha->sc_link.flags = SDEV_BOUNCE;
-
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = scsi_alloc_bus();
- if(!scbus)
- return 0;
- scbus->adapter_link = &uha->sc_link;
-
- /*
- * ask the adapter what subunits are present
- */
- scsi_attachdevs(scbus);
-
- return 1;
-}
-
-/*
- * Return some information to the caller about
- * the adapter and its capabilities
- */
-u_int32_t
-uha_adapter_info(unit)
- int unit;
-{
- return (2); /* 2 outstanding requests at a time per device */
-}
-
-/*
- * Catch an interrupt from the adaptor
- */
-static void
-uhaintr(unit)
- int unit;
-{
- struct uha_data *uha = uhadata[unit];
- struct mscp *mscp;
- u_char uhastat;
- unsigned long int mboxval;
- struct uha_reg *ur;
- struct uha_bits *ub;
- int port;
-
- ur = uha->ur;
- ub = uha->ub;
- port = uha->baseport;
-
-#ifdef UHADEBUG
- printf("uhaintr ");
-#endif /*UHADEBUG */
-
- while ((uhastat = inb(ur->sint)) & ub->sintp) {
- /*
- * First get all the information and then
- * acknowledge the interrupt
- */
- mboxval = inl(ur->icmptr);
- outb(ur->sint, ub->icm_ack);
- if (uha->flags & UHA_24F) outb(ur->icmcmd, 0);
-
-#ifdef UHADEBUG
- printf("status = 0x%x ", uhastat);
-#endif /*UHADEBUG*/
- /*
- * Process the completed operation
- */
-
- mscp = uha_mscp_phys_kv(uha, mboxval);
- if (!mscp) {
- printf("uha: BAD MSCP RETURNED\n");
- return; /* whatever it was, it'll timeout */
- }
- untimeout(uha_timeout, (caddr_t)mscp, mscp->xs->timeout_ch);
-
- uha_done(uha, mscp);
- }
-}
-
-/*
- * We have a mscp which has been processed by the adaptor, now we look to see
- * how the operation went.
- */
-void
-uha_done(uha, mscp)
- struct uha_data *uha;
- struct mscp *mscp;
-{
- struct scsi_sense_data *s1, *s2;
- struct scsi_xfer *xs = mscp->xs;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n"));
- /*
- * Otherwise, put the results of the operation
- * into the xfer and call whoever started it
- */
- if (((mscp->ha_status != UHA_NO_ERR) || (mscp->targ_status != SCSI_OK))
- && ((xs->flags & SCSI_ERR_OK) == 0)) {
-
- s1 = &(mscp->mscp_sense);
- s2 = &(xs->sense);
-
- if (mscp->ha_status != UHA_NO_ERR) {
- switch (mscp->ha_status) {
- case UHA_SBUS_ABORT_ERR:
- case UHA_SBUS_TIMEOUT: /* No sel response */
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("abort or timeout; ha_status 0x%x\n",
- mscp->ha_status));
- xs->error = XS_TIMEOUT;
- break;
- case UHA_SBUS_OVER_UNDER:
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("scsi bus xfer over/underrun\n"));
- xs->error = XS_DRIVER_STUFFUP;
- break;
- default: /* Other scsi protocol messes */
- xs->error = XS_DRIVER_STUFFUP;
- printf("uha%d: unexpected ha_status 0x%x (target status 0x%x)\n",
- uha->unit, mscp->ha_status,
- mscp->targ_status);
- break;
- }
- } else {
- /* Target status problem */
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("target err 0x%x\n",
- mscp->targ_status));
- switch (mscp->targ_status) {
- case 0x02:
- *s2 = *s1;
- xs->error = XS_SENSE;
- break;
- case 0x08:
- xs->error = XS_BUSY;
- break;
- default:
- printf("uha%d: unexpected targ_status 0x%x\n",
- uha->unit, mscp->targ_status);
- xs->error = XS_DRIVER_STUFFUP;
- break;
- }
- }
- }
- else {
- /* All went correctly OR errors expected */
- xs->resid = 0;
- xs->error = 0;
- }
- xs->flags |= ITSDONE;
- uha_free_mscp(uha, mscp, xs->flags);
- scsi_done(xs);
-}
-
-/*
- * A mscp (and hence a mbx-out) is put onto the free list.
- */
-void
-uha_free_mscp(uha, mscp, flags)
- struct uha_data *uha;
- struct mscp *mscp;
- int flags;
-{
- unsigned int opri = 0;
-
- if (!(flags & SCSI_NOMASK))
- opri = splbio();
-
- mscp->next = uha->free_mscp;
- uha->free_mscp = mscp;
- mscp->flags = MSCP_FREE;
- /*
- * If there were none, wake abybody waiting for
- * one to come free, starting with queued entries
- */
- if (!mscp->next) {
- wakeup((caddr_t)&uha->free_mscp);
- }
- if (!(flags & SCSI_NOMASK))
- splx(opri);
-}
-
-/*
- * Get a free mscp
- *
- * If there are none, see if we can allocate a new one. If so, put it in the
- * hash table too otherwise either return an error or sleep.
- */
-static struct mscp *
-uha_get_mscp(uha, flags)
- struct uha_data *uha;
- int flags;
-{
- unsigned opri = 0;
- struct mscp *mscpp;
- int hashnum;
-
- if (!(flags & SCSI_NOMASK))
- opri = splbio();
- /*
- * If we can and have to, sleep waiting for one to come free
- * but only if we can't allocate a new one
- */
- while (!(mscpp = uha->free_mscp)) {
- if (uha->nummscps < UHA_MSCP_MAX) {
- if (mscpp = (struct mscp *)malloc(sizeof(struct mscp),
- M_TEMP,
- M_NOWAIT)) {
- bzero(mscpp, sizeof(struct mscp));
- uha->nummscps++;
- mscpp->flags = MSCP_ACTIVE;
- /*
- * put in the phystokv hash table
- * Never gets taken out.
- */
- mscpp->hashkey = KVTOPHYS(mscpp);
- hashnum = MSCP_HASH(mscpp->hashkey);
- mscpp->nexthash = uha->mscphash[hashnum];
- uha->mscphash[hashnum] = mscpp;
- } else {
- printf("uha%d: Can't malloc MSCP\n", uha->unit);
- }
- goto gottit;
- } else {
- if (!(flags & SCSI_NOSLEEP)) {
- tsleep((caddr_t)&uha->free_mscp, PRIBIO,
- "uhamscp", 0);
- }
- }
- }
- if (mscpp) {
- /* Get MSCP from from free list */
- uha->free_mscp = mscpp->next;
- mscpp->flags = MSCP_ACTIVE;
- }
- gottit:
- if (!(flags & SCSI_NOMASK))
- splx(opri);
-
- return (mscpp);
-}
-
-/*
- * given a physical address, find the mscp that it corresponds to.
- */
-static struct mscp *
-uha_mscp_phys_kv(uha, mscp_phys)
- struct uha_data *uha;
- long int mscp_phys;
-{
- int hashnum = MSCP_HASH(mscp_phys);
- struct mscp *mscpp = uha->mscphash[hashnum];
-
- while (mscpp) {
- if (mscpp->hashkey == mscp_phys)
- break;
- mscpp = mscpp->nexthash;
- }
- return mscpp;
-}
-
-/*
- * Start the board, ready for normal operation
- */
-int
-uha_init(uha)
- struct uha_data *uha;
-{
- volatile unsigned char model;
- volatile unsigned char submodel;
- unsigned char config_reg1;
- unsigned char config_reg2;
- unsigned char dma_ch;
- unsigned char irq_ch;
- unsigned char uha_id;
- int port = uha->baseport;
- int resetcount = 4000; /* 4 secs? */
- struct uha_reg *ur = uha->ur;
- struct uha_bits *ub = uha->ub;
-
- /*
- * Prepare to use a 14/34F.
- */
- ur->id = port + 0x04;
- ur->type = port + 0x00; /* 24F only */
- ur->ectl = port + 0x00; /* 24F only */
- ur->config = port + 0x06; /* 0-1 for 14F */
- ur->lmask = port + 0x00;
- ur->lint = port + 0x01;
- ur->smask = port + 0x02;
- ur->sint = port + 0x03;
- ur->ogmcmd = port + 0x00; /* 24F only */
- ur->ogmptr = port + 0x08;
- ur->icmcmd = port + 0x00; /* 24F only */
- ur->icmptr = port + 0x0c;
-
- ub->ldip = UHA_LDIP;
- ub->adrst = UHA_ADRST;
- ub->sbrst = UHA_SBRST;
- ub->asrst = UHA_ASRST;
- ub->abort = UHA_ABORT;
- ub->ogmint = UHA_OGMINT;
- ub->sintp = UHA_SINTP;
- ub->abort_succ = UHA_ABORT_SUCC;
- ub->abort_fail = UHA_ABORT_FAIL;
- ub->abort_ack = UHA_ABORT_ACK;
- ub->icm_ack = UHA_ICM_ACK;
-
- model = inb(ur->id);
- submodel = inb(ur->id + 1);
- if ((model != 0x56) & (submodel != 0x40)) return(ENXIO);
- printf("uha%d: reading board settings, ", uha->unit);
-
- config_reg1 = inb(ur->config);
- config_reg2 = inb(ur->config + 1);
- dma_ch = (config_reg1 & 0xc0);
- irq_ch = (config_reg1 & 0x30);
- uha_id = (config_reg2 & 0x07);
-
- switch (dma_ch) {
- case UHA_DMA_CH5:
- uha->dma = 5;
- printf("dma=5 ");
- break;
- case UHA_DMA_CH6:
- uha->dma = 6;
- printf("dma=6 ");
- break;
- case UHA_DMA_CH7:
- uha->dma = 7;
- printf("dma=7 ");
- break;
- default:
- printf("illegal dma jumper setting\n");
- return (EIO);
- }
- switch (irq_ch) {
- case UHA_IRQ10:
- uha->vect = 10;
- printf("int=10 ");
- break;
- case UHA_IRQ11:
- uha->vect = 11;
- printf("int=11 ");
- break;
- case UHA_IRQ14:
- uha->vect = 14;
- printf("int=14 ");
- break;
- case UHA_IRQ15:
- uha->vect = 15;
- printf("int=15 ");
- break;
- default:
- printf("illegal int jumper setting\n");
- return (EIO);
- }
-
- /* who are we on the scsi bus */
- printf("id=%x\n", uha_id);
- uha->our_id = uha_id;
-
- /*
- * Note that we are going and return (to probe)
- */
- outb(ur->lint, ub->asrst);
- while (--resetcount) {
- if (inb(ur->lint))
- break;
- DELAY(1000); /* 1 mSec per loop */
- }
- if (resetcount == 0) {
- printf("uha%d: board timed out during reset\n", uha->unit);
- return (ENXIO);
- }
- outb(ur->smask, 0x81); /* make sure interrupts are enabled */
- uha->flags |= UHA_INIT;
- return (0);
-}
-
-
-/*
- * Initialize an Ultrastor 24F
- */
-int
-uha24_init(uha)
- struct uha_data *uha;
-{
- unsigned char p0, p1, p2, p3, p5, p7;
- unsigned char id[7], rev, haid;
- int port = 0, irq;
- int resetcount = 4000;
- struct uha_reg *ur = uha->ur;
- struct uha_bits *ub = uha->ub;
-
- /* Search for the 24F's product ID */
- uha_slot++;
- while (uha_slot < EISA_MAX_SLOTS) {
- /*
- * Prepare to use a 24F.
- */
- port = EISA_CONFIG | (uha_slot << 12);
- ur->id = port + 0x00;
- ur->type = port + 0x02;
- ur->ectl = port + 0x04;
- ur->config = port + 0x05; /* 0-2 for 24F */
- ur->lmask = port + 0x0c;
- ur->lint = port + 0x0d;
- ur->smask = port + 0x0e;
- ur->sint = port + 0x0f;
- ur->ogmcmd = port + 0x16;
- ur->ogmptr = port + 0x17;
- ur->icmcmd = port + 0x1b;
- ur->icmptr = port + 0x1c;
-
- ub->ldip = U24_LDIP;
- ub->adrst = U24_ADRST;
- ub->sbrst = U24_SBRST;
- ub->asrst = U24_ASRST;
- ub->abort = U24_ABORT;
- ub->ogmint = U24_OGMINT;
- ub->sintp = U24_SINTP;
- ub->abort_succ = U24_ABORT_SUCC;
- ub->abort_fail = U24_ABORT_FAIL;
- ub->abort_ack = U24_ABORT_ACK;
- ub->icm_ack = U24_ICM_ACK;
-
- /*
- * Make sure an EISA card is installed in this slot,
- * and if it is make sure that the card is enabled.
- */
- outb(ur->id, 0xff);
- p0 = inb(ur->id);
- if ((p0 == 0xff) ||
- ((p0 & 0x80) != 0) ||
- ((inb(ur->ectl) & EISA_DISABLE) == 0)) {
- uha_slot++;
- continue;
- }
-
- /* Found an enabled card. Grab the product ID. */
- p1 = inb(ur->id+1);
- p2 = inb(ur->type);
- p3 = inb(ur->type+1);
- id[0] = 0x40 + ((p0 >> 2) & 0x1f);
- id[1] = 0x40 + (((p0 & 0x03) << 3) | ((p1 >> 5) & 0x07));
- id[2] = 0x40 + (p1 & 0x1f);
- id[3] = hex2ascii((p2 >> 4) & 0x0f);
- id[4] = hex2ascii(p2 & 0x0f);
- id[5] = hex2ascii((p3 >> 4) & 0x0f);
- id[6] = '\0';
- rev = p3 & 0xf;
-
- /* We only want the 24F product ID. */
- if (!strcmp(id, "USC024")) break;
- uha_slot++;
- }
- if (uha_slot == EISA_MAX_SLOTS) return(ENODEV);
-
- /* We have the card! Grab remaining config. */
- p5 = inb(ur->config);
- p7 = inb(ur->config+2);
-
- switch (p5 & 0xf0) {
- case 0x10: irq = 15; break;
- case 0x20: irq = 14; break;
- case 0x40: irq = 11; break;
- case 0x80: irq = 10; break;
- default:
- printf("uha%d: bad 24F irq\n", uha->unit);
- return(ENXIO);
- }
-
- haid = (p7 & 0x07);
- printf("uha%d: UltraStor 24F int=%d id=%d\n", uha->unit, irq, haid);
-
- /* Issue SCSI and adapter reset */
- outb(ur->lint, ub->asrst);
- while (--resetcount) {
- if (inb(ur->lint))
- break;
- DELAY(1000); /* 1 mSec per loop */
- }
- if (resetcount == 0) {
- printf("uha%d: board timed out during reset\n", uha->unit);
- return (ENXIO);
- }
- outb(ur->smask, 0xc2); /* make sure interrupts are enabled */
- uha->flags |= (UHA_INIT | UHA_24F);
- uha->baseport = port;
- uha->our_id = haid;
- uha->vect = irq;
- uha->dma = -1;
- return(0);
-}
-
-#ifndef min
-#define min(x,y) (x < y ? x : y)
-#endif /* min */
-
-void
-uhaminphys(bp)
- struct buf *bp;
-{
- if (bp->b_bcount > ((UHA_NSEG - 1) * PAGESIZ)) {
- bp->b_bcount = ((UHA_NSEG - 1) * PAGESIZ);
- }
-}
-
-/*
- * start a scsi operation given the command and the data address. Also
- * needs the unit, target and lu.
- */
-static int32_t
-uha_scsi_cmd(xs)
- struct scsi_xfer *xs;
-{
- struct mscp *mscp;
- struct uha_dma_seg *sg;
- int seg; /* scatter gather seg being worked on */
- int thiskv;
- unsigned long int thisphys, nextphys;
- int bytes_this_seg, bytes_this_page, datalen, flags;
- struct uha_data *uha;
- int s;
- unsigned long int templen;
-
- uha = (struct uha_data *)xs->sc_link->adapter_softc;
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_scsi_cmd\n"));
- /*
- * get a mscp (mbox-out) to use. If the transfer
- * is from a buf (possibly from interrupt time)
- * then we can't allow it to sleep
- */
- flags = xs->flags;
- if (xs->bp)
- flags |= (SCSI_NOSLEEP); /* just to be sure */
- if (flags & ITSDONE) {
- printf("uha%d: Already done?", uha->unit);
- xs->flags &= ~ITSDONE;
- }
- if (!(flags & INUSE)) {
- printf("uha%d: Not in use?", uha->unit);
- xs->flags |= INUSE;
- }
- if (!(mscp = uha_get_mscp(uha, flags))) {
- xs->error = XS_DRIVER_STUFFUP;
- return (TRY_AGAIN_LATER);
- }
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("start mscp(%p)\n", mscp));
- mscp->xs = xs;
-
- /*
- * Put all the arguments for the xfer in the mscp
- */
- if (flags & SCSI_RESET) {
- mscp->opcode = 0x04;
- mscp->ca = 0x01;
- } else {
- mscp->opcode = 0x02;
- mscp->ca = 0x01;
- }
- if (flags & SCSI_DATA_IN) {
- mscp->xdir = 0x01;
- }
- if (flags & SCSI_DATA_OUT) {
- mscp->xdir = 0x02;
- }
-#ifdef GOTTABEJOKING
- if (xs->sc_link->lun != 0) {
- xs->error = XS_DRIVER_STUFFUP;
- uha_free_mscp(uha, mscp, flags);
- return (HAD_ERROR);
- }
-#endif
- mscp->dcn = 0x00;
- mscp->chan = 0x00;
- mscp->target = xs->sc_link->target;
- mscp->lun = xs->sc_link->lun;
- mscp->link.addr[0] = 0x00;
- mscp->link.addr[1] = 0x00;
- mscp->link.addr[2] = 0x00;
- mscp->link.addr[3] = 0x00;
- mscp->link_id = 0x00;
- mscp->cdblen = xs->cmdlen;
- scratch = KVTOPHYS(&(mscp->mscp_sense));
- mscp->sense.addr[0] = (scratch & 0xff);
- mscp->sense.addr[1] = ((scratch >> 8) & 0xff);
- mscp->sense.addr[2] = ((scratch >> 16) & 0xff);
- mscp->sense.addr[3] = ((scratch >> 24) & 0xff);
- mscp->senselen = sizeof(mscp->mscp_sense);
- mscp->ha_status = 0x00;
- mscp->targ_status = 0x00;
-
- if (xs->datalen) { /* should use S/G only if not zero length */
- scratch = KVTOPHYS(mscp->uha_dma);
- mscp->data.addr[0] = (scratch & 0xff);
- mscp->data.addr[1] = ((scratch >> 8) & 0xff);
- mscp->data.addr[2] = ((scratch >> 16) & 0xff);
- mscp->data.addr[3] = ((scratch >> 24) & 0xff);
- sg = mscp->uha_dma;
- seg = 0;
- mscp->sgth = 0x01;
-
-#ifdef TFS
- if (flags & SCSI_DATA_UIO) {
- iovp = ((struct uio *) xs->data)->uio_iov;
- datalen = ((struct uio *) xs->data)->uio_iovcnt;
- xs->datalen = 0;
- while ((datalen) && (seg < UHA_NSEG)) {
- scratch = (unsigned long) iovp->iov_base;
- sg->addr.addr[0] = (scratch & 0xff);
- sg->addr.addr[1] = ((scratch >> 8) & 0xff);
- sg->addr.addr[2] = ((scratch >> 16) & 0xff);
- sg->addr.addr[3] = ((scratch >> 24) & 0xff);
- xs->datalen += *(unsigned long *) sg->len.len = iovp->iov_len;
- SC_DEBUGN(xs->sc_link, SDEV_DB4, ("(0x%x@0x%x)",
- iovp->iov_len,
- iovp->iov_base));
- sg++;
- iovp++;
- seg++;
- datalen--;
- }
- } else
-#endif /*TFS */
- {
- /*
- * Set up the scatter gather block
- */
-
- SC_DEBUG(xs->sc_link, SDEV_DB4,
- ("%ld @%p:- ", xs->datalen, xs->data));
- datalen = xs->datalen;
- thiskv = (int) xs->data;
- thisphys = KVTOPHYS(thiskv);
- templen = 0;
-
- while ((datalen) && (seg < UHA_NSEG)) {
- bytes_this_seg = 0;
-
- /* put in the base address */
- sg->addr.addr[0] = (thisphys & 0xff);
- sg->addr.addr[1] = ((thisphys >> 8) & 0xff);
- sg->addr.addr[2] = ((thisphys >> 16) & 0xff);
- sg->addr.addr[3] = ((thisphys >> 24) & 0xff);
-
- SC_DEBUGN(xs->sc_link, SDEV_DB4, ("0x%lx",
- thisphys));
-
- /* do it at least once */
- nextphys = thisphys;
- while ((datalen) && (thisphys == nextphys))
- /*
- * This page is contiguous (physically) with
- * the the last, just extend the length
- */
- {
- /* how far to the end of the page */
- nextphys = (thisphys & (~(PAGESIZ - 1)))
- + PAGESIZ;
- bytes_this_page = nextphys - thisphys;
- /**** or the data ****/
- bytes_this_page = min(bytes_this_page
- ,datalen);
- bytes_this_seg += bytes_this_page;
- datalen -= bytes_this_page;
-
- /* get more ready for the next page */
- thiskv = (thiskv & (~(PAGESIZ - 1)))
- + PAGESIZ;
- if (datalen)
- thisphys = KVTOPHYS(thiskv);
- }
- /*
- * next page isn't contiguous, finish the seg
- */
- SC_DEBUGN(xs->sc_link, SDEV_DB4,
- ("(0x%x)", bytes_this_seg));
- sg->len.len[0] = (bytes_this_seg & 0xff);
- sg->len.len[1] = ((bytes_this_seg >> 8) & 0xff);
- sg->len.len[2] = ((bytes_this_seg >> 16) & 0xff);
- sg->len.len[3] = ((bytes_this_seg >> 24) & 0xff);
- templen += bytes_this_seg;
- sg++;
- seg++;
- }
- }
-
- /* end of iov/kv decision */
- mscp->datalen.len[0] = (templen & 0xff);
- mscp->datalen.len[1] = ((templen >> 8) & 0xff);
- mscp->datalen.len[2] = ((templen >> 16) & 0xff);
- mscp->datalen.len[3] = ((templen >> 24) & 0xff);
- mscp->sg_num = seg;
-
- SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
- if (datalen) { /* there's still data, must have run out of segs! */
- printf("uha%d: uha_scsi_cmd, more than %d DMA segs\n",
- uha->unit, UHA_NSEG);
- xs->error = XS_DRIVER_STUFFUP;
- uha_free_mscp(uha, mscp, flags);
- return (HAD_ERROR);
- }
- } else { /* No data xfer, use non S/G values */
- mscp->data.addr[0] = 0x00;
- mscp->data.addr[1] = 0x00;
- mscp->data.addr[2] = 0x00;
- mscp->data.addr[3] = 0x00;
- mscp->datalen.len[0] = 0x00;
- mscp->datalen.len[1] = 0x00;
- mscp->datalen.len[2] = 0x00;
- mscp->datalen.len[3] = 0x00;
- mscp->xdir = 0x03;
- mscp->sgth = 0x00;
- mscp->sg_num = 0x00;
- }
-
- /*
- * Put the scsi command in the mscp and start it
- */
- bcopy(xs->cmd, mscp->cdb, xs->cmdlen);
-
- /*
- * Usually return SUCCESSFULLY QUEUED
- */
- if (!(flags & SCSI_NOMASK)) {
- s = splbio();
- uha_send_mbox(uha, mscp);
- xs->timeout_ch = timeout(uha_timeout, (caddr_t)mscp,
- (xs->timeout * hz) / 1000);
- splx(s);
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
- return (SUCCESSFULLY_QUEUED);
- }
-
- /*
- * If we can't use interrupts, poll on completion
- */
- uha_send_mbox(uha, mscp);
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_wait\n"));
- do {
- if (uha_poll(uha, xs->timeout)) {
- if (!(xs->flags & SCSI_SILENT))
- printf("uha%d: cmd fail\n", uha->unit);
- if (!(uha_abort(uha, mscp))) {
- printf("uha%d: abort failed in wait\n",
- uha->unit);
- uha_free_mscp(uha, mscp, flags);
- }
- xs->error = XS_DRIVER_STUFFUP;
- return (HAD_ERROR);
- }
- }
- while (!(xs->flags & ITSDONE)); /* something (?) else finished */
- if (xs->error) {
- return (HAD_ERROR);
- }
- return (COMPLETE);
-}
-
-static void
-uha_timeout(arg1)
- void *arg1;
-{
- struct mscp *mscp = (struct mscp *)arg1;
- struct uha_data *uha;
- int s = splbio();
-
- uha = (struct uha_data *)mscp->xs->sc_link->adapter_softc;
- printf("uha%d:%d:%d (%s%d) timed out ", uha->unit
- ,mscp->xs->sc_link->target
- ,mscp->xs->sc_link->lun
- ,mscp->xs->sc_link->device->name
- ,mscp->xs->sc_link->dev_unit);
-
-#ifdef UHADEBUG
- uha_print_active_mscp(uha);
-#endif /*UHADEBUG */
-
- if ((uha_abort(uha, mscp) != 1) || (mscp->flags = MSCP_ABORTED)) {
- printf("AGAIN");
- mscp->xs->retries = 0; /* I MEAN IT ! */
- uha_done(uha, mscp);
- } else { /* abort the operation that has timed out */
- printf("\n");
- mscp->xs->timeout_ch = timeout(uha_timeout, (caddr_t)mscp,
- 2 * hz);
- mscp->flags = MSCP_ABORTED;
- }
- splx(s);
-}
-
-#ifdef UHADEBUG
-void
-uha_print_mscp(mscp)
- struct mscp *mscp;
-{
- printf("mscp:%x op:%x cmdlen:%d senlen:%d\n"
- ,mscp
- ,mscp->opcode
- ,mscp->cdblen
- ,mscp->senselen);
- printf(" sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x flags:%x\n"
- ,mscp->sgth
- ,mscp->sg_num
- ,mscp->datalen
- ,mscp->ha_status
- ,mscp->targ_status
- ,mscp->flags);
- show_scsi_cmd(mscp->xs);
-}
-
-void
-uha_print_active_mscp(struct uha_data *uha)
-{
- struct mscp *mscp;
- int i = 0;
-
- while (i < MSCP_HASH_SIZE) {
- mscp = uha->mscphash[i];
- while (mscp) {
- if (mscp->flags != MSCP_FREE) {
- uha_print_mscp(mscp);
- }
- mscp = mscp->nexthash;
- }
- i++;
- }
-}
-#endif /*UHADEBUG */
-#endif /*KERNEL */
diff --git a/sys/i386/isa/wd7000.c b/sys/i386/isa/wd7000.c
deleted file mode 100644
index 3da995f..0000000
--- a/sys/i386/isa/wd7000.c
+++ /dev/null
@@ -1,727 +0,0 @@
-/*
- * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
- * All rights reserved.
- *
- * Written by Olof Johansson (offe@ludd.luth.se) 1995.
- * Based on code written by Theo de Raadt (deraadt@fsa.ca).
- *
- * 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 at Ludd, University of Lule}.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- /* All bugs are subject to removal without further notice */
-
-/*
- * offe 01/07/95
- *
- * This version of the driver _still_ doesn't implement scatter/gather for the
- * WD7000-FASST2. This is due to the fact that my controller doesn't seem to
- * support it. That, and the lack of documentation makes it impossible for
- * me to implement it.
- * What I've done instead is allocated a local buffer, contiguous buffer big
- * enough to handle the requests. I haven't seen any read/write bigger than 64k,
- * so I allocate a buffer of 64+16k. The data that needs to be DMA'd to/from
- * the controller is copied to/from that buffer before/after the command is
- * sent to the card.
- */
-
-#include "wds.h"
-#if NWDS > 0
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-
-#include <scsi/scsiconf.h>
-
-#include <machine/clock.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#include <i386/isa/isa_device.h>
-
-static struct scsi_device wds_dev =
-{
- NULL,
- NULL,
- NULL,
- NULL,
- "wds",
- 0,
- { 0, 0 }
-};
-
-/*
- XXX THIS SHOULD BE FIXED!
- I haven't got the KERNBASE-version to work, but on my system the kernel
- is at virtual address 0xFxxxxxxx, responding to physical address
- 0x0xxxxxxx.
-#define PHYSTOKV(x) ((x) + KERNBASE)
-*/
-#define PHYSTOKV(x) ((x) | 0xf0000000)
-#define KVTOPHYS(x) vtophys(x)
-/* 0x10000 (64k) should be enough. But just to be sure... */
-#define BUFSIZ 0x12000
-
-
-/* WD7000 registers */
-#define WDS_STAT 0 /* read */
-#define WDS_IRQSTAT 1 /* read */
-
-#define WDS_CMD 0 /* write */
-#define WDS_IRQACK 1 /* write */
-#define WDS_HCR 2 /* write */
-
-/* WDS_STAT (read) defs */
-#define WDS_IRQ 0x80
-#define WDS_RDY 0x40
-#define WDS_REJ 0x20
-#define WDS_INIT 0x10
-
-/* WDS_IRQSTAT (read) defs */
-#define WDSI_MASK 0xc0
-#define WDSI_ERR 0x00
-#define WDSI_MFREE 0x80
-#define WDSI_MSVC 0xc0
-
-/* WDS_CMD (write) defs */
-#define WDSC_NOOP 0x00
-#define WDSC_INIT 0x01
-#define WDSC_DISUNSOL 0x02
-#define WDSC_ENAUNSOL 0x03
-#define WDSC_IRQMFREE 0x04
-#define WDSC_SCSIRESETSOFT 0x05
-#define WDSC_SCSIRESETHARD 0x06
-#define WDSC_MSTART(m) (0x80 + (m))
-#define WDSC_MMSTART(m) (0xc0 + (m))
-
-/* WDS_HCR (write) defs */
-#define WDSH_IRQEN 0x08
-#define WDSH_DRQEN 0x04
-#define WDSH_SCSIRESET 0x02
-#define WDSH_ASCRESET 0x01
-
-struct wds_cmd {
- u_char cmd;
- u_char targ;
- u_char scb[12]; /*u_char scb[12];*/
- u_char stat;
- u_char venderr;
- u_char len[3];
- u_char data[3];
- u_char next[3];
- u_char write;
- u_char xx[6];
-};
-
-struct wds_req {
- struct wds_cmd cmd;
- struct wds_cmd sense;
- struct scsi_xfer *sxp;
- int busy, polled;
- int done, ret, ombn;
-};
-
-#define WDSX_SCSICMD 0x00
-#define WDSX_OPEN_RCVBUF 0x80
-#define WDSX_RCV_CMD 0x81
-#define WDSX_RCV_DATA 0x82
-#define WDSX_RCV_DATASTAT 0x83
-#define WDSX_SND_DATA 0x84
-#define WDSX_SND_DATASTAT 0x85
-#define WDSX_SND_CMDSTAT 0x86
-#define WDSX_READINIT 0x88
-#define WDSX_READSCSIID 0x89
-#define WDSX_SETUNSOLIRQMASK 0x8a
-#define WDSX_GETUNSOLIRQMASK 0x8b
-#define WDSX_GETFIRMREV 0x8c
-#define WDSX_EXECDIAG 0x8d
-#define WDSX_SETEXECPARM 0x8e
-#define WDSX_GETEXECPARM 0x8f
-
-struct wds_mb {
- u_char stat;
- u_char addr[3];
-};
-/* ICMB status value */
-#define ICMB_OK 0x01
-#define ICMB_OKERR 0x02
-#define ICMB_ETIME 0x04
-#define ICMB_ERESET 0x05
-#define ICMB_ETARCMD 0x06
-#define ICMB_ERESEL 0x80
-#define ICMB_ESEL 0x81
-#define ICMB_EABORT 0x82
-#define ICMB_ESRESET 0x83
-#define ICMB_EHRESET 0x84
-
-struct wds_setup {
- u_char cmd;
- u_char scsi_id;
- u_char buson_t;
- u_char busoff_t;
- u_char xx;
- u_char mbaddr[3];
- u_char nomb;
- u_char nimb;
-};
-
-#define WDS_NOMB 8
-#define WDS_NIMB 8
-#define MAXSIMUL 8
-
-static int wdsunit=0;
-
-static u_char wds_data[NWDS][BUFSIZ];
-static u_char wds_data_in_use[NWDS];
-
-static struct wds {
- int addr;
- struct wds_req wdsr[MAXSIMUL];
- struct wds_mb ombs[WDS_NOMB], imbs[WDS_NIMB];
- struct scsi_link sc_link;
-} wds[NWDS];
-
-static int wdsprobe(struct isa_device *);
-static void wds_minphys(struct buf *);
-static struct wds_req *wdsr_alloc(int);
-static int32_t wds_scsi_cmd(struct scsi_xfer *);
-static u_int32_t wds_adapter_info(int);
-static ointhand2_t wdsintr;
-static int wds_done(int, struct wds_cmd *, u_char);
-static int wdsattach(struct isa_device *);
-static int wds_init(struct isa_device *);
-static int wds_cmd(int, u_char *, int);
-static void wds_wait(int, int, int);
-
-struct isa_driver wdsdriver =
-{
- wdsprobe,
- wdsattach,
- "wds"
-};
-
-static struct scsi_adapter wds_switch =
-{
- wds_scsi_cmd,
- wds_minphys,
- 0,
- 0,
- wds_adapter_info,
- "wds",
- {0,0}
-};
-
-int
-wdsprobe(struct isa_device *dev)
-{
- if(wdsunit > NWDS)
- return 0;
-
- dev->id_unit = wdsunit; /* XXX WRONG! */
- wds[wdsunit].addr = dev->id_iobase;
-
- if(wds_init(dev) != 0)
- return 0;
- wdsunit++;
- return 8;
-}
-
-void
-wds_minphys(struct buf *bp)
-{
- if(bp->b_bcount > BUFSIZ)
- bp->b_bcount = BUFSIZ;
-}
-
-struct wds_req *
-wdsr_alloc(int unit)
-{
- struct wds_req *r;
- int x;
- int i;
-
- r = NULL;
- x = splbio();
- for(i=0; i<MAXSIMUL; i++)
- if(!wds[unit].wdsr[i].busy)
- {
- r = &wds[unit].wdsr[i];
- r->busy = 1;
- break;
- }
- if(!r)
- {
- splx(x);
- return NULL;
- }
-
- r->ombn = -1;
- for(i=0; i<WDS_NOMB; i++)
- if(!wds[unit].ombs[i].stat)
- {
- wds[unit].ombs[i].stat = 1;
- r->ombn = i;
- break;
- }
- if(r->ombn == -1 )
- {
- r->busy = 0;
- splx(x);
- return NULL;
- }
- splx(x);
- return r;
-}
-
-int32_t
-wds_scsi_cmd(struct scsi_xfer *sxp)
-{
- struct wds_req *r;
- int unit = sxp->sc_link->adapter_unit;
- int base;
- u_char c;
- int i;
-
- base = wds[unit].addr;
-
- if( sxp->flags & SCSI_RESET)
- {
- printf("reset!\n");
- return COMPLETE;
- }
-
- r = wdsr_alloc(unit);
- if(r==NULL)
- {
- printf("no request slot available!\n");
- sxp->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
- r->done = 0;
- r->sxp = sxp;
-
- if(sxp->flags & SCSI_DATA_UIO)
- {
- printf("UIO!\n");
- sxp->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
-
- scsi_uto3b(KVTOPHYS(&r->cmd),wds[unit].ombs[r->ombn].addr);
-
- bzero(&r->cmd, sizeof r->cmd);
- r->cmd.cmd = WDSX_SCSICMD;
- r->cmd.targ = (sxp->sc_link->target << 5) | sxp->sc_link->lun;
- bcopy(sxp->cmd, &r->cmd.scb, sxp->cmdlen<12 ? sxp->cmdlen : 12);
- scsi_uto3b(sxp->datalen, r->cmd.len);
-
- if(wds_data_in_use[unit])
- {
- sxp->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
- else
- wds_data_in_use[unit] = 1;
-
- if(sxp->datalen && !(sxp->flags&SCSI_DATA_IN))
- bcopy(sxp->data, wds_data[unit], sxp->datalen);
-
- scsi_uto3b(sxp->datalen ? KVTOPHYS(wds_data[unit]) : 0, r->cmd.data);
-
- r->cmd.write = (sxp->flags&SCSI_DATA_IN)? 0x80 : 0x00;
-
- scsi_uto3b(KVTOPHYS(&r->sense),r->cmd.next);
-
- bzero(&r->sense, sizeof r->sense);
- r->sense.cmd = r->cmd.cmd;
- r->sense.targ = r->cmd.targ;
- r->sense.scb[0] = REQUEST_SENSE;
- scsi_uto3b(KVTOPHYS(&sxp->sense),r->sense.data);
- scsi_uto3b(sizeof(sxp->sense), r->sense.len);
- r->sense.write = 0x80;
-
- if(sxp->flags & SCSI_NOMASK)
- {
- outb(base+WDS_HCR, WDSH_DRQEN);
- r->polled = 1;
- } else
- {
- outb(base+WDS_HCR, WDSH_IRQEN|WDSH_DRQEN);
- r->polled = 0;
- }
-
- c = WDSC_MSTART(r->ombn);
-
- if( wds_cmd(base, &c, sizeof c) != 0)
- {
- printf("wds%d: unable to start outgoing mbox\n", unit);
- r->busy = 0;
- wds[unit].ombs[r->ombn].stat = 0;
-
- return TRY_AGAIN_LATER;
- }
-
- if(sxp->flags & SCSI_NOMASK)
- {
- repoll:
-
- i = 0;
- while(!(inb(base+WDS_STAT) & WDS_IRQ))
- {
-
- DELAY(20000);
- if(++i == 20)
- {
- outb(base + WDS_IRQACK, 0);
- /*r->busy = 0;*/
- sxp->error = XS_TIMEOUT;
- return HAD_ERROR;
- }
- }
- wdsintr(unit);
- if(r->done)
- {
- r->sxp->flags |= ITSDONE;
- r->busy = 0;
- return r->ret;
- }
- goto repoll;
- }
-
- return SUCCESSFULLY_QUEUED;
-}
-
-u_int32_t
-wds_adapter_info(int unit)
-{
- return 1;
-}
-
-static void
-wdsintr(int unit)
-{
- struct wds_cmd *pc, *vc;
- struct wds_mb *in;
- u_char stat;
- u_char c;
-
- if(!inb(wds[unit].addr+WDS_STAT) & WDS_IRQ)
- {
- outb(wds[unit].addr + WDS_IRQACK, 0);
- return;
- }
-
- c = inb(wds[unit].addr + WDS_IRQSTAT);
- if( (c&WDSI_MASK) == WDSI_MSVC)
- {
- c = c & ~WDSI_MASK;
- in = &wds[unit].imbs[c];
-
- pc = (struct wds_cmd *)scsi_3btou(in->addr);
- vc = (struct wds_cmd *)PHYSTOKV((intptr_t)(void *)pc);
- stat = in->stat;
-
- wds_done(unit, vc, stat);
- in->stat = 0;
-
- outb(wds[unit].addr + WDS_IRQACK, 0);
- }
-}
-
-int
-wds_done(int unit, struct wds_cmd *c, u_char stat)
-{
- struct wds_req *r;
- int i;
-
- r = (struct wds_req *)NULL;
-
- for(i=0; i<MAXSIMUL; i++)
- if( c == &wds[unit].wdsr[i].cmd && !wds[unit].wdsr[i].done)
- {
- r = &wds[unit].wdsr[i];
- break;
- }
- if(r == (struct wds_req *)NULL)
- {
- /* failed to find request! */
- return 1;
- }
-
- r->done = 1;
- wds[unit].ombs[r->ombn].stat = 0;
- r->ret = HAD_ERROR;
- switch(stat)
- {
- case ICMB_OK:
- r->ret = COMPLETE;
- if(r->sxp)
- r->sxp->resid = 0;
- break;
- case ICMB_OKERR:
- if(!(r->sxp->flags & SCSI_ERR_OK) && c->stat)
- {
- r->sxp->sense.error_code = c->venderr;
- r->sxp->error=XS_SENSE;
- }
- else
- r->sxp->error=XS_NOERROR;
- r->ret = COMPLETE;
- break;
- case ICMB_ETIME:
- r->sxp->error = XS_TIMEOUT;
- r->ret = HAD_ERROR;
- break;
- case ICMB_ERESET:
- case ICMB_ETARCMD:
- case ICMB_ERESEL:
- case ICMB_ESEL:
- case ICMB_EABORT:
- case ICMB_ESRESET:
- case ICMB_EHRESET:
- r->sxp->error = XS_DRIVER_STUFFUP;
- r->ret = HAD_ERROR;
- break;
- }
-
- if(r->sxp)
- if(r->sxp->datalen && (r->sxp->flags&SCSI_DATA_IN))
- bcopy(wds_data[unit],r->sxp->data,r->sxp->datalen);
-
- wds_data_in_use[unit] = 0;
-
- if(!r->polled)
- {
- r->sxp->flags |= ITSDONE;
- scsi_done(r->sxp);
- }
-
- r->busy = 0;
-
- return 0;
-}
-
-static int
-wds_getvers(int unit)
-{
- struct wds_req *r;
- int base;
- u_char c;
- int i;
-
- base = wds[unit].addr;
-
- r = wdsr_alloc(unit);
- if(!r)
- {
- printf("wds%d: no request slot available!\n", unit);
- return -1;
- }
-
- r->done = 0;
- r->sxp = NULL;
-
- scsi_uto3b(KVTOPHYS(&r->cmd), wds[unit].ombs[r->ombn].addr);
-
- bzero(&r->cmd, sizeof r->cmd);
- r->cmd.cmd = WDSX_GETFIRMREV;
-
- outb(base+WDS_HCR, WDSH_DRQEN);
- r->polled = 1;
-
- c = WDSC_MSTART(r->ombn);
- if(wds_cmd(base, (u_char *)&c, sizeof c))
- {
- printf("wds%d: version request failed\n", unit);
- r->busy = 0;
- wds[unit].ombs[r->ombn].stat = 0;
- return -1;
- }
-
- while(1)
- {
- i = 0;
- while( (inb(base+WDS_STAT) & WDS_IRQ) == 0)
- {
- DELAY(9000);
- if(++i == 20)
- return -1;
- }
- wdsintr(unit);
- if(r->done)
- {
- printf("wds%d: firmware version %d.%02d\n", unit,
- r->cmd.targ, r->cmd.scb[0]);
- r->busy = 0;
- return 0;
- }
- }
-}
-
-int
-wdsattach(struct isa_device *dev)
-{
- int masunit;
- static u_long versprobe=0; /* max 32 controllers */
- int unit = dev->id_unit;
- struct scsibus_data *scbus;
-
- dev->id_ointr = wdsintr;
- masunit = dev->id_unit;
-
- if( !(versprobe & (1<<masunit)))
- {
- versprobe |= (1<<masunit);
- if(wds_getvers(masunit)==-1)
- printf("wds%d: getvers failed\n", masunit);
- }
-
- printf("wds%d: using %d bytes for dma buffer\n",unit,BUFSIZ);
-
- wds[unit].sc_link.adapter_unit = unit;
- wds[unit].sc_link.adapter_targ = 7;
- wds[unit].sc_link.adapter = &wds_switch;
- wds[unit].sc_link.device = &wds_dev;
- wds[unit].sc_link.flags = SDEV_BOUNCE;
-
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = scsi_alloc_bus();
- if(!scbus)
- return 0;
- scbus->adapter_link = &wds[unit].sc_link;
-
- scsi_attachdevs(scbus);
-
- return 1;
-}
-
-int
-wds_init(struct isa_device *dev)
-{
- struct wds_setup init;
- int base;
- int unit, i;
- struct wds_cmd wc;
-
- unit = dev->id_unit;
- base = wds[unit].addr;
-
- /*
- * Sending a command causes the CMDRDY bit to clear.
- */
-
- outb(base+WDS_CMD, WDSC_NOOP);
- if( inb(base+WDS_STAT) & WDS_RDY)
- return 1;
-
- /*
- * the controller exists. reset and init.
- */
- outb(base+WDS_HCR, WDSH_ASCRESET|WDSH_SCSIRESET);
- DELAY(30);
- outb(base+WDS_HCR, 0);
-
- outb(base+WDS_HCR, WDSH_DRQEN);
-
- isa_dmacascade(dev->id_drq);
-
- if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY)
- {
- for(i=0; i<10; i++)
- {
- if( (inb(base+WDS_STAT) & (WDS_RDY)) == WDS_RDY)
- break;
- DELAY(40000);
- }
- if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) /* probe timeout */
- return 1;
- }
-
- bzero(&init, sizeof init);
- init.cmd = WDSC_INIT;
- init.scsi_id = 7;
- init.buson_t = 24;
- init.busoff_t = 48;
- scsi_uto3b(KVTOPHYS(wds[unit].ombs), init.mbaddr);
- init.xx = 0;
- init.nomb = WDS_NOMB;
- init.nimb = WDS_NIMB;
-
- wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
- if( wds_cmd(base, (u_char *)&init, sizeof init) != 0)
- {
- printf("wds%d: wds_cmd failed\n", unit);
- return 1;
- }
-
- wds_wait(base+WDS_STAT, WDS_INIT, WDS_INIT);
-
- wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
-
- bzero(&wc,sizeof wc);
- wc.cmd = WDSC_DISUNSOL;
- if( wds_cmd(base, (char *)&wc, sizeof wc) != 0)
- {
- printf("wds%d: wds_cmd failed\n", unit);
- return 1;
- }
-
- return 0;
-}
-
-int
-wds_cmd(int base, u_char *p, int l)
-{
- int s=splbio();
-
- while(l--)
- {
- do
- {
- outb(base+WDS_CMD,*p);
- wds_wait(base+WDS_STAT,WDS_RDY,WDS_RDY);
- } while (inb(base+WDS_STAT) & WDS_REJ);
- p++;
- }
-
- wds_wait(base+WDS_STAT,WDS_RDY,WDS_RDY);
-
- splx(s);
-
- return 0;
-}
-
-void
-wds_wait(int reg, int mask, int val)
-{
- while((inb(reg) & mask) != val);
-}
-
-#endif
OpenPOWER on IntegriCloud