diff options
-rw-r--r-- | share/man/man4/Makefile | 4 | ||||
-rw-r--r-- | share/man/man4/man4.hppa/gsc.4 | 8 | ||||
-rw-r--r-- | share/man/man4/man4.hppa/intro.4 | 14 | ||||
-rw-r--r-- | share/man/man4/man4.hppa/io.4 | 9 | ||||
-rw-r--r-- | share/man/man4/oosiop.4 | 124 | ||||
-rw-r--r-- | share/man/man4/osiop.4 | 18 | ||||
-rw-r--r-- | share/man/man4/scsi.4 | 8 | ||||
-rw-r--r-- | share/man/man4/siop.4 | 12 | ||||
-rw-r--r-- | sys/arch/hppa/conf/GENERIC | 6 | ||||
-rw-r--r-- | sys/arch/hppa/conf/RAMDISK | 6 | ||||
-rw-r--r-- | sys/arch/hppa/conf/files.hppa | 5 | ||||
-rw-r--r-- | sys/arch/hppa/gsc/oosiop_gsc.c | 169 | ||||
-rw-r--r-- | sys/arch/hppa/gsc/osiop_gsc.c | 26 | ||||
-rw-r--r-- | sys/dev/ic/oosiop.c | 1378 | ||||
-rw-r--r-- | sys/dev/ic/oosiopreg.h | 324 | ||||
-rw-r--r-- | sys/dev/ic/oosiopvar.h | 164 | ||||
-rw-r--r-- | sys/dev/microcode/siop/Makefile | 11 | ||||
-rw-r--r-- | sys/dev/microcode/siop/ncr53cxxx.c | 10 | ||||
-rw-r--r-- | sys/dev/microcode/siop/oosiop.ss | 150 |
19 files changed, 2392 insertions, 54 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 0fc31321be8..ffd72d40495 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.255 2004/03/06 03:40:24 krw Exp $ +# $OpenBSD: Makefile,v 1.256 2004/03/12 00:04:51 miod Exp $ MAN= aac.4 ac97.4 acphy.4 addcom.4 adv.4 aha.4 ahb.4 ahc.4 \ aic.4 amdpm.4 ami.4 amphy.4 an.4 aria.4 ast.4 atalk.4 \ @@ -19,7 +19,7 @@ MAN= aac.4 ac97.4 acphy.4 addcom.4 adv.4 aha.4 ahb.4 ahc.4 \ mii.4 mpt.4 mpu.4 mtd.4 mtdphy.4 mtio.4 ncr.4 ne.4 neo.4 \ netintro.4 nge.4 noct.4 nofn.4 ns.4 nsclpcsio.4 nsgphy.4 \ nsip.4 nsphy.4 nsphyter.4 null.4 ohci.4 opl.4 options.4 \ - osiop.4 pcdisplay.4 pchb.4 pci.4 pciide.4 pckbc.4 \ + oosiop.4 osiop.4 pcdisplay.4 pchb.4 pci.4 pciide.4 pckbc.4 \ pckbd.4 pcmcia.4 pcppi.4 pcscp.4 pf.4 pflog.4 pfsync.4 \ pms.4 ppb.4 ppp.4 pty.4 puc.4 qsphy.4 radio.4 raid.4 \ random.4 ray.4 rd.4 rl.4 rln.4 rlphy.4 route.4 rt.4 \ diff --git a/share/man/man4/man4.hppa/gsc.4 b/share/man/man4/man4.hppa/gsc.4 index 63c00eac70e..56582cf5714 100644 --- a/share/man/man4/man4.hppa/gsc.4 +++ b/share/man/man4/man4.hppa/gsc.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: gsc.4,v 1.17 2003/06/19 20:27:19 deraadt Exp $ +.\" $OpenBSD: gsc.4,v 1.18 2004/03/12 00:04:56 miod Exp $ .\" .\" .\" Copyright (c) 1999 Michael Shalayeff @@ -78,8 +78,12 @@ Human Interface Loop, for HP-proprietary input devices like keyboard and mice. Intel i82596 DX/CA 32-bit LAN coprocessor. .It Xr lpt 4 Centronics printer port. +.It Xr oosiop 4 +.Tn Symbios/NCR +53C700 SCSI I/O Processor. .It Xr osiop 4 -SCSI I/O processor. +.Tn Symbios/NCR +53C710 SCSI I/O Processor. .El .Pp Some of these diff --git a/share/man/man4/man4.hppa/intro.4 b/share/man/man4/man4.hppa/intro.4 index 0ef2a30d8f7..98c3780be09 100644 --- a/share/man/man4/man4.hppa/intro.4 +++ b/share/man/man4/man4.hppa/intro.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: intro.4,v 1.2 2004/01/15 15:10:00 mickey Exp $ +.\" $OpenBSD: intro.4,v 1.3 2004/03/12 00:04:56 miod Exp $ .\" .\" Copyright (c) 2002,2003 Paul Weissmann .\" All rights reserved. @@ -247,10 +247,12 @@ The Centronics printer port. The .Xr eisa 4 bus controller on most of the older 700 machines. +.It Xr oosiop 4 +.Tn Symbios/NCR +53C700 SCSI I/O processor. .It Xr osiop 4 -The -.Tn NCR 53c7x0 SCSI -I/O processor. +.Tn Symbios/NCR +53C710 SCSI I/O processor. .It Xr pdc 4 The PROM interface, allows to call the routines in the machine's PROM for things like initial console output and such. @@ -258,8 +260,8 @@ PROM for things like initial console output and such. The power button interface allowing graceful shutdown of the system should being depressed on the running system. .It Xr siop 4 -.Tn LSI/Symbios Logic/NCR 53c8xx SCSI -I/O processor. +.Tn LSI/Symbios Logic/NCR +53C8xx SCSI I/O processor. .It Xr sti 4 The system graphics driver. .It Xr wax 4 diff --git a/share/man/man4/man4.hppa/io.4 b/share/man/man4/man4.hppa/io.4 index 540f7505631..e43753a4550 100644 --- a/share/man/man4/man4.hppa/io.4 +++ b/share/man/man4/man4.hppa/io.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: io.4,v 1.4 2004/01/15 19:37:52 jmc Exp $ +.\" $OpenBSD: io.4,v 1.5 2004/03/12 00:04:56 miod Exp $ .\" .\" Copyright (c) 2003,2004 Paul Weissmann .\" All rights reserved. @@ -92,9 +92,11 @@ SCSI bus configuration: .Pp .Bl -tag -width XXXX -compact -offset indent .It SE +.Xr oosiop 4 +or .Xr osiop 4 ; -.Tn NCR53C700/710 -8-bit (fast) single-ended, +.Tn Symbios/NCR +53C700/710 8-bit (fast) single-ended, .It FWD .Xr siop 4 ; .Tn NCR53C720 @@ -135,6 +137,7 @@ Formac+ FDDI, .Xr ie 4 , .Xr intro 4 , .Xr lasi 4 , +.Xr oosiop 4 , .Xr osiop 4 , .Xr siop 4 , .Xr sti 4 , diff --git a/share/man/man4/oosiop.4 b/share/man/man4/oosiop.4 new file mode 100644 index 00000000000..b00cbc4e168 --- /dev/null +++ b/share/man/man4/oosiop.4 @@ -0,0 +1,124 @@ +.\" $OpenBSD: oosiop.4,v 1.1 2004/03/12 00:04:51 miod Exp $ +.\" $NetBSD: osiop.4,v 1.2 2001/09/22 01:44:55 wiz Exp $ +.\" +.\" Copyright (c) 2001 Izumi Tsutsui. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd March 12, 2004 +.Dt OOSIOP 4 +.Os +.Sh NAME +.Nm oosiop +.Nd Symbios/NCR 53C700 SCSI driver +.Sh SYNOPSIS +.Cd "# hppa" +.Cd "oosiop* at gsc? irq 9" +.Pp +.Cd "scsibus* at oosiop?" +.Sh DESCRIPTION +The +.Nm +driver provides support for the +.Tn Symbios/NCR +53C700 +.Tn SCSI +controller chip. +.Pp +The +.Tn Symbios/NCR +53C710 +.Tn SCSI +controller is handled by the +.Xr osiop 4 +driver, while the +.Tn Symbios/NCR +53C8xx +.Tn PCI +.Tn SCSI +host adapters are handled by the +.Xr siop 4 +driver. +.\" .Sh CONFIGURATION +.\" The +.\" .Nm +.\" driver supports the following +.\" .Sy flags +.\" for use in +.\" .Xr config 8 +.\" files: +.\" .Pp +.\" .Bl -tag -compact -width "bits 8-15:" +.\" .It bits 0-7 : +.\" disable disconnect/reselect for the corresponding +.\" .Tn SCSI +.\" target +.\" .It bits 8-15 : +.\" disable synchronous negotiation for +.\" .Tn SCSI +.\" target +.\" .It bits 16 : +.\" disable DMA interrupts +.\" .El +.\" .Pp +.\" .Qq Target +.\" is synonymous with +.\" .Tn SCSI +.\" ID number. +.\" .Pp +.\" Note that +.\" .Tn SCSI +.\" tape drives should be allowed to perform disconnect/reselect or performance +.\" will suffer. +.\" .Sh BUGS +.\" Neither +.\" .Tn DMA +.\" or synchronous data transfers are currently supported. +.Sh SEE ALSO +.Xr cd 4 , +.Xr ch 4 , +.Xr intro 4 , +.Xr osiop 4 , +.Xr scsi 4 , +.Xr sd 4 , +.Xr siop 4 , +.Xr ss 4 , +.Xr st 4 , +.Xr uk 4 +.Pp +.Pa http://www.lsilogic.com/techlib/techdocs/storage_stand_prod/ +.Sh HISTORY +.Nm +driver first appeared in +.Nx 1.6 , +and was ported to +.Ox 3.5 . +.Pp +The original +.Tn NCR +53C710 +driver appeared in +.Nx +1.0 amiga port, and Izumi Tsutsui +.Aq tsutsui@ceres.dti.ne.jp +modified the driver and made it machine-independent. diff --git a/share/man/man4/osiop.4 b/share/man/man4/osiop.4 index f8fbe41b2d0..8eb266bb6ea 100644 --- a/share/man/man4/osiop.4 +++ b/share/man/man4/osiop.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: osiop.4,v 1.3 2003/06/19 20:29:51 deraadt Exp $ +.\" $OpenBSD: osiop.4,v 1.4 2004/03/12 00:04:51 miod Exp $ .\" $NetBSD: osiop.4,v 1.2 2001/09/22 01:44:55 wiz Exp $ .\" .\" Copyright (c) 2001 Izumi Tsutsui. All rights reserved. @@ -25,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd May 12, 2001 +.Dd March 12, 2004 .Dt OSIOP 4 .Os .Sh NAME @@ -33,8 +33,7 @@ .Nd Symbios/NCR 53C710 SCSI driver .Sh SYNOPSIS .Cd "# hppa" -.Cd "osiop0 at gsc? irq 9" -.Cd "osiop1 at gsc? irq 3" +.Cd "osiop* at gsc? irq 9" .Pp .Cd "scsibus* at osiop?" .Sh DESCRIPTION @@ -46,18 +45,18 @@ driver provides support for the .Tn SCSI controller chip. .Pp -This driver does not support the +The .Tn Symbios/NCR 53C700 .Tn SCSI -controller. -.Pp -For the +controller is handled by the +.Xr oosiop 4 +driver, while the .Tn Symbios/NCR 53C8xx .Tn PCI .Tn SCSI -host adapters, use the +host adapters are handled by the .Xr siop 4 driver. .Sh CONFIGURATION @@ -99,6 +98,7 @@ will suffer. .Xr cd 4 , .Xr ch 4 , .Xr intro 4 , +.Xr oosiop 4 , .Xr scsi 4 , .Xr sd 4 , .Xr siop 4 , diff --git a/share/man/man4/scsi.4 b/share/man/man4/scsi.4 index d6a8c112cd3..4eeb6e08df6 100644 --- a/share/man/man4/scsi.4 +++ b/share/man/man4/scsi.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: scsi.4,v 1.15 2004/03/08 18:24:35 miod Exp $ +.\" $OpenBSD: scsi.4,v 1.16 2004/03/12 00:04:51 miod Exp $ .\" .\" Copyright (c) 1996 .\" Julian Elischer <julian@freebsd.org>. All rights reserved. @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 4, 1996 +.Dd March 12, 2004 .Dt SCSI 4 .Os .Sh NAME @@ -51,6 +51,8 @@ .Cd "scsibus at isp?" .Cd "scsibus at mpt?" .Cd "scsibus at ncr?" +.Cd "scsibus at oosiop?" +.Cd "scsibus at osiop?" .Cd "scsibus at pcscp?" .Cd "scsibus at siop?" .Cd "scsibus at trm?" @@ -221,6 +223,8 @@ shows more detailed information including DMA scatter-gather logs. .Xr isp 4 , .Xr mpt 4 , .Xr ncr 4 , +.Xr oosiop 4 , +.Xr osiop 4 , .Xr pcscp 4 , .Xr sd 4 , .Xr ses 4 , diff --git a/share/man/man4/siop.4 b/share/man/man4/siop.4 index ff2d00947f9..dc91a2797a0 100644 --- a/share/man/man4/siop.4 +++ b/share/man/man4/siop.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: siop.4,v 1.8 2003/06/06 10:29:41 jmc Exp $ +.\" $OpenBSD: siop.4,v 1.9 2004/03/12 00:04:51 miod Exp $ .\" $NetBSD: siop.4,v 1.3 2000/10/23 16:38:10 bouyer Exp $ .\" .\" Copyright (c) 2000 Manuel Bouyer. @@ -30,7 +30,7 @@ .\" INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd May 15, 2000 +.Dd March 12, 2004 .Dt SIOP 4 .Os .Sh NAME @@ -90,11 +90,19 @@ supports at most Ultra2-Wide with this chip) replaces the older .Nm ncr driver which supported most of these devices. +.Pp +Older 53C700 and 53C710 controllers are supported by the +.Xr oosiop 4 +and +.Xr osiop 4 +drivers, respectively. .Sh SEE ALSO .Xr cd 4 , .Xr ch 4 , .Xr intro 4 , .Xr ncr 4 , +.Xr oosiop 4 , +.Xr osiop 4 , .Xr pci 4 , .Xr scsi 4 , .Xr sd 4 , diff --git a/sys/arch/hppa/conf/GENERIC b/sys/arch/hppa/conf/GENERIC index c9e80bb2ee2..69f9c4be934 100644 --- a/sys/arch/hppa/conf/GENERIC +++ b/sys/arch/hppa/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.47 2004/02/26 02:29:56 mickey Exp $ +# $OpenBSD: GENERIC,v 1.48 2004/03/12 00:04:56 miod Exp $ # Machine architecture; required by config(8) machine hppa @@ -97,9 +97,11 @@ ie0 at gsc0 irq 8 # 82C596DX/CA ether #ie* at isa? port 0x300 irq 10 #ie* at pci? dev ? function ? #tms* at gsc? irq 10 # TMS380C26 Network Controller -osiop* at gsc? irq 9 # NCR 53C700/710 (Narrow SE) +osiop* at gsc? irq 9 # NCR 53C710 (Narrow SE) #osiop* at eisa? slot ? scsibus* at osiop? +oosiop* at gsc? disable irq 9 # NCR 53C700 (Narrow SE) +scsibus* at oosiop? harmony* at gsc? irq 13 # Audio Type 2 (CS4215/AD1849) audio* at harmony? gsckbc* at gsc? irq 26 diff --git a/sys/arch/hppa/conf/RAMDISK b/sys/arch/hppa/conf/RAMDISK index d04a4e8a6de..130806ac265 100644 --- a/sys/arch/hppa/conf/RAMDISK +++ b/sys/arch/hppa/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.26 2003/12/29 23:27:04 mickey Exp $ +# $OpenBSD: RAMDISK,v 1.27 2004/03/12 00:04:57 miod Exp $ # # Diskless kernel config # @@ -112,9 +112,11 @@ ie0 at gsc0 irq 8 # 82C596DX/CA ether #ie* at isa? port 0x300 irq 10 #ie* at pci? dev ? function ? #tms* at gsc? irq 10 # TMS380C26 Network Controller -osiop* at gsc? irq 9 # NCR 53C700/710 (Narrow SE) +osiop* at gsc? irq 9 # NCR 53C710 (Narrow SE) #osiop* at eisa? slot ? scsibus* at osiop? +oosiop* at gsc? disable irq 9 # NCR 53C700 (Narrow SE) +scsibus* at oosiop? #harmony* at gsc? irq 13 # Audio Type 2 (CS4215/AD1849) #audio* at harmony? gsckbc* at gsc? irq 26 diff --git a/sys/arch/hppa/conf/files.hppa b/sys/arch/hppa/conf/files.hppa index 23f3a60e089..4021d88bdec 100644 --- a/sys/arch/hppa/conf/files.hppa +++ b/sys/arch/hppa/conf/files.hppa @@ -1,4 +1,4 @@ -# $OpenBSD: files.hppa,v 1.50 2004/02/13 20:39:31 mickey Exp $ +# $OpenBSD: files.hppa,v 1.51 2004/03/12 00:04:57 miod Exp $ # # hppa-specific configuration info @@ -191,6 +191,9 @@ file arch/hppa/gsc/if_ie_gsc.c ie_gsc attach osiop at gsc with osiop_gsc file arch/hppa/gsc/osiop_gsc.c osiop_gsc +attach oosiop at gsc with oosiop_gsc +file arch/hppa/gsc/oosiop_gsc.c oosiop_gsc + attach hil at gsc with hil_gsc file arch/hppa/gsc/hil_gsc.c hil_gsc diff --git a/sys/arch/hppa/gsc/oosiop_gsc.c b/sys/arch/hppa/gsc/oosiop_gsc.c new file mode 100644 index 00000000000..80cec2b516e --- /dev/null +++ b/sys/arch/hppa/gsc/oosiop_gsc.c @@ -0,0 +1,169 @@ +/* $OpenBSD: oosiop_gsc.c,v 1.1 2004/03/12 00:04:57 miod Exp $ */ +/* $NetBSD: oosiop_gsc.c,v 1.2 2003/07/15 02:29:25 lukem Exp $ */ + +/* + * Copyright (c) 2001 Matt Fredette. All rights reserved. + * Copyright (c) 2001,2002 Izumi Tsutsui. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 1998 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Michael Shalayeff. + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/buf.h> +#include <sys/malloc.h> + +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> + +#include <machine/cpu.h> +#include <machine/intr.h> +#include <machine/iomod.h> +#include <machine/autoconf.h> +#include <machine/bus.h> + +#include <dev/ic/oosiopreg.h> +#include <dev/ic/oosiopvar.h> + +#include <hppa/dev/cpudevs.h> +#include <hppa/gsc/gscbusvar.h> + +#define OOSIOP_GSC_RESET 0x0000 +#define OOSIOP_GSC_OFFSET 0x0100 + +int oosiop_gsc_match(struct device *, void *, void *); +void oosiop_gsc_attach(struct device *, struct device *, void *); +int oosiop_gsc_intr(void *); + +struct cfattach oosiop_gsc_ca = { + sizeof(struct oosiop_softc), oosiop_gsc_match, oosiop_gsc_attach +}; + +int +oosiop_gsc_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct gsc_attach_args *ga = aux; + + if (ga->ga_type.iodc_type != HPPA_TYPE_FIO || + ga->ga_type.iodc_sv_model != HPPA_FIO_SCSI) + return 0; + + return 1; +} + +void +oosiop_gsc_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct oosiop_softc *sc = (void *)self; + struct gsc_attach_args *ga = aux; + bus_space_handle_t ioh; + + sc->sc_bst = ga->ga_iot; + sc->sc_dmat = ga->ga_dmatag; + if (bus_space_map(sc->sc_bst, ga->ga_hpa, + OOSIOP_GSC_OFFSET + OOSIOP_NREGS, 0, &ioh)) + panic("oosiop_gsc_attach: couldn't map I/O ports"); + if (bus_space_subregion(sc->sc_bst, ioh, + OOSIOP_GSC_OFFSET, OOSIOP_NREGS, &sc->sc_bsh)) + panic("oosiop_gsc_attach: couldn't get chip ports"); + + sc->sc_freq = ga->ga_ca.ca_pdc_iodc_read->filler2[14]; + if (!sc->sc_freq) + sc->sc_freq = 50 * 1000000; + + sc->sc_chip = OOSIOP_700; + sc->sc_id = 7; /* XXX */ + + /* + * Reset the SCSI subsystem. + */ + bus_space_write_1(sc->sc_bst, ioh, OOSIOP_GSC_RESET, 0); + DELAY(1000); + + /* + * Call common attachment + */ +#ifdef OOSIOP_DEBUG + { + extern int oosiop_debug; + oosiop_debug = -1; + } +#endif /* OOSIOP_DEBUG */ + oosiop_attach(sc); + + (void)gsc_intr_establish((struct gsc_softc *)parent, + ga->ga_irq, IPL_BIO, oosiop_gsc_intr, sc, sc->sc_dev.dv_xname); +} + +/* + * interrupt handler + */ +int +oosiop_gsc_intr(arg) + void *arg; +{ + struct oosiop_softc *sc = arg; + int rv; + + rv = oosiop_intr(sc); + +#ifdef USELEDS + ledctl(PALED_DISK, 0, 0); +#endif + + return (rv); +} diff --git a/sys/arch/hppa/gsc/osiop_gsc.c b/sys/arch/hppa/gsc/osiop_gsc.c index f9b879148a0..c928bdd5dd0 100644 --- a/sys/arch/hppa/gsc/osiop_gsc.c +++ b/sys/arch/hppa/gsc/osiop_gsc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: osiop_gsc.c,v 1.10 2004/02/13 21:28:19 mickey Exp $ */ +/* $OpenBSD: osiop_gsc.c,v 1.11 2004/03/12 00:04:57 miod Exp $ */ /* $NetBSD: osiop_gsc.c,v 1.6 2002/10/02 05:17:50 thorpej Exp $ */ /* @@ -79,7 +79,7 @@ #include <hppa/gsc/gscbusvar.h> /* #include <hppa/hppa/machdep.h> */ -#define OSIOP_GSC_RESET 0x0000 +#define OSIOP_GSC_RESET 0x0000 #define OSIOP_GSC_OFFSET 0x0100 int osiop_gsc_match(struct device *, void *, void *); @@ -98,8 +98,7 @@ osiop_gsc_match(parent, match, aux) struct gsc_attach_args *ga = aux; if (ga->ga_type.iodc_type != HPPA_TYPE_FIO || - (ga->ga_type.iodc_sv_model != HPPA_FIO_GSCSI /* && - ga->ga_type.iodc_sv_model != HPPA_FIO_SCSI */)) + ga->ga_type.iodc_sv_model != HPPA_FIO_GSCSI) return 0; return 1; @@ -117,27 +116,20 @@ osiop_gsc_attach(parent, self, aux) sc->sc_bst = ga->ga_iot; sc->sc_dmat = ga->ga_dmatag; if (bus_space_map(sc->sc_bst, ga->ga_hpa, - OSIOP_GSC_OFFSET + OSIOP_NREGS, 0, &ioh)) + OSIOP_GSC_OFFSET + OSIOP_NREGS, 0, &ioh)) panic("osiop_gsc_attach: couldn't map I/O ports"); if (bus_space_subregion(sc->sc_bst, ioh, - OSIOP_GSC_OFFSET, OSIOP_NREGS, &sc->sc_reg)) + OSIOP_GSC_OFFSET, OSIOP_NREGS, &sc->sc_reg)) panic("osiop_gsc_attach: couldn't get chip ports"); sc->sc_clock_freq = ga->ga_ca.ca_pdc_iodc_read->filler2[14] / 1000000; if (!sc->sc_clock_freq) sc->sc_clock_freq = 50; - if (ga->ga_ca.ca_type.iodc_sv_model == HPPA_FIO_GSCSI) { - sc->sc_dcntl = OSIOP_DCNTL_EA; - /* XXX set burst mode to 8 words (32 bytes) */ - sc->sc_ctest7 = OSIOP_CTEST7_CDIS; - sc->sc_dmode = OSIOP_DMODE_BL8; /* | OSIOP_DMODE_FC2 */ - } else { - sc->sc_dcntl = 0; - sc->sc_ctest7 = 0; - sc->sc_dmode = 0; /* | OSIOP_DMODE_FC2 */ - } - + sc->sc_dcntl = OSIOP_DCNTL_EA; + /* XXX set burst mode to 8 words (32 bytes) */ + sc->sc_ctest7 = OSIOP_CTEST7_CDIS; + sc->sc_dmode = OSIOP_DMODE_BL8; /* | OSIOP_DMODE_FC2 */ sc->sc_flags = 0; sc->sc_id = 7; /* XXX */ diff --git a/sys/dev/ic/oosiop.c b/sys/dev/ic/oosiop.c new file mode 100644 index 00000000000..dc633457488 --- /dev/null +++ b/sys/dev/ic/oosiop.c @@ -0,0 +1,1378 @@ +/* $OpenBSD: oosiop.c,v 1.1 2004/03/12 00:04:57 miod Exp $ */ +/* $NetBSD: oosiop.c,v 1.4 2003/10/29 17:45:55 tsutsui Exp $ */ + +/* + * Copyright (c) 2001 Shuichiro URATA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NCR53C700 SCSI I/O processor (OOSIOP) driver + * + * TODO: + * - More better error handling. + * - Implement tagged queuing. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/timeout.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/buf.h> +#include <sys/malloc.h> +#include <sys/queue.h> + +#include <uvm/uvm_extern.h> + +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> +#include <scsi/scsi_message.h> + +#include <machine/cpu.h> +#include <machine/bus.h> + +#include <dev/ic/oosiopreg.h> +#include <dev/ic/oosiopvar.h> + +/* 53C700 script */ +#include <dev/microcode/siop/oosiop.out> + +int oosiop_alloc_cb(struct oosiop_softc *, int); + +static __inline void oosiop_relocate_io(struct oosiop_softc *, bus_addr_t); +static __inline void oosiop_relocate_tc(struct oosiop_softc *, bus_addr_t); +static __inline void oosiop_fixup_select(struct oosiop_softc *, bus_addr_t, + int); +static __inline void oosiop_fixup_jump(struct oosiop_softc *, bus_addr_t, + bus_addr_t); +static __inline void oosiop_fixup_move(struct oosiop_softc *, bus_addr_t, + bus_size_t, bus_addr_t); + +void oosiop_load_script(struct oosiop_softc *); +void oosiop_setup_sgdma(struct oosiop_softc *, struct oosiop_cb *); +void oosiop_setup_dma(struct oosiop_softc *); +void oosiop_flush_fifo(struct oosiop_softc *); +void oosiop_clear_fifo(struct oosiop_softc *); +void oosiop_phasemismatch(struct oosiop_softc *); +void oosiop_setup_syncxfer(struct oosiop_softc *); +void oosiop_set_syncparam(struct oosiop_softc *, int, int, int); +void oosiop_minphys(struct buf *); +int oosiop_scsicmd(struct scsi_xfer *); +void oosiop_done(struct oosiop_softc *, struct oosiop_cb *); +void oosiop_timeout(void *); +void oosiop_reset(struct oosiop_softc *); +void oosiop_reset_bus(struct oosiop_softc *); +void oosiop_scriptintr(struct oosiop_softc *); +void oosiop_msgin(struct oosiop_softc *, struct oosiop_cb *); + +/* Trap interrupt code for unexpected data I/O */ +#define DATAIN_TRAP 0xdead0001 +#define DATAOUT_TRAP 0xdead0002 + +/* Possible TP and SCF conbination */ +static const struct { + u_int8_t tp; + u_int8_t scf; +} synctbl[] = { + {0, 1}, /* SCLK / 4.0 */ + {1, 1}, /* SCLK / 5.0 */ + {2, 1}, /* SCLK / 6.0 */ + {3, 1}, /* SCLK / 7.0 */ + {1, 2}, /* SCLK / 7.5 */ + {4, 1}, /* SCLK / 8.0 */ + {5, 1}, /* SCLK / 9.0 */ + {6, 1}, /* SCLK / 10.0 */ + {3, 2}, /* SCLK / 10.5 */ + {7, 1}, /* SCLK / 11.0 */ + {4, 2}, /* SCLK / 12.0 */ + {5, 2}, /* SCLK / 13.5 */ + {3, 3}, /* SCLK / 14.0 */ + {6, 2}, /* SCLK / 15.0 */ + {4, 3}, /* SCLK / 16.0 */ + {7, 2}, /* SCLK / 16.5 */ + {5, 3}, /* SCLK / 18.0 */ + {6, 3}, /* SCLK / 20.0 */ + {7, 3} /* SCLK / 22.0 */ +}; +#define NSYNCTBL (sizeof(synctbl) / sizeof(synctbl[0])) + +#define oosiop_period(sc, tp, scf) \ + (((1000000000 / (sc)->sc_freq) * (tp) * (scf)) / 40) + +struct cfdriver oosiop_cd = { + NULL, "oosiop", DV_DULL +}; + +struct scsi_adapter oosiop_adapter = { + oosiop_scsicmd, + oosiop_minphys, + NULL, + NULL +}; + +struct scsi_device oosiop_dev = { + NULL, + NULL, + NULL, + NULL +}; + +void +oosiop_attach(struct oosiop_softc *sc) +{ + bus_size_t scrsize; + bus_dma_segment_t seg; + struct oosiop_cb *cb; + int err, i, nseg; + + /* + * Allocate DMA-safe memory for the script and map it. + */ + scrsize = round_page(sizeof(oosiop_script)); + err = bus_dmamem_alloc(sc->sc_dmat, scrsize, PAGE_SIZE, 0, &seg, 1, + &nseg, BUS_DMA_NOWAIT); + if (err) { + printf(": failed to allocate script memory, err=%d\n", err); + return; + } + err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, scrsize, + (caddr_t *)&sc->sc_scr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT); + if (err) { + printf(": failed to map script memory, err=%d\n", err); + return; + } + err = bus_dmamap_create(sc->sc_dmat, scrsize, 1, scrsize, 0, + BUS_DMA_NOWAIT, &sc->sc_scrdma); + if (err) { + printf(": failed to create script map, err=%d\n", err); + return; + } + err = bus_dmamap_load(sc->sc_dmat, sc->sc_scrdma, sc->sc_scr, scrsize, + NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE); + if (err) { + printf(": failed to load script map, err=%d\n", err); + return; + } + bzero(sc->sc_scr, scrsize); + sc->sc_scrbase = sc->sc_scrdma->dm_segs[0].ds_addr; + + /* Initialize command block array */ + TAILQ_INIT(&sc->sc_free_cb); + TAILQ_INIT(&sc->sc_cbq); + if (oosiop_alloc_cb(sc, OOSIOP_NCB) != 0) + return; + + /* Use first cb to reselection msgin buffer */ + cb = TAILQ_FIRST(&sc->sc_free_cb); + sc->sc_reselbuf = cb->xferdma->dm_segs[0].ds_addr + + offsetof(struct oosiop_xfer, msgin[0]); + + for (i = 0; i < OOSIOP_NTGT; i++) { + sc->sc_tgt[i].nexus = NULL; + sc->sc_tgt[i].flags = 0; + } + + /* Setup asynchronous clock divisor parameters */ + if (sc->sc_freq <= 25000000) { + sc->sc_ccf = 10; + sc->sc_dcntl = OOSIOP_DCNTL_CF_1; + } else if (sc->sc_freq <= 37500000) { + sc->sc_ccf = 15; + sc->sc_dcntl = OOSIOP_DCNTL_CF_1_5; + } else if (sc->sc_freq <= 50000000) { + sc->sc_ccf = 20; + sc->sc_dcntl = OOSIOP_DCNTL_CF_2; + } else { + sc->sc_ccf = 30; + sc->sc_dcntl = OOSIOP_DCNTL_CF_3; + } + + if (sc->sc_chip == OOSIOP_700) + sc->sc_minperiod = oosiop_period(sc, 4, sc->sc_ccf); + else + sc->sc_minperiod = oosiop_period(sc, 4, 10); + + if (sc->sc_minperiod < 25) + sc->sc_minperiod = 25; /* limit to 10MB/s */ + + printf(": NCR53C700%s rev %d, %dMHz, SCSI ID %d\n", + sc->sc_chip == OOSIOP_700_66 ? "-66" : "", + oosiop_read_1(sc, OOSIOP_CTEST7) >> 4, + sc->sc_freq / 1000000, sc->sc_id); + /* + * Reset all + */ + oosiop_reset(sc); + oosiop_reset_bus(sc); + + /* + * Start SCRIPTS processor + */ + oosiop_load_script(sc); + sc->sc_active = 0; + oosiop_write_4(sc, OOSIOP_DSP, sc->sc_scrbase + Ent_wait_reselect); + + /* + * Fill in the sc_link. + */ + sc->sc_link.adapter = &oosiop_adapter; + sc->sc_link.adapter_softc = sc; + sc->sc_link.device = &oosiop_dev; + sc->sc_link.openings = 4; + sc->sc_link.adapter_buswidth = OOSIOP_NTGT; + sc->sc_link.adapter_target = sc->sc_id; + sc->sc_link.quirks = ADEV_NODOORLOCK; + + /* + * Now try to attach all the sub devices. + */ + config_found(&sc->sc_dev, &sc->sc_link, scsiprint); +} + +int +oosiop_alloc_cb(struct oosiop_softc *sc, int ncb) +{ + struct oosiop_cb *cb; + struct oosiop_xfer *xfer; + bus_size_t xfersize; + bus_dma_segment_t seg; + int i, s, err, nseg; + + /* + * Allocate oosiop_cb. + */ + cb = malloc(sizeof(struct oosiop_cb) * ncb, M_DEVBUF, M_NOWAIT); + if (cb == NULL) { + printf(": failed to allocate cb memory\n"); + return (ENOMEM); + } + bzero(cb, sizeof(struct oosiop_cb) * ncb); + + /* + * Allocate DMA-safe memory for the oosiop_xfer and map it. + */ + xfersize = sizeof(struct oosiop_xfer) * ncb; + err = bus_dmamem_alloc(sc->sc_dmat, xfersize, PAGE_SIZE, 0, &seg, 1, + &nseg, BUS_DMA_NOWAIT); + if (err) { + printf(": failed to allocate xfer block memory, err=%d\n", err); + return (err); + } + err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, xfersize, + (caddr_t *)(void *)&xfer, BUS_DMA_NOWAIT | BUS_DMA_COHERENT); + if (err) { + printf(": failed to map xfer block memory, err=%d\n", err); + return (err); + } + + /* Initialize each command block */ + for (i = 0; i < ncb; i++) { + err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, + 0, BUS_DMA_NOWAIT, &cb->cmddma); + if (err) { + printf(": failed to create cmddma map, err=%d\n", err); + return (err); + } + + err = bus_dmamap_create(sc->sc_dmat, OOSIOP_MAX_XFER, + OOSIOP_NSG, OOSIOP_DBC_MAX, 0, BUS_DMA_NOWAIT, + &cb->datadma); + if (err) { + printf(": failed to create datadma map, err=%d\n", err); + return (err); + } + + err = bus_dmamap_create(sc->sc_dmat, + sizeof(struct oosiop_xfer), 1, sizeof(struct oosiop_xfer), + 0, BUS_DMA_NOWAIT, &cb->xferdma); + if (err) { + printf(": failed to create xfer block map, err=%d\n", + err); + return (err); + } + err = bus_dmamap_load(sc->sc_dmat, cb->xferdma, xfer, + sizeof(struct oosiop_xfer), NULL, BUS_DMA_NOWAIT); + if (err) { + printf(": failed to load xfer block, err=%d\n", err); + return (err); + } + + cb->xfer = xfer; + + s = splbio(); + TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain); + splx(s); + + cb++; + xfer++; + } + + return (0); +} + +static __inline void +oosiop_relocate_io(struct oosiop_softc *sc, bus_addr_t addr) +{ + u_int32_t dcmd; + int32_t dsps; + + dcmd = letoh32(sc->sc_scr[addr / 4 + 0]); + dsps = letoh32(sc->sc_scr[addr / 4 + 1]); + + /* convert relative to absolute */ + if (dcmd & 0x04000000) { + dcmd &= ~0x04000000; +#if 0 + /* + * sign extension isn't needed here because + * ncr53cxxx.c generates 32 bit dsps. + */ + dsps <<= 8; + dsps >>= 8; +#endif + sc->sc_scr[addr / 4 + 0] = htole32(dcmd); + dsps += addr + 8; + } + + sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase); +} + +static __inline void +oosiop_relocate_tc(struct oosiop_softc *sc, bus_addr_t addr) +{ + u_int32_t dcmd; + int32_t dsps; + + dcmd = letoh32(sc->sc_scr[addr / 4 + 0]); + dsps = letoh32(sc->sc_scr[addr / 4 + 1]); + + /* convert relative to absolute */ + if (dcmd & 0x00800000) { + dcmd &= ~0x00800000; + sc->sc_scr[addr / 4] = htole32(dcmd); +#if 0 + /* + * sign extension isn't needed here because + * ncr53cxxx.c generates 32 bit dsps. + */ + dsps <<= 8; + dsps >>= 8; +#endif + dsps += addr + 8; + } + + sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase); +} + +static __inline void +oosiop_fixup_select(struct oosiop_softc *sc, bus_addr_t addr, int id) +{ + u_int32_t dcmd; + + dcmd = letoh32(sc->sc_scr[addr / 4]); + dcmd &= 0xff00ffff; + dcmd |= 0x00010000 << id; + sc->sc_scr[addr / 4] = htole32(dcmd); +} + +static __inline void +oosiop_fixup_jump(struct oosiop_softc *sc, bus_addr_t addr, bus_addr_t dst) +{ + + sc->sc_scr[addr / 4 + 1] = htole32(dst); +} + +static __inline void +oosiop_fixup_move(struct oosiop_softc *sc, bus_addr_t addr, bus_size_t dbc, + bus_addr_t dsps) +{ + u_int32_t dcmd; + + dcmd = letoh32(sc->sc_scr[addr / 4]); + dcmd &= 0xff000000; + dcmd |= dbc & 0x00ffffff; + sc->sc_scr[addr / 4 + 0] = htole32(dcmd); + sc->sc_scr[addr / 4 + 1] = htole32(dsps); +} + +void +oosiop_load_script(struct oosiop_softc *sc) +{ + int i; + + /* load script */ + for (i = 0; i < sizeof(oosiop_script) / sizeof(oosiop_script[0]); i++) + sc->sc_scr[i] = htole32(oosiop_script[i]); + + /* relocate script */ + for (i = 0; i < (sizeof(oosiop_script) / 8); i++) { + switch (oosiop_script[i * 2] >> 27) { + case 0x08: /* select */ + case 0x0a: /* wait reselect */ + oosiop_relocate_io(sc, i * 8); + break; + case 0x10: /* jump */ + case 0x11: /* call */ + oosiop_relocate_tc(sc, i * 8); + break; + } + } + + oosiop_fixup_move(sc, Ent_p_resel_msgin_move, 1, sc->sc_reselbuf); + OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE); +} + +void +oosiop_setup_sgdma(struct oosiop_softc *sc, struct oosiop_cb *cb) +{ + struct oosiop_xfer *xfer = cb->xfer; + struct scsi_xfer *xs = cb->xs; + int i, n, off; + + OOSIOP_XFERSCR_SYNC(sc, cb, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + off = cb->curdp; + + if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { + /* Find start segment */ + for (i = 0; i < cb->datadma->dm_nsegs; i++) { + if (off < cb->datadma->dm_segs[i].ds_len) + break; + off -= cb->datadma->dm_segs[i].ds_len; + } + + /* build MOVE block */ + if (xs->flags & SCSI_DATA_IN) { + n = 0; + while (i < cb->datadma->dm_nsegs) { + xfer->datain_scr[n * 2 + 0] = + htole32(0x09000000 | + (cb->datadma->dm_segs[i].ds_len - off)); + xfer->datain_scr[n * 2 + 1] = + htole32(cb->datadma->dm_segs[i].ds_addr + + off); + n++; + i++; + off = 0; + } + xfer->datain_scr[n * 2 + 0] = htole32(0x80080000); + xfer->datain_scr[n * 2 + 1] = + htole32(sc->sc_scrbase + Ent_phasedispatch); + } + if (xs->flags & SCSI_DATA_OUT) { + n = 0; + while (i < cb->datadma->dm_nsegs) { + xfer->dataout_scr[n * 2 + 0] = + htole32(0x08000000 | + (cb->datadma->dm_segs[i].ds_len - off)); + xfer->dataout_scr[n * 2 + 1] = + htole32(cb->datadma->dm_segs[i].ds_addr + + off); + n++; + i++; + off = 0; + } + xfer->dataout_scr[n * 2 + 0] = htole32(0x80080000); + xfer->dataout_scr[n * 2 + 1] = + htole32(sc->sc_scrbase + Ent_phasedispatch); + } + } + if ((xs->flags & SCSI_DATA_IN) == 0) { + xfer->datain_scr[0] = htole32(0x98080000); + xfer->datain_scr[1] = htole32(DATAIN_TRAP); + } + if ((xs->flags & SCSI_DATA_OUT) == 0) { + xfer->dataout_scr[0] = htole32(0x98080000); + xfer->dataout_scr[1] = htole32(DATAOUT_TRAP); + } + OOSIOP_XFERSCR_SYNC(sc, cb, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); +} + +/* + * Setup DMA pointer into script. + */ +void +oosiop_setup_dma(struct oosiop_softc *sc) +{ + struct oosiop_cb *cb; + bus_addr_t xferbase; + + cb = sc->sc_curcb; + xferbase = cb->xferdma->dm_segs[0].ds_addr; + + OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE); + + oosiop_fixup_select(sc, Ent_p_select, cb->id); + oosiop_fixup_jump(sc, Ent_p_datain_jump, xferbase + + offsetof(struct oosiop_xfer, datain_scr[0])); + oosiop_fixup_jump(sc, Ent_p_dataout_jump, xferbase + + offsetof(struct oosiop_xfer, dataout_scr[0])); + oosiop_fixup_move(sc, Ent_p_msgin_move, 1, xferbase + + offsetof(struct oosiop_xfer, msgin[0])); + oosiop_fixup_move(sc, Ent_p_extmsglen_move, 1, xferbase + + offsetof(struct oosiop_xfer, msgin[1])); + oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen, xferbase + + offsetof(struct oosiop_xfer, msgout[0])); + oosiop_fixup_move(sc, Ent_p_status_move, 1, xferbase + + offsetof(struct oosiop_xfer, status)); + oosiop_fixup_move(sc, Ent_p_cmdout_move, cb->xs->cmdlen, + cb->cmddma->dm_segs[0].ds_addr); + + OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE); +} + +void +oosiop_flush_fifo(struct oosiop_softc *sc) +{ + + oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) | + OOSIOP_DFIFO_FLF); + while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) != + OOSIOP_CTEST1_FMT) + ; + oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) & + ~OOSIOP_DFIFO_FLF); +} + +void +oosiop_clear_fifo(struct oosiop_softc *sc) +{ + + oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) | + OOSIOP_DFIFO_CLF); + while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) != + OOSIOP_CTEST1_FMT) + ; + oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) & + ~OOSIOP_DFIFO_CLF); +} + +void +oosiop_phasemismatch(struct oosiop_softc *sc) +{ + struct oosiop_cb *cb; + u_int32_t dsp, dbc, n, i, len; + u_int8_t dfifo, sstat1; + + cb = sc->sc_curcb; + if (cb == NULL) + return; + + dsp = oosiop_read_4(sc, OOSIOP_DSP); + dbc = oosiop_read_4(sc, OOSIOP_DBC) & OOSIOP_DBC_MAX; + len = 0; + + n = dsp - cb->xferdma->dm_segs[0].ds_addr - 8; + if (n >= offsetof(struct oosiop_xfer, datain_scr[0]) && + n < offsetof(struct oosiop_xfer, datain_scr[OOSIOP_NSG * 2])) { + n -= offsetof(struct oosiop_xfer, datain_scr[0]); + n >>= 3; + OOSIOP_DINSCR_SYNC(sc, cb, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + for (i = 0; i <= n; i++) + len += letoh32(cb->xfer->datain_scr[i * 2]) & + 0x00ffffff; + OOSIOP_DINSCR_SYNC(sc, cb, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + /* All data in the chip are already flushed */ + } else if (n >= offsetof(struct oosiop_xfer, dataout_scr[0]) && + n < offsetof(struct oosiop_xfer, dataout_scr[OOSIOP_NSG * 2])) { + n -= offsetof(struct oosiop_xfer, dataout_scr[0]); + n >>= 3; + OOSIOP_DOUTSCR_SYNC(sc, cb, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + for (i = 0; i <= n; i++) + len += letoh32(cb->xfer->dataout_scr[i * 2]) & + 0x00ffffff; + OOSIOP_DOUTSCR_SYNC(sc, cb, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + dfifo = oosiop_read_1(sc, OOSIOP_DFIFO); + dbc += ((dfifo & OOSIOP_DFIFO_BO) - (dbc & OOSIOP_DFIFO_BO)) & + OOSIOP_DFIFO_BO; + + sstat1 = oosiop_read_1(sc, OOSIOP_SSTAT1); + if (sstat1 & OOSIOP_SSTAT1_OLF) + dbc++; + if ((sc->sc_tgt[cb->id].sxfer != 0) && + (sstat1 & OOSIOP_SSTAT1_ORF) != 0) + dbc++; + + oosiop_clear_fifo(sc); + } else { + printf("%s: phase mismatch addr=%08x\n", sc->sc_dev.dv_xname, + oosiop_read_4(sc, OOSIOP_DSP) - 8); + oosiop_clear_fifo(sc); + return; + } + + len -= dbc; + if (len) { + cb->curdp += len; + oosiop_setup_sgdma(sc, cb); + } +} + +void +oosiop_setup_syncxfer(struct oosiop_softc *sc) +{ + int id; + + id = sc->sc_curcb->id; + if (sc->sc_chip != OOSIOP_700) + oosiop_write_1(sc, OOSIOP_SBCL, sc->sc_tgt[id].scf); + + oosiop_write_1(sc, OOSIOP_SXFER, sc->sc_tgt[id].sxfer); +} + +void +oosiop_set_syncparam(struct oosiop_softc *sc, int id, int period, int offset) +{ + int i, p; + + printf("%s: target %d now using 8 bit ", sc->sc_dev.dv_xname, id); + + if (offset == 0) { + /* Asynchronous */ + sc->sc_tgt[id].scf = 0; + sc->sc_tgt[id].sxfer = 0; + printf("asynchronous"); + } else { + /* Synchronous */ + if (sc->sc_chip == OOSIOP_700) { + for (i = 4; i < 12; i++) { + p = oosiop_period(sc, i, sc->sc_ccf); + if (p >= period) + break; + } + if (i == 12) { + printf("%s: target %d period too large\n", + sc->sc_dev.dv_xname, id); + i = 11; /* XXX */ + } + sc->sc_tgt[id].scf = 0; + sc->sc_tgt[id].sxfer = ((i - 4) << 4) | offset; + } else { + for (i = 0; i < NSYNCTBL; i++) { + p = oosiop_period(sc, synctbl[i].tp + 4, + (synctbl[i].scf + 1) * 5); + if (p >= period) + break; + } + if (i == NSYNCTBL) { + printf("%s: target %d period too large\n", + sc->sc_dev.dv_xname, id); + i = NSYNCTBL - 1; /* XXX */ + } + sc->sc_tgt[id].scf = synctbl[i].scf; + sc->sc_tgt[id].sxfer = (synctbl[i].tp << 4) | offset; + } + /* XXX print actual ns period... */ + printf(" synchronous"); + } + printf(" xfers\n"); +} + +void +oosiop_minphys(struct buf *bp) +{ + + if (bp->b_bcount > OOSIOP_MAX_XFER) + bp->b_bcount = OOSIOP_MAX_XFER; + minphys(bp); +} + +int +oosiop_scsicmd(struct scsi_xfer *xs) +{ + struct oosiop_softc *sc; + struct oosiop_cb *cb; + struct oosiop_xfer *xfer; + int s, err; + + sc = (struct oosiop_softc *)xs->sc_link->adapter_softc; + + s = splbio(); + cb = TAILQ_FIRST(&sc->sc_free_cb); + TAILQ_REMOVE(&sc->sc_free_cb, cb, chain); + splx(s); + + cb->xs = xs; + cb->xsflags = xs->flags; + cb->datalen = xs->datalen; + cb->flags = 0; + cb->id = xs->sc_link->target; + cb->lun = xs->sc_link->lun; + cb->curdp = 0; + cb->savedp = 0; + xfer = cb->xfer; + + /* Setup SCSI command buffer DMA */ + err = bus_dmamap_load(sc->sc_dmat, cb->cmddma, xs->cmd, + xs->cmdlen, NULL, ((xs->flags & SCSI_NOSLEEP) ? + BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | BUS_DMA_WRITE); + if (err) { + printf("%s: unable to load cmd DMA map: %d", + sc->sc_dev.dv_xname, err); + xs->error = XS_DRIVER_STUFFUP; + TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain); + scsi_done(xs); + return (COMPLETE); + } + bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, xs->cmdlen, + BUS_DMASYNC_PREWRITE); + + /* Setup data buffer DMA */ + if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { + err = bus_dmamap_load(sc->sc_dmat, cb->datadma, + xs->data, xs->datalen, NULL, + ((xs->flags & SCSI_NOSLEEP) ? + BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | + BUS_DMA_STREAMING | + ((xs->flags & SCSI_DATA_IN) ? BUS_DMA_READ : + BUS_DMA_WRITE)); + if (err) { + printf("%s: unable to load data DMA map: %d", + sc->sc_dev.dv_xname, err); + xs->error = XS_DRIVER_STUFFUP; + bus_dmamap_unload(sc->sc_dmat, cb->cmddma); + TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain); + scsi_done(xs); + return (COMPLETE); + } + bus_dmamap_sync(sc->sc_dmat, cb->datadma, + 0, xs->datalen, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + } + + oosiop_setup_sgdma(sc, cb); + + /* Setup msgout buffer */ + OOSIOP_XFERMSG_SYNC(sc, cb, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + xfer->msgout[0] = MSG_IDENTIFY(cb->lun, + (cb->xfer->scsi_cmd.opcode != REQUEST_SENSE)); + cb->msgoutlen = 1; + + if (sc->sc_tgt[cb->id].flags & TGTF_SYNCNEG) { + /* Send SDTR */ + xfer->msgout[1] = MSG_EXTENDED; + xfer->msgout[2] = MSG_EXT_SDTR_LEN; + xfer->msgout[3] = MSG_EXT_SDTR; + xfer->msgout[4] = sc->sc_minperiod; + xfer->msgout[5] = OOSIOP_MAX_OFFSET; + cb->msgoutlen = 6; + sc->sc_tgt[cb->id].flags &= ~TGTF_SYNCNEG; + sc->sc_tgt[cb->id].flags |= TGTF_WAITSDTR; + } + + xfer->status = SCSI_OOSIOP_NOSTATUS; + + OOSIOP_XFERMSG_SYNC(sc, cb, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + s = splbio(); + + /* + * Always initialize timeout so it does not contain trash + * that could confuse timeout_del(). + */ + timeout_set(&xs->stimeout, oosiop_timeout, cb); + + TAILQ_INSERT_TAIL(&sc->sc_cbq, cb, chain); + + if (!sc->sc_active) { + /* Abort script to start selection */ + oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT); + } + if (xs->flags & SCSI_POLL) { + /* Poll for command completion */ + while ((xs->flags & ITSDONE) == 0) { + delay(1000); + oosiop_intr(sc); + } + } else { + /* start expire timer */ + timeout_add(&xs->stimeout, (xs->timeout / 1000) * hz); + } + + splx(s); + + if ((xs->flags & ITSDONE) == 0) + return (SUCCESSFULLY_QUEUED); + else + return (COMPLETE); +} + +void +oosiop_done(struct oosiop_softc *sc, struct oosiop_cb *cb) +{ + struct scsi_xfer *xs; + struct scsi_link *periph; + int autosense; + + xs = cb->xs; + periph = xs->sc_link; + + /* + * Record if this is the completion of an auto sense + * scsi command, and then reset the flag so we don't loop + * when such a command fails or times out. + */ + autosense = cb->flags & CBF_AUTOSENSE; + cb->flags &= ~CBF_AUTOSENSE; + + if (cb == sc->sc_curcb) + sc->sc_curcb = NULL; + if (cb == sc->sc_lastcb) + sc->sc_lastcb = NULL; + sc->sc_tgt[cb->id].nexus = NULL; + + if (cb->datalen > 0) { + bus_dmamap_sync(sc->sc_dmat, cb->datadma, 0, xs->datalen, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->sc_dmat, cb->datadma); + } + + timeout_del(&xs->stimeout); + + xs->status = cb->xfer->status; + + if (cb->flags & CBF_SELTOUT) + xs->error = XS_SELTIMEOUT; + else if (cb->flags & CBF_TIMEOUT) + xs->error = XS_TIMEOUT; + else switch (xs->status) { + case SCSI_OK: + if (autosense == 0) + xs->error = XS_NOERROR; + else + xs->error = XS_SENSE; + break; + + case SCSI_BUSY: + xs->error = XS_BUSY; + break; + case SCSI_CHECK: + if (autosense == 0) + cb->flags |= CBF_AUTOSENSE; + else + xs->error = XS_DRIVER_STUFFUP; + break; + case SCSI_OOSIOP_NOSTATUS: + /* the status byte was not updated, cmd was aborted. */ + xs->error = XS_SELTIMEOUT; + break; + + default: + xs->error = XS_RESET; + break; + } + + if ((cb->flags & CBF_AUTOSENSE) == 0) { + /* Put it on the free list. */ +FREE: + TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain); + xs->resid = 0; + xs->flags |= ITSDONE; + scsi_done(xs); + } else { + /* Set up REQUEST_SENSE command */ + struct scsi_sense *cmd = + (struct scsi_sense *)&cb->xfer->scsi_cmd; + int err; + + bzero(cmd, sizeof(*cmd)); + cmd->opcode = REQUEST_SENSE; + cmd->byte2 = xs->sc_link->lun << 5; + cmd->length = sizeof(xs->sense); + + /* Sotup DMA map for data buffer */ + cb->xsflags &= SCSI_POLL | SCSI_NOSLEEP; + cb->xsflags |= SCSI_DATA_IN; + cb->datalen = sizeof xs->sense; + + err = bus_dmamap_load(sc->sc_dmat, cb->datadma, + &xs->sense, sizeof(xs->sense), NULL, + BUS_DMA_NOWAIT | BUS_DMA_STREAMING | BUS_DMA_READ); + if (err) { + printf("%s: unable to load REQUEST_SENSE data DMA map: %d", + sc->sc_dev.dv_xname, err); + xs->error = XS_DRIVER_STUFFUP; + goto FREE; + } + bus_dmamap_sync(sc->sc_dmat, cb->datadma, + 0, sizeof(xs->sense), BUS_DMASYNC_PREREAD); + + TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain); + if ((cb->xs->flags & SCSI_POLL) == 0) { + /* start expire timer */ + timeout_add(&xs->stimeout, (xs->timeout / 1000) * hz); + } + } +} + +void +oosiop_timeout(void *arg) +{ + struct oosiop_cb *cb = arg; + struct scsi_xfer *xs = cb->xs; + struct oosiop_softc *sc = xs->sc_link->adapter_softc; + int s; + + sc_print_addr(xs->sc_link); + printf("command 0x%02x timeout on xs %p\n", xs->cmd->opcode, xs); + + s = splbio(); + + cb->flags |= CBF_TIMEOUT; + oosiop_done(sc, cb); + + splx(s); +} + +void +oosiop_reset(struct oosiop_softc *sc) +{ + int i, s; + + s = splbio(); + + /* Stop SCRIPTS processor */ + oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT); + delay(100); + oosiop_write_1(sc, OOSIOP_ISTAT, 0); + + /* Reset the chip */ + oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl | OOSIOP_DCNTL_RST); + delay(100); + oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl); + delay(10000); + + /* Set up various chip parameters */ + oosiop_write_1(sc, OOSIOP_SCNTL0, OOSIOP_ARB_FULL | OOSIOP_SCNTL0_EPG); + oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_ESR); + oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl); + oosiop_write_1(sc, OOSIOP_DMODE, OOSIOP_DMODE_BL_8); + oosiop_write_1(sc, OOSIOP_SCID, OOSIOP_SCID_VALUE(sc->sc_id)); + oosiop_write_1(sc, OOSIOP_DWT, 0xff); /* Enable DMA timeout */ + oosiop_write_1(sc, OOSIOP_CTEST7, 0); + oosiop_write_1(sc, OOSIOP_SXFER, 0); + + /* Clear all interrupts */ + (void)oosiop_read_1(sc, OOSIOP_SSTAT0); + (void)oosiop_read_1(sc, OOSIOP_SSTAT1); + (void)oosiop_read_1(sc, OOSIOP_DSTAT); + + /* Enable interrupts */ + oosiop_write_1(sc, OOSIOP_SIEN, + OOSIOP_SIEN_M_A | OOSIOP_SIEN_STO | OOSIOP_SIEN_SGE | + OOSIOP_SIEN_UDC | OOSIOP_SIEN_RST | OOSIOP_SIEN_PAR); + oosiop_write_1(sc, OOSIOP_DIEN, + OOSIOP_DIEN_ABRT | OOSIOP_DIEN_SSI | OOSIOP_DIEN_SIR | + OOSIOP_DIEN_WTD | OOSIOP_DIEN_IID); + + /* Set target state to asynchronous */ + for (i = 0; i < OOSIOP_NTGT; i++) { + sc->sc_tgt[i].flags = 0; + sc->sc_tgt[i].scf = 0; + sc->sc_tgt[i].sxfer = 0; + } + + splx(s); +} + +void +oosiop_reset_bus(struct oosiop_softc *sc) +{ + int s, i; + + s = splbio(); + + /* Assert SCSI RST */ + oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_RST); + delay(25); /* Reset hold time (25us) */ + oosiop_write_1(sc, OOSIOP_SCNTL1, 0); + + /* Remove all nexuses */ + for (i = 0; i < OOSIOP_NTGT; i++) { + if (sc->sc_tgt[i].nexus) { + sc->sc_tgt[i].nexus->xfer->status = + SCSI_OOSIOP_NOSTATUS; /* XXX */ + oosiop_done(sc, sc->sc_tgt[i].nexus); + } + } + + sc->sc_curcb = NULL; + + delay(250000); /* Reset to selection (250ms) */ + + splx(s); +} + +/* + * interrupt handler + */ +int +oosiop_intr(struct oosiop_softc *sc) +{ + struct oosiop_cb *cb; + u_int32_t dcmd; + u_int8_t istat, dstat, sstat0; + + istat = oosiop_read_1(sc, OOSIOP_ISTAT); + + if ((istat & (OOSIOP_ISTAT_SIP | OOSIOP_ISTAT_DIP)) == 0) + return (0); + + sc->sc_nextdsp = Ent_wait_reselect; + + /* DMA interrupts */ + if (istat & OOSIOP_ISTAT_DIP) { + oosiop_write_1(sc, OOSIOP_ISTAT, 0); + + dstat = oosiop_read_1(sc, OOSIOP_DSTAT); + + if (dstat & OOSIOP_DSTAT_ABRT) { + sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) - + sc->sc_scrbase - 8; + + if (sc->sc_nextdsp == Ent_p_resel_msgin_move && + (oosiop_read_1(sc, OOSIOP_SBCL) & OOSIOP_ACK)) { + if ((dstat & OOSIOP_DSTAT_DFE) == 0) + oosiop_flush_fifo(sc); + sc->sc_nextdsp += 8; + } + } + + if (dstat & OOSIOP_DSTAT_SSI) { + sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) - + sc->sc_scrbase; + printf("%s: single step %08x\n", sc->sc_dev.dv_xname, + sc->sc_nextdsp); + } + + if (dstat & OOSIOP_DSTAT_SIR) { + if ((dstat & OOSIOP_DSTAT_DFE) == 0) + oosiop_flush_fifo(sc); + oosiop_scriptintr(sc); + } + + if (dstat & OOSIOP_DSTAT_WTD) { + printf("%s: DMA time out\n", sc->sc_dev.dv_xname); + oosiop_reset(sc); + } + + if (dstat & OOSIOP_DSTAT_IID) { + dcmd = oosiop_read_4(sc, OOSIOP_DBC); + if ((dcmd & 0xf8000000) == 0x48000000) { + printf("%s: REQ asserted on WAIT DISCONNECT\n", + sc->sc_dev.dv_xname); + sc->sc_nextdsp = Ent_phasedispatch; /* XXX */ + } else { + printf("%s: invalid SCRIPTS instruction " + "addr=%08x dcmd=%08x dsps=%08x\n", + sc->sc_dev.dv_xname, + oosiop_read_4(sc, OOSIOP_DSP) - 8, dcmd, + oosiop_read_4(sc, OOSIOP_DSPS)); + oosiop_reset(sc); + OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE); + oosiop_load_script(sc); + } + } + + if ((dstat & OOSIOP_DSTAT_DFE) == 0) + oosiop_clear_fifo(sc); + } + + /* SCSI interrupts */ + if (istat & OOSIOP_ISTAT_SIP) { + if (istat & OOSIOP_ISTAT_DIP) + delay(1); + sstat0 = oosiop_read_1(sc, OOSIOP_SSTAT0); + + if (sstat0 & OOSIOP_SSTAT0_M_A) { + /* SCSI phase mismatch during MOVE operation */ + oosiop_phasemismatch(sc); + sc->sc_nextdsp = Ent_phasedispatch; + } + + if (sstat0 & OOSIOP_SSTAT0_STO) { + if (sc->sc_curcb) { + sc->sc_curcb->flags |= CBF_SELTOUT; + oosiop_done(sc, sc->sc_curcb); + } + } + + if (sstat0 & OOSIOP_SSTAT0_SGE) { + printf("%s: SCSI gross error\n", sc->sc_dev.dv_xname); + oosiop_reset(sc); + } + + if (sstat0 & OOSIOP_SSTAT0_UDC) { + /* XXX */ + if (sc->sc_curcb) { + printf("%s: unexpected disconnect\n", + sc->sc_dev.dv_xname); + oosiop_done(sc, sc->sc_curcb); + } + } + + if (sstat0 & OOSIOP_SSTAT0_RST) + oosiop_reset(sc); + + if (sstat0 & OOSIOP_SSTAT0_PAR) + printf("%s: parity error\n", sc->sc_dev.dv_xname); + } + + /* Start next command if available */ + if (sc->sc_nextdsp == Ent_wait_reselect && TAILQ_FIRST(&sc->sc_cbq)) { + cb = sc->sc_curcb = TAILQ_FIRST(&sc->sc_cbq); + TAILQ_REMOVE(&sc->sc_cbq, cb, chain); + sc->sc_tgt[cb->id].nexus = cb; + + oosiop_setup_dma(sc); + oosiop_setup_syncxfer(sc); + sc->sc_lastcb = cb; + sc->sc_nextdsp = Ent_start_select; + + /* Schedule timeout */ + if ((cb->xs->flags & SCSI_POLL) == 0) { + /* start expire timer */ + timeout_add(&cb->xs->stimeout, + (cb->xs->timeout / 1000) * hz); + } + } + + sc->sc_active = (sc->sc_nextdsp != Ent_wait_reselect); + + /* Restart script */ + oosiop_write_4(sc, OOSIOP_DSP, sc->sc_nextdsp + sc->sc_scrbase); + + return (1); +} + +void +oosiop_scriptintr(struct oosiop_softc *sc) +{ + struct oosiop_cb *cb; + u_int32_t icode; + u_int32_t dsp; + int i; + u_int8_t sfbr, resid, resmsg; + + cb = sc->sc_curcb; + icode = oosiop_read_4(sc, OOSIOP_DSPS); + + switch (icode) { + case A_int_done: + if (cb) + oosiop_done(sc, cb); + break; + + case A_int_msgin: + if (cb) + oosiop_msgin(sc, cb); + break; + + case A_int_extmsg: + /* extended message in DMA setup request */ + sfbr = oosiop_read_1(sc, OOSIOP_SFBR); + OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE); + oosiop_fixup_move(sc, Ent_p_extmsgin_move, sfbr, + cb->xferdma->dm_segs[0].ds_addr + + offsetof(struct oosiop_xfer, msgin[2])); + OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE); + sc->sc_nextdsp = Ent_rcv_extmsg; + break; + + case A_int_resel: + /* reselected */ + resid = oosiop_read_1(sc, OOSIOP_SFBR); + for (i = 0; i < OOSIOP_NTGT; i++) + if (resid & (1 << i)) + break; + if (i == OOSIOP_NTGT) { + printf("%s: missing reselection target id\n", + sc->sc_dev.dv_xname); + break; + } + sc->sc_resid = i; + sc->sc_nextdsp = Ent_wait_resel_identify; + + if (cb) { + /* Current command was lost arbitration */ + sc->sc_tgt[cb->id].nexus = NULL; + TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain); + sc->sc_curcb = NULL; + } + + break; + + case A_int_res_id: + cb = sc->sc_tgt[sc->sc_resid].nexus; + resmsg = oosiop_read_1(sc, OOSIOP_SFBR); + if (MSG_ISIDENTIFY(resmsg) && cb && + (resmsg & MSG_IDENTIFY_LUNMASK) == cb->lun) { + sc->sc_curcb = cb; + if (cb != sc->sc_lastcb) { + oosiop_setup_dma(sc); + oosiop_setup_syncxfer(sc); + sc->sc_lastcb = cb; + } + if (cb->curdp != cb->savedp) { + cb->curdp = cb->savedp; + oosiop_setup_sgdma(sc, cb); + } + sc->sc_nextdsp = Ent_ack_msgin; + } else { + /* Reselection from invalid target */ + oosiop_reset_bus(sc); + } + break; + + case A_int_resfail: + /* reselect failed */ + break; + + case A_int_disc: + /* disconnected */ + sc->sc_curcb = NULL; + break; + + case A_int_err: + /* generic error */ + dsp = oosiop_read_4(sc, OOSIOP_DSP); + printf("%s: script error at 0x%08x\n", sc->sc_dev.dv_xname, + dsp - 8); + sc->sc_curcb = NULL; + break; + + case DATAIN_TRAP: + printf("%s: unexpected datain\n", sc->sc_dev.dv_xname); + /* XXX: need to reset? */ + break; + + case DATAOUT_TRAP: + printf("%s: unexpected dataout\n", sc->sc_dev.dv_xname); + /* XXX: need to reset? */ + break; + + default: + printf("%s: unknown intr code %08x\n", sc->sc_dev.dv_xname, + icode); + break; + } +} + +void +oosiop_msgin(struct oosiop_softc *sc, struct oosiop_cb *cb) +{ + struct oosiop_xfer *xfer; + int msgout; + + xfer = cb->xfer; + sc->sc_nextdsp = Ent_ack_msgin; + msgout = 0; + + OOSIOP_XFERMSG_SYNC(sc, cb, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + switch (xfer->msgin[0]) { + case MSG_EXTENDED: + switch (xfer->msgin[2]) { + case MSG_EXT_SDTR: + if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) { + /* Host initiated SDTR */ + sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR; + } else { + /* Target initiated SDTR */ + if (xfer->msgin[3] < sc->sc_minperiod) + xfer->msgin[3] = sc->sc_minperiod; + if (xfer->msgin[4] > OOSIOP_MAX_OFFSET) + xfer->msgin[4] = OOSIOP_MAX_OFFSET; + xfer->msgout[0] = MSG_EXTENDED; + xfer->msgout[1] = MSG_EXT_SDTR_LEN; + xfer->msgout[2] = MSG_EXT_SDTR; + xfer->msgout[3] = xfer->msgin[3]; + xfer->msgout[4] = xfer->msgin[4]; + cb->msgoutlen = 5; + msgout = 1; + } + oosiop_set_syncparam(sc, cb->id, (int)xfer->msgin[3], + (int)xfer->msgin[4]); + oosiop_setup_syncxfer(sc); + break; + + default: + /* Reject message */ + xfer->msgout[0] = MSG_MESSAGE_REJECT; + cb->msgoutlen = 1; + msgout = 1; + break; + } + break; + + case MSG_SAVEDATAPOINTER: + cb->savedp = cb->curdp; + break; + + case MSG_RESTOREPOINTERS: + if (cb->curdp != cb->savedp) { + cb->curdp = cb->savedp; + oosiop_setup_sgdma(sc, cb); + } + break; + + case MSG_MESSAGE_REJECT: + if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) { + /* SDTR rejected */ + sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR; + oosiop_set_syncparam(sc, cb->id, 0, 0); + oosiop_setup_syncxfer(sc); + } + break; + + default: + /* Reject message */ + xfer->msgout[0] = MSG_MESSAGE_REJECT; + cb->msgoutlen = 1; + msgout = 1; + } + + OOSIOP_XFERMSG_SYNC(sc, cb, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + if (msgout) { + OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE); + oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen, + cb->xferdma->dm_segs[0].ds_addr + + offsetof(struct oosiop_xfer, msgout[0])); + OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE); + sc->sc_nextdsp = Ent_sendmsg; + } +} diff --git a/sys/dev/ic/oosiopreg.h b/sys/dev/ic/oosiopreg.h new file mode 100644 index 00000000000..f924a2f0877 --- /dev/null +++ b/sys/dev/ic/oosiopreg.h @@ -0,0 +1,324 @@ +/* $OpenBSD: oosiopreg.h,v 1.1 2004/03/12 00:04:57 miod Exp $ */ +/* $NetBSD: oosiopreg.h,v 1.3 2003/11/02 11:07:45 wiz Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)siopreg.h 7.3 (Berkeley) 2/5/91 + */ + +/* + * NCR 53C700 SCSI interface hardware description. + * + * From the Mach scsi driver for the 53C700 and amiga siop driver + */ + +#define OOSIOP_SCNTL0 0x00 /* rw: SCSI control reg 0 */ +#define OOSIOP_SCNTL1 0x01 /* rw: SCSI control reg 1 */ +#define OOSIOP_SDID 0x02 /* rw: SCSI destination ID */ +#define OOSIOP_SIEN 0x03 /* rw: SCSI interrupt enable */ +#define OOSIOP_SCID 0x04 /* rw: SCSI Chip ID reg */ +#define OOSIOP_SXFER 0x05 /* rw: SCSI Transfer reg */ +#define OOSIOP_SODL 0x06 /* rw: SCSI Output Data Latch */ +#define OOSIOP_SOCL 0x07 /* rw: SCSI Output Control Latch */ +#define OOSIOP_SFBR 0x08 /* ro: SCSI First Byte Received */ +#define OOSIOP_SIDL 0x09 /* ro: SCSI Input Data Latch */ +#define OOSIOP_SBDL 0x0a /* ro: SCSI Bus Data Lines */ +#define OOSIOP_SBCL 0x0b /* rw: SCSI Bus Control Lines */ +#define OOSIOP_DSTAT 0x0c /* ro: DMA status */ +#define OOSIOP_SSTAT0 0x0d /* ro: SCSI status reg 0 */ +#define OOSIOP_SSTAT1 0x0e /* ro: SCSI status reg 1 */ +#define OOSIOP_SSTAT2 0x0f /* ro: SCSI status reg 2 */ +#define OOSIOP_SCRA0 0x10 /* rw: Scratch A */ +#define OOSIOP_SCRA1 0x11 +#define OOSIOP_SCRA2 0x12 +#define OOSIOP_SCRA3 0x13 +#define OOSIOP_CTEST0 0x14 /* ro: Chip test register 0 */ +#define OOSIOP_CTEST1 0x15 /* ro: Chip test register 1 */ +#define OOSIOP_CTEST2 0x16 /* ro: Chip test register 2 */ +#define OOSIOP_CTEST3 0x17 /* ro: Chip test register 3 */ +#define OOSIOP_CTEST4 0x18 /* rw: Chip test register 4 */ +#define OOSIOP_CTEST5 0x19 /* rw: Chip test register 5 */ +#define OOSIOP_CTEST6 0x1a /* rw: Chip test register 6 */ +#define OOSIOP_CTEST7 0x1b /* rw: Chip test register 7 */ +#define OOSIOP_TEMP 0x1c /* rw: Temporary Stack reg */ +#define OOSIOP_DFIFO 0x20 /* rw: DMA FIFO */ +#define OOSIOP_ISTAT 0x21 /* rw: Interrupt Status reg */ +#define OOSIOP_CTEST8 0x22 /* rw: Chip test register 8 */ +#define OOSIOP_CTEST9 0x23 /* ro: Chip test register 9 */ +#define OOSIOP_DBC 0x24 /* rw: DMA Byte Counter reg */ +#define OOSIOP_DCMD 0x27 /* rw: DMA Command Register */ +#define OOSIOP_DNAD 0x28 /* rw: DMA Next Address */ +#define OOSIOP_DSP 0x2c /* rw: DMA SCRIPTS Pointer reg */ +#define OOSIOP_DSPS 0x30 /* rw: DMA SCRIPTS Pointer Save reg */ +#define OOSIOP_DMODE 0x34 /* rw: DMA Mode reg */ +#define OOSIOP_RES35 0x35 +#define OOSIOP_RES36 0x36 +#define OOSIOP_RES37 0x37 +#define OOSIOP_RES38 0x38 +#define OOSIOP_DIEN 0x39 /* rw: DMA Interrupt Enable */ +#define OOSIOP_DWT 0x3a /* rw: DMA Watchdog Timer */ +#define OOSIOP_DCNTL 0x3b /* rw: DMA Control reg */ +#define OOSIOP_SCRB0 0x3c /* rw: Scratch B */ +#define OOSIOP_SCRB1 0x3d +#define OOSIOP_SCRB2 0x3e +#define OOSIOP_SCRB3 0x3f + +#define OOSIOP_NREGS 0x40 + + +/* + * Register defines + */ + +/* Scsi control register 0 (scntl0) */ + +#define OOSIOP_SCNTL0_ARB 0xc0 /* Arbitration mode */ +#define OOSIOP_ARB_SIMPLE 0x00 +#define OOSIOP_ARB_FULL 0xc0 +#define OOSIOP_SCNTL0_START 0x20 /* Start Sequence */ +#define OOSIOP_SCNTL0_WATN 0x10 /* (Select) With ATN */ +#define OOSIOP_SCNTL0_EPC 0x08 /* Enable Parity Checking */ +#define OOSIOP_SCNTL0_EPG 0x04 /* Enable Parity Generation */ +#define OOSIOP_SCNTL0_AAP 0x02 /* Assert ATN on Parity Error */ +#define OOSIOP_SCNTL0_TRG 0x01 /* Target Mode */ + +/* Scsi control register 1 (scntl1) */ + +#define OOSIOP_SCNTL1_EXC 0x80 /* Extra Clock Cycle of data setup */ +#define OOSIOP_SCNTL1_ADB 0x40 /* Assert Data Bus */ +#define OOSIOP_SCNTL1_ESR 0x20 /* Enable Selection/Reselection */ +#define OOSIOP_SCNTL1_CON 0x10 /* Connected */ +#define OOSIOP_SCNTL1_RST 0x08 /* Assert RST */ +#define OOSIOP_SCNTL1_AESP 0x04 /* Assert even SCSI parity */ +#define OOSIOP_SCNTL1_SND 0x02 /* Start Send operation */ +#define OOSIOP_SCNTL1_RCV 0x01 /* Start Receive operation */ + +/* Scsi interrupt enable register (sien) */ + +#define OOSIOP_SIEN_M_A 0x80 /* Phase Mismatch or ATN active */ +#define OOSIOP_SIEN_FC 0x40 /* Function Complete */ +#define OOSIOP_SIEN_STO 0x20 /* (Re)Selection timeout */ +#define OOSIOP_SIEN_SEL 0x10 /* (Re)Selected */ +#define OOSIOP_SIEN_SGE 0x08 /* SCSI Gross Error */ +#define OOSIOP_SIEN_UDC 0x04 /* Unexpected Disconnect */ +#define OOSIOP_SIEN_RST 0x02 /* RST asserted */ +#define OOSIOP_SIEN_PAR 0x01 /* Parity Error */ + +/* Scsi chip ID (scid) */ + +#define OOSIOP_SCID_VALUE(i) (1 << i) + +/* Scsi transfer register (sxfer) */ + +#define OOSIOP_SXFER_DHP 0x80 /* Disable Halt on Parity error/ + ATN asserted */ +#define OOSIOP_SXFER_TP 0x70 /* Synch Transfer Period */ + /* see specs for formulas: + Period = TCP * (4 + XFERP ) + TCP = 1 + CLK + 1..2; + */ +#define OOSIOP_SXFER_MO 0x0f /* Synch Max Offset */ +#define OOSIOP_MAX_OFFSET 8 + +/* Scsi output data latch register (sodl) */ + +/* Scsi output control latch register (socl) */ + +#define OOSIOP_REQ 0x80 /* SCSI signal <x> asserted */ +#define OOSIOP_ACK 0x40 +#define OOSIOP_BSY 0x20 +#define OOSIOP_SEL 0x10 +#define OOSIOP_ATN 0x08 +#define OOSIOP_MSG 0x04 +#define OOSIOP_CD 0x02 +#define OOSIOP_IO 0x01 + +#define OOSIOP_PHASE(socl) SCSI_PHASE(socl) + +/* Scsi first byte received register (sfbr) */ + +/* Scsi input data latch register (sidl) */ + +/* Scsi bus data lines register (sbdl) */ + +/* Scsi bus control lines register (sbcl). Same as socl */ + +#define OOSIOP_SBCL_SSCF1 0x02 /* wo */ +#define OOSIOP_SBCL_SSCF0 0x01 /* wo */ + +/* DMA status register (dstat) */ + +#define OOSIOP_DSTAT_DFE 0x80 /* DMA FIFO empty */ +#define OOSIOP_DSTAT_ABRT 0x10 /* Aborted */ +#define OOSIOP_DSTAT_SSI 0x08 /* SCRIPT Single Step */ +#define OOSIOP_DSTAT_SIR 0x04 /* SCRIPT Interrupt Instruction */ +#define OOSIOP_DSTAT_WTD 0x02 /* Watchdog Timeout Detected */ +#define OOSIOP_DSTAT_IID 0x01 /* Invalid Instruction Detected */ + +/* Scsi status register 0 (sstat0) */ + +#define OOSIOP_SSTAT0_M_A 0x80 /* Phase Mismatch or ATN active */ +#define OOSIOP_SSTAT0_FC 0x40 /* Function Complete */ +#define OOSIOP_SSTAT0_STO 0x20 /* (Re)Selection timeout */ +#define OOSIOP_SSTAT0_SEL 0x10 /* (Re)Selected */ +#define OOSIOP_SSTAT0_SGE 0x08 /* SCSI Gross Error */ +#define OOSIOP_SSTAT0_UDC 0x04 /* Unexpected Disconnect */ +#define OOSIOP_SSTAT0_RST 0x02 /* RST asserted */ +#define OOSIOP_SSTAT0_PAR 0x01 /* Parity Error */ + +/* Scsi status register 1 (sstat1) */ + +#define OOSIOP_SSTAT1_ILF 0x80 /* Input latch (sidl) full */ +#define OOSIOP_SSTAT1_ORF 0x40 /* output reg (sodr) full */ +#define OOSIOP_SSTAT1_OLF 0x20 /* output latch (sodl) full */ +#define OOSIOP_SSTAT1_AIP 0x10 /* Arbitration in progress */ +#define OOSIOP_SSTAT1_LOA 0x08 /* Lost arbitration */ +#define OOSIOP_SSTAT1_WOA 0x04 /* Won arbitration */ +#define OOSIOP_SSTAT1_RST 0x02 /* SCSI RST current value */ +#define OOSIOP_SSTAT1_SDP 0x01 /* SCSI SDP current value */ + +/* Scsi status register 2 (sstat2) */ + +#define OOSIOP_SSTAT2_FF 0xf0 /* SCSI FIFO flags (bytecount) */ +#define OOSIOP_SCSI_FIFO_DEEP 8 +#define OOSIOP_SSTAT2_SDP 0x08 /* Latched (on REQ) SCSI SDP */ +#define OOSIOP_SSTAT2_MSG 0x04 /* Latched SCSI phase */ +#define OOSIOP_SSTAT2_CD 0x02 +#define OOSIOP_SSTAT2_IO 0x01 + +/* Chip test register 0 (ctest0) */ + +#define OOSIOP_CTEST0_RTRG 0x02 /* Real Target Mode */ +#define OOSIOP_CTEST0_DDIR 0x01 /* Xfer direction (1-> from SCSI bus) */ + +/* Chip test register 1 (ctest1) */ + +#define OOSIOP_CTEST1_FMT 0xf0 /* Byte empty in DMA FIFO bottom + (high->byte3) */ +#define OOSIOP_CTEST1_FFL 0x0f /* Byte full in DMA FIFO top, same */ + +/* Chip test register 2 (ctest2) */ + +#define OOSIOP_CTEST2_SOFF 0x20 /* Synch Offset compare + (1-> zero Init, max Tgt) */ +#define OOSIOP_CTEST2_SFP 0x10 /* SCSI FIFO Parity */ +#define OOSIOP_CTEST2_DFP 0x08 /* DMA FIFO Parity */ +#define OOSIOP_CTEST2_TEOP 0x04 /* True EOP (a-la 5380) */ +#define OOSIOP_CTEST2_DREQ 0x02 /* DREQ status */ +#define OOSIOP_CTEST2_DACK 0x01 /* DACK status */ + +/* Chip test register 3 (ctest3) read-only, top of SCSI FIFO */ + +/* Chip test register 4 (ctest4) */ + +#define OOSIOP_CTEST4_ZMOD 0x40 /* High-impedance outputs */ +#define OOSIOP_CTEST4_SZM 0x20 /* ditto, SCSI "outputs" */ +#define OOSIOP_CTEST4_SLBE 0x10 /* SCSI loopback enable */ +#define OOSIOP_CTEST4_SFWR 0x08 /* SCSI FIFO write enable (from sodl) */ +#define OOSIOP_CTEST4_FBL 0x07 /* DMA FIFO Byte Lane select + (from ctest6) 4->0, .. 7->3 */ + +/* Chip test register 5 (ctest5) */ + +#define OOSIOP_CTEST5_ADCK 0x80 /* Clock Address Incrementor */ +#define OOSIOP_CTEST5_BBCK 0x40 /* Clock Byte counter */ +#define OOSIOP_CTEST5_ROFF 0x20 /* Reset SCSI offset */ +#define OOSIOP_CTEST5_MASR 0x10 /* Master set/reset pulses + (of bits 3-0) */ +#define OOSIOP_CTEST5_DDIR 0x08 /* (re)set internal DMA direction */ +#define OOSIOP_CTEST5_EOP 0x04 /* (re)set internal EOP */ +#define OOSIOP_CTEST5_DREQ 0x02 /* (re)set internal REQ */ +#define OOSIOP_CTEST5_DACK 0x01 /* (re)set internal ACK */ + +/* Chip test register 6 (ctest6) DMA FIFO access */ + +/* Chip test register 7 (ctest7) */ + +#define OOSIOP_CTEST7_STD 0x10 /* Selection timeout disable */ +#define OOSIOP_CTEST7_DFP 0x08 /* DMA FIFO parity bit */ +#define OOSIOP_CTEST7_EVP 0x04 /* Even parity (to host bus) */ +#define OOSIOP_CTEST7_DIFF 0x01 /* Differential mode */ + +/* DMA FIFO register (dfifo) */ + +#define OOSIOP_DFIFO_FLF 0x80 /* Flush (spill) DMA FIFO */ +#define OOSIOP_DFIFO_CLF 0x40 /* Clear DMA and SCSI FIFOs */ +#define OOSIOP_DFIFO_BO 0x3f /* FIFO byte offset counter */ + +/* Interrupt status register (istat) */ + +#define OOSIOP_ISTAT_ABRT 0x80 /* Abort operation */ +#define OOSIOP_ISTAT_CON 0x08 /* Connected */ +#define OOSIOP_ISTAT_PRE 0x04 /* Pointer register empty */ +#define OOSIOP_ISTAT_SIP 0x02 /* SCSI Interrupt pending */ +#define OOSIOP_ISTAT_DIP 0x01 /* DMA Interrupt pending */ + +/* Chip test register 8 (ctest8) */ + +/* DMA Byte Counter register (dbc) */ +#define OOSIOP_DBC_MAX 0x00ffffff + +/* DMA Mode register (dmode) */ + +#define OOSIOP_DMODE_BL_MASK 0xc0 /* 0->1 1->2 2->4 3->8 */ +#define OOSIOP_DMODE_BL_1 0x00 +#define OOSIOP_DMODE_BL_2 0x40 +#define OOSIOP_DMODE_BL_4 0x80 +#define OOSIOP_DMODE_BL_8 0xc0 +#define OOSIOP_DMODE_BW16 0x20 /* Bus Width is 16 bits */ +#define OOSIOP_DMODE_286 0x10 /* 286 mode */ +#define OOSIOP_DMODE_IO_M 0x08 /* xfer data to memory or I/O space */ +#define OOSIOP_DMODE_FAM 0x04 /* fixed address mode */ +#define OOSIOP_DMODE_PIPE 0x02 /* SCRIPTS in Pipeline mode */ +#define OOSIOP_DMODE_MAN 0x01 /* SCRIPTS in Manual start mode */ + +/* DMA interrupt enable register (dien) */ + +#define OOSIOP_DIEN_BF 0x20 /* On Bus Fault */ +#define OOSIOP_DIEN_ABRT 0x10 /* On Abort */ +#define OOSIOP_DIEN_SSI 0x08 /* On SCRIPTS sstep */ +#define OOSIOP_DIEN_SIR 0x04 /* On SCRIPTS intr instruction */ +#define OOSIOP_DIEN_WTD 0x02 /* On watchdog timeout */ +#define OOSIOP_DIEN_IID 0x01 /* On illegal instruction detected */ + +/* DMA control register (dcntl) */ + +#define OOSIOP_DCNTL_CF_MASK 0xc0 /* Clock frequency dividers: */ +#define OOSIOP_DCNTL_CF_2 0x00 /* 0 --> 37.51..50.00 MHz, div=2 */ +#define OOSIOP_DCNTL_CF_1_5 0x40 /* 1 --> 25.01..37.50 MHz, div=1.5 */ +#define OOSIOP_DCNTL_CF_1 0x80 /* 2 --> 16.67..25.00 MHz, div=1 */ +#define OOSIOP_DCNTL_CF_3 0xc0 /* 3 --> 50.01..66.67 MHz, div=3 */ +#define OOSIOP_DCNTL_S16 0x20 /* SCRIPTS fetches 16bits at a time */ +#define OOSIOP_DCNTL_SSM 0x10 /* Single step mode */ +#define OOSIOP_DCNTL_LLM 0x08 /* Enable SCSI Low-level mode */ +#define OOSIOP_DCNTL_STD 0x04 /* Start DMA operation */ +#define OOSIOP_DCNTL_RST 0x01 /* Software reset */ diff --git a/sys/dev/ic/oosiopvar.h b/sys/dev/ic/oosiopvar.h new file mode 100644 index 00000000000..e197773efb4 --- /dev/null +++ b/sys/dev/ic/oosiopvar.h @@ -0,0 +1,164 @@ +/* $OpenBSD: oosiopvar.h,v 1.1 2004/03/12 00:04:57 miod Exp $ */ +/* $NetBSD: oosiopvar.h,v 1.2 2003/05/03 18:11:23 wiz Exp $ */ + +/* + * Copyright (c) 2001 Shuichiro URATA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define OOSIOP_NTGT 8 /* Max targets */ +#define OOSIOP_NCB 32 /* Initial command buffers */ +#define OOSIOP_NSG (MIN(btoc(MAXPHYS) + 1, 32)) /* Max S/G operation */ +#define OOSIOP_MAX_XFER ctob(OOSIOP_NSG - 1) + +struct oosiop_xfer { + /* script for scatter/gather DMA (move*nsg+jump) */ + u_int32_t datain_scr[(OOSIOP_NSG + 1) * 2]; + u_int32_t dataout_scr[(OOSIOP_NSG + 1) * 2]; + + u_int8_t msgin[8]; + u_int8_t msgout[8]; + u_int8_t status; + u_int8_t pad[7]; + + struct scsi_generic scsi_cmd; /* DMA'able copy of xs->cmd */ + u_int32_t pad2[1+4]; /* pad to 256 bytes */ +} __packed; + +#define SCSI_OOSIOP_NOSTATUS 0xff /* device didn't report status */ + +#define OOSIOP_XFEROFF(x) offsetof(struct oosiop_xfer, x) +#define OOSIOP_DINSCROFF OOSIOP_XFEROFF(datain_scr[0]) +#define OOSIOP_DOUTSCROFF OOSIOP_XFEROFF(dataout_scr[0]) +#define OOSIOP_MSGINOFF OOSIOP_XFEROFF(msgin[0]) +#define OOSIOP_MSGOUTOFF OOSIOP_XFEROFF(msgout[0]) +#define OOSIOP_CMDOFF OOSIOP_XFEROFF(scsi_cmd) + +#define OOSIOP_XFERSCR_SYNC(sc, cb, ops) \ + bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_DINSCROFF, \ + OOSIOP_MSGINOFF - OOSIOP_DINSCROFF, (ops)) +#define OOSIOP_DINSCR_SYNC(sc, cb, ops) \ + bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_DINSCROFF, \ + OOSIOP_DOUTSCROFF - OOSIOP_DINSCROFF, (ops)) +#define OOSIOP_DOUTSCR_SYNC(sc, cb, ops) \ + bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_DOUTSCROFF,\ + OOSIOP_MSGINOFF - OOSIOP_DOUTSCROFF, (ops)) +#define OOSIOP_XFERMSG_SYNC(sc, cb, ops) \ + bus_dmamap_sync((sc)->sc_dmat, (cb)->xferdma, OOSIOP_MSGINOFF, \ + sizeof(struct oosiop_xfer) - OOSIOP_MSGINOFF, (ops)) + +#define OOSIOP_SCRIPT_SYNC(sc, ops) \ + bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_scrdma, \ + 0, sizeof(oosiop_script), (ops)) + +struct oosiop_cb { + TAILQ_ENTRY(oosiop_cb) chain; + + struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */ + int flags; + int id; /* target scsi id */ + int lun; /* target lun */ + + bus_dmamap_t cmddma; /* DMA map for command out */ + bus_dmamap_t datadma; /* DMA map for data I/O */ + bus_dmamap_t xferdma; /* DMA map for xfer block */ + + int curdp; /* current data pointer */ + int savedp; /* saved data pointer */ + int msgoutlen; + + int xsflags; /* copy of xs->flags */ + int datalen; /* copy of xs->datalen */ + + struct oosiop_xfer *xfer; /* DMA xfer block */ +}; + +/* oosiop_cb flags */ +#define CBF_SELTOUT 0x01 /* Selection timeout */ +#define CBF_TIMEOUT 0x02 /* Command timeout */ +#define CBF_AUTOSENSE 0x04 /* Request sense due to SCSI_CHECK */ + +struct oosiop_target { + struct oosiop_cb *nexus; + int flags; + u_int8_t scf; /* synchronous clock divisor */ + u_int8_t sxfer; /* synchronous period and offset */ +}; + +/* target flags */ +#define TGTF_SYNCNEG 0x01 /* Trigger synchronous negotiation */ +#define TGTF_WAITSDTR 0x02 /* Waiting SDTR from target */ + +struct oosiop_softc { + struct device sc_dev; + + bus_space_tag_t sc_bst; /* bus space tag */ + bus_space_handle_t sc_bsh; /* bus space handle */ + + bus_dma_tag_t sc_dmat; /* bus DMA tag */ + bus_dmamap_t sc_scrdma; /* script DMA map */ + + bus_addr_t sc_scrbase; /* script DMA base address */ + u_int32_t *sc_scr; /* ptr to script memory */ + + int sc_chip; /* 700 or 700-66 */ +#define OOSIOP_700 0 +#define OOSIOP_700_66 1 + + int sc_id; /* SCSI ID of this interface */ + int sc_freq; /* SCLK frequency */ + int sc_ccf; /* asynchronous divisor (*10) */ + u_int8_t sc_dcntl; + u_int8_t sc_minperiod; + + struct oosiop_target sc_tgt[OOSIOP_NTGT]; + + struct scsi_link sc_link; + + /* Lists of command blocks */ + TAILQ_HEAD(oosiop_cb_queue, oosiop_cb) sc_free_cb, + sc_cbq; + + struct oosiop_cb *sc_curcb; /* current command */ + struct oosiop_cb *sc_lastcb; /* last activated command */ + + bus_addr_t sc_reselbuf; /* msgin buffer for reselection */ + int sc_resid; /* reselected target id */ + + int sc_active; + int sc_nextdsp; +}; + +#define oosiop_read_1(sc, addr) \ + bus_space_read_1((sc)->sc_bst, (sc)->sc_bsh, (addr)) +#define oosiop_write_1(sc, addr, data) \ + bus_space_write_1((sc)->sc_bst, (sc)->sc_bsh, (addr), (data)) +/* XXX byte swapping should be handled by MD bus_space(9)? */ +#define oosiop_read_4(sc, addr) \ + letoh32(bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (addr))) +#define oosiop_write_4(sc, addr, data) \ + bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (addr), htole32(data)) + +void oosiop_attach(struct oosiop_softc *); +int oosiop_intr(struct oosiop_softc *); diff --git a/sys/dev/microcode/siop/Makefile b/sys/dev/microcode/siop/Makefile index db8a569b205..223a767324a 100644 --- a/sys/dev/microcode/siop/Makefile +++ b/sys/dev/microcode/siop/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.2 2003/01/08 02:11:38 krw Exp $ +# $OpenBSD: Makefile,v 1.3 2004/03/12 00:04:57 miod Exp $ # $NetBSD: Makefile,v 1.1 2000/04/21 17:57:01 bouyer Exp $ -all: siop.out osiop.out +all: siop.out osiop.out oosiop.out PROG= ncr53cxxx MKSHARE=no @@ -9,11 +9,14 @@ MAN= .include <bsd.prog.mk> -regen: siop.out osiop.out -headers: siop.out osiop.out +regen: siop.out osiop.out oosiop.out +headers: siop.out osiop.out oosiop.out siop.out: siop.ss ${PROG} ./${PROG} siop.ss -p siop.out osiop.out: osiop.ss ${PROG} ./${PROG} osiop.ss -p osiop.out + +oosiop.out: oosiop.ss ${PROG} + ./${PROG} oosiop.ss -p oosiop.out diff --git a/sys/dev/microcode/siop/ncr53cxxx.c b/sys/dev/microcode/siop/ncr53cxxx.c index d742fdd6c80..12b6c0aa06f 100644 --- a/sys/dev/microcode/siop/ncr53cxxx.c +++ b/sys/dev/microcode/siop/ncr53cxxx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ncr53cxxx.c,v 1.5 2003/06/27 20:38:49 krw Exp $ */ +/* $OpenBSD: ncr53cxxx.c,v 1.6 2004/03/12 00:04:57 miod Exp $ */ /* $NetBSD: ncr53cxxx.c,v 1.10 2002/04/21 22:40:10 bouyer Exp $ */ /* @@ -415,7 +415,7 @@ main (int argc, char *argv[]) if (outfp) { time_t cur_time; - fprintf(outfp, "/*\t$NetBSD: ncr53cxxx.c,v 1.10 2002/04/21 22:40:10 bouyer Exp $\t*/\n"); + fprintf(outfp, "/*\t$OpenBSD: ncr53cxxx.c,v 1.6 2004/03/12 00:04:57 miod Exp $\t*/\n"); fprintf(outfp, "/*\n"); fprintf(outfp, " *\tDO NOT EDIT - this file is automatically generated.\n"); time(&cur_time); @@ -1046,10 +1046,12 @@ void f_wait (void) errout ("Expected SELECT or RESELECT"); ++i; if (reserved ("rel", i)) { +#if 0 /* XXX driver will fix relative dsps to absolute */ if (arch < ARCH710) { errout ("Wrong arch for relative dsps"); return; } +#endif i += 2; inst1 = evaluate (i) - dsps - 8; inst0 |= 0x04000000; @@ -1157,10 +1159,12 @@ void transfer (int word0, int type) i = tokenix; inst0 = word0; if (type == 0 && reserved ("rel", i)) { +#if 0 /* XXX driver will fix relative dsps to absolute */ if (arch < ARCH710) { errout ("Wrong arch for relative dsps"); return; } +#endif inst1 = evaluate (i + 2) - dsps - 8; i += 4; inst0 |= 0x00800000; @@ -1244,10 +1248,12 @@ void select_reselect (int t) inst0 |= (evaluate (t++) & 0xff) << 16; if (tokens[t++].type == ',') { if (reserved ("rel", t)) { +#if 0 /* XXX driver will fix relative dsps to absolute */ if (arch < ARCH710) { errout ("Wrong arch for relative dsps"); return; } +#endif inst0 |= 0x04000000; inst1 = evaluate (t + 2) - dsps - 8; } diff --git a/sys/dev/microcode/siop/oosiop.ss b/sys/dev/microcode/siop/oosiop.ss new file mode 100644 index 00000000000..b1c084f803c --- /dev/null +++ b/sys/dev/microcode/siop/oosiop.ss @@ -0,0 +1,150 @@ +; $NetBSD: oosiop.ss,v 1.2 2003/04/06 09:48:42 tsutsui Exp $ + +; +; Copyright (c) 2001 Shuichiro URATA. All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; 3. The name of the author may not be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; + +; NCR 53c700 script +; + +ARCH 700 + +; interrupt codes +ABSOLUTE int_done = 0xbeef0000 +ABSOLUTE int_msgin = 0xbeef0001 +ABSOLUTE int_extmsg = 0xbeef0002 +ABSOLUTE int_resel = 0xbeef0003 +ABSOLUTE int_res_id = 0xbeef0004 +ABSOLUTE int_resfail = 0xbeef0005 +ABSOLUTE int_disc = 0xbeef0006 +ABSOLUTE int_err = 0xdeadbeef + +; patch entries +ENTRY p_resel_msgin_move +ENTRY p_select +ENTRY p_datain_jump +ENTRY p_dataout_jump +ENTRY p_msgin_move +ENTRY p_msgout_move +ENTRY p_cmdout_move +ENTRY p_status_move +ENTRY p_extmsglen_move +ENTRY p_extmsgin_move + + +PROC oosiop_script: + +ENTRY wait_reselect +wait_reselect: + WAIT RESELECT REL(reselect_fail) + INT int_resel +reselect_fail: + INT int_resfail + +ENTRY wait_resel_identify +wait_resel_identify: + INT int_err, WHEN NOT MSG_IN +p_resel_msgin_move: + MOVE 0, 0, WHEN MSG_IN + INT int_res_id + +ENTRY start_select +start_select: +p_select: + SELECT ATN 0, REL(wait_reselect) + +ENTRY phasedispatch +phasedispatch: + JUMP REL(msgin), WHEN MSG_IN + JUMP REL(msgout), WHEN MSG_OUT + JUMP REL(status), WHEN STATUS + JUMP REL(cmdout), WHEN CMD +p_datain_jump: + JUMP 0, WHEN DATA_IN +p_dataout_jump: + JUMP 0, WHEN DATA_OUT + INT int_err + +msgin: + CLEAR ATN +p_msgin_move: + MOVE 0, 0, WHEN MSG_IN + JUMP REL(complete), IF 0x00 + JUMP REL(extmsgsetup), IF 0x01 + JUMP REL(disconnect), IF 0x04 + INT int_msgin + +ENTRY ack_msgin +ack_msgin: + CLEAR ACK + JUMP REL(phasedispatch) + +ENTRY sendmsg +sendmsg: + SET ATN + CLEAR ACK +msgout: +p_msgout_move: + MOVE 0, 0, WHEN MSG_OUT + CLEAR ATN + JUMP REL(phasedispatch) + +cmdout: + CLEAR ATN +p_cmdout_move: + MOVE 0, 0, WHEN CMD + JUMP REL(phasedispatch) + +status: +p_status_move: + MOVE 0, 0, WHEN STATUS + JUMP REL(phasedispatch) + +disconnect: + CLEAR ACK + WAIT DISCONNECT + INT int_disc + +complete: + CLEAR ACK + WAIT DISCONNECT + INT int_done + +; receive extended message length +extmsgsetup: + CLEAR ACK + INT int_err, IF NOT MSG_IN +p_extmsglen_move: + MOVE 0, 0, WHEN MSG_IN + INT int_extmsg + +; receive extended message +ENTRY rcv_extmsg +rcv_extmsg: + CLEAR ACK + INT int_err, IF NOT MSG_IN +p_extmsgin_move: + MOVE 0, 0, WHEN MSG_IN + INT int_msgin |