Add support for the ``Firefox'' VAXstation 3520/3540/3820/3840 workstations,
authormiod <miod@openbsd.org>
Mon, 18 Aug 2008 23:19:15 +0000 (23:19 +0000)
committermiod <miod@openbsd.org>
Mon, 18 Aug 2008 23:19:15 +0000 (23:19 +0000)
currently limited to serial console and a single processor working.

All ``on-board'' devices, including the Q-bus adapter, but except for
the frame buffer, are supported. The machine will boot over the network
or from SCSI devices.

Lots of thanks to Al Kossow for www.bitsavers.org, on which I found the
technical documentation allowing me to complete this port (which was
lacking at the time I got that machine...).

43 files changed:
distrib/notes/vax/hardware
distrib/notes/vax/prep
share/man/man4/man4.vax/Makefile
share/man/man4/man4.vax/dz.4
share/man/man4/man4.vax/fwio.4 [new file with mode: 0644]
share/man/man4/man4.vax/intro.4
share/man/man4/man4.vax/le.4
share/man/man4/man4.vax/mbus.4 [new file with mode: 0644]
share/man/man4/man4.vax/sii.4 [new file with mode: 0644]
share/man/man4/man4.vax/uba.4
sys/arch/vax/conf/GENERIC
sys/arch/vax/conf/RAMDISK
sys/arch/vax/conf/files.vax
sys/arch/vax/dec/files.dec
sys/arch/vax/dec/sii.c [new file with mode: 0644]
sys/arch/vax/dec/siireg.h [new file with mode: 0644]
sys/arch/vax/dec/siivar.h [new file with mode: 0644]
sys/arch/vax/include/clock.h
sys/arch/vax/include/nexus.h
sys/arch/vax/include/rpb.h
sys/arch/vax/include/scb.h
sys/arch/vax/mbus/dz_fwio.c [new file with mode: 0644]
sys/arch/vax/mbus/files.mbus [new file with mode: 0644]
sys/arch/vax/mbus/fwio.c [new file with mode: 0644]
sys/arch/vax/mbus/fwioreg.h [new file with mode: 0644]
sys/arch/vax/mbus/fwiovar.h [new file with mode: 0644]
sys/arch/vax/mbus/if_le_fwio.c [new file with mode: 0644]
sys/arch/vax/mbus/mbus.c [new file with mode: 0644]
sys/arch/vax/mbus/mbusreg.h [new file with mode: 0644]
sys/arch/vax/mbus/mbusvar.h [new file with mode: 0644]
sys/arch/vax/mbus/sii_fwio.c [new file with mode: 0644]
sys/arch/vax/mbus/uba_mbus.c [new file with mode: 0644]
sys/arch/vax/uba/ubareg.h
sys/arch/vax/vax/autoconf.c
sys/arch/vax/vax/clock.c
sys/arch/vax/vax/conf.c
sys/arch/vax/vax/findcpu.c
sys/arch/vax/vax/ka60.c [new file with mode: 0644]
sys/arch/vax/vax/locore.c
sys/arch/vax/vax/machdep.c
sys/arch/vax/vax/pmap.c
sys/arch/vax/vax/scb.c
sys/arch/vax/vax/vm_machdep.c

index 04bc037..7b6332a 100644 (file)
@@ -1,10 +1,11 @@
-dnl    $OpenBSD: hardware,v 1.24 2008/08/06 18:23:56 miod Exp $
+dnl    $OpenBSD: hardware,v 1.25 2008/08/18 23:19:15 miod Exp $
 OpenBSD/MACHINE OSREV runs on a wide variety of VAX hardware.
 The following systems have been tested:
        - VAXstation 2000
        - VAXstation 3100/{30,40}
        - VAXstation 3100/{38,48}
        - VAXstation 3100/76
+       - VAXstation 3520,3540
        - VAXstation 4000/VLC
        - VAXstation 4000/60
        - VAXstation 4000/90
@@ -42,7 +43,8 @@ Supported devices {:-include-:}:
     * SCSI controllers:
        - NCR 5380 (asc) or NCR 53C9x (ncr) on-board SCSI
          (this {:-include-:}s most 3100s and VAXstation 4000s, as well
-          as the VAX 4000 10x series).
+          as the VAX 4000 10x series)
+       - SII (sii) SCSI on VAXstation 35x0 I/O module
 
     * Serial ports:
        - DZ*11 lines (also DZ*11 compatible lines on VAXstations) (dz)
index 943299f..01b1e4c 100644 (file)
@@ -1,4 +1,4 @@
-dnl    $OpenBSD: prep,v 1.8 2008/08/05 23:03:50 miod Exp $
+dnl    $OpenBSD: prep,v 1.9 2008/08/18 23:19:15 miod Exp $
 VAX machines don't generally need any specific preparation. You will need
 to properly identify the console port on your machine.
 
@@ -15,12 +15,20 @@ position. Be warned that early VAXstation 3100 models do not have a hole in
 the enclosure to access the switch, and will need to be opened for the
 switch to be flipped.
 
-As an exception to the above rule, VXT2000 machines have a W3 jumper on
-the motherboard, near the power supply connector. When the jumper is
-open, the VXT2000 will use the keyboard and frame buffer console (this
-is the factory configuration). Shorting the jumper will switch to
-serial console on the DB25 serial connector, and will disable the
-frame buffer.
+There are two exceptions to the above rule, however:
+
+- VXT2000 machines have a W3 jumper on the motherboard, near the power supply
+  connector. When the jumper is open, the VXT2000 will use the keyboard and
+  frame buffer console (this is the factory configuration). Shorting the
+  jumper will switch to serial console on the DB25 serial connector, and will
+  disable the frame buffer.
+
+- VAXstation 35x0 do not have a permanent setting to force console on the
+  printer/console serial port. It will, however, default to serial console
+  if the graphics option boards are removed from the machine, or if the
+  ``Halt'' button on the maintainence panel is kept pressed during powerup
+  or reset, until the I/O panel led indicator displays `B' and output
+  appears on the serial port.
 
 Note that, if the frame buffer in your VAXstation is not supported, OpenBSD
 will use serial port 3 as the console, as if the S3 switch had been in the
index 45e8104..180e929 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.22 2006/08/27 17:32:58 miod Exp $
+#      $OpenBSD: Makefile,v 1.23 2008/08/18 23:19:18 miod Exp $
 #      $NetBSD: Makefile,v 1.6 1996/03/03 17:13:09 thorpej Exp $
 #      from: @(#)Makefile      5.4 (Berkeley) 5/11/90
 
@@ -6,9 +6,10 @@
 # acc.4 ad.4 crl.4 css.4 ct.4 ddn.4 dh.4 dmc.4 dmf.4 dmv.4 dmz.4 dn.4
 # ec.4 en.4 ex.4 fl.4 hdh.4 hk.4 ht.4 hy.4 ik.4 il.4 ix.4 kg.4 lp.4 np.4
 # pcl.4 ps.4 tm.4 tmscp.4 tu.4 up.4 ut.4 uu.4 va.4 vp.4 vv.4
-MAN=   asc.4 autoconf.4 cons.4 de.4 dhu.4 dz.4 gpx.4 hp.4 ibus.4 intro.4 \
-       lcg.4 lcspx.4 le.4 led.4 lkkbd.4 lkms.4 mem.4 mscpbus.4 mt.4 mtc.4 \
-       ncr.4 qe.4 qsc.4 ra.4 rx.4 smg.4 ts.4 uba.4 uda.4 vsbus.4 vxtbus.4 ze.4
+MAN=   asc.4 autoconf.4 cons.4 de.4 dhu.4 dz.4 fwio.4 gpx.4 hp.4 \
+       ibus.4 intro.4 lcg.4 lcspx.4 le.4 led.4 lkkbd.4 lkms.4 \
+       mbus.4 mem.4 mscpbus.4 mt.4 mtc.4 ncr.4 qe.4 qsc.4 ra.4 rx.4 \
+       sii.4 smg.4 ts.4 uba.4 uda.4 vsbus.4 vxtbus.4 ze.4
 MLINKS=        mem.4 kmem.4
 MANSUBDIR=vax
 
index 297659e..fba30aa 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: dz.4,v 1.11 2007/05/31 19:19:57 jmc Exp $
+.\"    $OpenBSD: dz.4,v 1.12 2008/08/18 23:19:18 miod Exp $
 .\"    $NetBSD: dz.4,v 1.3 1996/03/03 17:13:29 thorpej Exp $
 .\"
 .\" Copyright (c) 1980, 1991 Regents of the University of California.
@@ -30,7 +30,7 @@
 .\"
 .\"     from: @(#)dz.4 6.3 (Berkeley) 3/27/91
 .\"
-.Dd $Mdocdate: May 31 2007 $
+.Dd $Mdocdate: August 18 2008 $
 .Dt DZ 4 vax
 .Os
 .Sh NAME
@@ -42,6 +42,7 @@ multiplexer device interface
 .Cd "dz0 at uba0 csr 0160100"
 .Cd "dz0 at vsbus0 csr 0x200a0000" Pq "DC-367"
 .Cd "dz0 at vsbus0 csr 0x25000000" Pq "VS4000/90 4000/10x MV3100/9x"
+.Cd "dz* at fwio?                " Pq "VAXstation 35x0 and 38x0"
 .Cd "lkkbd0 at dz0 line 0"
 .Cd "lkms0  at dz0 line 1"
 .Sh DESCRIPTION
@@ -51,24 +52,24 @@ provides 4 or 8 communication lines with partial modem control,
 adequate for
 .Ox
 dialup use.
-.Pp
-An optional argument
-.Ar flags
-may be supplied with the device specification
-in the config file indicating
-that the line corresponding to
-bit number
-.Ar i
-is not properly
-connected, and should be treated as hard-wired with carrier
-always present.
-Thus specifying
-.Ql flags 0x04
-for
-.Li dz0
-would cause line
-.Pa tty02
-to be treated in this way.
+.\" .Pp
+.\" An optional argument
+.\" .Ar flags
+.\" may be supplied with the device specification
+.\" in the config file indicating
+.\" that the line corresponding to
+.\" bit number
+.\" .Ar i
+.\" is not properly
+.\" connected, and should be treated as hard-wired with carrier
+.\" always present.
+.\" Thus specifying
+.\" .Ql flags 0x04
+.\" for
+.\" .Li dz0
+.\" would cause line
+.\" .Pa tty02
+.\" to be treated in this way.
 .Pp
 Normal I/O
 control parameters for individual lines are managed by
diff --git a/share/man/man4/man4.vax/fwio.4 b/share/man/man4/man4.vax/fwio.4
new file mode 100644 (file)
index 0000000..3a7e894
--- /dev/null
@@ -0,0 +1,48 @@
+.\"    $OpenBSD: fwio.4,v 1.1 2008/08/18 23:19:18 miod Exp $
+.\"
+.\" Copyright (c) 2008 Miodrag Vallat.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: August 18 2008 $
+.Dt FWIO 4 vax
+.Os
+.Sh NAME
+.Nm fwio
+.Nd Firefox Workstation I/O module
+.Sh SYNOPSIS
+.Cd "fwio* at mbus?"
+.Cd "dz* at fwio?"
+.Cd "le* at fwio?"
+.Cd "sii* at fwio?"
+.Sh DESCRIPTION
+The
+.Nm
+driver supports the M-bus I/O module found in VAXstation 35x0 and 38x0 series.
+Multiple modules may be installed in the system, and at least one is
+necessary for proper operation.
+.Pp
+The I/O module provides the following devices:
+.Pp
+.Bl -tag -width 8n -compact -offset indent
+.It Xr dz 4
+DZ-11 compatible serial interface, featuring a console or printer port on
+line 3, a modem port on line 2, and a keyboard and mouse port on lines 0 and 1.
+.It Xr le 4
+AMD LANCE Ethernet device
+.It Xr sii 4
+SII DSSI and SCSI controller
+.El
+.Sh SEE ALSO
+.Xr intro 4 ,
+.Xr mbus 4
index 08cc8b7..01e0862 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: intro.4,v 1.30 2008/03/31 12:43:41 jmc Exp $
+.\"    $OpenBSD: intro.4,v 1.31 2008/08/18 23:19:18 miod Exp $
 .\"    $NetBSD: intro.4,v 1.3 1996/03/03 17:13:44 thorpej Exp $
 .\"
 .\" Copyright (c) 1980, 1991 Regents of the University of California.
@@ -30,7 +30,7 @@
 .\"
 .\"     from: @(#)intro.4      6.6 (Berkeley) 3/27/91
 .\"
-.Dd $Mdocdate: March 31 2008 $
+.Dd $Mdocdate: August 18 2008 $
 .Dt INTRO 4 vax
 .Os
 .Sh NAME
@@ -110,6 +110,8 @@ DEC DEUNA/DELUA Ethernet device
 DHU-11/DHV-11 communications multiplexer
 .It Xr dz 4
 DZ-11 multiplexer device interface
+.It Xr fwio 4
+Firefox Workstation I/O module
 .It Xr gpx 4
 GPX color frame buffer
 .It Xr hp 4
@@ -128,6 +130,8 @@ VAX LED driver
 LK200/LK400 keyboard driver
 .It Xr lkms 4
 serial mouse driver
+.It Xr mbus 4
+VAXstation 35x0 and 38x0 bus
 .It Xr mscpbus 4
 MSCP device bus
 .It Xr mt 4
@@ -144,6 +148,8 @@ SC26C94 quad UART controller
 MSCP disk controller interface
 .It Xr rx 4
 DEC RX02 floppy disk interface
+.It Xr sii 4
+SII DSSI and SCSI controller
 .It Xr smg 4
 Small Monochrome Graphics frame buffer
 .It Xr ts 4
index ade6c83..dc68a64 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: le.4,v 1.12 2007/05/31 19:19:57 jmc Exp $
+.\"    $OpenBSD: le.4,v 1.13 2008/08/18 23:19:18 miod Exp $
 .\"
 .\" Copyright (c) 2000 Brandon Creighton
 .\"
@@ -23,7 +23,7 @@
 .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: May 31 2007 $
+.Dd $Mdocdate: August 18 2008 $
 .Dt LE 4 vax
 .Os
 .Sh NAME
@@ -32,6 +32,7 @@
 .Sh SYNOPSIS
 .Cd "le* at vsbus? csr 0x200e0000    " Pq "VAXstation onboard"
 .Cd "le* at ibus?                    " Pq "MicroVAX ibus"
+.Cd "le* at fwio?                    " Pq "VAXstation 35x0 and 38x0"
 .Sh DESCRIPTION
 The
 .Nm
@@ -45,7 +46,8 @@ chipset.
 .Pp
 Different machine configurations have varying types of connectors.
 The following types can be found:
-.Bl -tag -width 10n
+.Pp
+.Bl -tag -width 10n -compact -offset indent
 .It AUI/DIX
 15-pin connector (10base5)
 .It BNC
diff --git a/share/man/man4/man4.vax/mbus.4 b/share/man/man4/man4.vax/mbus.4
new file mode 100644 (file)
index 0000000..eb7c09d
--- /dev/null
@@ -0,0 +1,43 @@
+.\"    $OpenBSD: mbus.4,v 1.1 2008/08/18 23:19:18 miod Exp $
+.\"
+.\" Copyright (c) 2008 Miodrag Vallat.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: August 18 2008 $
+.Dt MBUS 4 vax
+.Os
+.Sh NAME
+.Nm mbus
+.Nd VAXstation 35x0 and 38x0 bus
+.Sh SYNOPSIS
+.Cd "mbus0 at mainbus0"
+.Sh DESCRIPTION
+The
+.Nm
+driver supports the M-bus found in VAXstation 35x0 and 38x0 series.
+It will perform the necessary configuration of all the boards connected
+to the bus, and will attach a specific driver if necessary.
+.Sh SUPPORTED DEVICES
+The following M-bus devices are supported:
+.Pp
+.Bl -tag -width 8n -compact -offset indent
+.It Xr fwio 4
+Firefox Workstation I/O module
+.\" .It Xr legss 4
+.\" Low-End Graphics Subsystem
+.It Xr uba 4
+UNIBUS/Q-bus controller
+.El
+.Sh SEE ALSO
+.Xr intro 4
diff --git a/share/man/man4/man4.vax/sii.4 b/share/man/man4/man4.vax/sii.4
new file mode 100644 (file)
index 0000000..b2a0db9
--- /dev/null
@@ -0,0 +1,43 @@
+.\"    $OpenBSD: sii.4,v 1.1 2008/08/18 23:19:18 miod Exp $
+.\"
+.\" Copyright (c) 2008 Miodrag Vallat.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: August 18 2008 $
+.Dt SII 4 vax
+.Os
+.Sh NAME
+.Nm sii
+.Nd SII DSSI and SCSI controller
+.Sh SYNOPSIS
+.Cd "sii* at fwio?"
+.Cd "scsibus* at sii?"
+.Sh DESCRIPTION
+The
+.Nm
+driver supports the SII controller, found on the I/O module on
+VAXstation 35x0 and 38x0 series.
+The SII controller can act as a DSSI or a SCSI controller, but not both.
+Only SCSI operation is supported under
+.Ox .
+.Sh SEE ALSO
+.Xr cd 4 ,
+.Xr ch 4 ,
+.Xr fwio 4 ,
+.Xr intro 4 ,
+.Xr scsi 4 ,
+.Xr sd 4 ,
+.Xr ss 4 ,
+.Xr st 4 ,
+.Xr uk 4
index cc79049..ab7527c 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: uba.4,v 1.12 2008/03/31 12:43:41 jmc Exp $
+.\"    $OpenBSD: uba.4,v 1.13 2008/08/18 23:19:18 miod Exp $
 .\"
 .\" Copyright (c) 2003 Jason L. Wright (jason@thought.net)
 .\" All rights reserved.
@@ -24,7 +24,7 @@
 .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: March 31 2008 $
+.Dd $Mdocdate: August 18 2008 $
 .Dt UBA 4 vax
 .Os
 .Sh NAME
@@ -32,6 +32,7 @@
 .Nd UNIBUS/Q-bus controller
 .Sh SYNOPSIS
 .Cd "uba0 at ibus0"
+.Cd "uba0 at mbus0 mid 0                    " Pq "VAXstation 35x0 and 38x0"
 .Sh DESCRIPTION
 The
 .Nm uba
index 67c30fa..aed6348 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: GENERIC,v 1.48 2006/11/06 20:28:20 miod Exp $
+#      $OpenBSD: GENERIC,v 1.49 2008/08/18 23:19:21 miod Exp $
 #
 # For further information on compiling OpenBSD kernels, see the config(8)
 # man page.
@@ -30,6 +30,7 @@ option                VAX46           # VS 4000/60
 option         VAX48           # VS 4000 VLC
 option         VAX49           # VS 4000/90
 option         VAX53           # VAX 4000 10X, MicroVAX 3100m9X
+option         VAX60           # VS 3[58][24]0
 option         VXT             # VXT2000 and VXT2000+
 
 # Old compat stuff; needed to run 4.3BSD Reno programs.
@@ -50,10 +51,11 @@ mainbus0    at root
 #sbi0          at mainbus0             # SBI, master bus on 11/780.
 #cmi0          at mainbus0             # 11/750 internal bus.
 #bi0           at mainbus0             # VAX 8200
-vsbus0         at mainbus0             # All VAXstations
+vsbus0         at mainbus0             # All VAXstations but 3[58][24]0
 ibus0          at mainbus0             # All Microvax
 #nbi0          at mainbus0             # VAX 8800
 #xmi0          at mainbus0             # VAX 6000
+mbus0          at mainbus0             # VS 3[58][24]0
 vxtbus0                at mainbus0             # VXT2000
 
 # Vsbus, the virtual VAXstation bus, and possible devices.
@@ -80,6 +82,16 @@ ze0          at ibus0                # SGEC on-board ethernet
 le0            at ibus0                # LANCE ethernet (MV3400)
 #shac0         at ibus0                # DSSI controller
 
+# M-bus found on VS 3[58][24]0
+fwio*          at mbus0 mid ?          # I/O module
+uba0           at mbus0 mid 0
+
+dz0            at fwio?                # DZ-11 like serial ports
+dz*            at fwio?                # DZ-11 (on additional fwio)
+le0            at fwio?                # LANCE ethernet
+le*            at fwio?                # LANCE (on additional fwio)
+sii*           at fwio?                # SII SCSI
+
 # VXT2000 devices
 ze0            at vxtbus0              # SGEC on-board ethernet
 qsc0           at vxtbus0              # serial ports
@@ -133,6 +145,7 @@ mt*         at mscpbus? drive?      # MSCP tape
 # SCSI devices
 scsibus*       at asc?
 scsibus*       at ncr?
+scsibus*       at sii?
 
 sd*            at scsibus?
 st*            at scsibus?
index bffd154..ec7e7f9 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: RAMDISK,v 1.29 2008/06/08 20:37:39 deraadt Exp $
+#      $OpenBSD: RAMDISK,v 1.30 2008/08/18 23:19:21 miod Exp $
 
 machine                vax                     # machine type
 
@@ -22,6 +22,7 @@ option                VAX46           # VS 4000/60
 option         VAX48           # VS 4000 VLC
 option         VAX49           # VS 4000/90
 option         VAX53           # VAX 4000/10{0,5,6}
+option         VAX60           # VS 3[58][24]0
 option         VXT             # VXT2000 and VXT2000+
 
 maxusers       8               # estimated number of users
@@ -61,6 +62,7 @@ vsbus0                at mainbus0             # All VAXstations
 ibus0          at mainbus0             # All Microvax
 #nbi0          at mainbus0             # VAX 8800
 #xmi0          at mainbus0             # VAX 6000
+mbus0          at mainbus0             # VS 3[58][24]0
 vxtbus0                at mainbus0             # VXT2000
 
 # Vsbus, the virtual VAXstation bus, and possible devices.
@@ -87,6 +89,16 @@ ze0          at ibus0                # SGEC on-board ethernet
 le0            at ibus0                # LANCE ethernet
 #shac0         at ibus0                # DSSI controller
 
+# M-bus found on VS 3[58][24]0
+fwio*          at mbus0 mid ?          # I/O module
+uba0           at mbus0 mid 0
+
+dz0            at fwio?                # DZ-11 like serial ports
+dz*            at fwio?                # DZ-11 (on additional fwio)
+le0            at fwio?                # LANCE ethernet
+le*            at fwio?                # LANCE (on additional fwio)
+sii*           at fwio?                # SII SCSI
+
 # VXT2000 devices
 ze0            at vxtbus0              # SGEC on-board ethernet
 qsc0           at vxtbus0              # serial ports
@@ -140,6 +152,7 @@ mt*         at mscpbus? drive?      # MSCP tape
 # SCSI devices
 scsibus*       at asc?
 scsibus*       at ncr?
+scsibus*       at sii?
 
 sd*            at scsibus?
 st*            at scsibus?
index 11ae4b2..0c34f42 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.vax,v 1.47 2008/08/18 23:07:22 miod Exp $
+#      $OpenBSD: files.vax,v 1.48 2008/08/18 23:19:21 miod Exp $
 #      $NetBSD: files.vax,v 1.60 1999/08/27 20:04:32 ragge Exp $
 #
 # new style config file for vax architecture
@@ -340,6 +340,9 @@ device      dh # XXX?
 attach dh at uba
 file   arch/vax/uba/dh.c                       dh needs-flag
 
+# M-bus on VS 3[58][24]0
+include "arch/vax/mbus/files.mbus"
+
 # Blinkenlichten
 device led
 attach led at mainbus
@@ -362,6 +365,7 @@ file        arch/vax/vax/ka46.c                     vax46
 file   arch/vax/vax/ka48.c                     vax48
 file   arch/vax/vax/ka49.c                     vax49
 file   arch/vax/vax/ka53.c                     vax53
+file   arch/vax/vax/ka60.c                     vax60
 file   arch/vax/vax/emulate.s                  insn_emulate
 file   arch/vax/vax/unimpl_emul.s              insn_emulate
 file   arch/vax/vax/ka650.c                    vax650
index fe2848d..1f81a9f 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.dec,v 1.5 2008/08/18 23:04:28 miod Exp $
+#      $OpenBSD: files.dec,v 1.6 2008/08/18 23:19:22 miod Exp $
 #      $NetBSD: files.dec,v 1.4 1999/08/04 07:17:51 nisimura Exp $
 #
 # Config file and device description for machine-independent
@@ -14,3 +14,7 @@ file  arch/vax/dec/wskbdmap_lk201.c           lkkbd
 
 # VSxxx mouse
 file   arch/vax/dec/vsms_ws.c                  lkms
+
+# DC7061 SII DSSI/SCSI controller
+device sii: scsi
+file   arch/vax/dec/sii.c                      sii
diff --git a/sys/arch/vax/dec/sii.c b/sys/arch/vax/dec/sii.c
new file mode 100644 (file)
index 0000000..0a677fa
--- /dev/null
@@ -0,0 +1,1798 @@
+/*     $OpenBSD: sii.c,v 1.1 2008/08/18 23:19:22 miod Exp $    */
+/*     $NetBSD: sii.c,v 1.42 2000/06/02 20:20:29 mhitch Exp $  */
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ *
+ *     @(#)sii.c       8.2 (Berkeley) 11/30/93
+ *
+ * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/devSII.c,
+ *     v 9.2 89/09/14 13:37:41 jhh Exp $ SPRITE (DECWRL)";
+ */
+
+/*
+ * SCSI interface driver
+ */
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_message.h>
+#ifdef DEBUG
+#include <scsi/scsi_disk.h>
+#endif
+
+#include <vax/dec/siireg.h>            /* device registers */
+#include <vax/dec/siivar.h>            /* softc and prototypes */
+
+/* XXX not in scsi/scsi_message.h */
+#define        MSG_EXT_MODIFY_DATA_PTR         0x00
+
+struct cfdriver sii_cd = {
+       NULL, "sii", DV_DULL
+};
+
+/*
+ * MACROS for timing out spin loops.
+ *
+ * Wait until expression is true.
+ *
+ * Control register bits can change at any time so when the CPU
+ * reads a register, the bits might change and
+ * invalidate the setup and hold times for the CPU.
+ * This macro reads the register twice to be sure the value is stable.
+ *
+ *     args:   var             - variable to save control register contents
+ *             reg             - control register to read
+ *             expr            - expression to spin on
+ *             spincount       - maximum number of times through the loop
+ *             cntr            - variable for number of tries
+ */
+#define        SII_WAIT_UNTIL(var, reg, expr, spincount, cntr) {       \
+               u_int tmp = reg;                                \
+               for (cntr = 0; cntr < spincount; cntr++) {      \
+                       while (tmp != (var = reg))              \
+                               tmp = var;                      \
+                       if (expr)                               \
+                               break;                          \
+                       if (cntr >= 100)                        \
+                               DELAY(100);                     \
+               }                                               \
+       }
+
+#ifdef DEBUG
+int    sii_debug = 1;
+int    sii_debug_cmd;
+int    sii_debug_bn;
+int    sii_debug_sz;
+#define NLOG 16
+struct sii_log {
+       u_short cstat;
+       u_short dstat;
+       u_short comm;
+       u_short msg;
+       int     rlen;
+       int     dlen;
+       int     target;
+} sii_log[NLOG], *sii_logp = sii_log;
+#endif
+
+#define NORESET        0
+#define RESET  1
+#define NOWAIT 0
+#define WAIT   1
+
+#if 0
+/*
+ * XXX That hardcoded 7 below implies SII_NCMD <= 7, which is not the case...
+ * XXX Thankfully all uses of SII_BUF_ADDR are in #if 0 sections (and this
+ * XXX should be reasonably safe as long as we use 7 as the host id).
+ */
+/*
+ * Define a safe address in the SCSI buffer for doing status & message DMA
+ * XXX why not add another field to softc?
+ */
+#define SII_BUF_ADDR(sc)       (SII_MAX_DMA_XFER_LENGTH * 7 * 2)
+#endif
+
+/*
+ * Forward references
+ */
+
+void   sii_Reset(struct sii_softc *sc, int resetbus);
+void   sii_StartCmd(struct sii_softc *sc, int target);
+void   sii_CmdDone(struct sii_softc *sc, int target, int error);
+void   sii_DoIntr(struct sii_softc *sc, u_int dstat);
+void   sii_StateChg(struct sii_softc *sc, u_int cstat);
+int    sii_GetByte(SIIRegs *regs, int phase, int ack);
+void   sii_DoSync(struct sii_softc *, State *);
+void   sii_StartDMA(SIIRegs *regs, int phase, u_int dmaAddr, int size);
+int    sii_scsi_cmd(struct scsi_xfer *);
+#ifdef DEBUG
+void   sii_DumpLog(void);
+#endif
+
+struct scsi_adapter sii_scsiswitch = {
+       sii_scsi_cmd,
+       minphys,
+       NULL,
+       NULL,
+       NULL
+};
+
+struct scsi_device sii_scsidev = {
+       NULL,
+       NULL,
+       NULL,
+       NULL
+};
+
+void
+sii_attach(sc)
+       struct sii_softc *sc;
+{
+       struct scsibus_attach_args saa;
+       int i;
+
+       sc->sc_target = -1;     /* no command active */
+
+       /*
+        * Give each target its own DMA buffer region.
+        * Make it big enough for 2 max transfers so we can ping pong buffers
+        * while we copy the data.
+        */
+       for (i = 0; i < SII_NCMD; i++) {
+               sc->sc_st[i].dmaAddr[0] =
+                       SII_MAX_DMA_XFER_LENGTH * 2 * i;
+               sc->sc_st[i].dmaAddr[1] = sc->sc_st[i].dmaAddr[0] +
+                       SII_MAX_DMA_XFER_LENGTH;
+       }
+
+       sii_Reset(sc, RESET);
+       printf("\n");
+
+       /*
+        * fill in the prototype scsi_link.
+        */
+       sc->sc_link.adapter = &sii_scsiswitch;
+       sc->sc_link.adapter_buswidth = 8;
+       sc->sc_link.adapter_softc = sc;
+       sc->sc_link.adapter_target = sc->sc_regs->id & SII_IDMSK;
+       sc->sc_link.device = &sii_scsidev;
+       sc->sc_link.openings = 1;       /* driver can't queue requests yet */
+
+       /*
+        * Now try to attach all the sub-devices
+        */
+       bzero(&saa, sizeof(saa));
+       saa.saa_sc_link = &sc->sc_link;
+       config_found(&sc->sc_dev, &saa, scsiprint);
+}
+
+/*
+ * Start activity on a SCSI device.
+ * We maintain information on each device separately since devices can
+ * connect/disconnect during an operation.
+ */
+
+int
+sii_scsi_cmd(xs)
+       struct scsi_xfer *xs;
+{
+       int target = xs->sc_link->target;
+       struct sii_softc *sc = xs->sc_link->adapter_softc;
+       int s;
+       int count;
+
+       s = splbio();
+       if (sc->sc_cmd[target]) {
+               splx(s);
+#ifdef DEBUG
+               printf("[busy at start]\n");
+#endif
+               return (TRY_AGAIN_LATER);
+       }
+       /*
+        * Build a ScsiCmd for this command and start it.
+        */
+       sc->sc_xs[target] = xs;
+       sc->sc_cmd[target] = &sc->sc_cmd_fake[target];  /* XXX */
+       sc->sc_cmd[target]->unit = 0;
+       sc->sc_cmd[target]->flags = 0;
+       sc->sc_cmd[target]->buflen = xs->datalen;
+       sc->sc_cmd[target]->buf = xs->data;
+       sc->sc_cmd[target]->cmdlen = xs->cmdlen;
+       sc->sc_cmd[target]->cmd = (u_char *)xs->cmd;
+       sc->sc_cmd[target]->lun = xs->sc_link->lun;
+       sii_StartCmd(sc, target);
+       splx(s);
+
+       if ((xs->flags & ITSDONE) != 0)
+               return (COMPLETE);
+       if ((xs->flags & SCSI_POLL) == 0)
+               return (SUCCESSFULLY_QUEUED);
+       count = xs->timeout;
+       while (count) {
+               s = splbio();
+#if 0
+               (void)sii_intr(sc);
+#else
+{
+       u_int dstat;
+
+       /*
+        * Find which controller caused the interrupt.
+        */
+       dstat = sc->sc_regs->dstat;
+       if (dstat & (SII_CI | SII_DI))
+               sii_DoIntr(sc, dstat);
+}
+#endif
+               splx(s);
+               if ((xs->flags & ITSDONE) != 0)
+                       break;
+               /* XXX schedule another command? */
+               DELAY(1000);
+               --count;
+       }
+       if ((xs->flags & ITSDONE) != 0)
+               return (COMPLETE);
+       xs->error = XS_TIMEOUT;
+       xs->flags |= ITSDONE;
+       s = splbio();
+       scsi_done(xs);
+       splx(s);
+       return (COMPLETE);
+}
+
+/*
+ * Check to see if any SII chips have pending interrupts
+ * and process as appropriate.
+ */
+int
+sii_intr(xxxsc)
+       void *xxxsc;
+{
+       struct sii_softc *sc = xxxsc;
+       u_int dstat;
+
+       /*
+        * Find which controller caused the interrupt.
+        */
+       dstat = sc->sc_regs->dstat;
+       if (dstat & (SII_CI | SII_DI)) {
+               sii_DoIntr(sc, dstat);
+               return (1);
+       }
+
+       return (0);
+}
+
+/*
+ * Reset the SII chip and do a SCSI reset if 'reset' is true.
+ * NOTE: if !cold && reset, should probably probe for devices
+ * since a SCSI bus reset will set UNIT_ATTENTION.
+ */
+void
+sii_Reset(sc, reset)
+       struct sii_softc* sc;
+       int reset;                              /* TRUE => reset SCSI bus */
+{
+       SIIRegs *regs = sc->sc_regs;
+
+#ifdef DEBUG
+       if (sii_debug > 1)
+               printf("sii: RESET\n");
+#endif
+       /*
+        * Reset the SII chip.
+        */
+       regs->comm = SII_CHRESET;
+       /*
+        * Set arbitrated bus mode.
+        */
+       regs->csr = SII_HPM;
+       /*
+        * Set host adapter ID.
+        */
+       regs->id = SII_ID_IO | sc->sc_hostid;
+       /*
+        * Enable SII to drive the SCSI bus.
+        */
+       regs->dictrl = SII_PRE;
+       regs->dmctrl = 0;
+
+       if (reset) {
+               int i;
+
+               /*
+                * Assert SCSI bus reset for at least 25 Usec to clear the
+                * world. SII_DO_RST is self clearing.
+                * Delay 250 ms before doing any commands.
+                */
+               regs->comm = SII_DO_RST;
+               DELAY(250000);
+
+               /* rearbitrate synchronous offset */
+               for (i = 0; i < SII_NCMD; i++)
+                       sc->sc_st[i].dmaReqAck = 0;
+       }
+
+       /*
+        * Clear any pending interrupts from the reset.
+        */
+       regs->cstat = regs->cstat;
+       regs->dstat = regs->dstat;
+       /*
+        * Set up SII for arbitrated bus mode, SCSI parity checking,
+        * Reselect Enable, and Interrupt Enable.
+        */
+       regs->csr = SII_HPM | SII_RSE | SII_PCE | SII_IE;
+}
+
+/*
+ * Start a SCSI command by sending the cmd data
+ * to a SCSI controller via the SII.
+ * Call the device done procedure if it can't be started.
+ * NOTE: we should be called with interrupts disabled.
+ */
+void
+sii_StartCmd(sc, target)
+       struct sii_softc *sc;   /* which SII to use */
+       int target;             /* which command to start */
+{
+       SIIRegs *regs;
+       ScsiCmd *scsicmd;
+       State *state;
+       u_int status;
+       int error, retval;
+
+       splassert(IPL_BIO);
+
+       /* if another command is currently in progress, just wait */
+       if (sc->sc_target >= 0)
+               return;
+
+       /* initialize state information for this command */
+       scsicmd = sc->sc_cmd[target];
+       state = &sc->sc_st[target];
+       state->flags = FIRST_DMA;
+       state->prevComm = 0;
+       state->dmalen = 0;
+       state->dmaCurPhase = -1;
+       state->dmaPrevPhase = -1;
+       state->dmaBufIndex = 0;
+       state->cmd = scsicmd->cmd;
+       state->cmdlen = scsicmd->cmdlen;
+       if ((state->buflen = scsicmd->buflen) == 0) {
+               state->dmaDataPhase = -1; /* illegal phase. shouldn't happen */
+               state->buf = (char *)0;
+       } else {
+               state->buf = scsicmd->buf;
+       }
+
+#ifdef DEBUG
+       if (sii_debug > 1) {
+               printf("sii_StartCmd: %s target %d cmd 0x%x addr %p size %d DMA %d\n",
+                       sc->sc_dev.dv_xname,
+                       target, scsicmd->cmd[0], scsicmd->buf, scsicmd->buflen,
+                       state->dmaDataPhase);
+       }
+       sii_debug_cmd = scsicmd->cmd[0];
+       if (scsicmd->cmd[0] == READ_BIG ||
+           scsicmd->cmd[0] == WRITE_BIG) {
+               sii_debug_bn = (scsicmd->cmd[2] << 24) |
+                       (scsicmd->cmd[3] << 16) |
+                       (scsicmd->cmd[4] << 8) |
+                       scsicmd->cmd[5];
+               sii_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8];
+       } else {
+               sii_debug_bn = 0;
+               sii_debug_sz = 0;
+       }
+#endif
+
+       /* try to select the target */
+       regs = sc->sc_regs;
+
+       /*
+        * Another device may have selected us; in which case,
+        * this command will be restarted later.
+        */
+       if ((status = regs->dstat) & (SII_CI | SII_DI)) {
+               sii_DoIntr(sc, status);
+               return;
+       }
+
+       sc->sc_target = target;
+#if 0
+       /* seem to have problems with synchronous transfers */
+       if (scsicmd->flags & SCSICMD_USE_SYNC) {
+               printf("sii_StartCmd: doing extended msg\n"); /* XXX */
+               /*
+                * Setup to send both the identify message and the synchronous
+                * data transfer request.
+                */
+               sc->sc_buf[0] = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG;
+               sc->sc_buf[1] = MSG_EXTENDED;
+               sc->sc_buf[2] = MSG_EXT_SDTR_LEN;
+               sc->sc_buf[3] = MSG_EXT_SDTR;
+               sc->sc_buf[4] = 0;
+               sc->sc_buf[5] = 3;              /* maximum SII chip supports */
+
+               state->dmaCurPhase = SII_MSG_OUT_PHASE,
+               state->dmalen = 6;
+               sc->sii_copytobuf(sc, sc->sc_buf, SII_BUF_ADDR(sc), 6);
+               regs->slcsr = target;
+               regs->dmctrl = state->dmaReqAck;
+               regs->dmaddrl = SII_BUF_ADDR(sc);
+               regs->dmaddrh = SII_BUF_ADDR(sc) >> 16;
+               regs->dmlotc = 6;
+               regs->comm = SII_DMA | SII_INXFER | SII_SELECT | SII_ATN |
+                       SII_CON | SII_MSG_OUT_PHASE;
+       } else
+#endif
+       {
+               /* do a chained, select with ATN and programmed I/O command */
+               regs->data = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG |
+                   scsicmd->lun;
+               regs->slcsr = target;
+               regs->dmctrl = state->dmaReqAck;
+               regs->comm = SII_INXFER | SII_SELECT | SII_ATN | SII_CON |
+                       SII_MSG_OUT_PHASE;
+       }
+
+       /*
+        * Wait for something to happen
+        * (should happen soon or we would use interrupts).
+        */
+       SII_WAIT_UNTIL(status, regs->cstat, status & (SII_CI | SII_DI),
+               SII_WAIT_COUNT/4, retval);
+
+       /* check to see if we are connected OK */
+       if ((status & (SII_RST | SII_SCH | SII_STATE_MSK)) ==
+           (SII_SCH | SII_CON)) {
+               regs->cstat = status;
+
+#ifdef DEBUG
+               sii_logp->target = target;
+               sii_logp->cstat = status;
+               sii_logp->dstat = 0;
+               sii_logp->comm = regs->comm;
+               sii_logp->msg = -1;
+               sii_logp->rlen = state->buflen;
+               sii_logp->dlen = state->dmalen;
+               if (++sii_logp >= &sii_log[NLOG])
+                       sii_logp = sii_log;
+#endif
+
+               /* wait a short time for command phase */
+               SII_WAIT_UNTIL(status, regs->dstat, status & SII_MIS,
+                       SII_WAIT_COUNT, retval);
+#ifdef DEBUG
+               if (sii_debug > 2)
+                       printf("sii_StartCmd: ds %x cnt %d\n", status, retval);
+#endif
+               if ((status & (SII_CI | SII_MIS | SII_PHASE_MSK)) !=
+                   (SII_MIS | SII_CMD_PHASE)) {
+                       printf("sii_StartCmd: timeout cs %x ds %x cnt %d\n",
+                               regs->cstat, status, retval); /* XXX */
+                       /* process interrupt or continue until it happens */
+                       if (status & (SII_CI | SII_DI))
+                               sii_DoIntr(sc, status);
+                       return;
+               }
+               regs->dstat = SII_DNE;  /* clear Msg Out DMA done */
+
+               /* send command data */
+               sc->sii_copytobuf(sc, state->cmd, state->dmaAddr[0],
+                   state->cmdlen);
+               sii_StartDMA(regs, state->dmaCurPhase = SII_CMD_PHASE,
+                       state->dmaAddr[0], state->dmalen = scsicmd->cmdlen);
+
+               /* wait a little while for DMA to finish */
+               SII_WAIT_UNTIL(status, regs->dstat, status & (SII_CI | SII_DI),
+                       SII_WAIT_COUNT, retval);
+#ifdef DEBUG
+               if (sii_debug > 2)
+                       printf("sii_StartCmd: ds %x, cnt %d\n", status, retval);
+#endif
+               if (status & (SII_CI | SII_DI))
+                       sii_DoIntr(sc, status);
+#ifdef DEBUG
+               if (sii_debug > 2)
+                       printf("sii_StartCmd: DONE ds %x\n", regs->dstat);
+#endif
+               return;
+       }
+
+       /*
+        * Another device may have selected us; in which case,
+        * this command will be restarted later.
+        */
+       if (status & (SII_CI | SII_DI)) {
+               sii_DoIntr(sc, regs->dstat);
+               return;
+       }
+
+       /*
+        * Disconnect if selection command still in progress.
+        */
+       if (status & SII_SIP) {
+               error = XS_SELTIMEOUT;  /* device didn't respond */
+               regs->comm = SII_DISCON;
+               SII_WAIT_UNTIL(status, regs->cstat,
+                       !(status & (SII_CON | SII_SIP)),
+                       SII_WAIT_COUNT, retval);
+       } else
+               error = XS_BUSY;        /* couldn't get the bus */
+#ifdef DEBUG
+       if (sii_debug > 1)
+               printf("sii_StartCmd: Couldn't select target %d error %d\n",
+                       target, error);
+#endif
+       sc->sc_target = -1;
+       regs->cstat = 0xffff;
+       regs->dstat = 0xffff;
+       regs->comm = 0;
+       sii_CmdDone(sc, target, error);
+}
+
+/*
+ * Process interrupt conditions.
+ */
+void
+sii_DoIntr(sc, dstat)
+       struct sii_softc *sc;
+       u_int dstat;
+{
+       SIIRegs *regs = sc->sc_regs;
+       State *state;
+       u_int cstat;
+       int i, msg;
+       u_int comm;
+
+again:
+       comm = regs->comm;
+
+#ifdef DEBUG
+       if (sii_debug > 3)
+               printf("sii_DoIntr: cs %x, ds %x cm %x ",
+                       regs->cstat, dstat, comm);
+       sii_logp->target = sc->sc_target;
+       sii_logp->cstat = regs->cstat;
+       sii_logp->dstat = dstat;
+       sii_logp->comm = comm;
+       sii_logp->msg = -1;
+       if (sc->sc_target >= 0) {
+               sii_logp->rlen = sc->sc_st[sc->sc_target].buflen;
+               sii_logp->dlen = sc->sc_st[sc->sc_target].dmalen;
+       } else {
+               sii_logp->rlen = 0;
+               sii_logp->dlen = 0;
+       }
+       if (++sii_logp >= &sii_log[NLOG])
+               sii_logp = sii_log;
+#endif
+
+       regs->dstat = dstat;    /* acknowledge everything */
+
+       if (dstat & SII_CI) {
+               /* deglitch cstat register */
+               msg = regs->cstat;
+               while (msg != (cstat = regs->cstat))
+                       msg = cstat;
+               regs->cstat = cstat;    /* acknowledge everything */
+#ifdef DEBUG
+               if (sii_logp > sii_log)
+                       sii_logp[-1].cstat = cstat;
+               else
+                       sii_log[NLOG - 1].cstat = cstat;
+#endif
+
+               /* check for a BUS RESET */
+               if (cstat & SII_RST) {
+                       printf("%s: SCSI bus reset\n", sc->sc_dev.dv_xname);
+                       /* need to flush disconnected commands */
+                       for (i = 0; i < SII_NCMD; i++) {
+                               if (!sc->sc_cmd[i])
+                                       continue;
+                               sii_CmdDone(sc, i, XS_DRIVER_STUFFUP /* EIO */);
+                       }
+                       /* rearbitrate synchronous offset */
+                       for (i = 0; i < SII_NCMD; i++)
+                               sc->sc_st[i].dmaReqAck = 0;
+                       sc->sc_target = -1;
+                       return;
+               }
+
+#ifdef notdef
+               /*
+                * Check for a BUS ERROR.
+                * According to DEC, this feature doesn't really work
+                * and to just clear the bit if it's set.
+                */
+               if (cstat & SII_BER) {
+                       regs->cstat = SII_BER;
+               }
+#endif
+
+               /* check for state change */
+               if (cstat & SII_SCH) {
+                       sii_StateChg(sc, cstat);
+                       comm = regs->comm;
+               }
+       }
+
+       /* check for DMA completion */
+       if (dstat & SII_DNE) {
+               u_int dma;
+               char *buf;
+
+               /*
+                * There is a race condition with SII_SCH. There is a short
+                * window between the time a SII_SCH is seen after a disconnect
+                * and when the SII_SCH is cleared. A reselect can happen
+                * in this window and we will clear the SII_SCH without
+                * processing the reconnect.
+                */
+               if (sc->sc_target < 0) {
+                       cstat = regs->cstat;
+                       printf("%s: target %d DNE?? dev %d,%d cs %x\n",
+                               sc->sc_dev.dv_xname, sc->sc_target,
+                               regs->slcsr, regs->destat,
+                               cstat); /* XXX */
+                       if (cstat & SII_DST) {
+                               sc->sc_target = regs->destat;
+                               state = &sc->sc_st[sc->sc_target];
+                               state->prevComm = 0;
+                       } else
+                               panic("sc_target 1");
+               }
+               state = &sc->sc_st[sc->sc_target];
+               /* check for a PARITY ERROR */
+               if (dstat & SII_IPE) {
+                       state->flags |= PARITY_ERR;
+                       printf("%s: Parity error\n", sc->sc_dev.dv_xname);
+                       goto abort;
+               }
+               /* dmalen = amount left to transfer, i = amount transfered */
+               i = state->dmalen;
+               state->dmalen = 0;
+               state->dmaCurPhase = -1;
+#ifdef DEBUG
+               if (sii_debug > 4) {
+                       printf("DNE: amt %d ", i);
+                       if (!(dstat & SII_TCZ))
+                               printf("no TCZ?? (%d) ", regs->dmlotc);
+               } else if (!(dstat & SII_TCZ)) {
+                       printf("%s: device %d: no TCZ?? (%d)\n",
+                               sc->sc_dev.dv_xname, sc->sc_target, regs->dmlotc);
+                       sii_DumpLog(); /* XXX */
+               }
+#endif
+               switch (comm & SII_PHASE_MSK) {
+               case SII_CMD_PHASE:
+                       state->cmdlen -= i;
+                       break;
+
+               case SII_DATA_IN_PHASE:
+                       /* check for more data for the same phase */
+                       dma = state->dmaAddr[state->dmaBufIndex];
+                       buf = state->buf;
+                       state->buf += i;
+                       state->buflen -= i;
+                       if (state->buflen > 0 && !(dstat & SII_MIS)) {
+                               int len;
+
+                               /* start reading next chunk */
+                               len = state->buflen;
+                               if (len > SII_MAX_DMA_XFER_LENGTH)
+                                       len = SII_MAX_DMA_XFER_LENGTH;
+                               state->dmaBufIndex = !state->dmaBufIndex;
+                               sii_StartDMA(regs,
+                                       state->dmaCurPhase = SII_DATA_IN_PHASE,
+                                       state->dmaAddr[state->dmaBufIndex],
+                                       state->dmaCnt = state->dmalen = len);
+                               dstat &= ~(SII_IBF | SII_TBE);
+                       }
+                       /* copy in the data */
+                       sc->sii_copyfrombuf(sc, dma, buf, i);
+                       break;
+
+               case SII_DATA_OUT_PHASE:
+                       state->dmaBufIndex = !state->dmaBufIndex;
+                       state->buf += i;
+                       state->buflen -= i;
+
+                       /* check for more data for the same phase */
+                       if (state->buflen <= 0 || (dstat & SII_MIS))
+                               break;
+
+                       /* start next chunk */
+                       i = state->buflen;
+                       if (i > SII_MAX_DMA_XFER_LENGTH) {
+                               sii_StartDMA(regs, state->dmaCurPhase =
+                                       SII_DATA_OUT_PHASE,
+                                       state->dmaAddr[state->dmaBufIndex],
+                                       state->dmaCnt = state->dmalen =
+                                       SII_MAX_DMA_XFER_LENGTH);
+                               /* prepare for next chunk */
+                               i -= SII_MAX_DMA_XFER_LENGTH;
+                               if (i > SII_MAX_DMA_XFER_LENGTH)
+                                       i = SII_MAX_DMA_XFER_LENGTH;
+                               sc->sii_copytobuf(sc, (u_char *)(state->buf +
+                                   SII_MAX_DMA_XFER_LENGTH),
+                                   state->dmaAddr[!state->dmaBufIndex], i);
+                       } else {
+                               sii_StartDMA(regs, state->dmaCurPhase =
+                                       SII_DATA_OUT_PHASE,
+                                       state->dmaAddr[state->dmaBufIndex],
+                                       state->dmaCnt = state->dmalen = i);
+                       }
+                       dstat &= ~(SII_IBF | SII_TBE);
+               }
+       }
+
+       /* check for phase change or another MsgIn/Out */
+       if (dstat & (SII_MIS | SII_IBF | SII_TBE)) {
+               /*
+                * There is a race condition with SII_SCH. There is a short
+                * window between the time a SII_SCH is seen after a disconnect
+                * and when the SII_SCH is cleared. A reselect can happen
+                * in this window and we will clear the SII_SCH without
+                * processing the reconnect.
+                */
+               if (sc->sc_target < 0) {
+                       cstat = regs->cstat;
+                       printf("%s: target %d MIS?? dev %d,%d cs %x ds %x\n",
+                               sc->sc_dev.dv_xname, sc->sc_target,
+                               regs->slcsr, regs->destat,
+                               cstat, dstat); /* XXX */
+                       if (cstat & SII_DST) {
+                               sc->sc_target = regs->destat;
+                               state = &sc->sc_st[sc->sc_target];
+                               state->prevComm = 0;
+                       } else {
+#ifdef DEBUG
+                               sii_DumpLog();
+#endif
+                               panic("sc_target 2");
+                       }
+               }
+               state = &sc->sc_st[sc->sc_target];
+               switch (dstat & SII_PHASE_MSK) {
+               case SII_CMD_PHASE:
+                       if (state->dmaPrevPhase >= 0) {
+                               /* restart DMA after disconnect/reconnect */
+                               if (state->dmaPrevPhase != SII_CMD_PHASE) {
+                                       printf("%s: device %d: DMA reselect phase doesn't match\n",
+                                               sc->sc_dev.dv_xname, sc->sc_target);
+                                       goto abort;
+                               }
+                               state->dmaCurPhase = SII_CMD_PHASE;
+                               state->dmaPrevPhase = -1;
+                               regs->dmaddrl = state->dmaAddrL;
+                               regs->dmaddrh = state->dmaAddrH;
+                               regs->dmlotc = state->dmaCnt;
+                               if (state->dmaCnt & 1)
+                                       regs->dmabyte = state->dmaByte;
+                               regs->comm = SII_DMA | SII_INXFER |
+                                       (comm & SII_STATE_MSK) | SII_CMD_PHASE;
+#ifdef DEBUG
+                               if (sii_debug > 4)
+                                       printf("Cmd dcnt %d dadr %x ",
+                                               state->dmaCnt,
+                                               (state->dmaAddrH << 16) |
+                                                       state->dmaAddrL);
+#endif
+                       } else {
+                               /* send command data */
+                               i = state->cmdlen;
+                               if (i == 0) {
+                                       printf("%s: device %d: cmd count exceeded\n",
+                                               sc->sc_dev.dv_xname, sc->sc_target);
+                                       goto abort;
+                               }
+                               sc->sii_copytobuf(sc, state->cmd,
+                                   state->dmaAddr[0], i);
+                               sii_StartDMA(regs, state->dmaCurPhase =
+                                       SII_CMD_PHASE, state->dmaAddr[0],
+                                       state->dmaCnt = state->dmalen = i);
+                       }
+                       /* wait a short time for XFER complete */
+                       SII_WAIT_UNTIL(dstat, regs->dstat,
+                               dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
+                       if (dstat & (SII_CI | SII_DI)) {
+#ifdef DEBUG
+                               if (sii_debug > 4)
+                                       printf("cnt %d\n", i);
+                               else if (sii_debug > 0)
+                                       printf("sii_DoIntr: cmd wait ds %x cnt %d\n",
+                                               dstat, i);
+#endif
+                               goto again;
+                       }
+                       break;
+
+               case SII_DATA_IN_PHASE:
+               case SII_DATA_OUT_PHASE:
+                       if (state->cmdlen > 0) {
+                               printf("%s: device %d: cmd 0x%x: command data not all sent (%d) 1\n",
+                                       sc->sc_dev.dv_xname, sc->sc_target,
+                                       sc->sc_cmd[sc->sc_target]->cmd[0],
+                                       state->cmdlen);
+                               state->cmdlen = 0;
+#ifdef DEBUG
+                               sii_DumpLog();
+#endif
+                       }
+                       if (state->dmaPrevPhase >= 0) {
+                               /* restart DMA after disconnect/reconnect */
+                               if (state->dmaPrevPhase !=
+                                   (dstat & SII_PHASE_MSK)) {
+                                       printf("%s: device %d: DMA reselect phase doesn't match\n",
+                                               sc->sc_dev.dv_xname, sc->sc_target);
+                                       goto abort;
+                               }
+                               state->dmaCurPhase = state->dmaPrevPhase;
+                               state->dmaPrevPhase = -1;
+                               regs->dmaddrl = state->dmaAddrL;
+                               regs->dmaddrh = state->dmaAddrH;
+                               regs->dmlotc = state->dmaCnt;
+                               if (state->dmaCnt & 1)
+                                       regs->dmabyte = state->dmaByte;
+                               regs->comm = SII_DMA | SII_INXFER |
+                                       (comm & SII_STATE_MSK) |
+                                       state->dmaCurPhase;
+#ifdef DEBUG
+                               if (sii_debug > 4)
+                                       printf("Data %d dcnt %d dadr %x ",
+                                               state->dmaDataPhase,
+                                               state->dmaCnt,
+                                               (state->dmaAddrH << 16) |
+                                                       state->dmaAddrL);
+#endif
+                               break;
+                       }
+#ifdef DEBUG
+                       if (sii_debug > 4) {
+                               printf("Data %d ", state->dmaDataPhase);
+                               if (sii_debug > 5)
+                                       printf("\n");
+                       }
+#endif
+                       i = state->buflen;
+                       if (i == 0) {
+                               printf("%s: device %d: data count exceeded\n",
+                                       sc->sc_dev.dv_xname, sc->sc_target);
+                               goto abort;
+                       }
+                       if (i > SII_MAX_DMA_XFER_LENGTH)
+                               i = SII_MAX_DMA_XFER_LENGTH;
+                       if ((dstat & SII_PHASE_MSK) == SII_DATA_IN_PHASE) {
+                               sii_StartDMA(regs,
+                                       state->dmaCurPhase = SII_DATA_IN_PHASE,
+                                       state->dmaAddr[state->dmaBufIndex],
+                                       state->dmaCnt = state->dmalen = i);
+                               break;
+                       }
+                       /* start first chunk */
+                       if (state->flags & FIRST_DMA) {
+                               state->flags &= ~FIRST_DMA;
+                               sc->sii_copytobuf(sc, (u_char *)state->buf,
+                                   state->dmaAddr[state->dmaBufIndex], i);
+                       }
+                       sii_StartDMA(regs,
+                               state->dmaCurPhase = SII_DATA_OUT_PHASE,
+                               state->dmaAddr[state->dmaBufIndex],
+                               state->dmaCnt = state->dmalen = i);
+                       i = state->buflen - SII_MAX_DMA_XFER_LENGTH;
+                       if (i > 0) {
+                               /* prepare for next chunk */
+                               if (i > SII_MAX_DMA_XFER_LENGTH)
+                                       i = SII_MAX_DMA_XFER_LENGTH;
+                               sc->sii_copytobuf(sc, (u_char *)(state->buf +
+                                   SII_MAX_DMA_XFER_LENGTH),
+                                   state->dmaAddr[!state->dmaBufIndex], i);
+                       }
+                       break;
+
+               case SII_STATUS_PHASE:
+                       if (state->cmdlen > 0) {
+                               printf("%s: device %d: cmd 0x%x: command data not all sent (%d) 2\n",
+                                       sc->sc_dev.dv_xname, sc->sc_target,
+                                       sc->sc_cmd[sc->sc_target]->cmd[0],
+                                       state->cmdlen);
+                               state->cmdlen = 0;
+#ifdef DEBUG
+                               sii_DumpLog();
+#endif
+                       }
+
+                       /* read amount transfered if DMA didn't finish */
+                       if (state->dmalen > 0) {
+                               i = state->dmalen - regs->dmlotc;
+                               state->dmalen = 0;
+                               state->dmaCurPhase = -1;
+                               regs->dmlotc = 0;
+                               regs->comm = comm &
+                                       (SII_STATE_MSK | SII_PHASE_MSK);
+                               regs->dstat = SII_DNE;
+#ifdef DEBUG
+                               if (sii_debug > 4)
+                                       printf("DMA amt %d ", i);
+#endif
+                               switch (comm & SII_PHASE_MSK) {
+                               case SII_DATA_IN_PHASE:
+                                       /* copy in the data */
+                                       sc->sii_copyfrombuf(sc,
+                                           state->dmaAddr[state->dmaBufIndex],
+                                           state->buf, i);
+
+                               case SII_CMD_PHASE:
+                               case SII_DATA_OUT_PHASE:
+                                       state->buflen -= i;
+                               }
+                       }
+
+                       /* read a one byte status message */
+                       state->statusByte = msg =
+                               sii_GetByte(regs, SII_STATUS_PHASE, 1);
+                       if (msg < 0) {
+                               dstat = regs->dstat;
+                               goto again;
+                       }
+#ifdef DEBUG
+                       if (sii_debug > 4)
+                               printf("Status %x ", msg);
+                       if (sii_logp > sii_log)
+                               sii_logp[-1].msg = msg;
+                       else
+                               sii_log[NLOG - 1].msg = msg;
+#endif
+
+                       /* do a quick wait for COMMAND_COMPLETE */
+                       SII_WAIT_UNTIL(dstat, regs->dstat,
+                               dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
+                       if (dstat & (SII_CI | SII_DI)) {
+#ifdef DEBUG
+                               if (sii_debug > 4)
+                                       printf("cnt2 %d\n", i);
+#endif
+                               goto again;
+                       }
+                       break;
+
+               case SII_MSG_IN_PHASE:
+                       /*
+                        * Save DMA state if DMA didn't finish.
+                        * Be careful not to save state again after reconnect
+                        * and see RESTORE_POINTER message.
+                        * Note that the SII DMA address is not incremented
+                        * as DMA proceeds.
+                        */
+                       if (state->dmaCurPhase >= 0) {
+                               /* save DMA registers */
+                               state->dmaPrevPhase = state->dmaCurPhase;
+                               state->dmaCurPhase = -1;
+                               if (dstat & SII_OBB)
+                                       state->dmaByte = regs->dmabyte;
+                               i = regs->dmlotc;
+                               if (i != 0)
+                                       i = state->dmaCnt - i;
+                               /* note: no carry from dmaddrl to dmaddrh */
+                               state->dmaAddrL = regs->dmaddrl + i;
+                               state->dmaAddrH = regs->dmaddrh;
+                               state->dmaCnt = regs->dmlotc;
+                               if (state->dmaCnt == 0)
+                                       state->dmaCnt = SII_MAX_DMA_XFER_LENGTH;
+                               regs->comm = comm &
+                                       (SII_STATE_MSK | SII_PHASE_MSK);
+                               regs->dstat = SII_DNE;
+#ifdef DEBUG
+                               if (sii_debug > 4) {
+                                       printf("SavP dcnt %d dadr %x ",
+                                               state->dmaCnt,
+                                               (state->dmaAddrH << 16) |
+                                               state->dmaAddrL);
+                                       if (((dstat & SII_OBB) != 0) ^
+                                           (state->dmaCnt & 1))
+                                               printf("OBB??? ");
+                               } else if (sii_debug > 0) {
+                                       if (((dstat & SII_OBB) != 0) ^
+                                           (state->dmaCnt & 1)) {
+                                               printf("sii_DoIntr: OBB??? ds %x cnt %d\n",
+                                                       dstat, state->dmaCnt);
+                                               sii_DumpLog();
+                                       }
+                               }
+#endif
+                       }
+
+                       /* read a one byte message */
+                       msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 0);
+                       if (msg < 0) {
+                               dstat = regs->dstat;
+                               goto again;
+                       }
+#ifdef DEBUG
+                       if (sii_debug > 4)
+                               printf("MsgIn %x ", msg);
+                       if (sii_logp > sii_log)
+                               sii_logp[-1].msg = msg;
+                       else
+                               sii_log[NLOG - 1].msg = msg;
+#endif
+
+                       /* process message */
+                       switch (msg) {
+                       case MSG_CMDCOMPLETE:
+                               /* acknowledge last byte */
+                               regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+                                       (comm & SII_STATE_MSK);
+                               SII_WAIT_UNTIL(dstat, regs->dstat,
+                                       dstat & SII_DNE, SII_WAIT_COUNT, i);
+                               regs->dstat = SII_DNE;
+                               msg = sc->sc_target;
+                               sc->sc_target = -1;
+                               /*
+                                * Wait a short time for disconnect.
+                                * Don't be fooled if SII_BER happens first.
+                                * Note: a reselect may happen here.
+                                */
+                               SII_WAIT_UNTIL(cstat, regs->cstat,
+                                       cstat & (SII_RST | SII_SCH),
+                                       SII_WAIT_COUNT, i);
+                               if ((cstat & (SII_RST | SII_SCH |
+                                   SII_STATE_MSK)) == SII_SCH) {
+                                       regs->cstat = SII_SCH | SII_BER;
+                                       regs->comm = 0;
+                                       /*
+                                        * Double check that we didn't miss a
+                                        * state change between seeing it and
+                                        * clearing the SII_SCH bit.
+                                        */
+                                       i = regs->cstat;
+                                       if (!(i & SII_SCH) &&
+                                           (i & SII_STATE_MSK) !=
+                                           (cstat & SII_STATE_MSK))
+                                               sii_StateChg(sc, i);
+                               }
+#ifdef DEBUG
+                               if (sii_debug > 4)
+                                       printf("cs %x\n", cstat);
+#endif
+                               sii_CmdDone(sc, msg, XS_NOERROR);
+                               break;
+
+                       case MSG_EXTENDED:
+                               /* acknowledge last byte */
+                               regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+                                       (comm & SII_STATE_MSK);
+                               SII_WAIT_UNTIL(dstat, regs->dstat,
+                                       dstat & SII_DNE, SII_WAIT_COUNT, i);
+                               regs->dstat = SII_DNE;
+                               /* read the message length */
+                               msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 1);
+                               if (msg < 0) {
+                                       dstat = regs->dstat;
+                                       goto again;
+                               }
+                               sc->sc_buf[1] = msg;    /* message length */
+                               if (msg == 0)
+                                       msg = 256;
+                               /*
+                                * We read and acknowlege all the bytes
+                                * except the last so we can assert ATN
+                                * if needed before acknowledging the last.
+                                */
+                               for (i = 0; i < msg; i++) {
+                                       dstat = sii_GetByte(regs,
+                                               SII_MSG_IN_PHASE, i < msg - 1);
+                                       if ((int)dstat < 0) {
+                                               dstat = regs->dstat;
+                                               goto again;
+                                       }
+                                       sc->sc_buf[i + 2] = dstat;
+                               }
+
+                               switch (sc->sc_buf[2]) {
+                               case MSG_EXT_MODIFY_DATA_PTR:
+                                       /* acknowledge last byte */
+                                       regs->comm = SII_INXFER |
+                                               SII_MSG_IN_PHASE |
+                                               (comm & SII_STATE_MSK);
+                                       SII_WAIT_UNTIL(dstat, regs->dstat,
+                                               dstat & SII_DNE,
+                                               SII_WAIT_COUNT, i);
+                                       regs->dstat = SII_DNE;
+                                       i = (sc->sc_buf[3] << 24) |
+                                               (sc->sc_buf[4] << 16) |
+                                               (sc->sc_buf[5] << 8) |
+                                               sc->sc_buf[6];
+                                       if (state->dmaPrevPhase >= 0) {
+                                               state->dmaAddrL += i;
+                                               state->dmaCnt -= i;
+                                       }
+                                       break;
+
+                               case MSG_EXT_SDTR_LEN:
+                                       /*
+                                        * Acknowledge last byte and
+                                        * signal a request for MSG_OUT.
+                                        */
+                                       regs->comm = SII_INXFER | SII_ATN |
+                                               SII_MSG_IN_PHASE |
+                                               (comm & SII_STATE_MSK);
+                                       SII_WAIT_UNTIL(dstat, regs->dstat,
+                                               dstat & SII_DNE,
+                                               SII_WAIT_COUNT, i);
+                                       regs->dstat = SII_DNE;
+                                       sii_DoSync(sc, state);
+                                       break;
+
+                               default:
+                               reject:
+                                       /*
+                                        * Acknowledge last byte and
+                                        * signal a request for MSG_OUT.
+                                        */
+                                       regs->comm = SII_INXFER | SII_ATN |
+                                               SII_MSG_IN_PHASE |
+                                               (comm & SII_STATE_MSK);
+                                       SII_WAIT_UNTIL(dstat, regs->dstat,
+                                               dstat & SII_DNE,
+                                               SII_WAIT_COUNT, i);
+                                       regs->dstat = SII_DNE;
+
+                                       /* wait for MSG_OUT phase */
+                                       SII_WAIT_UNTIL(dstat, regs->dstat,
+                                               dstat & SII_TBE,
+                                               SII_WAIT_COUNT, i);
+
+                                       /* send a reject message */
+                                       regs->data = MSG_MESSAGE_REJECT;
+                                       regs->comm = SII_INXFER |
+                                               (regs->cstat & SII_STATE_MSK) |
+                                               SII_MSG_OUT_PHASE;
+                                       SII_WAIT_UNTIL(dstat, regs->dstat,
+                                               dstat & SII_DNE,
+                                               SII_WAIT_COUNT, i);
+                                       regs->dstat = SII_DNE;
+                               }
+                               break;
+
+                       case MSG_SAVEDATAPOINTER:
+                       case MSG_RESTOREPOINTERS:
+                               /* acknowledge last byte */
+                               regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+                                       (comm & SII_STATE_MSK);
+                               SII_WAIT_UNTIL(dstat, regs->dstat,
+                                       dstat & SII_DNE, SII_WAIT_COUNT, i);
+                               regs->dstat = SII_DNE;
+                               /* wait a short time for another msg */
+                               SII_WAIT_UNTIL(dstat, regs->dstat,
+                                       dstat & (SII_CI | SII_DI),
+                                       SII_WAIT_COUNT, i);
+                               if (dstat & (SII_CI | SII_DI)) {
+#ifdef DEBUG
+                                       if (sii_debug > 4)
+                                               printf("cnt %d\n", i);
+#endif
+                                       goto again;
+                               }
+                               break;
+
+                       case MSG_DISCONNECT:
+                               /* acknowledge last byte */
+                               regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+                                       (comm & SII_STATE_MSK);
+                               SII_WAIT_UNTIL(dstat, regs->dstat,
+                                       dstat & SII_DNE, SII_WAIT_COUNT, i);
+                               regs->dstat = SII_DNE;
+                               state->prevComm = comm;
+#ifdef DEBUG
+                               if (sii_debug > 4)
+                                       printf("disconn %d ", sc->sc_target);
+#endif
+                               /*
+                                * Wait a short time for disconnect.
+                                * Don't be fooled if SII_BER happens first.
+                                * Note: a reselect may happen here.
+                                */
+                               SII_WAIT_UNTIL(cstat, regs->cstat,
+                                       cstat & (SII_RST | SII_SCH),
+                                       SII_WAIT_COUNT, i);
+                               if ((cstat & (SII_RST | SII_SCH |
+                                   SII_STATE_MSK)) != SII_SCH) {
+#ifdef DEBUG
+                                       if (sii_debug > 4)
+                                               printf("cnt %d\n", i);
+#endif
+                                       dstat = regs->dstat;
+                                       goto again;
+                               }
+                               regs->cstat = SII_SCH | SII_BER;
+                               regs->comm = 0;
+                               sc->sc_target = -1;
+                               /*
+                                * Double check that we didn't miss a state
+                                * change between seeing it and clearing
+                                * the SII_SCH bit.
+                                */
+                               i = regs->cstat;
+                               if (!(i & SII_SCH) && (i & SII_STATE_MSK) !=
+                                   (cstat & SII_STATE_MSK))
+                                       sii_StateChg(sc, i);
+                               break;
+
+                       case MSG_MESSAGE_REJECT:
+                               /* acknowledge last byte */
+                               regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+                                       (comm & SII_STATE_MSK);
+                               SII_WAIT_UNTIL(dstat, regs->dstat,
+                                       dstat & SII_DNE, SII_WAIT_COUNT, i);
+                               regs->dstat = SII_DNE;
+                               printf("%s: device %d: message reject.\n",
+                                       sc->sc_dev.dv_xname, sc->sc_target);
+                               break;
+
+                       default:
+                               if (!(msg & MSG_IDENTIFYFLAG)) {
+                                       printf("%s: device %d: couldn't handle "
+                                           "message 0x%x... rejecting.\n",
+                                           sc->sc_dev.dv_xname, sc->sc_target,
+                                           msg);
+#ifdef DEBUG
+                                       sii_DumpLog();
+#endif
+                                       goto reject;
+                               }
+                               /* acknowledge last byte */
+                               regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
+                                       (comm & SII_STATE_MSK);
+                               SII_WAIT_UNTIL(dstat, regs->dstat,
+                                       dstat & SII_DNE, SII_WAIT_COUNT, i);
+                               regs->dstat = SII_DNE;
+                               /* may want to check LUN some day */
+                               /* wait a short time for another msg */
+                               SII_WAIT_UNTIL(dstat, regs->dstat,
+                                       dstat & (SII_CI | SII_DI),
+                                       SII_WAIT_COUNT, i);
+                               if (dstat & (SII_CI | SII_DI)) {
+#ifdef DEBUG
+                                       if (sii_debug > 4)
+                                               printf("cnt %d\n", i);
+#endif
+                                       goto again;
+                               }
+                       }
+                       break;
+
+               case SII_MSG_OUT_PHASE:
+#ifdef DEBUG
+                       if (sii_debug > 4)
+                               printf("MsgOut\n");
+#endif
+                       printf("MsgOut %x\n", state->flags); /* XXX */
+
+                       /*
+                        * Check for parity error.
+                        * Hardware will automatically set ATN
+                        * to request the device for a MSG_OUT phase.
+                        */
+                       if (state->flags & PARITY_ERR) {
+                               state->flags &= ~PARITY_ERR;
+                               regs->data = MSG_PARITY_ERROR;
+                       } else
+                               regs->data = MSG_NOOP;
+                       regs->comm = SII_INXFER | (comm & SII_STATE_MSK) |
+                               SII_MSG_OUT_PHASE;
+
+                       /* wait a short time for XFER complete */
+                       SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
+                               SII_WAIT_COUNT, i);
+#ifdef DEBUG
+                       if (sii_debug > 4)
+                               printf("ds %x i %d\n", dstat, i);
+#endif
+                       /* just clear the DNE bit and check errors later */
+                       if (dstat & SII_DNE) {
+                               regs->dstat = SII_DNE;
+                       }
+                       break;
+
+               default:
+                       printf("%s: Couldn't handle phase %d... ignoring.\n",
+                                  sc->sc_dev.dv_xname, dstat & SII_PHASE_MSK);
+               }
+       }
+
+#ifdef DEBUG
+       if (sii_debug > 3)
+               printf("\n");
+#endif
+       /*
+        * Check to make sure we won't be interrupted again.
+        * Deglitch dstat register.
+        */
+       msg = regs->dstat;
+       while (msg != (dstat = regs->dstat))
+               msg = dstat;
+       if (dstat & (SII_CI | SII_DI))
+               goto again;
+
+       if (sc->sc_target < 0) {
+               /* look for another device that is ready */
+               for (i = 0; i < SII_NCMD; i++) {
+                       /* don't restart a disconnected command */
+                       if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
+                               continue;
+                       sii_StartCmd(sc, i);
+                       break;
+               }
+       }
+       return;
+
+abort:
+       /* jump here to abort the current command */
+       printf("%s: device %d: current command terminated\n",
+               sc->sc_dev.dv_xname, sc->sc_target);
+#ifdef DEBUG
+       sii_DumpLog();
+#endif
+
+       if ((cstat = regs->cstat) & SII_CON) {
+               /* try to send an abort msg for awhile */
+               regs->dstat = SII_DNE;
+               regs->data = MSG_ABORT;
+               regs->comm = SII_INXFER | SII_ATN | (cstat & SII_STATE_MSK) |
+                       SII_MSG_OUT_PHASE;
+               SII_WAIT_UNTIL(dstat, regs->dstat,
+                       (dstat & (SII_DNE | SII_PHASE_MSK)) ==
+                       (SII_DNE | SII_MSG_OUT_PHASE),
+                       2 * SII_WAIT_COUNT, i);
+#ifdef DEBUG
+               if (sii_debug > 0)
+                       printf("Abort: cs %x ds %x i %d\n", cstat, dstat, i);
+#endif
+               if ((dstat & (SII_DNE | SII_PHASE_MSK)) ==
+                   (SII_DNE | SII_MSG_OUT_PHASE)) {
+                       /* disconnect if command in progress */
+                       regs->comm = SII_DISCON;
+                       SII_WAIT_UNTIL(cstat, regs->cstat,
+                               !(cstat & SII_CON), SII_WAIT_COUNT, i);
+               }
+       } else {
+#ifdef DEBUG
+               if (sii_debug > 0)
+                       printf("Abort: cs %x\n", cstat);
+#endif
+       }
+       regs->cstat = 0xffff;
+       regs->dstat = 0xffff;
+       regs->comm = 0;
+
+       i = sc->sc_target;
+       sc->sc_target = -1;
+       sii_CmdDone(sc, i, XS_DRIVER_STUFFUP /* EIO */);
+#ifdef DEBUG
+       if (sii_debug > 4)
+               printf("sii_DoIntr: after CmdDone target %d\n", sc->sc_target);
+#endif
+}
+
+void
+sii_StateChg(sc, cstat)
+       struct sii_softc *sc;
+       u_int cstat;
+{
+       SIIRegs *regs = sc->sc_regs;
+       State *state;
+       int i;
+
+#ifdef DEBUG
+       if (sii_debug > 4)
+               printf("SCH: ");
+#endif
+
+       switch (cstat & SII_STATE_MSK) {
+       case 0:
+               /* disconnect */
+               i = sc->sc_target;
+               sc->sc_target = -1;
+#ifdef DEBUG
+               if (sii_debug > 4)
+                       printf("disconn %d ", i);
+#endif
+               if (i >= 0 && !sc->sc_st[i].prevComm) {
+                       printf("%s: device %d: spurrious disconnect (%d)\n",
+                               sc->sc_dev.dv_xname, i, regs->slcsr);
+                       sc->sc_st[i].prevComm = 0;
+               }
+               break;
+
+       case SII_CON:
+               /* connected as initiator */
+               i = regs->slcsr;
+               if (sc->sc_target == i)
+                       break;
+               printf("%s: device %d: connect to device %d??\n",
+                       sc->sc_dev.dv_xname, sc->sc_target, i);
+               sc->sc_target = i;
+               break;
+
+       case SII_DST:
+               /*
+                * Wait for CON to become valid,
+                * chip is slow sometimes.
+                */
+               SII_WAIT_UNTIL(cstat, regs->cstat,
+                       cstat & SII_CON, SII_WAIT_COUNT, i);
+               if (!(cstat & SII_CON))
+                       panic("sii resel");
+               /* FALLTHROUGH */
+
+       case SII_CON | SII_DST:
+               /*
+                * Its a reselection. Save the ID and wait for
+                * interrupts to tell us what to do next
+                * (should be MSG_IN of IDENTIFY).
+                * NOTE: sc_target may be >= 0 if we were in
+                * the process of trying to start a command
+                * and were reselected before the select
+                * command finished.
+                */
+               sc->sc_target = i = regs->destat;
+               state = &sc->sc_st[i];
+               regs->comm = SII_CON | SII_DST | SII_MSG_IN_PHASE;
+               regs->dmctrl = state->dmaReqAck;
+               if (!state->prevComm) {
+                       printf("%s: device %d: spurious reselection\n",
+                               sc->sc_dev.dv_xname, i);
+                       break;
+               }
+               state->prevComm = 0;
+#ifdef DEBUG
+               if (sii_debug > 4)
+                       printf("resel %d ", sc->sc_target);
+#endif
+               break;
+
+#ifdef notyet
+       case SII_DST | SII_TGT:
+       case SII_CON | SII_DST | SII_TGT:
+               /* connected as target */
+               printf("%s: Selected by device %d as target!!\n",
+                       sc->sc_dev.dv_xname, regs->destat);
+               regs->comm = SII_DISCON;
+               SII_WAIT_UNTIL(!(regs->cstat & SII_CON),
+                       SII_WAIT_COUNT, i);
+               regs->cstat = 0xffff;
+               regs->dstat = 0xffff;
+               regs->comm = 0;
+               break;
+#endif
+
+       default:
+               printf("%s: Unknown state change (cs %x)!!\n",
+                       sc->sc_dev.dv_xname, cstat);
+#ifdef DEBUG
+               sii_DumpLog();
+#endif
+       }
+}
+
+/*
+ * Read one byte of data.
+ * If 'ack' is true, acknowledge the byte.
+ */
+int
+sii_GetByte(regs, phase, ack)
+       SIIRegs *regs;
+       int phase, ack;
+{
+       u_int dstat;
+       u_int state;
+       int i;
+       int data;
+
+       dstat = regs->dstat;
+       state = regs->cstat & SII_STATE_MSK;
+       i = -1;
+       if (!(dstat & SII_IBF) || (dstat & SII_MIS)) {
+               regs->comm = state | phase;
+               /* wait a short time for IBF */
+               SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_IBF,
+                       SII_WAIT_COUNT, i);
+#ifdef DEBUG
+               if (!(dstat & SII_IBF))
+                       printf("status no IBF\n");
+#endif
+       }
+       if (dstat & SII_DNE) { /* XXX */
+               printf("sii_GetByte: DNE set 5\n");
+#ifdef DEBUG
+               sii_DumpLog();
+#endif
+               regs->dstat = SII_DNE;
+       }
+       data = regs->data;
+       /* check for parity error */
+       if (dstat & SII_IPE) {
+#ifdef DEBUG
+               if (sii_debug > 4)
+                       printf("cnt0 %d\n", i);
+#endif
+               printf("sii_GetByte: data %x ?? ds %x cm %x i %d\n",
+                       data, dstat, regs->comm, i); /* XXX */
+               data = -1;
+               ack = 1;
+       }
+
+       if (ack) {
+               regs->comm = SII_INXFER | state | phase;
+
+               /* wait a short time for XFER complete */
+               SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
+                       SII_WAIT_COUNT, i);
+
+               /* clear the DNE */
+               if (dstat & SII_DNE) {
+                       regs->dstat = SII_DNE;
+               }
+       }
+
+       return (data);
+}
+
+/*
+ * Exchange messages to initiate synchronous data transfers.
+ */
+void
+sii_DoSync(sc, state)
+       struct sii_softc *sc;
+       State *state;
+{
+       SIIRegs *regs = sc->sc_regs;
+       u_int dstat, comm;
+       int i, j;
+       u_int len;
+
+#ifdef DEBUG
+       if (sii_debug)
+               printf("sii_DoSync: len %d per %d req/ack %d\n",
+                       sc->sc_buf[1], sc->sc_buf[3], sc->sc_buf[4]);
+#endif
+
+       /* SII chip can only handle a minimum transfer period of ??? */
+       if (sc->sc_buf[3] < 64)
+               sc->sc_buf[3] = 64;
+       /* SII chip can only handle a maximum REQ/ACK offset of 3 */
+       len = sc->sc_buf[4];
+       if (len > 3)
+               len = 3;
+
+       sc->sc_buf[0] = MSG_EXTENDED;
+       sc->sc_buf[1] = MSG_EXT_SDTR_LEN;
+       sc->sc_buf[2] = MSG_EXT_SDTR;
+       sc->sc_buf[4] = len;
+#if 1
+       comm = SII_INXFER | SII_ATN | SII_MSG_OUT_PHASE |
+               (regs->cstat & SII_STATE_MSK);
+       regs->comm = comm & ~SII_INXFER;
+       for (j = 0; j < 5; j++) {
+               /* wait for target to request the next byte */
+               SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_TBE,
+                       SII_WAIT_COUNT, i);
+               if (!(dstat & SII_TBE) ||
+                   (dstat & SII_PHASE_MSK) != SII_MSG_OUT_PHASE) {
+                       printf("sii_DoSync: TBE? ds %x cm %x i %d\n",
+                               dstat, comm, i); /* XXX */
+                       return;
+               }
+
+               /* the last message byte should have ATN off */
+               if (j == 4)
+                       comm &= ~SII_ATN;
+
+               regs->data = sc->sc_buf[j];
+               regs->comm = comm;
+
+               /* wait a short time for XFER complete */
+               SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
+                       SII_WAIT_COUNT, i);
+
+               if (!(dstat & SII_DNE)) {
+                       printf("sii_DoSync: DNE? ds %x cm %x i %d\n",
+                               dstat, comm, i); /* XXX */
+                       return;
+               }
+
+               /* clear the DNE, other errors handled later */
+               regs->dstat = SII_DNE;
+       }
+#else  /* 0 */
+       sc->sii_copytobuf(sc, sc->sc_buf, SII_BUF_ADDR(sc), 5);
+       printf("sii_DoSync: %x %x %x ds %x\n",
+               ((u_short *)sc->sc_buf)[0], ((u_short *)sc->sc_buf)[1],
+               ((u_short *)sc->sc_buf)[2], regs->dstat); /* XXX */
+       regs->dmaddrl = SII_BUF_ADDR(sc);
+       regs->dmaddrh = SII_BUF_ADDR(sc) >> 16;
+       regs->dmlotc = 5;
+       regs->comm = SII_DMA | SII_INXFER | SII_ATN |
+               (regs->cstat & SII_STATE_MSK) | SII_MSG_OUT_PHASE;
+
+       /* wait a short time for XFER complete */
+       SII_WAIT_UNTIL(dstat, regs->dstat,
+               (dstat & (SII_DNE | SII_TCZ)) == (SII_DNE | SII_TCZ),
+               SII_WAIT_COUNT, i);
+
+       if ((dstat & (SII_DNE | SII_TCZ)) != (SII_DNE | SII_TCZ)) {
+               printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
+                       dstat, regs->comm, i, regs->dmlotc); /* XXX */
+               sii_DumpLog(); /* XXX */
+               return;
+       }
+       /* clear the DNE, other errors handled later */
+       regs->dstat = SII_DNE;
+#endif /* 0 */
+
+#if 0
+       SII_WAIT_UNTIL(dstat, regs->dstat, dstat & (SII_CI | SII_DI),
+               SII_WAIT_COUNT, i);
+       printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
+               dstat, regs->comm, i, regs->dmlotc); /* XXX */
+#endif
+
+       state->dmaReqAck = len;
+}
+
+/*
+ * Issue the sequence of commands to the controller to start DMA.
+ * NOTE: the data buffer should be word-aligned for DMA out.
+ */
+void
+sii_StartDMA(regs, phase, dmaAddr, size)
+       SIIRegs *regs;  /* which SII to use */
+       int phase;      /* phase to send/receive data */
+       u_int dmaAddr;  /* DMA buffer offset */
+       int size;       /* # of bytes to transfer */
+{
+
+       if (regs->dstat & SII_DNE) { /* XXX */
+               regs->dstat = SII_DNE;
+               printf("sii_StartDMA: DNE set\n");
+#ifdef DEBUG
+               sii_DumpLog();
+#endif
+       }
+       regs->dmaddrl = dmaAddr;
+       regs->dmaddrh = dmaAddr >> 16;
+       regs->dmlotc = size;
+       regs->comm = SII_DMA | SII_INXFER | (regs->cstat & SII_STATE_MSK) |
+               phase;
+
+#ifdef DEBUG
+       if (sii_debug > 5) {
+               printf("sii_StartDMA: cs 0x%x, ds 0x%x, cm 0x%x, size %d\n",
+                       regs->cstat, regs->dstat, regs->comm, size);
+       }
+#endif
+}
+
+/*
+ * Call the device driver's 'done' routine to let it know the command is done.
+ * The 'done' routine may try to start another command.
+ * To be fair, we should start pending commands for other devices
+ * before allowing the same device to start another command.
+ */
+void
+sii_CmdDone(sc, target, error)
+       struct sii_softc *sc;   /* which SII to use */
+       int target;                     /* which device is done */
+       int error;                      /* error code if any errors */
+{
+       ScsiCmd *scsicmd;
+       struct scsi_xfer *xs;
+       int i;
+
+       splassert(IPL_BIO);
+
+       scsicmd = sc->sc_cmd[target];
+#ifdef DIAGNOSTIC
+       if (target < 0 || !scsicmd)
+               panic("sii_CmdDone");
+#endif
+       sc->sc_cmd[target] = NULL;
+#ifdef DEBUG
+       if (sii_debug > 1) {
+               printf("sii_CmdDone: %s target %d cmd 0x%x err %d resid %d\n",
+                       sc->sc_dev.dv_xname,
+                       target, scsicmd->cmd[0], error, sc->sc_st[target].buflen);
+       }
+#endif
+
+       /* look for another device that is ready */
+       for (i = 0; i < SII_NCMD; i++) {
+               /* don't restart a disconnected command */
+               if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
+                       continue;
+               sii_StartCmd(sc, i);
+               break;
+       }
+
+       xs = sc->sc_xs[target];
+       xs->status = sc->sc_st[target].statusByte;
+       xs->error = error;
+       xs->resid = sc->sc_st[target].buflen;
+       xs->flags |= ITSDONE;
+       scsi_done(xs);
+}
+
+#ifdef DEBUG
+void
+sii_DumpLog()
+{
+       struct sii_log *lp;
+
+       printf("sii: cmd 0x%x bn %d cnt %d\n", sii_debug_cmd, sii_debug_bn,
+               sii_debug_sz);
+       lp = sii_logp;
+       do {
+               printf("target %d cs %x ds %x cm %x msg %x rlen %x dlen %x\n",
+                       lp->target, lp->cstat, lp->dstat, lp->comm, lp->msg,
+                       lp->rlen, lp->dlen);
+               if (++lp >= &sii_log[NLOG])
+                       lp = sii_log;
+       } while (lp != sii_logp);
+}
+#endif
diff --git a/sys/arch/vax/dec/siireg.h b/sys/arch/vax/dec/siireg.h
new file mode 100644 (file)
index 0000000..c83f0df
--- /dev/null
@@ -0,0 +1,235 @@
+/*     $OpenBSD: siireg.h,v 1.1 2008/08/18 23:19:22 miod Exp $ */
+/*     $NetBSD: siireg.h,v 1.2 2006/07/29 19:10:57 ad Exp $    */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * 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.
+ *
+ *     @(#)siireg.h    8.1 (Berkeley) 6/10/93
+ *
+ * sii.h --
+ *
+ *     SII registers.
+ *
+ *     Copyright (C) 1989 Digital Equipment Corporation.
+ *     Permission to use, copy, modify, and distribute this software and
+ *     its documentation for any purpose and without fee is hereby granted,
+ *     provided that the above copyright notice appears in all copies.
+ *     Digital Equipment Corporation makes no representations about the
+ *     suitability of this software for any purpose.  It is provided "as is"
+ *     without express or implied warranty.
+ *
+ * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/sii.h,
+ *     v 1.2 89/08/15 19:53:04 rab Exp  SPRITE (DECWRL)
+ */
+
+#ifndef _SII
+#define _SII
+
+/*
+ * SII hardware registers
+ */
+typedef volatile struct {
+       u_short sdb;            /* SCSI Data Bus and Parity */
+       u_short pad0;
+       u_short sc1;            /* SCSI Control Signals One */
+       u_short pad1;
+       u_short sc2;            /* SCSI Control Signals Two */
+       u_short pad2;
+       u_short csr;            /* Control/Status register */
+       u_short pad3;
+       u_short id;             /* Bus ID register */
+       u_short pad4;
+       u_short slcsr;          /* Select Control and Status Register */
+       u_short pad5;
+       u_short destat;         /* Selection Detector Status Register */
+       u_short pad6;
+       u_short dstmo;          /* DSSI Timeout Register */
+       u_short pad7;
+       u_short data;           /* Data Register */
+       u_short pad8;
+       u_short dmctrl;         /* DMA Control Register */
+       u_short pad9;
+       u_short dmlotc;         /* DMA Length of Transfer Counter */
+       u_short pad10;
+       u_short dmaddrl;        /* DMA Address Register Low */
+       u_short pad11;
+       u_short dmaddrh;        /* DMA Address Register High */
+       u_short pad12;
+       u_short dmabyte;        /* DMA Initial Byte Register */
+       u_short pad13;
+       u_short stlp;           /* DSSI Short Target List Pointer */
+       u_short pad14;
+       u_short ltlp;           /* DSSI Long Target List Pointer */
+       u_short pad15;
+       u_short ilp;            /* DSSI Initiator List Pointer */
+       u_short pad16;
+       u_short dsctrl;         /* DSSI Control Register */
+       u_short pad17;
+       u_short cstat;          /* Connection Status Register */
+       u_short pad18;
+       u_short dstat;          /* Data Transfer Status Register */
+       u_short pad19;
+       u_short comm;           /* Command Register */
+       u_short pad20;
+       u_short dictrl;         /* Diagnostic Control Register */
+       u_short pad21;
+       u_short clock;          /* Diagnostic Clock Register */
+       u_short pad22;
+       u_short bhdiag;         /* Bus Handler Diagnostic Register */
+       u_short pad23;
+       u_short sidiag;         /* SCSI IO Diagnostic Register */
+       u_short pad24;
+       u_short dmdiag;         /* Data Mover Diagnostic Register */
+       u_short pad25;
+       u_short mcdiag;         /* Main Control Diagnostic Register */
+       u_short pad26;
+} SIIRegs;
+
+/*
+ * SC1 - SCSI Control Signals One
+ */
+#define SII_SC1_MSK    0x1ff           /* All possible signals on the bus */
+#define SII_SC1_SEL    0x80            /* SCSI SEL signal active on bus */
+#define SII_SC1_ATN    0x08            /* SCSI ATN signal active on bus */
+
+/*
+ * SC2 - SCSI Control Signals Two
+ */
+#define SII_SC2_IGS    0x8             /* SCSI drivers for initiator mode */
+
+/*
+ * CSR - Control/Status Register
+ */
+#define SII_HPM        0x10                    /* SII in on an arbitrated SCSI bus */
+#define        SII_RSE 0x08                    /* 1 = respond to reselections */
+#define SII_SLE        0x04                    /* 1 = respond to selections */
+#define SII_PCE        0x02                    /* 1 = report parity errors */
+#define SII_IE 0x01                    /* 1 = enable interrupts */
+
+/*
+ * ID - Bus ID Register
+ */
+#define SII_ID_IO      0x8000          /* I/O */
+
+/*
+ * DESTAT - Selection Detector Status Register
+ */
+#define SII_IDMSK      0x7             /* ID of target reselected the SII */
+
+/*
+ * DMCTRL - DMA Control Register
+ */
+#define SII_ASYNC      0x00            /* REQ/ACK Offset for async mode */
+#define SII_SYNC       0x03            /* REQ/ACK Offset for sync mode */
+
+/*
+ * DMLOTC - DMA Length Of Transfer Counter
+ */
+#define SII_TCMSK      0x1fff          /* transfer count mask */
+
+/*
+ * CSTAT - Connection Status Register
+ */
+#define        SII_CI          0x8000  /* composite interrupt bit for CSTAT */
+#define SII_DI         0x4000  /* composite interrupt bit for DSTAT */
+#define SII_RST                0x2000  /* 1 if reset is asserted on SCSI bus */
+#define        SII_BER         0x1000  /* Bus error */
+#define        SII_OBC         0x0800  /* Out_en Bit Cleared (DSSI mode) */
+#define SII_TZ         0x0400  /* Target pointer Zero (STLP or LTLP is zero) */
+#define        SII_BUF         0x0200  /* Buffer service - outbound pkt to non-DSSI */
+#define SII_LDN                0x0100  /* List element Done */
+#define SII_SCH                0x0080  /* State Change */
+#define SII_CON                0x0040  /* SII is Connected to another device */
+#define SII_DST                0x0020  /* SII was Destination of current transfer */
+#define SII_TGT                0x0010  /* SII is operating as a Target */
+#define SII_STATE_MSK  0x0070  /* State Mask */
+#define SII_SWA                0x0008  /* Selected With Attention */
+#define SII_SIP                0x0004  /* Selection In Progress */
+#define SII_LST                0x0002  /* Lost arbitration */
+
+/*
+ * DSTAT - Data Transfer Status Register
+ */
+#define SII_DNE                0x2000  /* DMA transfer Done */
+#define SII_TCZ                0x1000  /* Transfer Count register is Zero */
+#define SII_TBE                0x0800  /* Transmit Buffer Empty */
+#define SII_IBF                0x0400  /* Input Buffer Full */
+#define SII_IPE                0x0200  /* Incoming Parity Error */
+#define SII_OBB                0x0100  /* Odd Byte Boundry */
+#define SII_MIS                0x0010  /* Phase Mismatch */
+#define SII_ATN                0x0008  /* ATN set by initiator if in Target mode */
+#define SII_MSG                0x0004  /* current bus state of MSG */
+#define SII_CD         0x0002  /* current bus state of C/D */
+#define SII_IO         0x0001  /* current bus state of I/O */
+#define SII_PHASE_MSK  0x0007  /* Phase Mask */
+
+/*
+ * The different phases.
+ */
+#define SII_MSG_IN_PHASE       0x7
+#define SII_MSG_OUT_PHASE      0x6
+#define SII_STATUS_PHASE       0x3
+#define SII_CMD_PHASE          0x2
+#define SII_DATA_IN_PHASE      0x1
+#define SII_DATA_OUT_PHASE     0x0
+
+/*
+ * COMM - Command Register
+ */
+#define        SII_DMA         0x8000  /* DMA mode */
+#define SII_DO_RST     0x4000  /* Assert reset on SCSI bus for 25 usecs */
+#define SII_RSL                0x1000  /* 0 = select, 1 = reselect desired device */
+
+/* Commands: I - Initiator, T - Target, D - Disconnected */
+#define SII_INXFER     0x0800  /* Information Transfer command (I,T) */
+#define SII_SELECT     0x0400  /* Select command               (D) */
+#define SII_REQDATA    0x0200  /* Request Data command         (T) */
+#define        SII_DISCON      0x0100  /* Disconnect command           (I,T,D) */
+#define SII_CHRESET    0x0080  /* Chip Reset command           (I,T,D) */
+
+/* Command state bits same as connection status register */
+/* Command phase bits same as data transfer status register */
+
+/*
+ * DICTRL - Diagnostic Control Register
+ */
+#define SII_PRE                0x4     /* Enable the SII to drive the SCSI bus */
+
+#define SII_WAIT_COUNT         10000   /* Delay count used for the SII chip */
+/*
+ * Max DMA transfer length for SII
+ * The SII chip only has a 13 bit counter. If 8192 is used as the max count,
+ * you can't tell the difference between a count of zero and 8192.
+ * 8190 is used instead of 8191 so the count is even.
+ */
+#define SII_MAX_DMA_XFER_LENGTH        8192
+
+#endif /* _SII */
diff --git a/sys/arch/vax/dec/siivar.h b/sys/arch/vax/dec/siivar.h
new file mode 100644 (file)
index 0000000..82a9251
--- /dev/null
@@ -0,0 +1,71 @@
+/*     $OpenBSD: siivar.h,v 1.1 2008/08/18 23:19:22 miod Exp $ */
+/*     $NetBSD: siivar.h,v 1.6 2000/06/02 20:16:51 mhitch Exp $        */
+
+#ifndef _SIIVAR_H
+#define _SIIVAR_H
+
+/*
+ * This structure contains information that a SCSI interface controller
+ * needs to execute a SCSI command.
+ */
+typedef struct ScsiCmd {
+       int     unit;           /* unit number passed to device done routine */
+       int     flags;          /* control flags for this command (see below) */
+       int     buflen;         /* length of the data buffer in bytes */
+       char    *buf;           /* pointer to data buffer for this command */
+       int     cmdlen;         /* length of data in cmdbuf */
+       u_char  *cmd;           /* buffer for the SCSI command */
+       int     error;          /* compatibility hack for new scsi */
+       int     lun;            /* LUN for MI SCSI */
+} ScsiCmd;
+
+typedef struct scsi_state {
+       int     statusByte;     /* status byte returned during STATUS_PHASE */
+       int     dmaDataPhase;   /* which data phase to expect */
+       int     dmaCurPhase;    /* SCSI phase if DMA is in progress */
+       int     dmaPrevPhase;   /* SCSI phase of DMA suspended by disconnect */
+       u_int   dmaAddr[2];     /* DMA buffer memory offsets */
+       int     dmaBufIndex;    /* which of the above is currently in use */
+       int     dmalen;         /* amount to transfer in this chunk */
+       int     cmdlen;         /* total remaining amount of cmd to transfer */
+       u_char  *cmd;           /* current pointer within scsicmd->cmd */
+       int     buflen;         /* total remaining amount of data to transfer */
+       char    *buf;           /* current pointer within scsicmd->buf */
+       u_short flags;          /* see below */
+       u_short prevComm;       /* command reg before disconnect */
+       u_short dmaCtrl;        /* DMA control register if disconnect */
+       u_short dmaAddrL;       /* DMA address register if disconnect */
+       u_short dmaAddrH;       /* DMA address register if disconnect */
+       u_short dmaCnt;         /* DMA count if disconnect */
+       u_short dmaByte;        /* DMA byte if disconnect on odd boundary */
+       u_short dmaReqAck;      /* DMA synchronous xfer offset or 0 if async */
+} State;
+
+/* state flags */
+#define FIRST_DMA      0x01    /* true if no data DMA started yet */
+#define PARITY_ERR     0x02    /* true if parity error seen */
+
+#define SII_NCMD       8
+struct sii_softc {
+       struct device sc_dev;           /* us as a device */
+       struct scsi_link sc_link;               /* scsi link struct */
+       ScsiCmd sc_cmd_fake[SII_NCMD];          /* XXX - hack!!! */
+       struct scsi_xfer *sc_xs[SII_NCMD];      /* XXX - hack!!! */
+       SIIRegs *sc_regs;               /* HW address of SII controller chip */
+       int     sc_flags;
+       int     sc_target;              /* target SCSI ID if connected */
+       int     sc_hostid;
+       ScsiCmd *sc_cmd[SII_NCMD];      /* active command indexed by ID */
+       void    (*sii_copytobuf)(void *, u_char *, u_int, int);
+       void    (*sii_copyfrombuf)(void *, u_int, u_char *, int);
+
+       State   sc_st[SII_NCMD];        /* state info for each active command */
+
+       u_char  sc_buf[258];    /* used for extended messages */
+};
+
+/* Machine-independent back-end attach entry point */
+void   sii_attach(struct sii_softc *sc);
+int    sii_intr(void *sc);
+
+#endif /* _SIIVAR_H */
index ff228c7..00caf4d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: clock.h,v 1.7 2008/08/15 22:41:46 miod Exp $ */
+/*     $OpenBSD: clock.h,v 1.8 2008/08/18 23:19:24 miod Exp $ */
 /*     $NetBSD: clock.h,v 1.4 1999/09/06 19:52:53 ragge Exp $ */
 /*
  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
@@ -74,3 +74,6 @@ int   generic_clkread(time_t);
 void   generic_clkwrite(void);
 int    chip_clkread(time_t);
 void   chip_clkwrite(void);
+
+int    yeartonum(int);
+int    numtoyear(int);
index 69c7583..fe2101f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nexus.h,v 1.13 2006/08/27 16:55:41 miod Exp $ */
+/*     $OpenBSD: nexus.h,v 1.14 2008/08/18 23:19:24 miod Exp $ */
 /*     $NetBSD: nexus.h,v 1.17 2000/06/04 17:58:19 ragge Exp $ */
 
 /*-
@@ -54,6 +54,7 @@ struct        mainbus_attach_args {
 #define        VAX_IBUS        8       /* Internal Microvax bus */
 #define        VAX_XMIBUS      9       /* XMI master bus (6000) */
 #define        VAX_VXTBUS      10      /* Pseudo VXT2000 bus */
+#define        VAX_MBUS        11      /* M-bus (KA60) */
 
 #define        VAX_LEDS        0x42    /* pseudo value to attach led0 */
 
index 1f2ca79..1a4438b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rpb.h,v 1.10 2002/06/11 09:36:24 hugh Exp $ */
+/*     $OpenBSD: rpb.h,v 1.11 2008/08/18 23:19:24 miod Exp $ */
 /*     $NetBSD: rpb.h,v 1.6 1998/07/01 09:37:11 ragge Exp $ */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
@@ -113,6 +113,7 @@ struct rpb {                /* size         description */
 #define        BDEV_NK         35
 #define        BDEV_RD         36      /* ST506/MFM disk on HDC9224 */
 #define        BDEV_ST         37      /* SCSI tape on NCR5380 */
+#define        BDEV_SDS        39      /* SCSI disk on SII */
 #define        BDEV_SD         42      /* SCSI disk on NCR5380 */
 #define BDEV_SDN       46      /* SCSI disk on NCR5394 */
 #define        BDEV_CNSL       64
index 5f2b6d8..cc16863 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: scb.h,v 1.9 2007/04/10 18:31:44 miod Exp $    */
+/*     $OpenBSD: scb.h,v 1.10 2008/08/18 23:19:24 miod Exp $   */
 /*     $NetBSD: scb.h,v 1.11 2000/07/10 09:14:34 ragge Exp $   */
 
 /*
@@ -131,10 +131,11 @@ extern    const struct ivec_dsp idsptch;
 extern struct scb *scb;
 extern struct ivec_dsp *scb_vec;
 
-extern paddr_t scb_init (paddr_t);
-extern int scb_vecref (int *, int *);
-extern void scb_fake (int, int);
-extern void scb_vecalloc (int, void(*)(void *), void *, int, struct evcount *);
+extern paddr_t scb_init(paddr_t);
+extern int scb_vecref(int *, int *);
+extern void scb_fake(int, int);
+extern void scb_stray(void *);
+extern void scb_vecalloc(int, void(*)(void *), void *, int, struct evcount *);
 #endif /* _KERNEL */
 
 #endif /* _VAX_SCB_H */
diff --git a/sys/arch/vax/mbus/dz_fwio.c b/sys/arch/vax/mbus/dz_fwio.c
new file mode 100644 (file)
index 0000000..678d833
--- /dev/null
@@ -0,0 +1,215 @@
+/*     $OpenBSD: dz_fwio.c,v 1.1 2008/08/18 23:19:25 miod Exp $        */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 1998 Ludd, University of Lule}, Sweden.
+ * 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 at Ludd, University of 
+ *     Lule}, Sweden and its contributors.
+ * 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/device.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+#include <vax/mbus/fwiovar.h>
+
+#include <vax/qbus/dzreg.h>
+#include <vax/qbus/dzvar.h>
+
+#include <vax/dec/dzkbdvar.h>
+
+#include <sys/tty.h>
+#include <dev/cons.h>
+
+#include "dzkbd.h"
+#include "dzms.h"
+
+int    dz_fwio_match(struct device *, void *, void *);
+void   dz_fwio_attach(struct device *, struct device *, void *);
+
+struct cfattach dz_fwio_ca = {
+       sizeof(struct dz_softc), dz_fwio_match, dz_fwio_attach
+};
+
+extern struct cfdriver dz_cd;
+
+int    dz_fwio_intr(void *);
+
+#define        DZ_FWIO_CSR     0
+#define        DZ_FWIO_RBUF    4
+#define        DZ_FWIO_DTR     9
+#define        DZ_FWIO_BREAK   13
+#define        DZ_FWIO_TBUF    12
+#define        DZ_FWIO_TCR     8
+#define        DZ_FWIO_DCD     13
+#define        DZ_FWIO_RING    13
+
+int
+dz_fwio_match(struct device *parent, void *vcf, void *aux)
+{
+       struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+
+       return strcmp(faa->faa_dev, dz_cd.cd_name) == 0 ? 1 : 0;
+}
+
+void
+dz_fwio_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+       struct dz_softc *sc = (struct dz_softc *)self;
+       paddr_t basepa;
+#if NDZKBD > 0 || NDZMS > 0
+       struct dzkm_attach_args daa;
+       extern struct consdev wsdisplay_cons;
+#endif
+       extern vaddr_t dz_console_regs;
+       vaddr_t dz_regs;
+       unsigned int vec;
+       int console;
+       int serial_console;
+
+       vec = faa->faa_vecbase + FBIC_DEVIRQ2 * 4;
+       printf(" vec %d: ", vec);
+
+       /*
+        * Map registers.
+        */
+
+       if (dz_console_regs != 0 && faa->faa_mid == mbus_ioslot) {
+               dz_regs = dz_console_regs;
+               console = 1;
+               serial_console = 1;     /* XXX forced for now */
+               if (serial_console)
+                       printf("console, ");
+       } else {
+               basepa = faa->faa_base + FWIO_DZ_REG_OFFSET;
+               dz_regs = vax_map_physmem(basepa, 1);
+               console = 0;
+       }
+
+       /* 
+        * XXX - This is evil and ugly, but...
+        * due to the nature of how bus_space_* works on VAX, this will
+        * be perfectly good until everything is converted.
+        */
+       sc->sc_ioh = dz_regs;
+
+       sc->sc_dr.dr_csr = DZ_FWIO_CSR;
+       sc->sc_dr.dr_rbuf = DZ_FWIO_RBUF;
+       sc->sc_dr.dr_tbuf = DZ_FWIO_TBUF;
+       sc->sc_dr.dr_tcr = DZ_FWIO_TCR;
+       sc->sc_dr.dr_dtr = DZ_FWIO_DTR;
+       sc->sc_dr.dr_break = DZ_FWIO_BREAK;
+       sc->sc_dr.dr_dcd = DZ_FWIO_DCD;
+       sc->sc_dr.dr_ring = DZ_FWIO_RING;
+
+       sc->sc_type = DZ_DZV;
+
+       /* no modem ctrl bits except on line 2 */
+       sc->sc_dsr = (1 << 0) | (1 << 1) | (1 << 3);
+
+       printf("4 lines");
+
+       /*
+        * Complete attachment.
+        */
+
+       dzattach(sc);
+
+       /*
+        * Register interrupt handler.
+        */
+
+       if (mbus_intr_establish(vec, IPL_TTY, dz_fwio_intr, sc,
+           self->dv_xname) != 0) {
+               printf("\n%s: can't establish interrupt\n", self->dv_xname);
+               return;
+       }
+       
+       /*
+        * Attach input devices, if any.
+        */
+
+#if NDZKBD > 0
+       daa.daa_line = 0;
+       DZ_WRITE_WORD(sc, dr_rbuf, DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) |
+           DZ_LPR_8_BIT_CHAR | daa.daa_line);
+       daa.daa_flags =
+           (console && cn_tab == &wsdisplay_cons ? DZKBD_CONSOLE : 0);
+       config_found(self, &daa, dz_print);
+#endif
+#if NDZMS > 0
+       daa.daa_line = 1;
+       DZ_WRITE_WORD(sc, dr_rbuf, DZ_LPR_RX_ENABLE | (DZ_LPR_B4800 << 8) |
+           DZ_LPR_8_BIT_CHAR | DZ_LPR_PARENB | DZ_LPR_OPAR | daa.daa_line);
+       daa.daa_flags = 0;
+       config_found(self, &daa, dz_print);
+#endif
+}
+
+int
+dz_fwio_intr(void *v)
+{
+       struct dz_softc *sc = (struct dz_softc *)v;
+
+       /*
+        * FBIC expects edge interrupts, while the dz does level
+        * interrupts. To avoid missing interrupts while servicing,
+        * we disable further device interrupts while servicing.
+        */
+       DZ_WRITE_WORD(sc, dr_csr,
+           DZ_READ_WORD(sc, dr_csr) & ~(DZ_CSR_RXIE | DZ_CSR_TXIE));
+
+       dzrint(sc);
+       dzxint(sc);
+
+       DZ_WRITE_WORD(sc, dr_csr,
+           DZ_READ_WORD(sc, dr_csr) | (DZ_CSR_RXIE | DZ_CSR_TXIE));
+
+       return 1;
+}
diff --git a/sys/arch/vax/mbus/files.mbus b/sys/arch/vax/mbus/files.mbus
new file mode 100644 (file)
index 0000000..8b69291
--- /dev/null
@@ -0,0 +1,29 @@
+#      $OpenBSD: files.mbus,v 1.1 2008/08/18 23:19:25 miod Exp $
+
+# VAXstation 3[58][24]0 internal bus
+device mbus { [mid = -1] }
+attach mbus at mainbus
+file   arch/vax/mbus/mbus.c                    mbus
+
+# L2003 Firefox Workstation I/O Module
+device fwio {}
+attach fwio at mbus
+file   arch/vax/mbus/fwio.c                    fwio
+
+attach dz at fwio with dz_fwio: dzcons
+file   arch/vax/mbus/dz_fwio.c                 dz_fwio
+
+attach le at fwio with le_fwio
+file   arch/vax/mbus/if_le_fwio.c              le_fwio
+
+attach sii at fwio with sii_fwio
+file   arch/vax/mbus/sii_fwio.c                sii_fwio
+
+# L2008 CQBIC
+attach uba at mbus with uba_mbus
+file   arch/vax/mbus/uba_mbus.c                uba_mbus
+
+# L2001 or L2010 CPU
+# L2004 LEGSS video
+# (with L2005 8-plane output module and optional L2006 16-plane module)
+# L2007 memory
diff --git a/sys/arch/vax/mbus/fwio.c b/sys/arch/vax/mbus/fwio.c
new file mode 100644 (file)
index 0000000..32d62fc
--- /dev/null
@@ -0,0 +1,111 @@
+/*     $OpenBSD: fwio.c,v 1.1 2008/08/18 23:19:25 miod Exp $   */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Firefox Workstation I/O Module
+ *
+ * This M-bus board sports:
+ * - a System Support Chip implementing the (off cpu) clocks.
+ * - a SII controller, in SCSI mode, with 128KB static memory.
+ * - a LANCE Ethernet controller, with 128KB static memory.
+ * - a DZQ11-compatible DC7085 4 lines serial controller.
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/nexus.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+#include <vax/mbus/fwiovar.h>
+
+struct fwio_softc {
+       struct device   sc_dev;
+       int             sc_loc[1];      /* locators override */
+};
+
+void   fwio_attach(struct device *, struct device *, void *);
+int    fwio_match(struct device *, void *, void *);
+
+struct cfdriver fwio_cd = {
+       NULL, "fwio", DV_DULL
+};
+
+const struct cfattach fwio_ca = {
+       sizeof(struct fwio_softc), fwio_match, fwio_attach
+};
+
+int    fwio_print(void *, const char *);
+
+int
+fwio_match(struct device *parent, void *vcf, void *aux)
+{
+       struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+
+       if (maa->maa_class == CLASS_IO && maa->maa_interface == INTERFACE_FBIC)
+               return 1;
+
+       return 0;
+}
+
+void
+fwio_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+       struct fwio_softc *sc = (struct fwio_softc *)self;
+       struct fwio_attach_args faa;
+
+       printf("\n");
+
+       /*
+        * Save our mid in locators.  booted_sd() in autoconf.c depends
+        * on this to find the correct boot device.
+        */
+       sc->sc_loc[0] = maa->maa_mid;
+       self->dv_cfdata->cf_loc = sc->sc_loc;
+
+       faa.faa_mid = maa->maa_mid;
+       faa.faa_base = MBUS_SLOT_BASE(maa->maa_mid);
+       faa.faa_vecbase = maa->maa_vecbase;
+
+       faa.faa_dev = "dz";
+       (void)config_found(self, &faa, fwio_print);
+
+       faa.faa_dev = "le";
+       (void)config_found(self, &faa, fwio_print);
+
+       faa.faa_dev = "sii";
+       (void)config_found(self, &faa, fwio_print);
+}
+
+int
+fwio_print(void *aux, const char *pnp)
+{
+       struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+
+       if (pnp != NULL)
+               printf("%s at %s", faa->faa_dev, pnp);
+
+       return (UNCONF);
+}
diff --git a/sys/arch/vax/mbus/fwioreg.h b/sys/arch/vax/mbus/fwioreg.h
new file mode 100644 (file)
index 0000000..81b4a69
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $OpenBSD: fwioreg.h,v 1.1 2008/08/18 23:19:25 miod Exp $        */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Firefox Workstation I/O Module registers and memory layout
+ */
+
+#define        FWIO_SSC_REMAP_ADDR     0x21400000
+
+#define        FWIO_SII_REG_OFFSET     0x000000
+#define        FWIO_LANCE_REG_OFFSET   0x200000
+#define        FWIO_SII_BUF_OFFSET     0x400000
+#define        FWIO_SII_BUF_SIZE       0x020000
+#define        FWIO_DZ_REG_OFFSET      0x600000
+#define        FWIO_IOCSR_OFFSET       0x800000
+#define        FWIO_ESAR_OFFSET        0x800000
+#define        FWIO_LANCE_BUF_OFFSET   0xa00000
+#define        FWIO_LANCE_BUF_SIZE     0x020000
+
+/*
+ * IOCSR bits
+ */
+
+#define        FWIO_IOCSR_CNSL         0x80000000 /* break on line 3 asserts MHALT */
+#define        FWIO_IOCSR_MRUN         0x40000000 /* assert MRUN */
+#define        FWIO_IOCSR_CLKIEN       0x20000000 /* drive MCLKI */
+#define        FWIO_IOCSR_RSTWS        0x10000000 /* reset workstation */
+
+#define        FWIO_ESAR_MASK          0x00ff0000
+#define        FWIO_ESAR_SHIFT         16
diff --git a/sys/arch/vax/mbus/fwiovar.h b/sys/arch/vax/mbus/fwiovar.h
new file mode 100644 (file)
index 0000000..05f5e4a
--- /dev/null
@@ -0,0 +1,28 @@
+/*     $OpenBSD: fwiovar.h,v 1.1 2008/08/18 23:19:25 miod Exp $        */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Firefox Workstation I/O Module subdevice attachment glue
+ */
+
+struct fwio_attach_args {
+       const char      *faa_dev;
+       unsigned int     faa_mid;
+       paddr_t          faa_base;
+       unsigned int     faa_vecbase;
+};
diff --git a/sys/arch/vax/mbus/if_le_fwio.c b/sys/arch/vax/mbus/if_le_fwio.c
new file mode 100644 (file)
index 0000000..8a00115
--- /dev/null
@@ -0,0 +1,272 @@
+/*     $OpenBSD: if_le_fwio.c,v 1.1 2008/08/18 23:19:25 miod Exp $     */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ *
+ *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#if INET
+#include <netinet/in.h>
+#endif
+#include <netinet/if_ether.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+#include <vax/mbus/fwiovar.h>
+
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
+
+struct le_fwio_softc {
+       struct am7990_softc sc_am7990;
+       volatile uint16_t *sc_rap;
+       volatile uint16_t *sc_rdp;
+};
+
+int    le_fwio_match(struct device *, void *, void *);
+void   le_fwio_attach(struct device *, struct device *, void *);
+
+struct cfattach le_fwio_ca = {
+       sizeof(struct le_fwio_softc), le_fwio_match, le_fwio_attach
+};
+
+int    le_fwio_intr(void *);
+uint16_t le_fwio_rdcsr(struct am7990_softc *, uint16_t);
+void   le_fwio_wrcsr(struct am7990_softc *, uint16_t, uint16_t);
+void   le_fwio_wrcsr_interrupt(struct am7990_softc *, uint16_t, uint16_t);
+
+int
+le_fwio_match(struct device *parent, void *vcf, void *aux)
+{
+       struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+
+       return strcmp(faa->faa_dev, le_cd.cd_name) == 0 ? 1 : 0;
+}
+
+void
+le_fwio_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+       struct le_fwio_softc *sc = (struct le_fwio_softc *)self;
+       unsigned int vec;
+       uint32_t *esar;
+       int i;
+
+       vec = faa->faa_vecbase + FBIC_DEVIRQ1 * 4;
+       printf(" vec %d", vec);
+
+       /*
+        * Map registers.
+        */
+
+       sc->sc_rdp = (volatile uint16_t *)
+           vax_map_physmem(faa->faa_base + FWIO_LANCE_REG_OFFSET, 1);
+       sc->sc_rap = sc->sc_rdp + 2;
+
+       /*
+        * Register access functions.
+        */
+
+       sc->sc_am7990.sc_rdcsr = le_fwio_rdcsr;
+       sc->sc_am7990.sc_wrcsr = le_fwio_wrcsr;
+
+       /*
+        * Map buffers.
+        */
+
+       sc->sc_am7990.sc_mem =
+           (void *)uvm_km_valloc(kernel_map, FWIO_LANCE_BUF_SIZE);
+       if (sc->sc_am7990.sc_mem == NULL) {
+               vax_unmap_physmem(faa->faa_base + FWIO_LANCE_REG_OFFSET, 1);
+               printf(": can't map buffers\n");
+               return;
+       }
+
+       ioaccess((vaddr_t)sc->sc_am7990.sc_mem, faa->faa_base +
+           FWIO_LANCE_BUF_OFFSET, FWIO_LANCE_BUF_SIZE >> VAX_PGSHIFT);
+
+       sc->sc_am7990.sc_addr = FWIO_LANCE_BUF_OFFSET;
+       sc->sc_am7990.sc_memsize = FWIO_LANCE_BUF_SIZE;
+       sc->sc_am7990.sc_conf3 = 0;
+
+       sc->sc_am7990.sc_copytodesc = am7990_copytobuf_contig;
+       sc->sc_am7990.sc_copyfromdesc = am7990_copyfrombuf_contig;
+       sc->sc_am7990.sc_copytobuf = am7990_copytobuf_contig;
+       sc->sc_am7990.sc_copyfrombuf = am7990_copyfrombuf_contig;
+       sc->sc_am7990.sc_zerobuf = am7990_zerobuf_contig;
+
+       /*
+        * Get the Ethernet address from the Station Address ROM.
+        */
+
+       esar = (uint32_t *)vax_map_physmem(faa->faa_base + FWIO_ESAR_OFFSET, 1);
+       for (i = 0; i < 6; i++)
+               sc->sc_am7990.sc_arpcom.ac_enaddr[i] =
+                   (esar[i] & FWIO_ESAR_MASK) >> FWIO_ESAR_SHIFT;
+       vax_unmap_physmem((vaddr_t)esar, 1);
+       bcopy(self->dv_xname, sc->sc_am7990.sc_arpcom.ac_if.if_xname, IFNAMSIZ);
+
+       /*
+        * Register interrupt handler.
+        */
+
+       if (mbus_intr_establish(vec, IPL_NET, le_fwio_intr, sc,
+           self->dv_xname) != 0) {
+               vax_unmap_physmem(faa->faa_base + FWIO_LANCE_REG_OFFSET, 1);
+               uvm_km_free(kernel_map, (vaddr_t)sc->sc_am7990.sc_mem,
+                   FWIO_LANCE_BUF_SIZE);
+               printf(": can't establish interrupt\n");
+               return;
+       }
+
+       /*
+        * Complete attachment.
+        */
+
+       am7990_config(&sc->sc_am7990);
+}
+
+int
+le_fwio_intr(void *v)
+{
+       struct le_fwio_softc *lsc = (struct le_fwio_softc *)v;
+       int rc;
+
+       /*
+        * FBIC expects edge interrupts, while the LANCE does level
+        * interrupts. To avoid missing interrupts while servicing,
+        * we disable further device interrupts while servicing.
+        *
+        * However, am7990_intr() will flip the interrupt enable bit
+        * itself; we override wrcsr with a specific version during
+        * servicing, so as not to reenable interrupts accidentally...
+        */
+       lsc->sc_am7990.sc_wrcsr = le_fwio_wrcsr_interrupt;
+
+       rc = am7990_intr(v);
+
+       lsc->sc_am7990.sc_wrcsr = le_fwio_wrcsr;
+       /*
+        * ...but we should not forget to reenable interrupts at this point!
+        */
+       le_fwio_wrcsr(&lsc->sc_am7990, LE_CSR0, LE_C0_INEA |
+           le_fwio_rdcsr(&lsc->sc_am7990, LE_CSR0));
+
+       return rc;
+}
+
+uint16_t
+le_fwio_rdcsr(struct am7990_softc *sc, uint16_t port)
+{
+       struct le_fwio_softc *lsc = (struct le_fwio_softc *)sc;
+
+       *lsc->sc_rap = port;
+       return *lsc->sc_rdp;
+}
+
+void
+le_fwio_wrcsr(struct am7990_softc *sc, uint16_t port, uint16_t val)
+{
+       struct le_fwio_softc *lsc = (struct le_fwio_softc *)sc;
+
+       *lsc->sc_rap = port;
+       *lsc->sc_rdp = val;
+}
+
+void
+le_fwio_wrcsr_interrupt(struct am7990_softc *sc, uint16_t port, uint16_t val)
+{
+       if (port == LE_CSR0)
+               val &= ~LE_C0_INEA;
+
+       le_fwio_wrcsr(sc, port, val);
+}
diff --git a/sys/arch/vax/mbus/mbus.c b/sys/arch/vax/mbus/mbus.c
new file mode 100644 (file)
index 0000000..a9fc921
--- /dev/null
@@ -0,0 +1,441 @@
+/*     $OpenBSD: mbus.c,v 1.1 2008/08/18 23:19:25 miod Exp $   */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/nexus.h>
+#include <machine/scb.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+
+#define        PR_CPUID 14
+
+/*
+ * FBIC interrupt handlers
+ */
+struct fbic_irq {
+       int     (*fi_fn)(void *);
+       void    *fi_arg;
+       struct evcount fi_cnt;
+       int     fi_ipl;
+};
+
+/*
+ * Generic information for each slot.
+ *
+ * This information is maintained at the mbus level, rather than
+ * enforcing each child driver to provide it.  This allows proper
+ * M-bus configuration on slots where no driver attaches.
+ */
+
+struct fbic {
+       paddr_t         base;
+       vaddr_t         regs;
+       int             vecbase;
+       struct fbic_irq *firq[FBIC_DEVIRQMAX];
+};
+
+struct mbus_slot {
+       uint8_t         ms_interface;   /* MODTYPE interface */
+       uint8_t         ms_class;       /* MODTYPE class */
+
+       unsigned int    ms_nfbic;
+       struct fbic     ms_fbic[2];
+};
+
+struct mbus_softc {
+       struct device   sc_dev;
+       struct mbus_slot *sc_slots[MBUS_SLOT_MAX];
+};
+
+void   mbus_attach(struct device *, struct device *, void *);
+int    mbus_match(struct device *, void *, void *);
+
+struct cfdriver mbus_cd = {
+       NULL, "mbus", DV_DULL
+};
+
+const struct cfattach mbus_ca = {
+       sizeof(struct mbus_softc), mbus_match, mbus_attach
+};
+
+void   mbus_initialize_cpu(struct mbus_slot *, unsigned int, int);
+void   mbus_initialize_device(struct mbus_slot *, unsigned int, uint8_t);
+void   mbus_intr_dispatch(void *);
+int    mbus_print(void *, const char *);
+int    mbus_submatch(struct device *, void *, void *);
+
+unsigned int mbus_ioslot = (unsigned int)-1;
+
+int
+mbus_match(struct device *parent, void *vcf, void *aux)
+{
+       struct mainbus_attach_args *maa = (struct mainbus_attach_args *)aux;
+
+       return maa->maa_bustype == VAX_MBUS ? 1 : 0;
+}
+
+void
+mbus_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct mbus_softc *sc = (struct mbus_softc *)self;
+       struct mbus_slot *ms;
+       unsigned int mid;
+       struct mbus_attach_args maa;
+       paddr_t pa;
+       vaddr_t fbic;
+       uint32_t modtype;
+       uint8_t class, interface;
+
+       printf("\n");
+
+       /*
+        * Walk the bus and probe slots.
+        * We will also record information about all occupied slots,
+        * and keep a permanent mapping of their FBIC, as we will end
+        * up needing to play with them often...
+        */
+
+       for (mid = 0; mid < MBUS_SLOT_MAX; mid++) {
+
+               /*
+                * Map main (and often, only) FBIC.
+                */
+
+               pa = MBUS_SLOT_BASE(mid);
+               fbic = vax_map_physmem(pa + FBIC_BASE, 1);
+               if (fbic == NULL)
+                       panic("unable to map slot %d registers", mid);
+
+               if (badaddr((caddr_t)(fbic + FBIC_MODTYPE), 4) != 0)
+                       modtype = 0;
+               else
+                       modtype = *(uint32_t *)(fbic + FBIC_MODTYPE);
+
+               if (modtype == 0 || modtype == 0xffffffff) {
+                       vax_unmap_physmem(fbic, 1);
+                       continue;
+               }
+
+               /*
+                * The slot is populated.  Write things down.
+                */
+
+               ms = (struct mbus_slot *)malloc(sizeof(*ms),
+                   M_DEVBUF, M_NOWAIT | M_ZERO);
+               if (ms == NULL)
+                       panic("not enough memory to probe M-bus");
+
+               sc->sc_slots[mid] = ms;
+               ms->ms_nfbic = 1;       /* only one so far! */
+               ms->ms_fbic[0].base = pa + FBIC_BASE;
+               ms->ms_fbic[0].regs = fbic;
+
+               class = (modtype & MODTYPE_CLASS_MASK) >> MODTYPE_CLASS_SHIFT;
+               interface = (modtype & MODTYPE_INTERFACE_MASK) >>
+                   MODTYPE_INTERFACE_SHIFT;
+
+               ms->ms_interface = interface;
+               ms->ms_class = class;
+
+               /*
+                * If there are two FBICs on this board, map the second one.
+                */
+
+               if (class == CLASS_CPU) {
+                       /* the FBIC we mapped is in fact the second one... */
+                       ms->ms_fbic[1].base = ms->ms_fbic[0].base;
+                       ms->ms_fbic[1].regs = ms->ms_fbic[0].regs;
+                       ms->ms_nfbic = 2;
+                       fbic = vax_map_physmem(pa + FBIC_CPUA_BASE, 1);
+                       if (fbic == NULL)
+                               panic("unable to map slot %d registers", mid);
+                       ms->ms_fbic[0].base = pa + FBIC_CPUA_BASE;
+                       ms->ms_fbic[0].regs = fbic;
+               }
+
+               /*
+                * Perform a minimal sane initialization.
+                */
+
+               if (class == CLASS_CPU) {
+                       mbus_initialize_cpu(ms, mid, 0);
+                       mbus_initialize_cpu(ms, mid, 1);
+               } else
+                       mbus_initialize_device(ms, mid, interface);
+
+               /*
+                * Attach subdevices if possible.
+                */
+
+               maa.maa_mid = mid;
+               maa.maa_class = class;
+               maa.maa_subclass = (modtype & MODTYPE_SUBCLASS_MASK) >>
+                   MODTYPE_SUBCLASS_SHIFT;
+               maa.maa_interface = interface;
+               maa.maa_revision = (modtype & MODTYPE_REVISION_MASK) >>
+                   MODTYPE_REVISION_SHIFT;
+               maa.maa_addr = pa;
+               maa.maa_vecbase = ms->ms_fbic[0].vecbase;
+
+               (void)config_found_sm(self, &maa, mbus_print, mbus_submatch);
+       }
+}
+
+int
+mbus_print(void *aux, const char *pnp)
+{
+       struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+       int rc = UNCONF;
+       const char *descr;
+
+       switch (maa->maa_class) {
+       case CLASS_BA:
+               descr = "Bus Adaptor";
+               break;
+       case CLASS_GRAPHICS:
+               descr = "Graphics";
+               break;
+       case CLASS_IO:
+               descr = "I/O Module";
+               break;
+       case CLASS_CPU:
+               descr = "cpu";
+               break;
+       case CLASS_MEMORY:
+               descr = maa->maa_interface == INTERFACE_FMDC ?
+                   "ECC memory" : "Memory";
+               break;
+       default:
+               rc = UNSUPP;
+               break;
+       }
+
+       if (maa->maa_interface != INTERFACE_FBIC) {
+               if (maa->maa_class != CLASS_MEMORY ||
+                   (maa->maa_interface != INTERFACE_FMCM &&
+                    maa->maa_interface != INTERFACE_FMDC))
+                       rc = UNSUPP;
+       }
+
+       if (pnp != NULL) {
+               if (rc == UNSUPP) {
+                       printf("logic board class %02x:%02x interface %u.%u ",
+                           maa->maa_class, maa->maa_subclass,
+                           maa->maa_interface, maa->maa_revision);
+                       if (descr != NULL)
+                               printf("(%s)", descr);
+               } else
+                       printf("%s", descr);
+               printf(" at %s", pnp);
+       }
+       printf(" mid %u", maa->maa_mid);
+
+       return (rc);
+}
+
+int
+mbus_submatch(struct device *parent, void *vcf, void *aux)
+{
+       struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+       struct cfdata *cf = (struct cfdata *)vcf;
+
+       /*
+        * If attachment specifies the mid, it has to match.
+        */
+       if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != maa->maa_mid)
+               return 0;
+
+       return (*cf->cf_attach->ca_match)(parent, vcf, aux);
+}
+
+/*
+ * CPU board initialization.
+ */
+
+void
+mbus_initialize_cpu(struct mbus_slot *ms, unsigned int mid, int cpu)
+{
+       struct fbic *fbic = &ms->ms_fbic[cpu];
+       uint32_t fbicsr;
+       int cpuid;
+
+       cpuid = (mid << CPUID_MID_SHIFT) |
+           (cpu != 0 ? CPUID_PROC_1 : CPUID_PROC_0);
+
+       /*
+        * Clear error log
+        */
+       *(uint32_t *)(fbic->regs + FBIC_BUSCSR) = BUSCSR_RESET;
+
+       /*
+        * Set (IPI) interrupt vectors base, but do not enable them yet.
+        */
+       fbic->vecbase = MBUS_VECTOR_BASE(mid, cpu);
+       *(uint32_t *)(fbic->regs + FBIC_IPDVINT) = 0 /* IPDVINT_IPUNIT */ |
+           (fbic->vecbase & IPDVINT_VECTOR_MASK);
+
+       /*
+        * Enable all interrupt sources if on the boot processor,
+        * disable them otherwise (this does not affect IPIs).
+        */
+       fbicsr = *(uint32_t *)(fbic->regs + FBIC_BUSCSR);
+       if (cpuid == mfpr(PR_CPUID))
+               fbicsr |= FBICSR_IRQEN_MASK;
+       else
+               fbicsr &= ~FBICSR_IRQEN_MASK;
+
+       /*
+        * Route interrupts from the M-bus to the CVAX.
+        */
+       fbicsr &= ~FBICSR_IRQC2M_MASK;
+
+       /*
+        * Allow the CPU to be halted.
+        */
+       fbicsr |= FBICSR_HALTEN;
+
+       *(uint32_t *)(fbic->regs + FBIC_BUSCSR) = fbicsr;
+}
+
+/*
+ * Device board initialization.
+ */
+
+void
+mbus_initialize_device(struct mbus_slot *ms, unsigned int mid,
+    uint8_t interface)
+{
+       struct fbic *fbic = ms->ms_fbic;
+       uint32_t fbicsr;
+
+       /*
+        * Clear error log if applicable
+        */
+       if (interface == INTERFACE_FBIC || interface == INTERFACE_FMDC)
+               *(uint32_t *)(fbic->regs + FBIC_BUSCSR) = BUSCSR_RESET;
+
+       if (interface == INTERFACE_FBIC) {
+               /*
+                * Set interrupt vector base.
+                */
+               fbic->vecbase = MBUS_VECTOR_BASE(mid, 0);
+               *(uint32_t *)(fbic->regs + FBIC_IPDVINT) = IPDVINT_DEVICE |
+                   (fbic->vecbase & IPDVINT_VECTOR_MASK);
+
+               /*
+                * Disable all interrupt sources, and route them
+                * from the devices to the M-bus.
+                */
+               fbicsr = *(uint32_t *)(fbic->regs + FBIC_BUSCSR);
+               fbicsr &= ~FBICSR_IRQEN_MASK;
+               fbicsr |= FBICSR_IRQC2M_MASK;
+               *(uint32_t *)(fbic->regs + FBIC_BUSCSR) = fbicsr;
+       }
+}
+
+/*
+ * Interrupt handling.
+ */
+
+int
+mbus_intr_establish(unsigned int vec, int ipl, int (*fn)(void *), void *arg,
+    const char *name)
+{
+       struct mbus_softc *sc;
+       struct mbus_slot *ms;
+       struct fbic *fbic;
+       struct fbic_irq *fi;
+       uint32_t fbicsr;
+       unsigned int mid, fbicirq;
+
+       mid = MBUS_VECTOR_TO_MID(vec);
+
+#ifdef DIAGNOSTIC
+       if (mid >= MBUS_SLOT_MAX)
+               return EINVAL;
+       if (mbus_cd.cd_ndevs == 0)
+               return ENXIO;
+#endif
+       sc = (struct mbus_softc *)mbus_cd.cd_devs[0];
+#ifdef DIAGNOSTIC
+       if (sc == NULL)
+               return ENXIO;
+#endif
+       ms = sc->sc_slots[mid];
+#ifdef DIAGNOSTIC
+       if (ms == NULL)
+               return ENXIO;
+#endif
+       fi = (struct fbic_irq *)malloc(sizeof *fi, M_DEVBUF, M_NOWAIT);
+       if (fi == NULL)
+               return ENOMEM;
+
+       /*
+        * This interface is intended to be used for device interrupts
+        * only, so there is no need to handle dual-FBIC slots.
+        */
+       fbic = &ms->ms_fbic[0 /* MBUS_VECTOR_TO_FBIC(vec) */];
+
+       fi->fi_fn = fn;
+       fi->fi_arg = arg;
+       fi->fi_ipl = ipl;
+       evcount_attach(&fi->fi_cnt, name, &fi->fi_ipl, &evcount_intr);
+
+       fbicirq = MBUS_VECTOR_TO_IRQ(vec);
+       fbic->firq[fbicirq] = fi;
+       scb_vecalloc(vec, mbus_intr_dispatch, fi, SCB_ISTACK, &fi->fi_cnt);
+
+       /*
+        * Enable device interrupt in the module FBIC.  Proper direction
+        * has been setup in mbus_slot_initialize().
+        */
+
+       fbicsr = *(uint32_t *)(fbic->regs + FBIC_BUSCSR);
+       fbicsr |= fbicirq << FBICSR_IRQEN_SHIFT;
+       *(uint32_t *)(fbic + FBIC_BUSCSR) = fbicsr;
+
+       return 0;
+}
+
+/*
+ * Interrupt dispatcher.
+ */
+
+void
+mbus_intr_dispatch(void *v)
+{
+       struct fbic_irq *fi = (struct fbic_irq *)v;
+       int s;
+
+       /*
+        * FBIC interrupts are at fixed levels.  In case the level is
+        * below the level the driver expects the interrupt at, we need
+        * to raise spl to be safe (e.g. for sii).
+        */
+       s = _splraise(fi->fi_ipl);
+       (void)(*fi->fi_fn)(fi->fi_arg);
+       splx(s);
+}
diff --git a/sys/arch/vax/mbus/mbusreg.h b/sys/arch/vax/mbus/mbusreg.h
new file mode 100644 (file)
index 0000000..cea06e6
--- /dev/null
@@ -0,0 +1,251 @@
+/*     $OpenBSD: mbusreg.h,v 1.1 2008/08/18 23:19:25 miod Exp $        */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * M-bus
+ *
+ * The M-bus connects up to 8 slots, of 32MB memory space each.
+ *
+ * All these modules contain a ``Firefox Bus Interface Chip'' (FBIC),
+ * which provides common registers at the end of each slot address space,
+ * allowing modules to recognize and configure each other.
+ */
+
+#define        MBUS_SLOT_MAX                   8
+
+/*
+ * Addressing
+ *
+ * The M-bus provides a 32-bit address space.
+ *
+ * The low half (bit 31 clear) is the physical memory space (and being on
+ * vax, really stops at 512MB).
+ * The high half is the I/O space, where each slot has a 32MB window.
+ * In addition to its window, there are two 128MB areas, allowing a given
+ * module to provide functionnality regardless of its actual position on
+ * the bus.
+ *
+ * From the host CPU, the M-bus I/O space is remapped in the vax I/O space.
+ *
+ * The address map is thus:
+ * M-bus address       CPU address     Length
+ * 0000.0000           0000.0000       2000.0000       memory space
+ * 8000.0000           2000.0000       0800.0000       global I/O
+ * 8800.0000           2800.0000       0800.0000       local I/O
+ * 9000.0000           3000.0000       0200.0000       slot 0 I/O
+ * 9200.0000           3200.0000       0200.0000       slot 1 I/O
+ * 9400.0000           3400.0000       0200.0000       slot 2 I/O
+ * 9600.0000           3600.0000       0200.0000       slot 3 I/O
+ * 9800.0000           3800.0000       0200.0000       slot 4 I/O
+ * 9a00.0000           3a00.0000       0200.0000       slot 5 I/O
+ * 9c00.0000           3c00.0000       0200.0000       slot 6 I/O
+ * 9e00.0000           3e00.0000       0200.0000       slot 7 I/O
+ */
+
+/* base address of a slot, as seen from the cpu */
+#define        MBUS_SLOT_BASE(s)               (0x30000000 + ((s) << 25))
+
+/* convert I/O space addresses (assumed to be in their correct range) */
+#define        HOST_TO_MBUS(pa)                ((pa) ^ 0xa0000000)
+#define        MBUS_TO_HOST(pa)                ((pa) ^ 0xa0000000)
+
+/*
+ * Common FBIC slot registers
+ */
+
+/* FBIC or compatible registers occupy the last page (running down)... */
+#define        FBIC_BASE                       0x1fffe00
+/* ...but dual-CPU modules have two of them. */
+#define        FBIC_CPUA_BASE                  0x0fffe00
+#define        FBIC_CPUB_BASE                  0x1fffe00
+
+/* module identification */
+#define        FBIC_MODTYPE                    0x1fc
+/* M-bus error status */
+#define        FBIC_BUSCSR                     0x1f8
+/* M-bus error control signal log */
+#define        FBIC_BUSCTL                     0x1f4
+/* M-bus error address signal log */
+#define        FBIC_BUSADR                     0x1f0
+/* M-bus error data signal log */
+#define        FBIC_BUSDAT                     0x1ec
+/* FBIC control and status */
+#define        FBIC_CSR                        0x1e8
+/* I/O space range decode */
+#define        FBIC_RANGE                      0x1e4
+/* Interprocessor and device interrupt */
+#define        FBIC_IPDVINT                    0x1e0
+/* Unique software ID */
+#define        FBIC_WHAMI                      0x1dc
+/* Unique hardware ID */
+#define        FBIC_CPUID                      0x1d8
+/* Interlock 1 address */
+#define        FBIC_IADR1                      0x1d4
+/* Interlock 2 address */
+#define        FBIC_IADR2                      0x1d0
+/* Console scratch register */
+#define        FBIC_SAVGPR                     0x1c4
+
+/*
+ * Module identification
+ */
+#define        MODTYPE_CLASS_MASK              0x000000ff
+#define        MODTYPE_CLASS_SHIFT             0
+#define        CLASS_BA                        0x01
+#define        CLASS_GRAPHICS                  0x02
+#define        CLASS_IO                        0x04
+#define        CLASS_CPU                       0x08
+#define        CLASS_MEMORY                    0x10
+#define        MODTYPE_SUBCLASS_MASK           0x0000ff00
+#define        MODTYPE_SUBCLASS_SHIFT          8
+#define        MODTYPE_INTERFACE_MASK          0x00ff0000
+#define        MODTYPE_INTERFACE_SHIFT         16
+#define        INTERFACE_FBIC                  0x01
+#define        INTERFACE_FMDC                  0x02 /* ECC memory */
+#define        INTERFACE_FMCM                  0xfe /* 8MB board */
+#define        MODTYPE_REVISION_MASK           0xff000000
+#define        MODTYPE_REVISION_SHIFT          24
+
+/*
+ * M-bus error status and error logging
+ * Conditions are active low
+ */
+#define        BUSCSR_FRZN                     0x80000000 /* logging frozen */
+#define        BUSCSR_ARB                      0x40000000 /* arbitration error */
+#define        BUSCSR_ICMD                     0x20000000 /* invalid MCMD encoding */
+#define        BUSCSR_IDAT                     0x10000000 /* invalid data supplied */
+#define        BUSCSR_MTPE                     0x08000000 /* tag parity error */
+#define        BUSCSR_MDPE                     0x04000000 /* MDAL parity error */
+#define        BUSCSR_MSPE                     0x02000000 /* MSTATUS parity error */
+#define        BUSCSR_MCPE                     0x01000000 /* MCMD parity error */
+#define        BUSCSR_ILCK                     0x00800000 /* interlock violation */
+#define        BUSCSR_MTO                      0x00400000 /* slave timeout */
+#define        BUSCSR_NOS                      0x00200000 /* no slave response */
+#define        BUSCSR_CTO                      0x00100000 /* CDAL data cycle timeout */
+#define        BUSCSR_CDPE                     0x00080000 /* CDAL parity error */
+#define        BUSCSR_CTPE                     0x00040000 /* CDAL tag parity error */
+#define        BUSCSR_SERR                     0x00020000 /* error on MSTATUS */
+#define        BUSCSR_DBLE                     0x00010000 /* double M-bus error */
+
+#define        BUSCSR_RESET                    0xffff0000 /* reset all conditions */
+
+/*
+ * FBIC control and status
+ */
+#define        FBICSR_MFMD_MASK                0xc0000000 /* manufacturing mode */
+#define        FBICSR_CMISS                    0x08000000 /* CVAX cache miss */
+#define        FBICSR_EXCAEN                   0x04000000 /* external cache enable */
+#define        FBICSR_HALTCPU                  0x02000000 /* CVAX halt */
+#define        FBICSR_RESET                    0x01000000 /* CVAX reset */
+#define        FBICSR_IRQEN_MASK               0x00f00000 /* interrupt enables */
+#define        FBICSR_IRQEN_SHIFT              20
+#define        FBIC_DEVIRQ0            0
+#define        FBIC_DEVIRQ1            1
+#define        FBIC_DEVIRQ2            2
+#define        FBIC_DEVIRQ3            3
+#define        FBIC_DEVIRQMAX          4
+#define        FBICSR_IRQC2M_MASK              0x000f0000 /* interrupt direction */
+#define        FBICSR_IRQC2M_SHIFT             16
+#define        FBICSR_LEDS_MASK                0x00003f00 /* module leds, active low */
+#define        FBICSR_LEDS_SHIFT               8
+#define        FBICSR_HALTEN                   0x00000080 /* halt enable */
+#define        FBICSR_TSTFNC_MASK              0x0000007e /* test function */
+#define        FBICSR_TSTFNC_SHIFT             1
+#define        TSTFNC_NORMAL_MODE              0x1f       /* normal operation */
+#define        FBICSR_CDPE                     0x00000001 /* CVAX parity enable */
+
+/*
+ * I/O Range
+ *
+ * This programs an M-bus address range which in the global I/O space, which
+ * is answered by this module.  Note that the upper bit in the match field
+ * must be set, for the address to be in the I/O space; this is why the
+ * upper bit of the mask field acts as an enable.
+ */
+#define        RANGE_MATCH                     0xffff0000 /* address bits 31:16 */
+#define        RANGE_ENABLE                    0x00008000 /* mask address bit 31 */
+#define        RANGE_MASK                      0x00007fff /* address bits 30:16 */
+
+/*
+ * Interprocessor and device interrupts
+ */
+#define        IPDVINT_IPL17                   0x08000000 /* trigger IRQ3 */
+#define        IPDVINT_IPL16                   0x04000000 /* trigger IRQ2 */
+#define        IPDVINT_IPL15                   0x02000000 /* trigger IRQ1 */
+#define        IPDVINT_IPL14                   0x01000000 /* trigger IRQ0 */
+#define        IPDVINT_IPUNIT                  0x00020000 /* interrupts CPU */
+#define        IPDVINT_DEVICE                  0x00010000 /* interrupts M-bus */
+#define        IPDVINT_VECTOR_MASK             0x0000fff0 /* interrupt vector */
+#define        IPDVINT_VECTOR_SHIFT            4
+#define        IPDVINT_IPL_MASK                0x0000000c /* interrupt ipl */
+#define        IPDVINT_IPL_SHIFT               2
+
+/*
+ * CPUID (also EPR 14)
+ */
+#define        CPUID_MID_MASK                  0x0000001c /* slot mid */
+#define        CPUID_MID_SHIFT                 2
+#define        CPUID_PROC_MASK                 0x00000003 /* slot processor id */
+#define        CPUID_PROC_SHIFT                0
+#define        CPUID_PROC_0                    0x00
+#define        CPUID_PROC_1                    0x03
+
+/*
+ * FMCM registers (not FBIC compatible except for MODTYPE and BUSCSR)
+ */
+
+/* module identification */
+#define        FMCM_MODTYPE                    0x1fc
+/* M-bus error status */
+/* NOTE: only implements FRZN, ICMD, MDPE, MSPE and MCPE */
+#define        FMCM_BUSCSR                     0x1f8
+/* FMCM control and status register */
+#define        FMCM_FMDCSR                     0x1f4
+/* Memory space base address register */
+#define        FMCM_BASEADDR                   0x1f0
+
+#define        FMDCSR_ISOLATE                  0x00008000 /* no MABORT on error */
+#define        FMDCSR_DIAGNOSTIC_REFRESH_START 0x00004000
+#define        FMDCSR_REFRESH_PERIOD_SELECT    0x00002000 /* set: slow (80ns) */
+#define        FMDCSR_DISABLE_REFRESH          0x00001000
+
+#define        BASEADDR_STARTADDR_MASK         0x7ff00000
+#define        BASEADDR_MEMORY_SPACE_ENABLE    0x80000000
+
+/*
+ * Interrupt vector assignments
+ *
+ * Since each FBIC controls four interrupts, and passes the IPI in bits
+ * 3:2 of the vector number, we have to reserve them on 0x10 boundaries.
+ *
+ * Note that this is different from the usual scheme of using bits 5:4
+ * for this purpose.
+ *
+ * CPU boards also use the IPDVINT to have an extra 0x10 range for IPIs.
+ *
+ * To make things simpler, we use a static assignment where the number is
+ * computed from the mid and fbic number (for cpu boards).
+ *
+ * This means the 0x100..0x1fc range is used for M-bus interrupts only.
+ * Q-bus interrupts will use the usual 0x200..0x3fc range.
+ */
+
+#define        MBUS_VECTOR_BASE(mid,fbic)      (0x100 + (mid) * 0x20 + (fbic) * 0x10)
+#define        MBUS_VECTOR_TO_MID(vec)         (((vec) - 0x100) >> 5)
+#define        MBUS_VECTOR_TO_FBIC(vec)        (((vec) & 0x10) >> 4)
+#define        MBUS_VECTOR_TO_IRQ(vec)         (((vec) & 0xc) >> 2)
diff --git a/sys/arch/vax/mbus/mbusvar.h b/sys/arch/vax/mbus/mbusvar.h
new file mode 100644 (file)
index 0000000..d48fdda
--- /dev/null
@@ -0,0 +1,33 @@
+/*     $OpenBSD: mbusvar.h,v 1.1 2008/08/18 23:19:25 miod Exp $        */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+struct mbus_attach_args {
+       unsigned int    maa_mid;
+       uint8_t         maa_class;
+       uint8_t         maa_subclass;
+       uint8_t         maa_interface;
+       uint8_t         maa_revision;
+       paddr_t         maa_addr;
+       unsigned int    maa_vecbase;
+};
+
+extern unsigned int mbus_ioslot;
+
+int    mbus_intr_establish(unsigned int, int, int (*)(void *), void *,
+           const char *);
+uint32_t mbus_ddb_hook(int, uint32_t);
diff --git a/sys/arch/vax/mbus/sii_fwio.c b/sys/arch/vax/mbus/sii_fwio.c
new file mode 100644 (file)
index 0000000..f1d329a
--- /dev/null
@@ -0,0 +1,163 @@
+/*     $OpenBSD: sii_fwio.c,v 1.1 2008/08/18 23:19:25 miod Exp $       */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+#include <vax/mbus/fwiovar.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_message.h>
+
+#include <vax/dec/siireg.h>
+#include <vax/dec/siivar.h>
+
+struct sii_fwio_softc {
+       struct sii_softc sc_dev;
+       u_char *sc_buf;
+};
+
+int    sii_fwio_match(struct device *, void *, void *);
+void   sii_fwio_attach(struct device *, struct device *, void *);
+
+struct cfattach sii_fwio_ca = {
+       sizeof(struct sii_fwio_softc), sii_fwio_match, sii_fwio_attach
+};
+
+extern struct cfdriver sii_cd;
+
+void   sii_fwio_copyfrombuf(void *, u_int, u_char *, int);
+void   sii_fwio_copytobuf(void *, u_char *, u_int, int);
+int    sii_fwio_intr(void *);
+
+int
+sii_fwio_match(struct device *parent, void *vcf, void *aux)
+{
+       struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+
+       return strcmp(faa->faa_dev, sii_cd.cd_name) == 0 ? 1 : 0;
+}
+
+void
+sii_fwio_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct fwio_attach_args *faa = (struct fwio_attach_args *)aux;
+       struct sii_fwio_softc *sfc = (struct sii_fwio_softc *)self;
+       struct sii_softc *sc = &sfc->sc_dev;
+       unsigned int vec;
+
+       vec = faa->faa_vecbase + FBIC_DEVIRQ0 * 4;
+       printf(" vec %d", vec);
+
+       /*
+        * Map registers.
+        */
+
+       sc->sc_regs =
+           (SIIRegs *)vax_map_physmem(faa->faa_base + FWIO_SII_REG_OFFSET, 1);
+
+       /*
+        * Map buffers.
+        */
+
+       sfc->sc_buf = (u_char *)uvm_km_valloc(kernel_map, FWIO_SII_BUF_SIZE);
+       if (sfc->sc_buf == NULL) {
+               vax_unmap_physmem(faa->faa_base + FWIO_SII_REG_OFFSET, 1);
+               printf(": can't map buffers\n");
+               return;
+       }
+
+       ioaccess((vaddr_t)sfc->sc_buf, faa->faa_base + FWIO_SII_BUF_OFFSET,
+           FWIO_SII_BUF_SIZE >> VAX_PGSHIFT);
+
+       sc->sii_copytobuf = sii_fwio_copytobuf;
+       sc->sii_copyfrombuf = sii_fwio_copyfrombuf;
+
+       /*
+        * Register interrupt handler.
+        */
+
+       if (mbus_intr_establish(vec, IPL_BIO, sii_fwio_intr, sfc,
+           self->dv_xname) != 0) {
+               vax_unmap_physmem(faa->faa_base + FWIO_SII_REG_OFFSET, 1);
+               uvm_km_free(kernel_map, (vaddr_t)sfc->sc_buf,
+                   FWIO_SII_BUF_SIZE);
+               printf(": can't establish interrupt\n");
+               return;
+       }
+
+       /*
+        * Complete attachment.
+        */
+       sc->sc_hostid = 7;      /* hardcoded */
+       sii_attach(sc);
+}
+
+int
+sii_fwio_intr(void *v)
+{
+       struct sii_softc *sc = (struct sii_softc *)v;
+       int rc;
+       uint16_t csr;
+
+       /*
+        * FBIC expects edge interrupts, while the sii does level
+        * interrupts. To avoid missing interrupts while servicing,
+        * we disable further device interrupts while servicing.
+        */
+       csr = sc->sc_regs->csr;
+       sc->sc_regs->csr = csr & ~SII_IE;
+
+       rc = sii_intr(v);
+
+       sc->sc_regs->csr = csr;
+
+       return rc;
+}
+
+/*
+ * Copy data between the fixed SCSI buffers. The sii driver only ``knows''
+ * offsets inside the SCSI buffer.
+ */
+
+void
+sii_fwio_copyfrombuf(void *v, u_int offs, u_char *dst, int len)
+{
+       struct sii_fwio_softc *sc = (struct sii_fwio_softc *)v;
+       u_char *src = sc->sc_buf + offs;
+
+       memcpy(dst, src, len);
+}
+
+void
+sii_fwio_copytobuf(void *v, u_char *src, u_int offs, int len)
+{
+       struct sii_fwio_softc *sc = (struct sii_fwio_softc *)v;
+       u_char *dst = sc->sc_buf + offs;
+
+       memcpy(dst, src, len);
+}
diff --git a/sys/arch/vax/mbus/uba_mbus.c b/sys/arch/vax/mbus/uba_mbus.c
new file mode 100644 (file)
index 0000000..ed78ffd
--- /dev/null
@@ -0,0 +1,174 @@
+/*     $OpenBSD: uba_mbus.c,v 1.1 2008/08/18 23:19:25 miod Exp $       */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (c) 1996 Jonathan Stone.
+ * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1982, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)uba.c       7.10 (Berkeley) 12/16/90
+ *     @(#)autoconf.c  7.20 (Berkeley) 5/9/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/mtpr.h>
+#include <machine/sgmap.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+
+#include <arch/vax/qbus/ubavar.h>
+#include <arch/vax/uba/uba_common.h>
+#include <arch/vax/uba/ubareg.h>
+
+#define        QBASIZE (8192 * VAX_NBPG)
+
+void   uba_mbus_attach(struct device *, struct device *, void *);
+int    uba_mbus_match(struct device *, void *, void *);
+
+const struct cfattach uba_mbus_ca = {
+       sizeof(struct uba_vsoftc), uba_mbus_match, uba_mbus_attach
+};
+
+void   uba_mbus_beforescan(struct uba_softc*);
+void   uba_mbus_init(struct uba_softc*);
+
+extern struct vax_bus_space vax_mem_bus_space;
+
+int
+uba_mbus_match(struct device *parent, void *vcf, void *aux)
+{
+       struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+
+       /*
+        * There can only be one QBus adapter (because it uses range-mapped
+        * MBus I/O), and it has to be in slot zero for connectivity reasons.
+        */
+       if (maa->maa_mid != 0)
+               return 0;
+
+       if (maa->maa_class == CLASS_BA && maa->maa_interface == INTERFACE_FBIC)
+               return 1;
+
+       return 0;
+}
+
+void
+uba_mbus_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct mbus_attach_args *maa = (struct mbus_attach_args *)aux;
+       struct uba_vsoftc *sc = (void *)self;
+       paddr_t modaddr;
+       vaddr_t fbic;
+
+       printf(": Q22\n");
+
+       /*
+        * Configure M-Bus I/O range.
+        *
+        * This will map the sgmap at 2008xxxx (QBAMAP), and the doorbell
+        * registers at 2000xxxx (QIOPAGE).
+        */
+       modaddr = MBUS_SLOT_BASE(maa->maa_mid);
+       fbic = vax_map_physmem(modaddr + FBIC_BASE, 1);
+       if (fbic == NULL) {
+               printf("%s: can't setup M-bus range register\n");
+               return;
+       }
+       *(uint32_t *)(fbic + FBIC_RANGE) =
+           (HOST_TO_MBUS(QBAMAP & RANGE_MATCH)) | RANGE_ENABLE |
+           ((QBAMAP ^ QIOPAGE) >> 16);
+       vax_unmap_physmem(fbic, 1);
+
+       /*
+        * There is nothing special to do to enable interrupt routing;
+        * the CQBIC will route Q-bus interrupts to the C-bus, and
+        * mbus(4) has already configured our FBIC interrupt registers
+        * to route C-bus interrupts to the M-bus (whether they are
+        * generated by the FBIC or by the Q-bus), which will make them
+        * visible to the processor.
+        *
+        * Note that we do not enable the boards' FBIC memory error
+        * interrupt yet.
+        */
+
+       /*
+        * Fill in bus specific data.
+        */
+       sc->uv_sc.uh_beforescan = uba_mbus_beforescan;
+       sc->uv_sc.uh_ubainit = uba_mbus_init;
+       sc->uv_sc.uh_iot = &vax_mem_bus_space;
+       sc->uv_sc.uh_dmat = &sc->uv_dmat;
+
+       /*
+        * Fill in variables used by the sgmap system.
+        */
+       sc->uv_size = QBASIZE;  /* Size in bytes of Qbus space */
+       sc->uv_addr = QBAMAP;   /* Physical address of map registers */
+
+       uba_dma_init(sc);
+       uba_attach(&sc->uv_sc, QIOPAGE);
+}
+
+/*
+ * Called when the CQBIC is set up; to enable DMA access from
+ * Q-bus devices to main memory.
+ */
+void
+uba_mbus_beforescan(sc)
+       struct uba_softc *sc;
+{
+       bus_space_write_2(sc->uh_tag, sc->uh_ioh, QIPCR, Q_LMEAE);
+}
+
+void
+uba_mbus_init(sc)
+       struct uba_softc *sc;
+{
+       DELAY(500000);
+       uba_mbus_beforescan(sc);
+}
index f225c6e..4870197 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ubareg.h,v 1.12 2008/08/18 23:10:39 miod Exp $ */
+/*     $OpenBSD: ubareg.h,v 1.13 2008/08/18 23:19:27 miod Exp $ */
 /*     $NetBSD: ubareg.h,v 1.11 2000/01/24 02:40:36 matt Exp $ */
 
 /*-
@@ -63,7 +63,7 @@
 #define DW730  3               /* has adaptor regs, no sr: 750, 730 */
 #endif
 
-#if VAX630 || VAX650 || VAX660 || VAX670
+#if VAX630 || VAX650 || VAX660 || VAX670 || VAX60
 #define QBA    4               /* 22-bit Q-bus, no adaptor regs: uVAX II */
 #endif
 
@@ -190,7 +190,7 @@ struct uba_regs {
  * Symbolic BUS addresses for UBAs.
  */
 
-#if VAX630 || VAX650
+#if VAX630 || VAX650 || VAX60
 #define QBAMAP 0x20088000
 #define QMEM   0x30000000
 #define QIOPAGE        0x20000000
index ca7153c..82d551c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: autoconf.c,v 1.30 2008/07/21 04:35:54 todd Exp $      */
+/*     $OpenBSD: autoconf.c,v 1.31 2008/08/18 23:19:29 miod Exp $      */
 /*     $NetBSD: autoconf.c,v 1.45 1999/10/23 14:56:05 ragge Exp $      */
 
 /*
 #include <machine/ioa.h>
 #include <machine/ka820.h>
 #include <machine/ka750.h>
-#include <machine/ka650.h>
 #include <machine/clock.h>
 #include <machine/rpb.h>
+#ifdef VAX60
+#include <vax/mbus/mbusreg.h>
+#endif
 
 #include <dev/cons.h>
 
 #include <vax/bi/bireg.h>
 
 void   dumpconf(void); /* machdep.c */
-void   gencnslask(void);
 
 struct cpu_dep *dep_call;
 
 int    mastercpu;      /* chief of the system */
 
 struct device *bootdv;
-int booted_partition;  /* defaults to 0 (aka 'a' partition */
+int booted_partition;  /* defaults to 0 (aka 'a' partition) */
 
 void
 cpu_configure()
@@ -340,27 +341,29 @@ booted_sd(struct device *dev, void *aux)
 
        /* Is this a SCSI device? */
        if (jmfr("sd", dev, BDEV_SD) && jmfr("cd", dev, BDEV_SD) &&
-           jmfr("sd", dev, BDEV_SDN) && jmfr("cd", dev, BDEV_SDN))
+           jmfr("sd", dev, BDEV_SDN) && jmfr("cd", dev, BDEV_SDN) &&
+           jmfr("sd", dev, BDEV_SDS) && jmfr("cd", dev, BDEV_SDS))
                return 0;
 
-#ifdef __NetBSD__
-       if (sa->sa_periph->periph_channel->chan_bustype->bustype_type !=
-           SCSIPI_BUSTYPE_SCSI)
-               return 0; /* ``Cannot happen'' */
-#endif
-
        if (sa->sa_sc_link->target != rpb.unit)
                return 0; /* Wrong unit */
 
        ppdev = dev->dv_parent->dv_parent;
 
        /* VS3100 NCR 53C80 (si) & VS4000 NCR 53C94 (asc) */
-       if (((jmfr("ncr",  ppdev, BDEV_SD) == 0) ||     /* old name */
+       if (((jmfr("ncr", ppdev, BDEV_SD) == 0) ||      /* old name */
            (jmfr("asc", ppdev, BDEV_SD) == 0) ||
            (jmfr("asc", ppdev, BDEV_SDN) == 0)) &&
            (ppdev->dv_cfdata->cf_loc[0] == rpb.csrphy))
                        return 1;
 
+#ifdef VAX60
+       /* VS35x0 (sii) */
+       if (jmfr("sii", ppdev, BDEV_SDS) == 0 && rpb.csrphy ==
+           MBUS_SLOT_BASE(ppdev->dv_parent->dv_cfdata->cf_loc[0]))
+               return 1;
+#endif
+
        return 0; /* Where did we come from??? */
 }
 #endif
index 1990ebe..085e580 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: clock.c,v 1.20 2008/08/15 22:41:48 miod Exp $  */
+/*     $OpenBSD: clock.c,v 1.21 2008/08/18 23:19:29 miod Exp $  */
 /*     $NetBSD: clock.c,v 1.35 2000/06/04 06:16:58 matt Exp $   */
 /*
  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
@@ -44,9 +44,6 @@
 #include <machine/cpu.h>
 #include <machine/uvax.h>
 
-int    yeartonum(int);
-int    numtoyear(int);
-
 struct evcount clock_intrcnt;
 
 /*
index 69f4a90..c142eeb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.54 2008/05/14 20:49:48 miod Exp $ */
+/*     $OpenBSD: conf.c,v 1.55 2008/08/18 23:19:29 miod Exp $ */
 /*     $NetBSD: conf.c,v 1.44 1999/10/27 16:38:54 ragge Exp $  */
 
 /*-
@@ -163,7 +163,7 @@ struct      consdev constab[]={
 #else
 #define NGEN   0
 #endif
-#if VAX410 || VAX43 || VAX46 || VAX48 || VAX49 || VAX53
+#if VAX410 || VAX43 || VAX46 || VAX48 || VAX49 || VAX53 || VAX60
 #if NDZ > 0
        cons_init(dz),  /* DZ11-like serial console on VAXstations */
 #endif
index bc6a4b6..8b6a76f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: findcpu.c,v 1.12 2006/08/27 16:55:41 miod Exp $       */
+/*     $OpenBSD: findcpu.c,v 1.13 2008/08/18 23:19:29 miod Exp $       */
 /*     $NetBSD: findcpu.c,v 1.5 1999/08/23 19:10:43 ragge Exp $        */
 /*
  * Copyright (c) 1994, 1998 Ludd, University of Lule}, Sweden.
@@ -51,7 +51,7 @@ int vax_boardtype;    /* machine dependend, combination of SID and SIE */
  
 int vax_cpudata = 0;   /* contents of the SID register */
 int vax_siedata = 0;   /* contents of the SIE register */
-int vax_confdata;      /* machine dependend, configuration/setup data */
+int vax_confdata;      /* machine dependent, configuration/setup data */
 
 void   findcpu(void);
 
@@ -112,6 +112,9 @@ findcpu(void)
                        break;
 
                case VAX_BTYP_60:
+                       vax_bustype = VAX_MBUS;
+                       break;
+
                case VAX_BTYP_630:
                case VAX_BTYP_650:
                case VAX_BTYP_660:
diff --git a/sys/arch/vax/vax/ka60.c b/sys/arch/vax/vax/ka60.c
new file mode 100644 (file)
index 0000000..a8db3f1
--- /dev/null
@@ -0,0 +1,358 @@
+/*     $OpenBSD: ka60.c,v 1.1 2008/08/18 23:19:29 miod Exp $   */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mt. Xinu.
+ *
+ * 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.
+ *
+ *     @(#)ka650.c     7.7 (Berkeley) 12/16/90
+ */
+
+/*
+ * VAXstation 3500 (KA60) specific code. Based on the KA650 specific code.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <uvm/uvm_extern.h>
+
+#include <machine/cvax.h>
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <machine/mtpr.h>
+#include <machine/nexus.h>
+#include <machine/psl.h>
+#include <machine/sid.h>
+#include <machine/rpb.h>
+#include <machine/cca.h>
+#include <machine/scb.h>
+
+#include <vax/mbus/mbusreg.h>
+#include <vax/mbus/mbusvar.h>
+#include <vax/mbus/fwioreg.h>
+
+int    ka60_clkread(time_t);
+void   ka60_clkwrite(void);
+void   ka60_clrf(void);
+void   ka60_conf(void);
+void   ka60_halt(void);
+void   ka60_hardclock(struct clockframe *);
+void   ka60_init(void);
+int    ka60_mchk(caddr_t);
+void   ka60_memerr(void);
+void   ka60_reboot(int);
+
+struct cpu_dep ka60_calls = {
+       ka60_init,
+       ka60_mchk,
+       ka60_memerr,
+       ka60_conf,
+       ka60_clkread,
+       ka60_clkwrite,
+       3,      /* ~VUPS */
+       2,      /* SCB pages */
+#if 0  /* this ought to work, dammit! */
+       cvax_halt,
+       cvax_reboot,
+#else
+       ka60_halt,
+       ka60_reboot,
+#endif
+       ka60_clrf,
+       NULL,
+       ka60_hardclock
+};
+
+void   ka60_memwrtmo(void *);
+
+struct cca *cca;
+unsigned int cca_size;
+
+unsigned int ka60cpus = 1;
+uint32_t *ka60_iocsr;
+
+/*
+ * Early system initialization, while still running physical.
+ *
+ * The PROM will have enabled the L2 cache, but each individual
+ * CPU still has its own L1 cache disabled.
+ *
+ * L1 cache configuration is similar to KA650, without external
+ * configuration registers.
+ */
+void
+ka60_init()
+{
+       unsigned int mid;
+       paddr_t fbicaddr;
+       uint32_t modtype, fbicrange;
+       int i;
+
+       /*
+        * Enable CPU cache.
+        */
+       mtpr(CADR_SEN2 | CADR_SEN1 | CADR_CENI | CADR_CEND, PR_CADR);
+
+       cca = (struct cca *)rpb.cca_addr;       /* physical!!! */
+       if (cca == NULL) {
+               /*
+                * If things are *that* wrong, stick to 2 cpus and a
+                * monoprocessor kernel, really.  We could try looking
+                * for a CCA signature from the top of memory downwards,
+                * or count CPU boards to get the correct number of
+                * processors, but is it really worth doing? I don't
+                * think we are in Kansas anymore anyway...
+                */
+               ka60cpus = 2;
+       } else {
+               cca_size = vax_atop(cca->cca_size);
+
+               /*
+                * Count the other processors.
+                */
+               for (i = 0; i < cca->cca_nproc; i++)
+                       if (cca->cca_console & (1 << i))
+                               ka60cpus++;
+       }
+
+       snprintf(cpu_model, sizeof cpu_model, "VAXstation 35%d0", ka60cpus);
+
+       /*
+        * Silence memory write timeout errors now.
+        */
+       scb_vecalloc(0x60, ka60_memwrtmo, NULL, 0, NULL);
+
+       /*
+        * We need to find out which M-bus slot contains the I/O
+        * module.  This could not have been done before because
+        * we were not able to handle machine check (and thus run
+        * badaddr() on each slot), and this has to be done before
+        * consinit() may try to talk to the serial ports.
+        *
+        * Note that there might be multiple I/O modules in the system.
+        * We do not know which I/O module the PROM will prefer; however
+        * since only one module should be configured to map the SSC at
+        * its preferred address, it is possible to find out which one
+        * has been selected.
+        */
+
+       for (mid = 0; mid < MBUS_SLOT_MAX; mid++) {
+               fbicaddr = MBUS_SLOT_BASE(mid) + FBIC_BASE;
+               if (badaddr((caddr_t)(fbicaddr + FBIC_MODTYPE), 4) != 0)
+                       continue;
+               modtype = *(uint32_t *)(fbicaddr + FBIC_MODTYPE);
+               if ((modtype & MODTYPE_CLASS_MASK) >> MODTYPE_CLASS_SHIFT !=
+                   CLASS_IO)
+                       continue;
+
+               mbus_ioslot = mid;
+
+               fbicrange = *(uint32_t *)(fbicaddr + FBIC_RANGE);
+               if (fbicrange ==
+                   ((HOST_TO_MBUS(CVAX_SSC) & RANGE_MATCH) | RANGE_ENABLE))
+                       break;
+       }
+
+       if ((int)mbus_ioslot < 0) {
+               /*
+                * This shouldn't happen. Try mid #5 (enclosure slot #4) as a
+                * supposedly sane default.
+                */
+               mbus_ioslot = 5;
+       }
+}
+
+/*
+ * Early system initialization, while running virtual, and before
+ * devices are probed.
+ */
+void
+ka60_conf()
+{
+       printf("cpu0: KA60\n");
+
+       cvax_ssc_ptr = (void *)vax_map_physmem(CVAX_SSC, 3);
+
+       /*
+        * Remap the CCA now we're running virtual.
+        */
+       if (cca != NULL)
+               cca = (void *)vax_map_physmem((paddr_t)cca, cca_size);
+
+       /*
+        * Map the IOCSR register of the main I/O module, and enable
+        * CPU clock.  We'll need this mapping for reset as well.
+        */
+       ka60_iocsr = (uint32_t *)vax_map_physmem(MBUS_SLOT_BASE(mbus_ioslot) +
+           FWIO_IOCSR_OFFSET, 1);
+       if (ka60_iocsr == 0)
+               panic("can not map IOCSR");
+
+       *ka60_iocsr |= FWIO_IOCSR_CLKIEN | FWIO_IOCSR_MRUN | FWIO_IOCSR_CNSL;
+}
+
+/*
+ * Corrected memory error trap.
+ */
+void
+ka60_memerr()
+{
+       printf("cpu0: corrected memory error\n");
+       /*
+        * Need to peek at the M-bus error logs, display anything
+        * interesting, and clear them.
+        */
+}
+
+/*
+ * Machine check trap.
+ */
+int
+ka60_mchk(caddr_t mcef)
+{
+       struct cvax_mchk_frame *mcf = (struct cvax_mchk_frame *)mcef;
+       u_int type = mcf->cvax_summary;
+       const char *descr;
+
+       printf("machine check %x", type);
+       descr = cvax_mchk_descr(type);
+       if (descr != NULL)
+               printf(": %s", descr);
+       printf("\n\tvap %x istate1 %x istate2 %x pc %x psl %x\n",
+           mcf->cvax_mrvaddr, mcf->cvax_istate1, mcf->cvax_istate2,
+           mcf->cvax_pc, mcf->cvax_psl);
+
+       return MCHK_PANIC;
+}
+
+/*
+ * Clock routines.  They need to access the TODR through the SSC.
+ */
+int
+ka60_clkread(time_t base)
+{
+       unsigned klocka = cvax_ssc_ptr->ssc_todr;
+
+       /*
+        * Sanity check.
+        */
+       if (klocka < TODRBASE) {
+               if (klocka == 0) {
+                       printf("TODR stopped");
+                       cvax_ssc_ptr->ssc_todr = 1;     /* spin it */
+               } else
+                       printf("TODR too small");
+               return CLKREAD_BAD;
+       }
+
+       time.tv_sec = yeartonum(numtoyear(base)) + (klocka - TODRBASE) / 100;
+       return CLKREAD_OK;
+}
+
+void
+ka60_clkwrite()
+{
+       unsigned tid = time.tv_sec, bastid;
+
+       bastid = tid - yeartonum(numtoyear(tid));
+       cvax_ssc_ptr->ssc_todr = (bastid * 100) + TODRBASE;
+}
+
+void
+ka60_halt()
+{
+       printf("system halted.\n");
+       asm("halt");
+}
+
+void
+ka60_reboot(arg)
+       int arg;
+{
+       printf("resetting system...\n");
+       delay(500000);
+       *ka60_iocsr |= FWIO_IOCSR_RSTWS;
+}
+
+/*
+ * Probing empty M-bus slots causes this vector to be triggered.
+ *
+ * We get one after the first spl0(), if probing for the console
+ * slot caused us to look at empty slots, and then one per empty
+ * slot during autoconf.
+ *
+ * There shouldn't be any such error after autoconf, though.
+ */
+void
+ka60_memwrtmo(void *arg)
+{
+       /* do nothing */
+}
+
+void
+ka60_clrf(void)
+{
+       /*
+        * Restore the memory write timeout vector.
+        */
+       scb_vecalloc(0x60, scb_stray, (void *)0x60, SCB_ISTACK, NULL);
+}
+
+/*
+ * SSC clock interrupts come at level 0x16, which is not enough for
+ * our needs, so raise the level here before invoking hardclock().
+ */
+void
+ka60_hardclock(struct clockframe *cf)
+{
+       int s;
+
+       s = splclock();
+       hardclock(cf);
+       splx(s);
+}
index 7181a51..d9e4575 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: locore.c,v 1.33 2008/03/30 18:25:13 miod Exp $        */
+/*     $OpenBSD: locore.c,v 1.34 2008/08/18 23:19:29 miod Exp $        */
 /*     $NetBSD: locore.c,v 1.43 2000/03/26 11:39:45 ragge Exp $        */
 /*
  * Copyright (c) 1994, 1998 Ludd, University of Lule}, Sweden.
 #include <machine/pmap.h>
 #include <machine/nexus.h>
 #include <machine/rpb.h>
+#include <machine/cca.h>
 
 void   start(struct rpb *);
 void   main(void);
 
 extern paddr_t avail_end;
+extern int physmem;
 paddr_t        esym;
 u_int  proc0paddr;
 char   cpu_model[100];
@@ -78,6 +80,7 @@ extern struct cpu_dep ka650_calls;
 extern struct cpu_dep ka660_calls;
 extern struct cpu_dep ka670_calls;
 extern struct cpu_dep ka680_calls;
+extern struct cpu_dep ka60_calls;
 extern struct cpu_dep vxt_calls;
 
 /*
@@ -90,6 +93,7 @@ void
 start(struct rpb *prpb)
 {
        extern vaddr_t scratch;
+       int preserve_cca = 0;
 
        mtpr(AST_NO, PR_ASTLVL); /* Turn off ASTs */
 
@@ -300,6 +304,13 @@ start(struct rpb *prpb)
                dep_call = &ka820_calls;
                strlcpy(cpu_model, "VAX 8200", sizeof cpu_model);
                break;
+#endif
+#ifdef VAX60
+       case VAX_BTYP_60:
+               dep_call = &ka60_calls;
+               preserve_cca = 1;
+               /* cpu_model will be set in ka60_init */
+               break;
 #endif
        default:
                /* CPU not supported, just give up */
@@ -331,6 +342,33 @@ start(struct rpb *prpb)
                        avail_end += VAX_NBPG * 128;
        boothowto = prpb->rpb_bootr5;
 
+       physmem = atop(avail_end);
+
+       /*
+        * If we need to use the Console Communication Area, make sure
+        * we will not stomp over it.
+        *
+        * On KA60 systems, the PROM apparently forgets to keep the CCA
+        * out of the reported memory size.  It's no real surprise, as
+        * the memory bitmap pointed to by the CCA reports all physical
+        * memory (including itself and the CCA) as available!
+        * (which means the bitmap is not worth looking at either)
+        */
+
+       if (preserve_cca) {
+               if (prpb->cca_addr != 0 && avail_end > prpb->cca_addr) {
+                       struct cca *cca = (struct cca *)prpb->cca_addr;
+
+                       /*
+                        * XXX Should validate the CCA image here.
+                        */
+
+                       avail_end = prpb->cca_addr;
+                       if (cca->cca_bitmap != 0 && avail_end > cca->cca_bitmap)
+                               avail_end = cca->cca_bitmap;
+               }
+       }
+
         avail_end = TRUNC_PAGE(avail_end); /* be sure */
 
        proc0.p_addr = (struct user *)proc0paddr; /* XXX */
index 847792a..1eaa5fb 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.98 2008/08/18 23:08:57 miod Exp $ */
+/* $OpenBSD: machdep.c,v 1.99 2008/08/18 23:19:29 miod Exp $ */
 /* $NetBSD: machdep.c,v 1.108 2000/09/13 15:00:23 thorpej Exp $         */
 
 /*
@@ -174,7 +174,6 @@ cpu_startup()
        caddr_t         v;
        int             sz;
        vaddr_t         minaddr, maxaddr;
-       extern unsigned int avail_end;
        extern char     cpu_model[];
 
        /*
@@ -190,9 +189,8 @@ cpu_startup()
         if (dep_call->cpu_conf)
                 (*dep_call->cpu_conf)();
 
-       printf("real mem = %u (%uMB)\n", avail_end,
-           avail_end/1024/1024);
-       physmem = atop(avail_end);
+       printf("real mem = %u (%uMB)\n", ptoa(physmem),
+           ptoa(physmem)/1024/1024);
        mtpr(AST_NO, PR_ASTLVL);
        spl0();
 
@@ -228,7 +226,7 @@ cpu_startup()
        exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
                                 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
 
-#if VAX46 || VAX48 || VAX49 || VAX53
+#if VAX46 || VAX48 || VAX49 || VAX53 || VAX60
        /*
         * Allocate a submap for physio.  This map effectively limits the
         * number of processes doing physio at any one time.
@@ -237,7 +235,8 @@ cpu_startup()
         * can perform address translation, do not need this.
         */
        if (vax_boardtype == VAX_BTYP_46 || vax_boardtype == VAX_BTYP_48 ||
-           vax_boardtype == VAX_BTYP_49 || vax_boardtype == VAX_BTYP_1303)
+           vax_boardtype == VAX_BTYP_49 || vax_boardtype == VAX_BTYP_1303 ||
+           vax_boardtype == VAX_BTYP_60)
                phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
                    VM_PHYS_SIZE, 0, FALSE, NULL);
 #endif
@@ -283,10 +282,7 @@ dumpconf(void)
        if (nblks <= ctod(1))
                return;
 
-       /*
-        * XXX include the final RAM page which is not included in physmem.
-        */
-       dumpsize = physmem + 1;
+       dumpsize = physmem;
        if (dumpsize > atop(dbtob(nblks - dumplo)))
                dumpsize = atop(dbtob(nblks - dumplo));
        else if (dumplo == 0)
index 24b71bf..79dff3b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pmap.c,v 1.46 2008/08/15 22:38:23 miod Exp $ */
+/*     $OpenBSD: pmap.c,v 1.47 2008/08/18 23:19:29 miod Exp $ */
 /*     $NetBSD: pmap.c,v 1.74 1999/11/13 21:32:25 matt Exp $      */
 /*
  * Copyright (c) 1994, 1998, 1999 Ludd, University of Lule}, Sweden.
@@ -185,7 +185,7 @@ pmap_bootstrap()
        avail_start = scratch + 4 * VAX_NBPG - KERNBASE;
 
        /* Kernel message buffer */
-       avail_end -= MSGBUFSIZE;
+       avail_end -= round_page(MSGBUFSIZE);
        msgbufp = (void *)(avail_end + KERNBASE);
        msgbufp->msg_magic = MSG_MAGIC-1;       /* ensure that it will be zeroed */
 
@@ -257,9 +257,8 @@ pmap_bootstrap()
        /*
         * Now everything should be complete, start virtual memory.
         */
-       uvm_page_physload(avail_start >> PGSHIFT, avail_end >> PGSHIFT,
-           avail_start >> PGSHIFT, avail_end >> PGSHIFT,
-           VM_FREELIST_DEFAULT);
+       uvm_page_physload(atop(avail_start), atop(avail_end),
+           atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
        mtpr(sysptsize, PR_SLR);
        rpb.sbr = mfpr(PR_SBR);
        rpb.slr = mfpr(PR_SLR);
@@ -299,7 +298,7 @@ pmap_steal_memory(size, vstartp, vendp)
 #endif
 
        /*
-        * A vax only have one segment of memory.
+        * A vax only has one segment of memory.
         */
 
        v = (vm_physmem[0].avail_start << PGSHIFT) | KERNBASE;
index c826048..1150b9f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: scb.c,v 1.5 2004/07/07 23:10:46 deraadt Exp $ */
+/*     $OpenBSD: scb.c,v 1.6 2008/08/18 23:19:29 miod Exp $    */
 /*     $NetBSD: scb.c,v 1.12 2000/06/04 06:16:59 matt Exp $ */
 /*
  * Copyright (c) 1999 Ludd, University of Lule}, Sweden.
@@ -49,7 +49,6 @@
 struct scb *scb;
 struct ivec_dsp *scb_vec;
 
-static void scb_stray(void *);
 static volatile int vector, ipl, gotintr;
 
 /*
@@ -70,7 +69,7 @@ scb_init(paddr_t avail_start)
        /* Init the whole SCB with interrupt catchers */
        for (i = 0; i < (scb_size * VAX_NBPG)/4; i++) {
                ivec[i] = &scb_vec[i];
-               (int)ivec[i] |= 1; /* On istack, please */
+               (int)ivec[i] |= SCB_ISTACK; /* On istack, please */
                scb_vec[i] = idsptch;
                scb_vec[i].hoppaddr = scb_stray;
                scb_vec[i].pushlarg = (void *) (i * 4);
@@ -85,6 +84,7 @@ scb_init(paddr_t avail_start)
        for (i = 0; i < 64; i++)
                if (old[i])
                        ivec[i] = old[i];
+
        /* Last action: set the SCB */
        mtpr(avail_start, PR_SCBB);
 
index 2a2daf1..03a6d9e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vm_machdep.c,v 1.37 2008/02/16 22:59:34 miod Exp $    */
+/*     $OpenBSD: vm_machdep.c,v 1.38 2008/08/18 23:19:29 miod Exp $    */
 /*     $NetBSD: vm_machdep.c,v 1.67 2000/06/29 07:14:34 mrg Exp $           */
 
 /*
@@ -266,7 +266,7 @@ vmapbuf(bp, len)
        struct buf *bp;
        vsize_t len;
 {
-#if VAX46 || VAX48 || VAX49 || VAX53
+#if VAX46 || VAX48 || VAX49 || VAX53 || VAX60
        vaddr_t faddr, taddr, off;
        paddr_t pa;
        struct proc *p;
@@ -303,7 +303,7 @@ vunmapbuf(bp, len)
        struct buf *bp;
        vsize_t len;
 {
-#if VAX46 || VAX48 || VAX49 || VAX53
+#if VAX46 || VAX48 || VAX49 || VAX53 || VAX60
        vaddr_t addr, off;
 
        if (phys_map == NULL)