From 591f4054cb05388278bcfd1e86679a19494a6ae7 Mon Sep 17 00:00:00 2001
From: Hartmut Brandt <harti@FreeBSD.org>
Date: Thu, 12 Jun 2003 14:28:32 +0000
Subject: [PATCH] This is a driver for the physical layer chips used in ATM
 interfaces. It currently supports the PMC Sierra Lite, Ultra and 622 chips
 and the IDT 77105. The driver handles media options and state in a consistent
 manner for ATM drivers. The next commit to the midway driver will make it use
 utopia.

---
 etc/mtree/BSD.include.dist  |    2 +
 include/Makefile            |    2 +-
 share/man/man4/Makefile     |    1 +
 share/man/man4/utopia.4     |  131 +++
 share/man/man7/hier.7       |    4 +
 share/man/man9/Makefile     |    2 +-
 share/man/man9/utopia.9     |  305 +++++++
 sys/dev/utopia/idtphy.h     |  119 +++
 sys/dev/utopia/suni.h       | 1515 +++++++++++++++++++++++++++++++++++
 sys/dev/utopia/utopia.c     | 1082 +++++++++++++++++++++++++
 sys/dev/utopia/utopia.h     |  175 ++++
 sys/modules/Makefile        |    1 +
 sys/modules/utopia/Makefile |    8 +
 13 files changed, 3345 insertions(+), 2 deletions(-)
 create mode 100644 share/man/man4/utopia.4
 create mode 100644 share/man/man9/utopia.9
 create mode 100644 sys/dev/utopia/idtphy.h
 create mode 100644 sys/dev/utopia/suni.h
 create mode 100644 sys/dev/utopia/utopia.c
 create mode 100644 sys/dev/utopia/utopia.h
 create mode 100644 sys/modules/utopia/Makefile

diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index 91181f01612b..9df12298e4d5 100644
--- a/etc/mtree/BSD.include.dist
+++ b/etc/mtree/BSD.include.dist
@@ -30,6 +30,8 @@
         ..
         usb
         ..
+        utopia
+        ..
         wi
         ..
     ..
diff --git a/include/Makefile b/include/Makefile
index 8a4b261eb458..a9320029a061 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -32,7 +32,7 @@ LDIRS=	cam geom net netatalk netatm netgraph netinet netinet6 netipsec \
 	pccard posix4 sys vm
 
 LSUBDIRS=	cam/scsi dev/an dev/ic dev/iicbus dev/firewire dev/ofw \
-	dev/ppbus dev/smbus dev/usb dev/wi fs/devfs \
+	dev/ppbus dev/smbus dev/usb dev/wi dev/utopia fs/devfs \
 	fs/fdescfs fs/fifofs fs/msdosfs fs/ntfs fs/nullfs fs/nwfs fs/portalfs \
 	fs/procfs fs/smbfs fs/umapfs fs/unionfs isofs/cd9660 \
 	netatm/ipatm netatm/sigpvc netatm/spans netatm/uni \
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 8171ba2b2512..a7b0d574d686 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -256,6 +256,7 @@ MAN=	aac.4 \
 	urio.4 \
 	usb.4 \
 	uscanner.4 \
+	utopia.4 \
 	uvisor.4 \
 	uvscom.4 \
 	vga.4 \
diff --git a/share/man/man4/utopia.4 b/share/man/man4/utopia.4
new file mode 100644
index 000000000000..ff93994092b8
--- /dev/null
+++ b/share/man/man4/utopia.4
@@ -0,0 +1,131 @@
+.\" Copyright (c) 2003
+.\"	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+.\" 	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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" Author: Hartmut Brandt <harti@freebsd.org>
+.\"
+.\" $FreeBSD$
+.Dd May 8, 2003
+.Dt UTOPIA 4
+.Os FreeBSD
+.Sh NAME
+.Nm utopia
+.Nd Driver module for ATM PHY chips
+.Sh SYNOPSIS
+.Cd device utopia
+.Sh DESCRIPTION
+This module is used by all ATM drivers for cards that use S/Uni and IDT77105
+chips to provide uniform functionality.
+The module implements status monitoring
+in either interrupt or polling mode, media option handling and application
+access to chip registers.
+.Pp
+The driver implements several sysctls that accessible under the
+.Cm hw.atm.XXX
+tree, where
+.Cm XXX
+is the name of the ATM interface:
+.Bl -tag -width XXX
+.It Cm phy_regs
+When reading this sysctl an array of 8-bit unsigned integers is returned
+containing all accessible chip registers starting at register 0.
+A register can be written by writing three 8-bit unsigned integers to the
+sysctl: the register number, the new value and a bit mask.
+This changes all bits in the register for which the corresponding bit in the
+mask is one to the bit values from value.
+Note, that not all registers may
+be writeable.
+.It Cm phy_loopback
+allows to put the interface in one of several loopback modes.
+Not all modes and all combinations of modes are supported on all chips.
+The possible modes are:
+.Bl -tag -width XXX
+.It Dv UTP_LOOP_NONE (0x00)
+No loopback, normal operation.
+.It Dv UTP_LOOP_TIME (0x01)
+Timing source loopback. When this is set the transmitter's clock is
+derived from the receiver's clock.
+.It Dv UTP_LOOP_DIAG (0x02)
+Diagnostic loopback. In this mode the receiver's input is connected to the
+transmitter's output. The receiver gets back everything that is sent. The
+transmitter operates normally.
+.It Dv UTP_LOOP_LINE (0x04)
+Serial line loopback. This connects the line receiver to the line transmitter.
+The chip transmits all cells back that it receives. The receiver operates
+normally.
+.It Dv UTP_LOOP_PARAL (0x08)
+Parallel diagnostic loopback. This feeds back all transmitted cells into the
+receiver between the parallel/serial converters. The transmitter
+operates normally.
+.It Dv UTP_LOOP_TWIST (0x10)
+Twisted pair diagnostic loopback. Connects the high speed receive data to the
+high speed transmit data. All received data is sent back. The receiver
+operates normally.
+.It Dv UTP_LOOP_PATH (0x20)
+Diagnostic path loopback. This connectes the receiver input to the transmitter
+output just between the path overhead processor and the byte mux. The
+transmitter operates normally.
+.El
+.It Cm phy_type
+This is the detected type of the phy chip. Currently the following chips are
+supported:
+.Bl -tag -width XXX
+.It Dv UTP_TYPE_UNKNOWN (0)
+The module could not determine the type of the PHY chip.
+.It Dv UTP_TYPE_SUNI_LITE (1)
+PMC-5346 (S/Uni-Lite)
+.It Dv UTP_TYPE_SUNI_ULTRA (2)
+PMC-5350 (S/Uni-Ultra)
+.It Dv UTP_TYPE_SUNI_622 (3)
+PMC-5355 (S/Uni-622)
+.It Dv UTP_TYPE_IDT77105 (4)
+IDT77105 (25.6MBit UTP interface)
+.El
+.It Cm phy_name
+This is a string describing the type of the PHY chip.
+.El
+.Pp
+The
+.Nm
+module also interfaces with the ifmedia system.
+The module reports the current state of the carrier and will issue a
+warning message when the carrier state changes.
+While the physical media itself cannot be changed, several media options can:
+.Bl -tag -width XXX
+.It Cm SDH
+If the PHY is a S/Uni this flag switches the interface into SDH mode.
+If this option is not set (the default) the interface is in Sonet mode.
+.It Cm noscramb
+If the PHY is a S/Uni disable scrambling.
+This may be useful for debugging purposes.
+.It Cm unassigned
+Normally the interface emits idle cells when there are no other cells to
+transmit. This changes the default cell type to unassigned cells. This
+may be needed for interworking with public networks. Works only for S/Unis.
+.El
+.Sh SEE ALSO
+.Xr en 4,
+.Xr utopia 9
+.Sh AUTHOR
+.An Harti Brandt Aq harti@freebsd.org .
diff --git a/share/man/man7/hier.7 b/share/man/man7/hier.7
index de7c2f39cfb3..1c08fe89f8cd 100644
--- a/share/man/man7/hier.7
+++ b/share/man/man7/hier.7
@@ -189,6 +189,10 @@ see
 .Xr ppbus 4
 .It Pa usb/
 The USB subsystem
+.It Pa utopia/
+Physical chip driver for ATM interfaces;
+see
+.Xr utopia 4
 .It Pa wi/
 The
 .Xr wi 4
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index a5110177870c..85c2bc4bccfb 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -66,7 +66,7 @@ MAN=	BUF_LOCK.9 BUF_LOCKFREE.9 BUF_LOCKINIT.9 BUF_REFCNT.9 \
 	spl.9 store.9 style.9 suser.9 swi.9 sx.9 \
 	sysctl_add_oid.9 sysctl_ctx_init.9 \
 	taskqueue.9 thread_exit.9 time.9 timeout.9 tvtohz.9 \
-	ucred.9 uidinfo.9 uio.9 \
+	ucred.9 uidinfo.9 uio.9 utopia.9 \
 	vaccess.9 vaccess_acl_posix1e.9 vcount.9 \
 	vfs_busy.9 vfs_getnewfsid.9 vfs_getvfs.9 \
 	vfs_mount.9 vfs_mountedon.9 vfs_rootmountalloc.9 \
diff --git a/share/man/man9/utopia.9 b/share/man/man9/utopia.9
new file mode 100644
index 000000000000..8716bd6e4a53
--- /dev/null
+++ b/share/man/man9/utopia.9
@@ -0,0 +1,305 @@
+.\" Copyright (c) 2003
+.\"	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+.\" 	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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" Author: Hartmut Brandt <harti@freebsd.org>
+.\"
+.\" $FreeBSD$
+.Dd May 8, 2003
+.Dt UTOPIA 9
+.Os FreeBSD
+.Sh NAME
+.Nm utopia
+.Nd Driver module for ATM PHY chips
+.Sh SYNOPSIS
+.In dev/utopia/utopia.h
+.Ft int
+.Fn utopia_attach "struct utopia *utp" "struct ifatm *ifatm" "struct ifmedia *media" "struct mtx *lock" "struct sysctl_ctx_list *ctx" "struct sysctl_oid_list *tree" "const struct utopia_methods *vtab"
+.Ft void
+.Fn utopia_detach "struct utopia *utp"
+.Ft int
+.Fn utopia_start "struct utopia *utp"
+.Ft void
+.Fn utopia_stop "struct utopia *utp"
+.Ft void
+.Fn utopia_init_media "struct utopia *utp"
+.Ft void
+.Fn utopia_reset_media "struct utopia *utp"
+.Ft int
+.Fn utopia_reset "struct utopia *utp"
+.Ft int
+.Fn utopia_set_sdh "struct utopia *utp" "int sdh"
+.Ft int
+.Fn utopia_set_unass "struct utopia *utp" "int unass"
+.Ft int
+.Fn utopia_set_noscramb "struct utopia *utp" "int noscramb"
+.Ft int
+.Fn utopia_update_carrier "struct utopia *utp"
+.Ft int
+.Fn utopia_set_loopback "struct utopia *utp"  "u_int mode"
+.Ft void
+.Fn utopia_intr "struct utopia *utp"
+.Sh DESCRIPTION
+This module is used by all ATM drivers for cards that use a number of known
+PHY chips to provide uniform functionality.
+The module implements status monitoring in either interrupt or polling mode,
+media option handling and application access to PHY registers.
+.Pp
+To use this interface a driver must implement two functions for reading and
+writing PHY registers and initialize the following structure with pointers
+to these functions:
+.Bd -literal -offset indent
+struct utopia_methods {
+	int	(*readregs)(struct ifatm *, u_int reg,
+		    uint8_t *val, u_int *n);
+	int	(*writereg)(struct ifatm *, u_int reg,
+		    u_int mask, u_int val);
+};
+.Ed
+.Pp
+The
+.Fn readregs
+function should read PHY registers starting at register
+.Fa reg .
+The maximum number of registers to read is given by the integer pointed
+to by
+.Fa n .
+The function should either return 0 on success or an error code.
+In the first case
+.Fa *n
+should be set to the actual number of registers red.
+The
+.Fn writereg
+function should write one register.
+It must change all bits for which the corresponding bit in
+.Fa mask
+is 1 to the value of the corresponding bit in
+.Fa val .
+It returns either 0 on success or an error code.
+.Pp
+The ATM driver's private state block (softc) must begin with a
+.Vt "struct ifatm" .
+.Pp
+The
+.Vt "struct utopia"
+holds the current state of the PHY chip and contains the following fields:
+.Bd -literal -offset indent
+struct utopia {
+	struct ifatm	*ifatm;		/* driver data */
+	struct ifmedia	*media;		/* driver supplied */
+	struct mtx	*lock;		/* driver supplied */
+	const struct utopia_methods *methods;
+	LIST_ENTRY(utopia) link;	/* list of these structures */
+	u_int		flags;		/* flags set by the driver */
+	u_int		state;		/* current state */
+	u_int		carrier;	/* carrier state */
+	u_int		loopback;	/* loopback mode */
+	const struct utopia_chip *chip;	/* chip operations */
+};
+.Ed
+The public accessible fields have the following functions:
+.Bl -tag -width XXX
+.It Va ifatm
+Pointer to the driver's private data (softc).
+.It Va media
+Pointer to the driver's media structure.
+.Ir Va lock
+Pointer to a mutex provided by the driver. This mutex is used to synchronize
+with the kernel thread that handles device polling. It is locked in several
+places:
+.Bl -enum -offset indent
+.It
+In
+.Fn utopia_detach
+the mutex is locked to sleep and wait for the kernel thread to remove the
+.Vt "struct utopia"
+from the list of all utopia devices.
+Before returning to the caller the mutex is unlocked.
+.It
+In the
+.Nm
+kernel thread the mutex is locked and the
+.Fn utopia_carrier_update
+function is called with this mutex locked.
+This will result in the driver's
+.Fn readregs 
+function beeing called with the mutex locked.
+.It
+In the sysctl handlers the mutex will be locked before calling into the driver's
+.Fn readreg
+or
+.Fn writereg
+functions.
+.El
+.It Va flags
+Flags set by either the driver or the utopia module. The following flags are
+defined:
+.Bl -tag -width XXX
+.It Dv UTP_FL_NORESET
+If this flag is set the module will not try to write the
+SUNI master reset register. (set by the driver)
+.It Dv UTP_FL_POLL_CARRIER
+If this flag is set the module will periodically poll the carrier state
+(as opposed to interrupt driven carrier state changes). (set by the driver)
+.El
+.It Va state
+Flags describing the current state of the phy chip. These are managed
+by the module:
+.Bl -tag -width XXX
+.It Dv UTP_ST_ACTIVE
+The driver is active and the phy registers can be accessed.
+This is set by calling
+.Fn utopia_start ,
+which should be called either in the attach routine of the driver or
+in the network interface initialisation routine (depending on whether the
+registers are accessible all the time or only when the interface is up).
+.It Dv UTP_ST_SDH
+Interface is in SDH mode as opposed to SONET mode.
+.It Dv UTP_ST_UNASS
+Interface is producing unassigned cells instead of idle cells.
+.It Dv UTP_ST_NOSCRAMB
+Cell scrambling is switched off.
+.It Dv UTP_ST_DETACH
+(internal use) interface is currently detaching.
+.It Dv UTP_ST_ATTACHED
+The attach routine has been run successfully.
+.El
+.It Va carrier
+The carrier state of the interface. This field can have one of three values:
+.Bl -tag -width XXX
+.It Dv UTP_CARR_UNKNOWN
+Carrier state is still unknown.
+.It Dv UTP_CARR_OK
+Carrier has been detected.
+.It Dv UTP_CARR_LOST
+Carrier has been lost.
+.El
+.It Va loopback
+This is the current loopback mode of the interface. Note, that not all
+chips support all loopback modes. Refer to the chip documentation. The
+following modes may be supported:
+.Bl -tag -width XXX
+.It Dv UTP_LOOP_NONE
+No loopback, normal operation.
+.It Dv UTP_LOOP_TIME
+Timing source loopback. The transmitter clock is driven by the receive clock.
+.It Dv UTP_LOOP_DIAG
+Diagnostic loopback.
+.It Dv UTP_LOOP_LINE
+Serial line loopback.
+.It Dv UTP_LOOP_PARAL
+Parallel diagnostic loopback.
+.It Dv UTP_LOOP_TWIST
+Twisted pair diagnostic loopback.
+.It Dv UTP_LOOP_PATH
+Diagnostic path loopback.
+.El
+.It Va chip
+This points the a function vector for chip specific functions. Two fields
+in this vector a publically available:
+.Bl -tag -width XXX
+.It Va type
+This is the type of the detected PHY chip.
+One of:
+.Bl -tag -width XXX
+.It Dv UTP_TYPE_UNKNOWN (0)
+.It Dv UTP_TYPE_SUNI_LITE (1)
+.It Dv UTP_TYPE_SUNI_ULTRA (2)
+.It Dv UTP_TYPE_SUNI_622 (3)
+.It Dv UTP_TYPE_IDT77105 (4)
+.El
+.It Va name
+This is a string with the name of the PHY chip.
+.El
+.El
+.Pp
+The following functions are used by the driver during attach/detach and/or
+initialisation/stopping the interface:
+.Bl -tag -width XXX
+.It Fn utopia_attach
+Attach the PHY chip. This is called with a preallocated
+.Vt "struct utopia"
+(which may be part of the driver's softc).
+The module initializes all fields of the utopia state and the media field.
+User settable flags should be set after the call to
+.Fn utopia_attach .
+This function may fail due to the inability to install the sysctl handlers.
+In this case it will return -1.
+On success 0 is returned and the
+.Dv UTP_ST_ATTACHED
+flag is set.
+.It Fn utopia_detach
+Remove the utopia attachment from the system. This cancels all outstanding polling
+timeouts.
+.It Fn utopia_start
+Start operation of that PHY. This should be called at a time
+when the PHY registers are known to be accessible. This may be either in
+the driver's attach function or when the interface is set running.
+.It Fn utopia_stop
+Stop operation of the PHY attachment. This may be called either in the detach
+function of the driver or when the interface is brought down.
+.It Fn utopia_init_media
+This must be called if the media field in the ATM MIB was changed. The function
+makes sure, that the ifmedia fields contain the same information as the
+ATM MIB.
+.It Fn utopia_reset_media
+This may be called to remove all media information from the ifmedia field.
+.El
+.Pp
+The following functions can be used to modify the PHY state while the interface
+is running:
+.Bl -tag -width XXX
+.It Fn utopia_reset
+Reset the operational parameters to the default state (SONET, idle cells,
+scrambling enabled). Returns 0 on success, an error code otherwise leaving
+the state undefined.
+.It Fn utopia_set_sdh
+If the argument is zero the chip is switched to Sonet mode, if it is non-zero
+the chip is switched to SDH mode. Returns 0 on success, an error code otherwise
+leaving the previous state.
+.It Fn utopia_set_unass
+If the argument is zero the chip is switched to produce idle cells, if it is
+non-zero the chip is switched to produce unassigned cells. Returns 0 on success,
+an error code otherwise leaving the previous state.
+.It Fn utopia_set_noscramb
+If the argument is zero enables scrambling, if it is
+non-zero disables scrambling. Returns 0 on success,
+an error code otherwise leaving the previous state.
+.It Fn utopia_update_carrier
+Check the carrier state and update the carrier field in the state structure.
+This will generate a message to the netgraph stack if the carrier state changes.
+For chips that are polled this is called automatically, for interrupt
+driven attachments this must be called on interrupts from the PHY chip.
+.It Fn utopia_set_loopback
+Set the loopback mode of the chip. Returns 0 on success, an error code
+otherwise leaving the previous state.
+.It Fn utopia_intr
+Called when an interrupt from the PHY chip is detected. This resets the
+interrupt state by reading all registers and, if the interrupt was from the
+RSOP, checks the carrier state.
+.El
+.Sh SEE ALSO
+.Xr utopia 4
+.Sh AUTHOR
+.An Harti Brandt Aq harti@freebsd.org .
diff --git a/sys/dev/utopia/idtphy.h b/sys/dev/utopia/idtphy.h
new file mode 100644
index 000000000000..0d55e7e449f1
--- /dev/null
+++ b/sys/dev/utopia/idtphy.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2003
+ *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * 	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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $FreeBSD$
+ *
+ * Register definitions for the following chips:
+ *	IDT 77105
+ */
+#ifndef _DEV_UTOPIA_IDTPHY_H
+#define	_DEV_UTOPIA_IDTPHY_H
+
+#define	IDTPHY_REGO_MCR		0x00
+#define	IDTPHY_REGN_MCR		"Master Control Register"
+#define	IDTPHY_REGX_MCR		"\020\010UPLO\7DREC\6ECEI\5TDPC\4DRIC\3HALTTX\2BYTEM\1EI"
+#define	IDTPHY_REGM_MCR_UPL0	0x80
+#define	IDTPHY_REGM_MCR_DREC	0x40
+#define	IDTPHY_REGM_MCR_ECEI	0x20
+#define	IDTPHY_REGM_MCR_TDPC	0x10
+#define	IDTPHY_REGM_MCR_DRIC	0x08
+#define	IDTPHY_REGM_MCR_HALTTX	0x04
+#define	IDTPHY_REGM_MCR_BYTEM	0x02
+#define	IDTPHY_REGM_MCR_EI	0x01
+
+#define	IDTPHY_REGO_ISTAT	0x01
+#define	IDTPHY_REGN_ISTAT	"Interrupt Status"
+#define	IDTPHY_REGX_ISTAT	"\020\7GOOD\6HECE\5SCRE\4TPE\3RSCC\2RSE\1RFO"
+#define	IDTPHY_REGM_ISTAT_GOOD	0x40	/* good signal bit */
+#define	IDTPHY_REGM_ISTAT_HECE	0x20	/* HEC error */
+#define	IDTPHY_REGM_ISTAT_SCRE	0x10	/* short cell received error */
+#define	IDTPHY_REGM_ISTAT_TPE	0x08	/* transmit parity error */
+#define	IDTPHY_REGM_ISTAT_RSCC	0x04	/* receive signal condition change */
+#define	IDTPHY_REGM_ISTAT_RSE	0x02	/* receive symbol error */
+#define	IDTPHY_REGM_ISTAT_RFO	0x01	/* read FIFO overrun */
+
+#define	IDTPHY_REGO_DIAG	0x02
+#define	IDTPHY_REGN_DIAG	"Diagnostic Control"
+#define	IDTPHY_REGX_DIAG	"\020\010FTD\7ROS\6MULTI\5RFLUSH\4ITPE\3IHECE\11\3\0NORM\11\3\2PLOOP\11\3\3LLOOP"
+#define	IDTPHY_REGM_DIAG_FTD	0x80	/* Force TxClav Deassert */
+#define	IDTPHY_REGM_DIAG_ROS	0x40	/* RxClav Operation Select */
+#define	IDTPHY_REGM_DIAG_MULTI	0x20	/* Multi-phy operation */
+#define	IDTPHY_REGM_DIAG_RFLUSH	0x10	/* clear receive Fifo */
+#define	IDTPHY_REGM_DIAG_ITPE	0x08	/* insert transmit payload error */
+#define	IDTPHY_REGM_DIAG_IHECE	0x04	/* insert transmit HEC error */
+#define	IDTPHY_REGM_DIAG_LOOP	0x03	/* loopback mode */
+#define	IDTPHY_REGM_DIAG_LOOP_NONE	0x00	/* normal */
+#define	IDTPHY_REGM_DIAG_LOOP_PHY	0x02	/* PHY loopback */
+#define	IDTPHY_REGM_DIAG_LOOP_LINE	0x03	/* Line loopback */
+
+#define	IDTPHY_REGO_LHEC	0x03
+#define	IDTPHY_REGN_LHEC	"LED Driver and HEC Status/Control"
+#define	IDTPHY_REGX_LHEC	"\020\7DRHEC\6DTHEC\11\x18\0CYC1\11\x18\1CYC2\11\x18\2CYC4\11\x18\3CYC8\3FIFOE\2TXLED\1RXLED"
+#define	IDTPHY_REGM_LHEC_DRHEC	0x40	/* disable receive HEC */
+#define	IDTPHY_REGM_LHEC_DTHEC	0x20	/* disable transmit HEC */
+#define	IDTPHY_REGM_LHEC_RXREF	0x18	/* RxRef pulse width */
+#define	IDTPHY_REGM_LHEC_RXREF1	0x00	/* 1 pulse */
+#define	IDTPHY_REGM_LHEC_RXREF2	0x08	/* 2 pulse */
+#define	IDTPHY_REGM_LHEC_RXREF4	0x10	/* 4 pulse */
+#define	IDTPHY_REGM_LHEC_RXREF8	0x18	/* 8 pulse */
+#define	IDTPHY_REGM_LHEC_FIFOE	0x04	/* Fifo empty */
+#define	IDTPHY_REGM_LHEC_TXLED	0x02	/* Tx LED status */
+#define	IDTPHY_REGM_LHEC_RXLED	0x01	/* Rx LED status */
+
+#define	IDTPHY_REGO_CNT		0x04	/* +0x05 */
+#define	IDTPHY_REGN_CNT		"Counter"
+
+#define	IDTPHY_REGO_CNTS	0x06
+#define	IDTPHY_REGN_CNTS	"Counter select"
+#define	IDTPHY_REGX_CNTS	"\020\4SEC\3TX\2RX\1HECE"
+#define	IDTPHY_REGM_CNTS_SEC	0x08	/* symbol error counter */
+#define	IDTPHY_REGM_CNTS_TX	0x04	/* Tx cells */
+#define	IDTPHY_REGM_CNTS_RX	0x02	/* Rx cells */
+#define	IDTPHY_REGM_CNTS_HECE	0x01	/* HEC errors */
+
+#define	IDTPHY_PRINT_77105					\
+	{ /* 00 */						\
+	  UTP_REGT_BITS,	IDTPHY_REGO_MCR,		\
+	  IDTPHY_REGN_MCR,	IDTPHY_REGX_MCR },		\
+	{ /* 01 */						\
+	  UTP_REGT_BITS,	IDTPHY_REGO_ISTAT,		\
+	  IDTPHY_REGN_ISTAT,	IDTPHY_REGX_ISTAT },		\
+	{ /* 02 */						\
+	  UTP_REGT_BITS,	IDTPHY_REGO_DIAG,		\
+	  IDTPHY_REGN_DIAG,	IDTPHY_REGX_DIAG },		\
+	{ /* 03 */						\
+	  UTP_REGT_BITS,	IDTPHY_REGO_LHEC,		\
+	  IDTPHY_REGN_LHEC,	IDTPHY_REGX_LHEC },		\
+	{ /* 04, 05 */						\
+	  UTP_REGT_INT16,	IDTPHY_REGO_CNT,		\
+	  IDTPHY_REGN_CNT,	NULL },				\
+	{ /* 06 */						\
+	  UTP_REGT_BITS,	IDTPHY_REGO_CNTS,		\
+	  IDTPHY_REGN_CNTS,	IDTPHY_REGX_CNTS }
+
+#endif	/* _DEV_UTOPIA_IDTPHY_H */
diff --git a/sys/dev/utopia/suni.h b/sys/dev/utopia/suni.h
new file mode 100644
index 000000000000..ac8e9978fc9c
--- /dev/null
+++ b/sys/dev/utopia/suni.h
@@ -0,0 +1,1515 @@
+/*
+ * Copyright (c) 2003
+ *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * 	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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $FreeBSD$
+ *
+ * Register definitions for the following chips:
+ *	PMC-Sierra PMC-5346 (S/UNI-LITE)
+ *	PMC-Sierra PMC-5350 (S/UNI-ULTRA)
+ *	PMC-Sierra PMC-5355 (S/UNI-622)
+ *
+ * All definitions ending with _ULTRA are for the ULTRA chip only, all
+ * definitions ending with _LITE are for the LITE chip only. Some registers
+ * are only in the ULTRA and the definitions are not suffixed. All other
+ * definitions are for all chips.
+ */
+#ifndef _DEV_UTOPIA_SUNI_H
+#define	_DEV_UTOPIA_SUNI_H
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_MRESET 	"Master Reset and Identity/Load Meters"
+#define	SUNI_REGO_MRESET		0x00
+#define	SUNI_REGM_MRESET_RESET		0x80
+#define	SUNI_REGM_MRESET_TYPE		0x70
+#define	SUNI_REGM_MRESET_TYPE_622	0x10
+#define	SUNI_REGM_MRESET_TYPE_LITE	0x30
+#define	SUNI_REGM_MRESET_TYPE_ULTRA	0x70
+#define	SUNI_REGM_MRESET_TIP_ULTRA	0x08
+#define	SUNI_REGM_MRESET_ID_ULTRA	0x07
+#define	SUNI_REGM_MRESET_ID_LITE	0x0f
+#define	SUNI_REGM_MRESET_ID_622		0x0f
+#define	SUNI_REGX_MRESET_ULTRA	"\020\10RESET\12\x70\12TYPE\4TIP\12\7\12ID"
+#define	SUNI_REGX_MRESET_LITE	"\020\10RESET\12\x70\12TYPE\12\xf\12ID"
+#define	SUNI_REGX_MRESET_622	"\020\10RESET\12\x70\12TYPE\12\xf\12ID"
+
+/* lite, ultra */
+#define	SUNI_REGN_MCONFIG "Master Configuration"
+#define	SUNI_REGO_MCONFIG		0x01
+#define	SUNI_REGM_MCONFIG_AUTOFEBE	0x40
+#define	SUNI_REGM_MCONFIG_AUTOLRDI	0x20
+#define	SUNI_REGM_MCONFIG_AUTOPRDI	0x10
+#define	SUNI_REGM_MCONFIG_TCAINV	0x08
+#define	SUNI_REGM_MCONFIG_RCAINV	0x04
+#define	SUNI_REGM_MCONFIG_RXDINV_LITE	0x02
+#define	SUNI_REGM_MCONFIG_TFP_IN_ULTRA	0x01
+#define	SUNI_REGM_MCONFIG_RESERVED	0x00
+#define	SUNI_REGX_MCONFIG_LITE "\020\7AUTOFEBE\6AUTOLRDI\5AUTOPRDI\4TCAINV\3RCAINV\2RXDINV"
+#define	SUNI_REGX_MCONFIG_ULTRA "\020\7AUTOFEBE\6AUTOLRDI\5AUTOPRDI\4TCAINV\3RCAINV\1TFPI_IN"
+
+/* 622 */
+#define	SUNI_REGM_MCONFIG_TPTBEN_622	0x80
+#define	SUNI_REGM_MCONFIG_TSTBEN_622	0x40
+#define	SUNI_REGM_MCONFIG_SDH_C1_622	0x20
+#define	SUNI_REGM_MCONFIG_FIXPTR_622	0x10
+#define	SUNI_REGM_MCONFIG_TMODE_622	0x0C
+#define	SUNI_REGM_MCONFIG_TMODE_STS1_BYTE	0x00
+#define	SUNI_REGM_MCONFIG_TMODE_STS3c		0x04
+#define	SUNI_REGM_MCONFIG_TMODE_STS1_BIT	0x08
+#define	SUNI_REGM_MCONFIG_TMODE_STS12c		0x0C
+#define	SUNI_REGM_MCONFIG_RMODE_622	0x03
+#define	SUNI_REGM_MCONFIG_RMODE_STS1_BYTE	0x00
+#define	SUNI_REGM_MCONFIG_RMODE_STS3c		0x01
+#define	SUNI_REGM_MCONFIG_RMODE_STS1_BIT	0x02
+#define	SUNI_REGM_MCONFIG_RMODE_STS12c		0x03
+#define	SUNI_REGX_MCONFIG_622	"\020\10TPTBEN\7TSTBEN\6SDH_C1\5FIXPTR\11\x0C\0x00XSTS1BYTE\11\0x0C\0x04XSTS3c\11\0x0C\0x08XSTS1BIT\11\0x0C\0x0CXSTS12c\11\0x03\0x00RSTS1BYTE\11\0x03\0x01RSTS3c\11\0x03\0x02RSTS1BIT\11\0x03\0x03RSTS12c"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_MISTATUS "Master Interrupt Status"
+#define	SUNI_REGO_MISTATUS		0x02
+#define	SUNI_REGM_MISTATUS_CSUI_ULTRA	0x80
+#define	SUNI_REGM_MISTATUS_TROOLI_LITE	0x80
+#define	SUNI_REGM_MISTATUS_SUNII_622	0x80
+#define	SUNI_REGM_MISTATUS_LCDI		0x40
+#define	SUNI_REGM_MISTATUS_STBI_622	0x40
+#define	SUNI_REGM_MISTATUS_CRUI_ULTRA	0x20
+#define	SUNI_REGM_MISTATUS_RDOOLI_LITE	0x20
+#define	SUNI_REGM_MISTATUS_RESERVED_622	0x20
+#define	SUNI_REGM_MISTATUS_TACPI	0x10
+#define	SUNI_REGM_MISTATUS_RACPI	0x08
+#define	SUNI_REGM_MISTATUS_RPOPI	0x04
+#define	SUNI_REGM_MISTATUS_RLOPI	0x02
+#define	SUNI_REGM_MISTATUS_RSOPI	0x01
+#define	SUNI_REGX_MISTATUS_LITE "\020\10TROOLI\7LCDI\6RDOOLI\5TACPI\4RACPI\3RPOPI\2RLOPI\1RSOPI"
+#define	SUNI_REGX_MISTATUS_ULTRA "\020\10CSUI\7LCDI\6CRUI\5TACPI\4RACPI\3RPOPI\2RLOPI\1RSOPI"
+#define	SUNI_REGX_MISTATUS_622	"\020\10S/UNII\7STBI\5TACPI\4RACPI\3RPOPI\2RLOPI\1RSOPI"
+
+/* ultra */
+#define	SUNI_REGN_MMCTRL	"Master Mode Control"
+#define	SUNI_REGO_MMCTRL		0x03
+#define	SUNI_REGM_MMCTRL_51		0x02
+#define	SUNI_REGM_MMCTRL_155		0x03
+#define	SUNI_REGX_MMCTRL	"\020\11\3\00251MBIT\11\3\003155MBIT"
+
+/* 622 */
+#define	SUNI_REGN_PISO		"PISO Interrupt"
+#define	SUNI_REGO_PISO			0x03
+#define	SUNI_REGM_PISO_PAEE		0x02
+#define	SUNI_REGM_PISO_PAEI		0x01
+#define	SUNI_REGX_PISO		"\020\2PAEE\1PAEI"
+
+/* ultra/lite */
+#define	SUNI_REGN_MCLKM		"Master Clock Monitor"
+#define	SUNI_REGO_MCLKM			0x04
+#define	SUNI_REGM_MCLKM_RFCLKA		0x10	/* ultra */
+#define	SUNI_REGM_MCLKM_TFCLKA		0x08	/* ultra */
+#define	SUNI_REGM_MCLKM_RRCLKA		0x08	/* lite */
+#define	SUNI_REGM_MCLKM_REFCLKA		0x04	/* ultra */
+#define	SUNI_REGM_MCLKM_TRCLKA		0x04	/* lite */
+#define	SUNI_REGM_MCLKM_RCLKA		0x02
+#define	SUNI_REGM_MCLKM_TCLKA		0x01
+#define	SUNI_REGX_MCLKM_LITE	"\020\4RRCLKA\3TRCLKA\2RCLKA\1TCLKA"
+#define	SUNI_REGX_MCLKM_ULTRA	"\020\5RFCLKA\4TFCLKA\3REFCLKA\2RCLKA\1TCLKA"
+
+/* 622 */
+#define	SUNI_REGN_MCTRLM	"Master Control/Monitor"
+#define	SUNI_REGO_MCTRLM		0x04
+#define	SUNI_REGM_MCTRLM_TCAINV		0x80
+#define	SUNI_REGM_MCTRLM_RCAINV		0x40
+#define	SUNI_REGM_MCTRLM_LLE		0x20
+#define	SUNI_REGM_MCTRLM_DLE		0x10
+#define	SUNI_REGM_MCTRLM_LOOPT		0x08
+#define	SUNI_REGM_MCTRLM_DPLE		0x04
+#define	SUNI_REGM_MCTRLM_PICLKA		0x02
+#define	SUNI_REGM_MCTRLM_TCLKA		0x01
+#define	SUNI_REGX_MCTRLM	"\020\10TCAINV\7RCAINV\6LLE\5DLE\4LOOPT\3DPLE\2PICLKA\1TCLKA"
+
+/* ultra/lite */
+#define	SUNI_REGN_MCTRL		"Master Control"
+#define	SUNI_REGO_MCTRL			0x05
+#define	SUNI_REGM_MCTRL_LCDE		0x80
+#define	SUNI_REGM_MCTRL_LCDV		0x40
+#define	SUNI_REGM_MCTRL_FIXPTR		0x20
+#define	SUNI_REGM_MCTRL_TPLE		0x10	/* ultra */
+#define	SUNI_REGM_MCTRL_PDLE		0x08	/* ultra */
+#define	SUNI_REGM_MCTRL_LLE		0x04
+#define	SUNI_REGM_MCTRL_SDLE		0x02	/* ultra */
+#define	SUNI_REGM_MCTRL_DLE		0x02	/* lite */
+#define	SUNI_REGM_MCTRL_LOOPT		0x01
+#define	SUNI_REGX_MCTRL_ULTRA	"\020\10LCDE\7LCDV\6FIXPTR\5TPLE\4PDLE\3LLE\2SDLE\1LOOPT"
+#define	SUNI_REGX_MCTRL_LITE	"\020\10LCDE\7LCDV\6FIXPTR\3LLE\2DLE\1LOOPT"
+
+/* 622 */
+#define	SUNI_REGN_MALARM	"Master Auto Alarm"
+#define	SUNI_REGO_MALARM		0x05
+#define	SUNI_REGM_MALARM_AUTOFEBE	0x04
+#define	SUNI_REGM_MALARM_AUTOLRDI	0x02
+#define	SUNI_REGM_MALARM_AUTOPRDI	0x01
+#define	SUNI_REGX_MALARM	"\020\4AUTOFEBE\2AUTOLRDI\1AUTOPRDI"
+
+/* ultra/lite */
+#define	SUNI_REGN_CLKSYN	"Clock Synthesis Control and Status"
+#define	SUNI_REGO_CLKSYN		0x06
+#define	SUNI_REGM_CLKSYN_TROOLI		0x20	/* ultra */
+#define	SUNI_REGM_CLKSYN_TROOLV		0x08
+#define	SUNI_REGM_CLKSYN_TROOLE		0x02
+#define	SUNI_REGM_CLKSYN_TREFSEL	0x01	/* lite */
+#define	SUNI_REGM_CLKSYN_RESERVED	0x00
+#define	SUNI_REGX_CLKSYN_ULTRA	"\020\6TROOLI\4TROOLV\2TROOLE"
+#define	SUNI_REGX_CLKSYN_LITE	"\020\4TROOLV\2TROOLE\1TREFSEL"
+
+/* 622 */
+#define	SUNI_REGN_POUT	"Parallel Output Port"
+#define	SUNI_REGO_POUT			0x06
+#define	SUNI_REGM_POUT_POP		0x3f
+#define	SUNI_REGX_POUT	"\020\12\x3f\12POP"
+
+/* ultra/lite */
+#define	SUNI_REGN_CLKREC "Clock Recovery Control and Status"
+#define	SUNI_REGO_CLKREC_LITE		0x07
+#define	SUNI_REGO_CLKREC_ULTRA		0x08
+#define	SUNI_REGM_CLKREC_RROOLI		0x40	/* ultra */
+#define	SUNI_REGM_CLKREC_RDOOLI		0x20	/* ultra */
+#define	SUNI_REGM_CLKREC_RROOLV		0x10
+#define	SUNI_REGM_CLKREC_RDOOLV		0x08
+#define	SUNI_REGM_CLKREC_RROOLE		0x04	/* ultra */
+#define	SUNI_REGM_CLKREC_RDOOLE		0x02
+#define	SUNI_REGM_CLKREC_RREFSEL	0x01	/* lite */
+#define	SUNI_REGM_CLKREC_RESERVED	0x00
+#define	SUNI_REGX_CLKREC_ULTRA "\020\7RROOLI\6RDOOLI\5RROOLV\4RDOOLV\3RROOLE\2RDOOLE"
+#define	SUNI_REGX_CLKREC_LITE "\020\5RROOLV\4RDOOLV\2RDOOLE\1RREFSEL"
+
+/* 622 */
+#define	SUNI_REGN_PIN	"Parallel Input Port"
+#define	SUNI_REGO_PIN			0x07
+
+/* 622 */
+#define	SUNI_REGN_PINV	"Parallel Input Port Value"
+#define	SUNI_REGO_PINV			0x08
+#define	SUNI_REGM_PINV_PIPV		0x0f
+#define	SUNI_REGX_PINV	"\020\12\0x0f\12PIPIV"
+
+/* ultra */
+#define	SUNI_REGN_CLKRECCFG	"Clock Recovery Configuration"
+#define	SUNI_REGO_CLKRECCFG		0x09
+#define	SUNI_REGM_CLKRECCFG_RESERVED	0x07
+#define	SUNI_REGX_CLKRECCFG	"\020"
+
+/* 622 */
+#define	SUNI_REGN_PINE	"Parallel Input Port Enable"
+#define	SUNI_REGO_PINE			0x09
+
+/* ultra */
+#define	SUNI_REGN_LTXCFG1 "Line Transmitter Configuration 1"
+#define	SUNI_REGO_LTXCFG1		0x0A
+#define	SUNI_REGM_LTXCFG1_VREFSEL	0x80
+#define	SUNI_REGM_LTXCFG1_OEN		0x20
+#define	SUNI_REGM_LTXCFG1_OTQ		0x10
+#define	SUNI_REGM_LTXCFG1_RESERVED	0x0C
+#define	SUNI_REGX_LTXCFG1 "\020\10VREFSEL\6OEN\5OTQ"
+
+/* 622 */
+#define	SUNI_REGN_XC1	"Transmit C1"
+#define	SUNI_REGO_XC1			0x0A
+
+/* ultra */
+#define	SUNI_REGN_LTXCFG2 "Line Transmitter Configuration 2"
+#define	SUNI_REGO_LTXCFG2		0x0B
+#define	SUNI_REGM_LTXCFG2_RESERVED	0xFF
+#define	SUNI_REGX_LTXCFG2 "\020"
+
+/* 622 */
+#define	SUNI_REGN_APSCS	"APS Control/Status"
+#define	SUNI_REGO_APSCS			0x0B
+#define	SUNI_REGM_APSCS_PSBFE		0x80
+#define	SUNI_REGM_APSCS_COAPSE		0x40
+#define	SUNI_REGM_APSCS_Z1E		0x20
+#define	SUNI_REGM_APSCS_Zi1		0x10
+#define	SUNI_REGM_APSCS_PSBFI		0x08
+#define	SUNI_REGM_APSCS_COAPSI		0x04
+#define	SUNI_REGM_APSCS_RESERVED	0x02
+#define	SUNI_REGM_APSCS_PSBFV		0x01
+#define	SUNI_REGX_APSCS	"\020\10PSBFE\7COAPSE\6Z1E\5Z1I\4PSBFI\3COAPSI\1PSBFV"
+
+/* ultra */
+#define	SUNI_REGN_LRXCFG "Line Receiver Configuration"
+#define	SUNI_REGO_LRXCFG		0x0C
+#define	SUNI_REGM_LRXCFG_RESERVED	0x01
+#define	SUNI_REGX_LRXCFG "\020"
+
+/* 622 */
+#define	SUNI_REGN_RK1	"Receive K1"
+#define	SUNI_REGO_RK1			0x0C
+
+/* 622 */
+#define	SUNI_REGN_RK2	"Receive K2"
+#define	SUNI_REGO_RK2			0x0D
+
+/* 622 */
+#define	SUNI_REGN_RZ1	"Receive Z1"
+#define	SUNI_REGO_RZ1			0x0E
+
+/* 622 */
+#define	SUNI_REGN_XZ1	"Transmit Z1"
+#define	SUNI_REGO_XZ1			0x0F
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RSOPCIE "RSOP Control/Interrupt Enable"
+#define	SUNI_REGO_RSOPCIE		0x10
+#define	SUNI_REGO_RSOPCIE_BIPWORD_622	0x80
+#define	SUNI_REGM_RSOPCIE_DDS		0x40
+#define	SUNI_REGM_RSOPCIE_FOOF		0x20
+#define	SUNI_REGM_RSOPCIE_RESV		0x10
+#define	SUNI_REGM_RSOPCIE_ALGO2_622	0x10
+#define	SUNI_REGM_RSOPCIE_BIPEE		0x08
+#define	SUNI_REGM_RSOPCIE_LOSE		0x04
+#define	SUNI_REGM_RSOPCIE_LOFE		0x02
+#define	SUNI_REGM_RSOPCIE_OOFE		0x01
+#define	SUNI_REGX_RSOPCIE	"\020\7DDS\6FOOF\4BIPEE\3LOSE\2LOFE\1OOFE"
+#define	SUNI_REGX_RSOPCIE_622	"\020\10BIPWORD\7DDS\6FOOF\5ALGO2\4BIPEE\3LOSE\2LOFE\1OOFE"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RSOPSIS "RSOP Status/Interrupt Status"
+#define	SUNI_REGO_RSOPSIS		0x11
+#define	SUNI_REGM_RSOPSIS_BIPEI		0x40
+#define	SUNI_REGM_RSOPSIS_LOSI		0x20
+#define	SUNI_REGM_RSOPSIS_LOFI		0x10
+#define	SUNI_REGM_RSOPSIS_OOFI		0x08
+#define	SUNI_REGM_RSOPSIS_LOSV		0x04
+#define	SUNI_REGM_RSOPSIS_LOFV		0x02
+#define	SUNI_REGM_RSOPSIS_OOFV		0x01
+#define	SUNI_REGX_RSOPSIS "\020\7BIPEI\6LOSI\5LOFI\4OOFI\3LOSV\2LOFV\1OOFV"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RSOP_BIP8 "RSOP Section BIP-8"
+#define	SUNI_REGO_RSOP_BIP8		0x12	/* +0x13 */
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TSOPCTRL "TSOP Control"
+#define	SUNI_REGO_TSOPCTRL		0x14
+#define	SUNI_REGM_TSOPCTRL_DS		0x40
+#define	SUNI_REGM_TSOPCTRL_LAIS		0x01
+#define	SUNI_REGM_TSOPCTRL_RESERVED	0x00
+#define	SUNI_REGX_TSOPCTRL "\020\7DS\1LAIS"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TSOPDIAG "TSOP Diagnostics"
+#define	SUNI_REGO_TSOPDIAG		0x15
+#define	SUNI_REGM_TSOPDIAG_DLOS		0x04
+#define	SUNI_REGM_TSOPDIAG_DBIP8	0x02
+#define	SUNI_REGM_TSOPDIAG_DFP		0x01
+#define	SUNI_REGX_TSOPDIAG "\020\3DLOS\2DBIP8\1DFP"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RLOPCTRL "RLOP Control/Status"
+#define	SUNI_REGO_RLOPCTRL		0x18
+#define	SUNI_REGO_RLOPCTRL_BIPWORD	0x80
+#define	SUNI_REGO_RLOPCTRL_ALLONES_622	0x40
+#define	SUNI_REGO_RLOPCTRL_AISDET_622	0x20
+#define	SUNI_REGO_RLOPCTRL_LRDIDET_622	0x10
+#define	SUNI_REGO_RLOPCTRL_BIPWORDO_622	0x08
+#define	SUNI_REGO_RLOPCTRL_LAISV	0x02
+#define	SUNI_REGO_RLOPCTRL_RDIV		0x01
+#define	SUNI_REGO_RLOPCTRL_RESERVED	0x00
+#define	SUNI_REGX_RLOPCTRL	"\020\10BIPWORD\2LAISV\1RDIV"
+#define	SUNI_REGX_RLOPCTRL_622	"\020\10BIPWORD\7ALLONES\6AISDET\5LRDIDET\4BIPWORDO\2LAISV\1RDIV"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RLOPINTR "RLOP Interrupt Enable/Interrupt Status"
+#define	SUNI_REGO_RLOPINTR		0x19
+#define	SUNI_REGO_RLOPINTR_FEBEE	0x80
+#define	SUNI_REGO_RLOPINTR_BIPEE	0x40
+#define	SUNI_REGO_RLOPINTR_LAISE	0x20
+#define	SUNI_REGO_RLOPINTR_RDIE		0x10
+#define	SUNI_REGO_RLOPINTR_FEBEI	0x08
+#define	SUNI_REGO_RLOPINTR_BIPEI	0x04
+#define	SUNI_REGO_RLOPINTR_LAISI	0x02
+#define	SUNI_REGO_RLOPINTR_RDII		0x01
+#define	SUNI_REGX_RLOPINTR "\020\10FEBEE\7BIPEE\6LAISE\5DRIE\4FEBEI\3BIPEI\2LAISI\1RDII"
+
+/* lite, ultra */
+#define	SUNI_REGN_RLOPBIP8_24 "RLOP Line BIP-8/24"
+#define	SUNI_REGO_RLOPBIP8_24		0x1A	/* +1B,1C */
+#define	SUNI_REGM_RLOPBIP8_24		0x0F
+
+/* 622 */
+#define	SUNI_REGN_RLOPBIP8_24_96 "RLOP Line BIP-8/24/96"
+#define	SUNI_REGO_RLOPBIP8_24_96	0x1A	/* +1B,1C */
+#define	SUNI_REGM_RLOPBIP8_24_96	0x0F
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RLOPFEBE "RLOP Line FEBE"
+#define	SUNI_REGO_RLOPFEBE		0x1D	/* +1E,1F */
+#define	SUNI_REGM_RLOPFEBE		0x0F
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TLOPCTRL "TLOP Control"
+#define	SUNI_REGO_TLOPCTRL		0x20
+#define	SUNI_REGM_TLOPCTRL_APSREG_622	0x20
+#define	SUNI_REGM_TLOPCTRL_RDI		0x01
+#define	SUNI_REGM_TLOPCTRL_RESERVED	0x00
+#define	SUNI_REGX_TLOPCTRL	"\020\1RDI"
+#define	SUNI_REGX_TLOPCTRL_622	"\020\6APSREG\1LRDI"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TLOPDIAG "TLOP Diagnostics"
+#define	SUNI_REGO_TLOPDIAG		0x21
+#define	SUNI_REGM_TLOPDIAG_DBIP		0x01
+#define	SUNI_REGX_TLOPDIAG "\020\1DBIP"
+
+/* 622 */
+#define	SUNI_REGN_TLOP_XK1	"TLOP Transmit K1"
+#define	SUNI_REGO_TLOP_XK1		0x22
+
+/* 622 */
+#define	SUNI_REGN_TLOP_XK2	"TLOP Transmit K2"
+#define	SUNI_REGO_TLOP_XK2		0x23
+
+/* 622 */
+#define	SUNI_REGN_SSTBCTRL	"SSTB Control"
+#define	SUNI_REGO_SSTBCTRL		0x28
+#define	SUNI_REGM_SSTBCTRL_RRAMACC	0x40
+#define	SUNI_REGM_SSTBCTRL_RTIUIE	0x20
+#define	SUNI_REGM_SSTBCTRL_RTIMIE	0x10
+#define	SUNI_REGM_SSTBCTRL_PER5		0x08
+#define	SUNI_REGM_SSTBCTRL_TNULL	0x04
+#define	SUNI_REGM_SSTBCTRL_NOSYNC	0x02
+#define	SUNI_REGM_SSTBCTRL_LEN16	0x01
+#define	SUNI_REGX_SSTBCTRL	"\020\7RRAMACC\6RTIUIE\5RTIMIE\4PER5\3TNULL\2NOSYNC\1LEN16"
+
+/* 622 */
+#define	SUNI_REGN_SSTBSTIS	"SSTB Section Trace Identifier Status"
+#define	SUNI_REGO_SSTBSTIS		0x29
+#define	SUNI_REGM_SSTBSTIS_BUSY		0x80
+#define	SUNI_REGM_SSTBSTIS_RTIUI	0x08
+#define	SUNI_REGM_SSTBSTIS_RTIUV	0x04
+#define	SUNI_REGM_SSTBSTIS_RTIMI	0x02
+#define	SUNI_REGM_SSTBSTIS_RTIMV	0x01
+#define	SUNI_REGX_SSTBSTIS	"\020\10BUSY\4RTIUI\3RTIUV\2RTIMI\1RTIMV"
+
+/* 622 */
+#define	SUNI_REGN_SSTBIAR	"SSTB Indirect Address Register"
+#define	SUNI_REGO_SSTBIAR		0x2A
+#define	SUNI_REGM_SSTBIAR_RWB		0x80
+#define	SUNI_REGM_SSTBIAR_A		0x7F
+#define	SUNI_REGX_SSTBIAR	"\020\10RWB\12\x7f\20"
+
+/* 622 */
+#define	SUNI_REGN_SSTBIDR	"SSTB Indirect Data Register"
+#define	SUNI_REGO_SSTBIDR		0x2B
+
+#if 0	/* see chip errata */
+/* 622 */
+#define	SUNI_REGN_SSTBECSM	"SSTB Expected Clock Synchronization Message"
+#define	SUNI_REGO_SSTBECSM		0x2C
+#endif
+
+/* 622 */
+#define	SUNI_REGN_SSTBCSMS	"SSTB Clock Synchronisation Message Status"
+#define	SUNI_REGO_SSTBCSMS		0x2D
+#define	SUNI_REGM_SSTBCSMS_RCSMUIE	0x80
+#define	SUNI_REGM_SSTBCSMS_RCSMMIE	0x40
+#define	SUNI_REGM_SSTBCSMS_RCSMUI	0x08
+#define	SUNI_REGM_SSTBCSMS_RCSMUV	0x04
+#define	SUNI_REGM_SSTBCSMS_RCSMMI	0x02
+#define	SUNI_REGM_SSTBCSMS_RCSMMV	0x01
+#define	SUNI_REGX_SSTBCSMS	"\020\10RCSMUIE\7RCSMMIE\4RCSMUI\3RCSMUV\2RCSMMI\1RCSMMV"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RPOPCTRL	"RPOP Status/Control"
+#define	SUNI_REGO_RPOPCTRL		0x30
+#define	SUNI_REGM_RPOPCTRL_LOP		0x20
+#define	SUNI_REGM_RPOPCTRL_PAIS		0x08
+#define	SUNI_REGM_RPOPCTRL_PRDI		0x04
+#define	SUNI_REGM_RPOPCTRL_NEWPTRI_622	0x02
+#define	SUNI_REGM_RPOPCTRL_NEWPTRE_622	0x01
+#define	SUNI_REGM_RPOPCTRL_RESERVED	0x00
+#define	SUNI_REGX_RPOPCTRL	"\020\6LOP\4PAIS\3PRDI"
+#define	SUNI_REGX_RPOPCTRL_622	"\020\6LOP\4PAIS\3PRDI\2NEWPTRI\1NEWPTRE"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RPOPISTAT	"RPOP Interrupt Status"
+#define	SUNI_REGO_RPOPISTAT		0x31
+#define	SUNI_REGM_RPOPISTAT_PSLI	0x80
+#define	SUNI_REGM_RPOPISTAT_LOPI	0x20
+#define	SUNI_REGM_RPOPISTAT_PAISI	0x08
+#define	SUNI_REGM_RPOPISTAT_PRDII	0x04
+#define	SUNI_REGM_RPOPISTAT_BIPEI	0x02
+#define	SUNI_REGM_RPOPISTAT_FEBEI	0x01
+#define	SUNI_REGX_RPOPISTAT	"\02010PSLI\6LOPI\4PAISI\3PRDII\2BIPEI\1FEBEI"
+
+/* 622 */
+#define	SUNI_REGN_RPOPPIS	"RPOP Pointer Interrupt Status"
+#define	SUNI_REGO_RPOPPIS		0x32
+#define	SUNI_REGM_RPOPPIS_ILLJREQI	0x80
+#define	SUNI_REGM_RPOPPIS_DISCOPAI	0x20
+#define	SUNI_REGM_RPOPPIS_INVNDFI	0x10
+#define	SUNI_REGM_RPOPPIS_ILLPTRI	0x08
+#define	SUNI_REGM_RPOPPIS_NSEI		0x04
+#define	SUNI_REGM_RPOPPIS_PSEI		0x02
+#define	SUNI_REGM_RPOPPIS_NDFI		0x01
+#define	SUNI_REGX_RPOPPIS	"\020\10ILLJREQI\6DISCOPAI\5INVNDFI\4ILLPTRI\3NSEI\2PSEI\1NDFI"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RPOPIEN	"RPOP Interrupt Enable"
+#define	SUNI_REGO_RPOPIEN		0x33
+#define	SUNI_REGM_RPOPIEN_PSLE		0x80
+#define	SUNI_REGM_RPOPIEN_LOPE		0x20
+#define	SUNI_REGM_RPOPIEN_PAISE		0x08
+#define	SUNI_REGM_RPOPIEN_PRDIE		0x04
+#define	SUNI_REGM_RPOPIEN_BIPEE		0x02
+#define	SUNI_REGM_RPOPIEN_FEBEE		0x01
+#define	SUNI_REGM_RPOPIEN_RESERVED	0x00
+#define	SUNI_REGX_RPOPIEN	"\02010PSLE\6LOPE\4PAISE\3PRDIE\2BIPEE\1FEBEE"
+
+/* 622 */
+#define	SUNI_REGN_RPOPPIE	"RPOP Pointer Interrupt Enable"
+#define	SUNI_REGO_RPOPPIE		0x34
+#define	SUNI_REGM_RPOPPIE_ILLJREQE	0x80
+#define	SUNI_REGM_RPOPPIE_DISCOPAE	0x20
+#define	SUNI_REGM_RPOPPIE_INVNDFE	0x10
+#define	SUNI_REGM_RPOPPIE_ILLPTRE	0x08
+#define	SUNI_REGM_RPOPPIE_NSEE		0x04
+#define	SUNI_REGM_RPOPPIE_PSEE		0x02
+#define	SUNI_REGM_RPOPPIE_NDFE		0x01
+#define	SUNI_REGX_RPOPPIE	"\020\10ILLJREQE\6DISCOPAE\5INVNDFE\4ILLPTRE\3NSEE\2PSEE\1NDFE"
+
+/* 622 */
+#define	SUNI_REGN_RPOPPTR	"RPOP Pointer"
+#define	SUNI_REGO_RPOPPTR		0x35	/* +36 */
+#define	SUNI_REGM_RPOPPTR_RDI10		0x20
+#define	SUNI_REGM_RPOPPTR_S		0x0c
+#define	SUNI_REGS_RPOPPTR_S		2
+#define	SUNI_REGM_RPOPPTR		0x03
+#define	SUNI_REGS_RPOPPTR		0
+#define	SUNI_REGX_RPOPPTR		"\020\6RDI10\12\xc\20S"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RPOPPSL "RPOP Path Signal Label"
+#define	SUNI_REGO_RPOPPSL		0x37
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RPOPBIP8 "RPOP Path BIP-8"
+#define	SUNI_REGO_RPOPBIP8		0x38	/* +39 */
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RPOPFEBE "RPOP Path FEBE"
+#define	SUNI_REGO_RPOPFEBE		0x3A	/* +3B */
+
+/* 622 */
+#define	SUNI_REGN_RPOPRDI	"RPOP RDI"
+#define	SUNI_REGO_RPOPRDI		0x3C
+#define	SUNI_REGM_RPOPRDI_BLKFEBE	0x10
+#define	SUNI_REGM_RPOPRDI_ARDIE		0x02
+#define	SUNI_REGM_RPOPRDI_ARDIV		0x01
+#define	SUNI_REGM_RPOPRDI_RESERVED	0x00
+#define	SUNI_REGX_RPOPRDI	"\020\5BLKFEBE\2ARDIE\1ARDIV"
+
+/* lite, ultra */
+#define	SUNI_REGN_RPOPBIP8CFG 	"RPOP Path BIP-8 Configuration"
+#define	SUNI_REGO_RPOPBIP8CFG		0x3D
+#define	SUNI_REGM_RPOPBIP8CFG_BLKBIP	0x20
+#define	SUNI_REGM_RPOPBIP8CFG_RESERVED	0x00
+#define	SUNI_REGX_RPOPBIP8CFG 	"\020\6BLKBIP"
+
+/* 622 */
+#define	SUNI_REGN_RPOPRING	"RPOP Ring Control"
+#define	SUNI_REGO_RPOPRING		0x3D
+#define	SUNI_REGM_RPOPRING_SOS		0x80
+#define	SUNI_REGM_RPOPRING_ENSS		0x40
+#define	SUNI_REGM_RPOPRING_BLKBIP	0x20
+#define	SUNI_REGM_RPOPRING_DISFS	0x10
+#define	SUNI_REGM_RPOPRING_BLKBIPO	0x08
+#define	SUNI_REGM_RPOPRING_RESERVED	0x00
+#define	SUNI_REGX_RPOPRING	"\020\10SOS\7ENSS\6BLKBIP\5DISFS\4BLKBIPO"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TPOPCTRL	"TPOP Control/Diagnostic"
+#define	SUNI_REGO_TPOPCTRL		0x40
+#define	SUNI_REGM_TPOPCTRL_EXCFS	0x80	/* 622 */
+#define	SUNI_REGM_TPOPCTRL_DB3		0x02
+#define	SUNI_REGM_TPOPCTRL_PAIS		0x01
+#define	SUNI_REGM_TPOPCTRL_RESERVED	0x00
+#define	SUNI_REGX_TPOPCTRL	"\020\2DB3\1PAIS"
+#define	SUNI_REGX_TPOPCTRL_622	"\020\4EXCFS\2DB3\1PAIS"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TPOPPTRC "TPOP Pointer Control"
+#define	SUNI_REGO_TPOPPTRC		0x41
+#define	SUNI_REGM_TPOPPTRC_FTPTR	0x40
+#define	SUNI_REGM_TPOPPTRC_SOS		0x20
+#define	SUNI_REGM_TPOPPTRC_PLD		0x10
+#define	SUNI_REGM_TPOPPTRC_NDF		0x08
+#define	SUNI_REGM_TPOPPTRC_NSE		0x04
+#define	SUNI_REGM_TPOPPTRC_PSE		0x02
+#define	SUNI_REGM_TPOPPTRC_RESERVED	0x00
+#define	SUNI_REGX_TPOPPTRC "\020\7FTPTR\6SOS\5PLD\4NDF\3NSE\2PSE"
+
+/* 622 */
+#define	SUNI_REGN_TPOPCP	"TPOP Current Pointer"
+#define	SUNI_REGO_TPOPCP		0x43	/* +44 */
+#define	SUNI_REGM_TPOPCP		0x03
+#define	SUNI_REGS_TPOPCP		0
+#define	SUNI_REGX_TPOPCP	"\020"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TPOPAPTR 	"TPOP Arbitrary Pointer"
+#define	SUNI_REGO_TPOPAPTR		0x45	/* +46 */
+#define	SUNI_REGM_TPOPAPTR_NDF		0xF0
+#define	SUNI_REGS_TPOPAPTR_NDF		4
+#define	SUNI_REGM_TPOPAPTR_S		0x0C
+#define	SUNI_REGS_TPOPAPTR_S		2
+#define	SUNI_REGM_TPOPAPTR		0x03
+#define	SUNI_REGS_TPOPAPTR		0
+#define	SUNI_REGX_TPOPAPTR	"\020\12\x0C\12S\12\xF0\12NDF"
+
+#define	SUNI_REGM_SONET			0
+#define	SUNI_REGM_SDH			2
+
+/* 622 */
+#define	SUNI_REGN_TPOPPT	"TPOP Path Trace"
+#define	SUNI_REGO_TPOPPT		0x47
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TPOPPSL	"TPOP Path Signal Label"
+#define	SUNI_REGO_TPOPPSL		0x48
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TPOPSTATUS "TPOP Path Status"
+#define	SUNI_REGO_TPOPSTATUS		0x49
+#define	SUNI_REGM_TPOPSTATUS_FEBE	0xF0
+#define	SUNI_REGS_TPOPSTATUS_FEBE	4
+#define	SUNI_REGM_TPOPSTATUS_PRDI	0x08
+#define	SUNI_REGM_TPOPSTATUS_G1		0x07
+#define	SUNI_REGS_TPOPSTATUS_G1		0
+#define	SUNI_REGX_TPOPSTATUS "\020\12\xF0\12FEBE\4PRDI\12\x7\12G"
+
+/* 622 */
+#define	SUNI_REGN_TPOPPUC	"TPOP Path User Channel"
+#define	SUNI_REGO_TPOPPUC		0x4A
+
+/* 622 */
+#define	SUNI_REGN_TPOPPG1	"TPOP Path Grow #1"
+#define	SUNI_REGO_TPOPPG1		0x4B
+
+/* 622 */
+#define	SUNI_REGN_TPOPPG2	"TPOP Path Grow #2"
+#define	SUNI_REGO_TPOPPG2		0x4C
+
+/* 622 */
+#define	SUNI_REGN_TPOPPG3	"TPOP Path Grow #3"
+#define	SUNI_REGO_TPOPPG3		0x4D
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_RACPCTRL	"RACP Control/Status"
+#define	SUNI_REGO_RACPCTRL		0x50
+#define	SUNI_REGM_RACPCTRL_OOCDV	0x80
+#define	SUNI_REGM_RACPCTRL_FSEN		0x80
+#define	SUNI_REGM_RACPCTRL_RXPTYP	0x40
+#define	SUNI_REGM_RACPCTRL_PASS		0x20
+#define	SUNI_REGM_RACPCTRL_DISCOR	0x10
+#define	SUNI_REGM_RACPCTRL_HCSPASS	0x08
+#define	SUNI_REGM_RACPCTRL_HCSADD	0x04
+#define	SUNI_REGM_RACPCTRL_DDSCR	0x02
+#define	SUNI_REGM_RACPCTRL_FIFORST	0x01
+#define	SUNI_REGX_RACPCTRL	"\020\10OOCDV\7RXPTYP\6PASS\5DISCO\4HCSPASS\3HCSADD\2DDSCR\1FIFORST"
+#define	SUNI_REGX_RACPCTRL_622	"\020\10FSEN\7RXPTYP\6PASS\5DISCO\4HCSPASS\3HCSADD\2DDSCR\1FIFORST"
+
+/* lite, ultra */
+#define	SUNI_REGN_RACPINTR "RACP Interrupt Enable/Status"
+#define	SUNI_REGO_RACPINTR		0x51
+#define	SUNI_REGM_RACPINTR_OOCDE	0x80
+#define	SUNI_REGM_RACPINTR_HCSE		0x40
+#define	SUNI_REGM_RACPINTR_FIFOE	0x20
+#define	SUNI_REGM_RACPINTR_OOCDI	0x10
+#define	SUNI_REGM_RACPINTR_CHCSI	0x08
+#define	SUNI_REGM_RACPINTR_UHCSI	0x04
+#define	SUNI_REGM_RACPINTR_FOVRI	0x02
+#define	SUNI_REGX_RACPINTR "\020\10OOCDE\7HCSE\6FIFOE\5OOCDI\4CHCSI\3UHCSI\2FOVRI"
+
+/* 622 */
+#define	SUNI_REGN_RACPIS	"RACP Interrupt Status"
+#define	SUNI_REGO_RACPIS		0x51
+#define	SUNI_REGM_RACPIS_OCDV		0x80
+#define	SUNI_REGM_RACPIS_LCDV		0x40
+#define	SUNI_REGM_RACPIS_OCDI		0x20
+#define	SUNI_REGM_RACPIS_LCDI		0x10
+#define	SUNI_REGM_RACPIS_CHCSI		0x08
+#define	SUNI_REGM_RACPIS_UHCSI		0x04
+#define	SUNI_REGM_RACPIS_FOVRI		0x02
+#define	SUNI_REGM_RACPIS_FUDRI		0x01
+#define	SUNI_REGX_RACPIS	"\020\10OCDV\7LCDV\6OCDI\5LCDI\4CHCSI\3UHCSI\2FOVRI\1FUDRI"
+
+/* lite, ultra */
+#define	SUNI_REGN_RACPPATTERN "RACP Match Header Pattern"
+#define	SUNI_REGO_RACPPATTERN		0x52
+#define	SUNI_REGM_RACPPATTERN_GFC	0xF0
+#define	SUNI_REGS_RACPPATTERN_GFC	4
+#define	SUNI_REGM_RACPPATTERN_PTI	0x0E
+#define	SUNI_REGS_RACPPATTERN_PTI	1
+#define	SUNI_REGM_RACPPATTERN_CLP	0x01
+#define	SUNI_REGS_RACPPATTERN_CLP	0
+#define	SUNI_REGX_RACPPATTERN "\020\12\xF0\12GFC\12\x0E\12PTI\1CLP"
+
+/* 622 */
+#define	SUNI_REGN_RACPIEC	"RACP Interrupt Enable/Control"
+#define	SUNI_REGO_RACPIEC		0x52
+#define	SUNI_REGM_RACPIEC_OCDE		0x80
+#define	SUNI_REGM_RACPIEC_LCDE		0x40
+#define	SUNI_REGM_RACPIEC_HCSE		0x20
+#define	SUNI_REGM_RACPIEC_FIFOE		0x10
+#define	SUNI_REGM_RACPIEC_LCDDROP	0x08
+#define	SUNI_REGM_RACPIEC_RCALEVEL0	0x04
+#define	SUNI_REGM_RACPIEC_HCSFTR	0x03
+#define	SUNI_REGX_RACPIEC	"\020\10OCDE\7LCDE\6HCSE\5FIFOE\4LCDDROP\3RCALEVEL0\12\0x3\12HCSFTR"
+
+/* lite, ultra */
+#define	SUNI_REGN_RACPMASK "RACP Match Header Mask"
+#define	SUNI_REGO_RACPMASK		0x53
+#define	SUNI_REGM_RACPMASK_MGFC		0xF0
+#define	SUNI_REGS_RACPMASK_MGFC		4
+#define	SUNI_REGM_RACPMASK_MPTI		0x0E
+#define	SUNI_REGS_RACPMASK_MPTI		1
+#define	SUNI_REGM_RACPMASK_MCLP		0x01
+#define	SUNI_REGS_RACPMASK_MCLP		0
+#define	SUNI_REGX_RACPMASK "\020\12\xF0\12MGFC\12\x0E\12MPTI\1MCLP"
+
+/* 622 */
+#define	SUNI_REGO_RACPPATTERN_622	0x53
+
+/* lite, ultra */
+#define	SUNI_REGN_RACPCHCS "RACP Correctable HCS Error Count"
+#define	SUNI_REGO_RACPCHCS		0x54
+
+/* 622 */
+#define	SUNI_REGO_RACPMASK_622		0x54
+
+/* lite, ultra */
+#define	SUNI_REGN_RACPUHCS "RACP Uncorrectable HCS Error Count"
+#define	SUNI_REGO_RACPUHCS		0x55
+
+/* 622 */
+#define	SUNI_REGO_RACPCHCS_622		0x55	/* +56 */
+#define	SUNI_REGM_RACPCHCS_622		0x0f
+
+/* lite, ultra */
+#define	SUNI_REGN_RACPCNT "RACP Receive Cell Counter"
+#define	SUNI_REGO_RACPCNT		0x56	/* +57,58 */
+#define	SUNI_REGM_RACPCNT		0x07
+
+/* 622 */
+#define	SUNI_REGO_RACPUHCS_622		0x57	/* +58 */
+#define	SUNI_REGM_RACPUHCS_622		0x0f
+
+/* 622 */
+#define	SUNI_REGO_RACPCNT_622		0x59	/* +5A,5B */
+#define	SUNI_REGM_RACPCNT_622		0x1F
+
+/* lite, ultra */
+#define	SUNI_REGN_RACPCFG "RACP Configuration"
+#define	SUNI_REGO_RACPCFG		0x59
+#define	SUNI_REGM_RACPCFG_RGFCE		0xF0
+#define	SUNI_REGS_RACPCFG_RGFCE		4
+#define	SUNI_REGM_RACPCFG_FSEN		0x08
+#define	SUNI_REGM_RACPCFG_LEVEL0	0x04
+#define	SUNI_REGM_RACPCFG_HCSFTR	0x03
+#define	SUNI_REGS_RACPCFG_HCSFTR	0
+#define	SUNI_REGX_RACPCFG "\020\12\xF0\20RGFCE\4FSEN\3RCALEVEL0\12\x03\12HCSFTR"
+
+/* 622 */
+#define	SUNI_REGN_RACPGFC	"RACP GFC Control/Misc. Control"
+#define	SUNI_REGO_RACPGFC		0x5C
+#define	SUNI_REGM_RACPGFC_CDDIS		0x80
+#define	SUNI_REGM_RACPGFC_RXBYTEPRTY	0x40
+#define	SUNI_REGM_RACPGFC_RGFCE		0x0f
+#define	SUNI_REGX_RACPGFC	"\020\10CDDIS\7RXBYTEPRTY\12\xf\20"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TACPCTRL "TACP Control/Status"
+#define	SUNI_REGO_TACPCTRL		0x60
+#define	SUNI_REGM_TACPCTRL_FIFOE	0x80
+#define	SUNI_REGM_TACPCTRL_TSOCI	0x40
+#define	SUNI_REGM_TACPCTRL_FOVRI	0x20
+#define	SUNI_REGM_TACPCTRL_DHCS		0x10
+#define	SUNI_REGM_TACPCTRL_HCSB		0x08	/* ultra, 622 */
+#define	SUNI_REGM_TACPCTRL_HCSADD	0x04
+#define	SUNI_REGM_TACPCTRL_DSCR		0x02
+#define	SUNI_REGM_TACPCTRL_FIFORST	0x01
+#define	SUNI_REGX_TACPCTRL_LITE		"\020\10FIFOE\7TSOCI\6FOVRI\5DHCS\3HCSADD\2DSCR\1FIFORST"
+#define	SUNI_REGX_TACPCTRL_ULTRA	"\020\10FIFOE\7TSOCI\6FOVRI\5DHCS\4HCSB\3HCSADD\2DSCR\1FIFORST"
+#define	SUNI_REGX_TACPCTRL_622		"\020\10FIFOE\7TSOCI\6FOVRI\5DHCS\4HCSB\3HCSADD\2DSCR\1FIFORST"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TACPIDLEH 	"TACP Idle/Unassigned Cell Header Pattern"
+#define	SUNI_REGO_TACPIDLEH		0x61
+#define	SUNI_REGM_TACPIDLEH_GFC		0xF0
+#define	SUNI_REGS_TACPIDLEH_GFC		4
+#define	SUNI_REGM_TACPIDLEH_PTI		0x0E
+#define	SUNI_REGS_TACPIDLEH_PTI		1
+#define	SUNI_REGM_TACPIDLEH_CLP		0x01
+#define	SUNI_REGS_TACPIDLEH_CLP		0
+#define	SUNI_REGX_TACPIDLEH 	"\020\12\xF0\20GFC\12\x0E\20PTI\12\x01\20CLP"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TACPIDLEP "TACP Idle/Unassigned Cell Payload Octet Pattern"
+#define	SUNI_REGO_TACPIDLEP		0x62
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TACPFIFOC		"TACP FIFO Control"
+#define	SUNI_REGO_TACPFIFOC		0x63
+#define	SUNI_REGM_TACPFIFOC_TXPTYP	0x80
+#define	SUNI_REGM_TACPFIFOC_TXPRTYE	0x40
+#define	SUNI_REGM_TACPFIFOC_TXPRTYI	0x10
+#define	SUNI_REGM_TACPFIFOC_TXPRTYI_622	0x30
+#define	SUNI_REGS_TACPFIFOC_TXPRTYI_622	4
+#define	SUNI_REGM_TACPFIFOC_FIFODP	0x0C
+#define	SUNI_REGS_TACPFIFOC_FIFODP	2
+#define	SUNI_REGM_TACPFIFOC_TCALEVEL0	0x02
+#define	SUNI_REGM_TACPFIFOC_HCSCTLEB	0x01
+#define	SUNI_REGM_TACPFIFOC_RESERVED	0x00
+#define	SUNI_REGX_TACPFIFOC		"\020\10TXPTYP\7TXPRTYE\5TXPRTYI\12\x0C\20FIFODP\2TCALEVEL0"
+#define	SUNI_REGX_TACPFIFOC_622		"\020\10TXPTYP\7TXPRTYE\12\x30\12TXPRTYI\12\x0C\20FIFODP\2TCALEVEL0\1HCSCTLEB"
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_TACPCNT "TACP Transmit Cell Counter"
+#define	SUNI_REGO_TACPCNT		0x64	/* +65,66 */
+#define	SUNI_REGM_TACPCNT		0x07
+#define	SUNI_REGM_TACPCNT_622		0x1F
+
+/* lite, ultra */
+#define	SUNI_REGN_TACPCFG "TACP Configuration"
+#define	SUNI_REGO_TACPCFG		0x67
+#define	SUNI_REGM_TACPCFG_TGFCE		0xF0
+#define	SUNI_REGS_TACPCFG_TGFCE		4
+#define	SUNI_REGM_TACPCFG_FSEN		0x08
+#define	SUNI_REGM_TACPCFG_H4INSB	0x04
+#define	SUNI_REGM_TACPCFG_FIXBYTE	0x03
+#define	SUNI_REGS_TACPCFG_FIXBYTE	0
+#define	SUNI_REGX_TACPCFG "\020\12\xF0\20TGFCE\4FSEN\3H4INSB\12\x03\20FIXBYTE"
+
+/* 622 */
+#define	SUNI_REGN_TACPGFC	"TACP Fixed Stuff/GFC"
+#define	SUNI_REGO_TACPGFC		0x67
+#define	SUNI_REGO_TACPGFC_TGFCE		0xf0
+#define	SUNI_REGS_TACPGFC_TGFCE		4
+#define	SUNI_REGO_TACPGFC_FSEN		0x08
+#define	SUNI_REGO_TACPGFC_TXBYTEPRTY	0x04
+#define	SUNI_REGO_TACPGFC_FIXBYTE	0x03
+#define	SUNI_REGS_TACPGFC_FIXBYTE	0
+#define	SUNI_REGX_TACPGFC	"\020\12\xf0\20TGFCE\4FSEN\3TXBYTEPRTY\12\x3\20FIXBYTE"
+
+/* 622 */
+#define	SUNI_REGN_SPTBCTRL	"SPTB Control"
+#define	SUNI_REGO_SPTBCTRL		0x68
+#define	SUNI_REGO_SPTBCTRL_RRAMACC	0x40
+#define	SUNI_REGO_SPTBCTRL_RTIUIE	0x20
+#define	SUNI_REGO_SPTBCTRL_RTIMIE	0x10
+#define	SUNI_REGO_SPTBCTRL_PER5		0x08
+#define	SUNI_REGO_SPTBCTRL_TNULL	0x04
+#define	SUNI_REGO_SPTBCTRL_NOSYNC	0x02
+#define	SUNI_REGO_SPTBCTRL_LEN16	0x01
+#define	SUNI_REGX_SPTBCTRL	"\020\7RRAMACC\6RTIUIE\5RTIMIE\4PER5\3TNULL\2NOSYNC\1LEN16"
+
+/* 622 */
+#define	SUNI_REGN_SPTBPTIS	"SPTB Path Trace Identifier Status"
+#define	SUNI_REGO_SPTBPTIS		0x69
+#define	SUNI_REGM_SPTBPTIS_BUSY		0x80
+#define	SUNI_REGM_SPTBPTIS_RTIUI	0x08
+#define	SUNI_REGM_SPTBPTIS_RTIUV	0x04
+#define	SUNI_REGM_SPTBPTIS_RTIMI	0x02
+#define	SUNI_REGM_SPTBPTIS_RTIMV	0x01
+#define	SUNI_REGX_SPTBPTIS	"\020\10BUSY\4RTIUI\3RTIUV\2RTIMI\1RTIMV"
+
+/* 622 */
+#define	SUNI_REGN_SPTBIAR	"SPTB Indirect Address Register"
+#define	SUNI_REGO_SPTBIAR		0x6A
+#define	SUNI_REGM_SPTBIAR_RWB		0x80
+#define	SUNI_REGM_SPTBIAR_A		0x7f
+#define	SUNI_REGX_SPTBIAR	"\020\10RWB\12\x7f\20A"
+
+/* 622 */
+#define	SUNI_REGN_SPTBIDR	"SPTB Indirect Data Register"
+#define	SUNI_REGO_SPTBIDR		0x6B
+
+/* 622 */
+#define	SUNI_REGN_SPTBEPSL	"SPTB Expected Path Signal Label"
+#define	SUNI_REGO_SPTBEPSL		0x6C
+
+/* 622 */
+#define	SUNI_REGN_SPTBPSLS	"SPTB Path Signal Label Status"
+#define	SUNI_REGO_SPTBPSLS		0x6D
+#define	SUNI_REGM_SPTBPSLS_RPSLUIE	0x80
+#define	SUNI_REGM_SPTBPSLS_RPSLMIE	0x40
+#define	SUNI_REGM_SPTBPSLS_RPSLUI	0x08
+#define	SUNI_REGM_SPTBPSLS_RPSLUV	0x04
+#define	SUNI_REGM_SPTBPSLS_RPSLMI	0x02
+#define	SUNI_REGM_SPTBPSLS_RPSLMV	0x01
+#define	SUNI_REGX_SPTBPSLS	"\020\10RPSLUIE\7RPSLMIE\4RPSLUI\3RPSLUV\2RPSLMI\1RPSLMV"
+
+/* ultra */
+#define	SUNI_REGN_POPCCTRL "POPC Control"
+#define	SUNI_REGO_POPCCTRL		0x68
+#define	SUNI_REGM_POPCCTRL_PDAT		0xC0
+#define	SUNI_REGS_POPCCTRL_PDAT		6
+#define	SUNI_REGM_POPCCTRL_TOGGLE	0x30
+#define	SUNI_REGS_POPCCTRL_TOGGLE	4
+#define	SUNI_REGM_POPCCTRL_TRAFFIC	0x02
+#define	SUNI_REGM_POPCCTRL_ALARM	0x01
+#define	SUNI_REGX_POPCCTRL "\020\12\xC0\20PDAT\12\x30\20TOGGLE\2TRAFFIC\1ALARM"
+
+/* ultra */
+#define	SUNI_REGN_POPCSTROBE0 "POPC Strobe Rate 0"
+#define	SUNI_REGO_POPCSTROBE0		0x69
+
+/* ultra */
+#define	SUNI_REGN_POPCSTROBE1 "POPC Strobe Rate 1"
+#define	SUNI_REGO_POPCSTROBE1		0x6A
+
+/* 622 */
+#define	SUNI_REGN_BERMCTRL	"BERM Control"
+#define	SUNI_REGO_BERMCTRL		0x70
+#define	SUNI_REGM_BERMCTRL_BERTEN	0x80
+#define	SUNI_REGM_BERMCTRL_BERIE	0x01
+#define	SUNI_REGX_BERMCTRL	"\020\10BERTEN\1BERIE"
+
+/* 622 */
+#define	SUNI_REGN_BERMINT	"BERM Interrupt"
+#define	SUNI_REGO_BERMINT		0x71
+#define	SUNI_REGM_BERMINT_TST		0xf0
+#define	SUNI_REGS_BERMINT_TST		4
+#define	SUNI_REGM_BERMINT_BERI		0x01
+#define	SUNI_REGX_BERMINT	"\020\12\xf0\20BERM_TST\1BERI"
+
+/* 622 */
+#define	SUNI_REGN_BERMLAP	"BERM Line BIP Accumulation Period"
+#define	SUNI_REGO_BERMLAP		0x72	/* +73 */
+
+/* 622 */
+#define	SUNI_REGN_BERMLT	"BERM Line BIP Threshold"
+#define	SUNI_REGO_BERMLT		0x74	/* +75 */
+
+/* lite, ultra, 622 */
+#define	SUNI_REGN_MTEST "Master Test"
+#define	SUNI_REGO_MTEST			0x80
+#define	SUNI_REGM_MTEST_DS27_53_622	0x80
+#define	SUNI_REGM_MTEST_BYPASS_ULTRA	0x40
+#define	SUNI_REGM_MTEST_PMCATST_ULTRA	0x20
+#define	SUNI_REGM_MTEST_PMCTST		0x10
+#define	SUNI_REGM_MTEST_DBCTRL		0x08
+#define	SUNI_REGM_MTEST_IOTST		0x04
+#define	SUNI_REGM_MTEST_HIZDATA		0x02
+#define	SUNI_REGM_MTEST_HIZIO		0x01
+#define	SUNI_REGX_MTEST_LITE	"\020\5PMCTST\4DBCTRL\3IOTST\2HIZDATA\1HIZIO"
+#define	SUNI_REGX_MTEST_ULTRA	"\020\7BYPASS\6PMCATST\5PMCTST\4DBCTRL\3IOTST\2HIZDATA\1HIZIO"
+#define	SUNI_REGX_MTEST_622	"\020\10DS27_53\5PMCTST\4DBCTRL\3IOTST\2HIZDATA\1HIZIO"
+
+/*
+ * Printing support
+ */
+#define	SUNI_PRINT_LITE							\
+	{ /* 00 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MRESET, 			\
+	  SUNI_REGN_MRESET,	SUNI_REGX_MRESET_LITE },		\
+	{ /* 01 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MCONFIG,			\
+	  SUNI_REGN_MCONFIG,	SUNI_REGX_MCONFIG_LITE },		\
+	{ /* 02 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MISTATUS,			\
+	  SUNI_REGN_MISTATUS,	SUNI_REGX_MISTATUS_LITE },		\
+	  /* 03 unused */						\
+	{ /* 04 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MCLKM,			\
+	  SUNI_REGN_MCLKM,	SUNI_REGX_MCLKM_LITE },			\
+	{ /* 05 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MCTRL,			\
+	  SUNI_REGN_MCTRL,	SUNI_REGX_MCTRL_LITE },			\
+	{ /* 06 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_CLKSYN,			\
+	  SUNI_REGN_CLKSYN,	SUNI_REGX_CLKSYN_LITE },		\
+	{ /* 07 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_CLKREC_LITE,			\
+	  SUNI_REGN_CLKREC,	SUNI_REGX_CLKREC_LITE },		\
+	  /* 08-0F unused */						\
+	{ /* 10 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RSOPCIE,			\
+	  SUNI_REGN_RSOPCIE,	SUNI_REGX_RSOPCIE },			\
+	{ /* 11 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RSOPSIS,			\
+	  SUNI_REGN_RSOPSIS,	SUNI_REGX_RSOPSIS },			\
+	{ /* 12, 13 */							\
+	  UTP_REGT_INT16,	SUNI_REGO_RSOP_BIP8,			\
+	  SUNI_REGN_RSOP_BIP8,	NULL },					\
+	{ /* 14 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TSOPCTRL,			\
+	  SUNI_REGN_TSOPCTRL,	SUNI_REGX_TSOPCTRL },			\
+	{ /* 15 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TSOPDIAG,			\
+	  SUNI_REGN_TSOPDIAG,	SUNI_REGX_TSOPDIAG },			\
+	  /* 16-17 unused */						\
+	{ /* 18 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RLOPCTRL,			\
+	  SUNI_REGN_RLOPCTRL,	SUNI_REGX_RLOPCTRL },			\
+	{ /* 19 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RLOPINTR,			\
+	  SUNI_REGN_RLOPINTR,	SUNI_REGX_RLOPINTR },			\
+	{ /* 1A, 1B, 1C */						\
+	  UTP_REGT_INT20,	SUNI_REGO_RLOPBIP8_24,			\
+	  SUNI_REGN_RLOPBIP8_24, NULL },				\
+	{ /* 1D, 1E, 1F */						\
+	  UTP_REGT_INT20,	SUNI_REGO_RLOPFEBE,			\
+	  SUNI_REGN_RLOPFEBE,	NULL },					\
+	{ /* 20 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TLOPCTRL,			\
+	  SUNI_REGN_TLOPCTRL,	SUNI_REGX_TLOPCTRL },			\
+	{ /* 21 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TLOPDIAG,			\
+	  SUNI_REGN_TLOPDIAG,	SUNI_REGX_TLOPDIAG },			\
+	  /* 22-2F unused */						\
+	{ /* 30 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPCTRL,			\
+	  SUNI_REGN_RPOPCTRL,	SUNI_REGX_RPOPCTRL },			\
+	{ /* 31 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPISTAT,			\
+	  SUNI_REGN_RPOPISTAT,	SUNI_REGX_RPOPISTAT },			\
+	  /* 32 unused */						\
+	{ /* 33 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPIEN,			\
+	  SUNI_REGN_RPOPIEN,	SUNI_REGX_RPOPIEN },			\
+	  /* 34-36 unused */						\
+	{ /* 37 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RPOPPSL,			\
+	  SUNI_REGN_RPOPPSL,	NULL },					\
+	{ /* 38, 39 */							\
+	  UTP_REGT_INT16,	SUNI_REGO_RPOPBIP8,			\
+	  SUNI_REGN_RPOPBIP8,	NULL },					\
+	{ /* 3A, 3B */							\
+	  UTP_REGT_INT16,	SUNI_REGO_RPOPFEBE,			\
+	  SUNI_REGN_RPOPFEBE,	NULL },					\
+	  /* 3C unused */						\
+	{ /* 3D */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPBIP8CFG,			\
+	  SUNI_REGN_RPOPBIP8CFG, SUNI_REGX_RPOPBIP8CFG },		\
+	  /* 3E-3F unused */						\
+	{ /* 40 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TPOPCTRL,			\
+	  SUNI_REGN_TPOPCTRL,	SUNI_REGX_TPOPCTRL },			\
+	{ /* 41 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TPOPPTRC,			\
+	  SUNI_REGN_TPOPPTRC,	SUNI_REGX_TPOPPTRC },			\
+	  /* 42-44 unused */						\
+	{ /* 45, 46 */							\
+	  UTP_REGT_INT10BITS,	SUNI_REGO_TPOPAPTR,			\
+	  SUNI_REGN_TPOPAPTR,	SUNI_REGX_TPOPAPTR },			\
+	  /* 47 unused */						\
+	{ /* 48 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TPOPPSL,			\
+	  SUNI_REGN_TPOPPSL,	NULL },					\
+	{ /* 49 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TPOPSTATUS,			\
+	  SUNI_REGN_TPOPSTATUS,	SUNI_REGX_TPOPSTATUS },			\
+	  /* 4A-4F unused */						\
+	{ /* 50 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPCTRL,			\
+	  SUNI_REGN_RACPCTRL,	SUNI_REGX_RACPCTRL },			\
+	{ /* 51 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPINTR,			\
+	  SUNI_REGN_RACPINTR,	SUNI_REGX_RACPINTR },			\
+	{ /* 52 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPPATTERN,			\
+	  SUNI_REGN_RACPPATTERN, SUNI_REGX_RACPPATTERN },		\
+	{ /* 53 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPMASK,			\
+	  SUNI_REGN_RACPMASK,	SUNI_REGX_RACPMASK },			\
+	{ /* 54 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RACPCHCS,			\
+	  SUNI_REGN_RACPCHCS,	NULL },					\
+	{ /* 55 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RACPUHCS,			\
+	  SUNI_REGN_RACPUHCS,	NULL },					\
+	{ /* 56, 57, 58 */						\
+	  UTP_REGT_INT19,	SUNI_REGO_RACPCNT,			\
+	  SUNI_REGN_RACPCNT,	NULL },					\
+	{ /* 59 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPCFG,			\
+	  SUNI_REGN_RACPCFG,	SUNI_REGX_RACPCFG },			\
+	  /* 5A-5F unused */						\
+	{ /* 60 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPCTRL,			\
+	  SUNI_REGN_TACPCTRL,	SUNI_REGX_TACPCTRL_LITE },		\
+	{ /* 61 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPIDLEH,			\
+	  SUNI_REGN_TACPIDLEH,	SUNI_REGX_TACPIDLEH },			\
+	{ /* 62 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TACPIDLEP,			\
+	  SUNI_REGN_TACPIDLEP,	NULL },					\
+	{ /* 63 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPFIFOC,			\
+	  SUNI_REGN_TACPFIFOC,	SUNI_REGX_TACPFIFOC },			\
+	{ /* 64, 65, 66 */						\
+	  UTP_REGT_INT19,	SUNI_REGO_TACPCNT,			\
+	  SUNI_REGN_TACPCNT,	NULL },					\
+	{ /* 67 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPGFC,			\
+	  SUNI_REGN_TACPGFC,	SUNI_REGX_TACPGFC },			\
+	  /* 68-7f unused */						\
+	{ /* 80 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MTEST,			\
+	  SUNI_REGN_MTEST,	SUNI_REGX_MTEST_LITE }
+
+#define	SUNI_PRINT_ULTRA						\
+	{ /* 00 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MRESET, 			\
+	  SUNI_REGN_MRESET,	SUNI_REGX_MRESET_ULTRA },		\
+	{ /* 01 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MCONFIG,			\
+	  SUNI_REGN_MCONFIG,	SUNI_REGX_MCONFIG_ULTRA },		\
+	{ /* 02 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MISTATUS,			\
+	  SUNI_REGN_MISTATUS,	SUNI_REGX_MISTATUS_ULTRA },		\
+	{ /* 03 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MMCTRL,			\
+	  SUNI_REGN_MMCTRL,	SUNI_REGX_MMCTRL },			\
+	{ /* 04 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MCLKM,			\
+	  SUNI_REGN_MCLKM,	SUNI_REGX_MCLKM_ULTRA },		\
+	{ /* 05 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MCTRL,			\
+	  SUNI_REGN_MCTRL,	SUNI_REGX_MCTRL_ULTRA },		\
+	{ /* 06 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_CLKSYN,			\
+	  SUNI_REGN_CLKSYN,	SUNI_REGX_CLKSYN_ULTRA },		\
+	  /* 07 unused */						\
+	{ /* 08 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_CLKREC_ULTRA,			\
+	  SUNI_REGN_CLKREC,	SUNI_REGX_CLKREC_ULTRA },		\
+	{ /* 09 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_CLKRECCFG,			\
+	  SUNI_REGN_CLKRECCFG,	SUNI_REGX_CLKRECCFG },			\
+	{ /* 0A */							\
+	  UTP_REGT_BITS,	SUNI_REGO_LTXCFG1,			\
+	  SUNI_REGN_LTXCFG1,	SUNI_REGX_LTXCFG1 },			\
+	{ /* 0B */							\
+	  UTP_REGT_BITS,	SUNI_REGO_LTXCFG2,			\
+	  SUNI_REGN_LTXCFG2,	SUNI_REGX_LTXCFG2 },			\
+	{ /* 0C */							\
+	  UTP_REGT_BITS,	SUNI_REGO_LRXCFG,			\
+	  SUNI_REGN_LRXCFG,	SUNI_REGX_LRXCFG },			\
+	  /* 0D-0F unused */						\
+	{ /* 10 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RSOPCIE,			\
+	  SUNI_REGN_RSOPCIE,	SUNI_REGX_RSOPCIE },			\
+	{ /* 11 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RSOPSIS,			\
+	  SUNI_REGN_RSOPSIS,	SUNI_REGX_RSOPSIS },			\
+	{ /* 12, 13 */							\
+	  UTP_REGT_INT16,	SUNI_REGO_RSOP_BIP8,			\
+	  SUNI_REGN_RSOP_BIP8,	NULL },					\
+	{ /* 14 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TSOPCTRL,			\
+	  SUNI_REGN_TSOPCTRL,	SUNI_REGX_TSOPCTRL },			\
+	{ /* 15 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TSOPDIAG,			\
+	  SUNI_REGN_TSOPDIAG,	SUNI_REGX_TSOPDIAG },			\
+	  /* 16-17 unused */						\
+	{ /* 18 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RLOPCTRL,			\
+	  SUNI_REGN_RLOPCTRL,	SUNI_REGX_RLOPCTRL },			\
+	{ /* 19 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RLOPINTR,			\
+	  SUNI_REGN_RLOPINTR,	SUNI_REGX_RLOPINTR },			\
+	{ /* 1A, 1B, 1C */						\
+	  UTP_REGT_INT20,	SUNI_REGO_RLOPBIP8_24,			\
+	  SUNI_REGN_RLOPBIP8_24, NULL },				\
+	{ /* 1D, 1E, 1F */						\
+	  UTP_REGT_INT20,	SUNI_REGO_RLOPFEBE,			\
+	  SUNI_REGN_RLOPFEBE,	NULL },					\
+	{ /* 20 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TLOPCTRL,			\
+	  SUNI_REGN_TLOPCTRL,	SUNI_REGX_TLOPCTRL },			\
+	{ /* 21 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TLOPDIAG,			\
+	  SUNI_REGN_TLOPDIAG,	SUNI_REGX_TLOPDIAG },			\
+	  /* 22-2F unused */						\
+	{ /* 30 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPCTRL,			\
+	  SUNI_REGN_RPOPCTRL,	SUNI_REGX_RPOPCTRL },			\
+	{ /* 31 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPISTAT,			\
+	  SUNI_REGN_RPOPISTAT,	SUNI_REGX_RPOPISTAT },			\
+	  /* 32 unused */						\
+	{ /* 33 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPIEN,			\
+	  SUNI_REGN_RPOPIEN,	SUNI_REGX_RPOPIEN },			\
+	  /* 34-36 unused */						\
+	{ /* 37 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RPOPPSL,			\
+	  SUNI_REGN_RPOPPSL,	NULL },					\
+	{ /* 38, 39 */							\
+	  UTP_REGT_INT16,	SUNI_REGO_RPOPBIP8,			\
+	  SUNI_REGN_RPOPBIP8,	NULL },					\
+	{ /* 3A, 3B */							\
+	  UTP_REGT_INT16,	SUNI_REGO_RPOPFEBE,			\
+	  SUNI_REGN_RPOPFEBE,	NULL },					\
+	  /* 3C unused */						\
+	{ /* 3D */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPBIP8CFG,			\
+	  SUNI_REGN_RPOPBIP8CFG, SUNI_REGX_RPOPBIP8CFG },		\
+	  /* 3E-3F unused */						\
+	{ /* 40 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TPOPCTRL,			\
+	  SUNI_REGN_TPOPCTRL,	SUNI_REGX_TPOPCTRL },			\
+	{ /* 41 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TPOPPTRC,			\
+	  SUNI_REGN_TPOPPTRC,	SUNI_REGX_TPOPPTRC },			\
+	  /* 42-44 unused */						\
+	{ /* 45, 46 */							\
+	  UTP_REGT_INT10BITS,	SUNI_REGO_TPOPAPTR,			\
+	  SUNI_REGN_TPOPAPTR,	SUNI_REGX_TPOPAPTR },			\
+	  /* 47 unused */						\
+	{ /* 48 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TPOPPSL,			\
+	  SUNI_REGN_TPOPPSL,	NULL },					\
+	{ /* 49 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TPOPSTATUS,			\
+	  SUNI_REGN_TPOPSTATUS,	SUNI_REGX_TPOPSTATUS },			\
+	  /* 4A-4F unused */						\
+	{ /* 50 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPCTRL,			\
+	  SUNI_REGN_RACPCTRL,	SUNI_REGX_RACPCTRL },			\
+	{ /* 51 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPINTR,			\
+	  SUNI_REGN_RACPINTR,	SUNI_REGX_RACPINTR },			\
+	{ /* 52 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPPATTERN,			\
+	  SUNI_REGN_RACPPATTERN, SUNI_REGX_RACPPATTERN },		\
+	{ /* 53 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPMASK,			\
+	  SUNI_REGN_RACPMASK,	SUNI_REGX_RACPMASK },			\
+	{ /* 54 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RACPCHCS,			\
+	  SUNI_REGN_RACPCHCS,	NULL },					\
+	{ /* 55 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RACPUHCS,			\
+	  SUNI_REGN_RACPUHCS,	NULL },					\
+	{ /* 56, 57, 58 */						\
+	  UTP_REGT_INT19,	SUNI_REGO_RACPCNT,			\
+	  SUNI_REGN_RACPCNT,	NULL },					\
+	{ /* 59 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPCFG,			\
+	  SUNI_REGN_RACPCFG,	SUNI_REGX_RACPCFG },			\
+	  /* 5A-5F unused */						\
+	{ /* 60 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPCTRL,			\
+	  SUNI_REGN_TACPCTRL,	SUNI_REGX_TACPCTRL_ULTRA },		\
+	{ /* 61 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPIDLEH,			\
+	  SUNI_REGN_TACPIDLEH,	SUNI_REGX_TACPIDLEH },			\
+	{ /* 62 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TACPIDLEP,			\
+	  SUNI_REGN_TACPIDLEP,	NULL },					\
+	{ /* 63 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPFIFOC,			\
+	  SUNI_REGN_TACPFIFOC,	SUNI_REGX_TACPFIFOC },			\
+	{ /* 64, 65, 66 */						\
+	  UTP_REGT_INT19,	SUNI_REGO_TACPCNT,			\
+	  SUNI_REGN_TACPCNT,	NULL },					\
+	{ /* 67 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPGFC,			\
+	  SUNI_REGN_TACPGFC,	SUNI_REGX_TACPGFC },			\
+	{ /* 68 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_POPCCTRL,			\
+	  SUNI_REGN_POPCCTRL,	SUNI_REGX_POPCCTRL },			\
+	{ /* 69 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_POPCSTROBE0,			\
+	  SUNI_REGN_POPCSTROBE0, NULL },				\
+	{ /* 6A */							\
+	  UTP_REGT_INT8,	SUNI_REGO_POPCSTROBE1,			\
+	  SUNI_REGN_POPCSTROBE1, NULL },				\
+	  /* 6B-7f unused */						\
+	{ /* 80 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MTEST,			\
+	  SUNI_REGN_MTEST,	SUNI_REGX_MTEST_ULTRA }
+
+#define	SUNI_PRINT_622 							\
+	{ /* 00 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MRESET, 			\
+	  SUNI_REGN_MRESET,	SUNI_REGX_MRESET_622 },			\
+	{ /* 01 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MCONFIG,			\
+	  SUNI_REGN_MCONFIG,	SUNI_REGX_MCONFIG_622 },		\
+	{ /* 02 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MISTATUS,			\
+	  SUNI_REGN_MISTATUS,	SUNI_REGX_MISTATUS_622 },		\
+	{ /* 03 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_PISO, 			\
+	  SUNI_REGN_PISO,	SUNI_REGX_PISO },			\
+	{ /* 04 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MCTRLM, 			\
+	  SUNI_REGN_MCTRLM,	SUNI_REGX_MCTRLM },			\
+	{ /* 05 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MALARM,			\
+	  SUNI_REGN_MALARM,	SUNI_REGX_MALARM },			\
+	{ /* 06 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_POUT,				\
+	  SUNI_REGN_POUT,	SUNI_REGX_POUT },			\
+	{ /* 07 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_PIN,				\
+	  SUNI_REGN_PIN,	NULL },					\
+	{ /* 08 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_PINV,				\
+	  SUNI_REGN_PINV,	SUNI_REGX_PINV },			\
+	{ /* 09 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_PINE,				\
+	  SUNI_REGN_PINE,	NULL },					\
+	{ /* 0A */							\
+	  UTP_REGT_INT8,	SUNI_REGO_XC1,				\
+	  SUNI_REGN_XC1,	NULL },					\
+	{ /* 0B */							\
+	  UTP_REGT_BITS,	SUNI_REGO_APSCS,			\
+	  SUNI_REGN_APSCS,	SUNI_REGX_APSCS },			\
+	{ /* 0C */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RK1,				\
+	  SUNI_REGN_RK1,	NULL },					\
+	{ /* 0D */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RK2,				\
+	  SUNI_REGN_RK2,	NULL },					\
+	{ /* 0E */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RZ1,				\
+	  SUNI_REGN_RZ1,	NULL },					\
+	{ /* 0F */							\
+	  UTP_REGT_INT8,	SUNI_REGO_XZ1,				\
+	  SUNI_REGN_XZ1,	NULL },					\
+	{ /* 10 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RSOPCIE,			\
+	  SUNI_REGN_RSOPCIE,	SUNI_REGX_RSOPCIE_622 },		\
+	{ /* 11 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RSOPSIS,			\
+	  SUNI_REGN_RSOPSIS,	SUNI_REGX_RSOPSIS },			\
+	{ /* 12, 13 */							\
+	  UTP_REGT_INT16,	SUNI_REGO_RSOP_BIP8,			\
+	  SUNI_REGN_RSOP_BIP8,	NULL },					\
+	{ /* 14 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TSOPCTRL,			\
+	  SUNI_REGN_TSOPCTRL,	SUNI_REGX_TSOPCTRL },			\
+	{ /* 15 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TSOPDIAG,			\
+	  SUNI_REGN_TSOPDIAG,	SUNI_REGX_TSOPDIAG },			\
+	  /* 16-17 unused */						\
+	{ /* 18 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RLOPCTRL,			\
+	  SUNI_REGN_RLOPCTRL,	SUNI_REGX_RLOPCTRL_622 },		\
+	{ /* 19 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RLOPINTR,			\
+	  SUNI_REGN_RLOPINTR,	SUNI_REGX_RLOPINTR },			\
+	{ /* 1A, 1B, 1C */						\
+	  UTP_REGT_INT20,	SUNI_REGO_RLOPBIP8_24_96,		\
+	  SUNI_REGN_RLOPBIP8_24_96, NULL },				\
+	{ /* 1D, 1E, 1F */						\
+	  UTP_REGT_INT20,	SUNI_REGO_RLOPFEBE,			\
+	  SUNI_REGN_RLOPFEBE,	NULL },					\
+	{ /* 20 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TLOPCTRL,			\
+	  SUNI_REGN_TLOPCTRL,	SUNI_REGX_TLOPCTRL_622 },		\
+	{ /* 21 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TLOPDIAG,			\
+	  SUNI_REGN_TLOPDIAG,	SUNI_REGX_TLOPDIAG },			\
+	{ /* 22 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TLOP_XK1,			\
+	  SUNI_REGN_TLOP_XK1,	NULL },					\
+	{ /* 23 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TLOP_XK2,			\
+	  SUNI_REGN_TLOP_XK2,	NULL },					\
+	  /* 24-27 unused */						\
+	{ /* 28 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_SSTBCTRL,			\
+	  SUNI_REGN_SSTBCTRL,	SUNI_REGX_SSTBCTRL },			\
+	{ /* 29 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_SSTBSTIS,			\
+	  SUNI_REGN_SSTBSTIS,	SUNI_REGX_SSTBSTIS },			\
+	{ /* 2A */							\
+	  UTP_REGT_BITS,	SUNI_REGO_SSTBIAR,			\
+	  SUNI_REGN_SSTBIAR,	SUNI_REGX_SSTBIAR },			\
+	{ /* 2B */							\
+	  UTP_REGT_INT8,	SUNI_REGO_SSTBIDR,			\
+	  SUNI_REGN_SSTBIDR,	NULL },					\
+	  /* 2C unused (see chip errata) */				\
+	{ /* 2D */							\
+	  UTP_REGT_BITS,	SUNI_REGO_SSTBCSMS,			\
+	  SUNI_REGN_SSTBCSMS,	SUNI_REGX_SSTBCSMS },			\
+	  /* 2E-2F unused */						\
+	{ /* 30 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPCTRL,			\
+	  SUNI_REGN_RPOPCTRL,	SUNI_REGX_RPOPCTRL_622 },		\
+	{ /* 31 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPISTAT,			\
+	  SUNI_REGN_RPOPISTAT,	SUNI_REGX_RPOPISTAT },			\
+	{ /* 32 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPPIS,			\
+	  SUNI_REGN_RPOPPIS,	SUNI_REGX_RPOPPIS },			\
+	{ /* 33 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPIEN,			\
+	  SUNI_REGN_RPOPIEN,	SUNI_REGX_RPOPIEN },			\
+	{ /* 34 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPPIE,			\
+	  SUNI_REGN_RPOPPIE,	SUNI_REGX_RPOPPIE },			\
+	{ /* 35, 36 */							\
+	  UTP_REGT_INT10BITS,	SUNI_REGO_RPOPPTR,			\
+	  SUNI_REGN_RPOPPTR,	SUNI_REGX_RPOPPTR },			\
+	{ /* 37 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_RPOPPSL,			\
+	  SUNI_REGN_RPOPPSL,	NULL },					\
+	{ /* 38, 39 */							\
+	  UTP_REGT_INT16,	SUNI_REGO_RPOPBIP8,			\
+	  SUNI_REGN_RPOPBIP8,	NULL },					\
+	{ /* 3A, 3B */							\
+	  UTP_REGT_INT16,	SUNI_REGO_RPOPFEBE,			\
+	  SUNI_REGN_RPOPFEBE,	NULL },					\
+	{ /* 3C */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPRDI,			\
+	  SUNI_REGN_RPOPRDI,	SUNI_REGX_RPOPRDI },			\
+	{ /* 3D */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RPOPRING,			\
+	  SUNI_REGN_RPOPRING,	SUNI_REGX_RPOPRING },			\
+	  /* 3E-3F unused */						\
+	{ /* 40 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TPOPCTRL,			\
+	  SUNI_REGN_TPOPCTRL,	SUNI_REGX_TPOPCTRL_622 },		\
+	{ /* 41 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TPOPPTRC,			\
+	  SUNI_REGN_TPOPPTRC,	SUNI_REGX_TPOPPTRC },			\
+	  /* 42 unused */						\
+	{ /* 43, 44 */							\
+	  UTP_REGT_INT10BITS,	SUNI_REGO_TPOPCP,			\
+	  SUNI_REGN_TPOPCP,	SUNI_REGX_TPOPCP },			\
+	{ /* 45, 46 */							\
+	  UTP_REGT_INT10BITS,	SUNI_REGO_TPOPAPTR,			\
+	  SUNI_REGN_TPOPAPTR,	SUNI_REGX_TPOPAPTR },			\
+	{ /* 47 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TPOPPT,			\
+	  SUNI_REGN_TPOPPT,	NULL },					\
+	{ /* 48 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TPOPPSL,			\
+	  SUNI_REGN_TPOPPSL,	NULL },					\
+	{ /* 49 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TPOPSTATUS,			\
+	  SUNI_REGN_TPOPSTATUS,	SUNI_REGX_TPOPSTATUS },			\
+	{ /* 4A */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TPOPPUC,			\
+	  SUNI_REGN_TPOPPUC,	NULL },					\
+	{ /* 4B */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TPOPPG1,			\
+	  SUNI_REGN_TPOPPG1,	NULL },					\
+	{ /* 4C */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TPOPPG2,			\
+	  SUNI_REGN_TPOPPG2,	NULL },					\
+	{ /* 4D */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TPOPPG3,			\
+	  SUNI_REGN_TPOPPG3,	NULL },					\
+	  /* 4E-4F unused */						\
+	{ /* 50 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPCTRL,			\
+	  SUNI_REGN_RACPCTRL,	SUNI_REGX_RACPCTRL_622 },		\
+	{ /* 51 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPIS,			\
+	  SUNI_REGN_RACPIS,	SUNI_REGX_RACPIS },			\
+	{ /* 52 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPIEC,			\
+	  SUNI_REGN_RACPIEC,	SUNI_REGX_RACPIEC },			\
+	{ /* 53 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPPATTERN_622,		\
+	  SUNI_REGN_RACPPATTERN, SUNI_REGX_RACPPATTERN },		\
+	{ /* 54 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPMASK_622,			\
+	  SUNI_REGN_RACPMASK,	SUNI_REGX_RACPMASK },			\
+	{ /* 55, 56 */							\
+	  UTP_REGT_INT12,	SUNI_REGO_RACPCHCS_622,			\
+	  SUNI_REGN_RACPCHCS,	NULL },					\
+	{ /* 57, 58 */							\
+	  UTP_REGT_INT12,	SUNI_REGO_RACPUHCS_622,			\
+	  SUNI_REGN_RACPUHCS,	NULL },					\
+	{ /* 59, 5A, 5B */						\
+	  UTP_REGT_INT21,	SUNI_REGO_RACPCNT_622,			\
+	  SUNI_REGN_RACPCNT,	NULL },					\
+	{ /* 5C */							\
+	  UTP_REGT_BITS,	SUNI_REGO_RACPGFC,			\
+	  SUNI_REGN_RACPGFC,	SUNI_REGX_RACPGFC },			\
+	  /* 5D-5F unused */						\
+	{ /* 60 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPCTRL,			\
+	  SUNI_REGN_TACPCTRL,	SUNI_REGX_TACPCTRL_622 },		\
+	{ /* 61 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPIDLEH,			\
+	  SUNI_REGN_TACPIDLEH,	SUNI_REGX_TACPIDLEH },			\
+	{ /* 62 */							\
+	  UTP_REGT_INT8,	SUNI_REGO_TACPIDLEP,			\
+	  SUNI_REGN_TACPIDLEP,	NULL },					\
+	{ /* 63 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPFIFOC,			\
+	  SUNI_REGN_TACPFIFOC,	SUNI_REGX_TACPFIFOC_622 },		\
+	{ /* 64, 65, 66 */						\
+	  UTP_REGT_INT21,	SUNI_REGO_TACPCNT,			\
+	  SUNI_REGN_TACPCNT,	NULL },					\
+	{ /* 67 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_TACPGFC,			\
+	  SUNI_REGN_TACPGFC,	SUNI_REGX_TACPGFC },			\
+	{ /* 68 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_SPTBCTRL,			\
+	  SUNI_REGN_SPTBCTRL,	SUNI_REGX_SPTBCTRL },			\
+	{ /* 69 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_SPTBPTIS,			\
+	  SUNI_REGN_SPTBPTIS,	SUNI_REGX_SPTBPTIS },			\
+	{ /* 6A */							\
+	  UTP_REGT_BITS,	SUNI_REGO_SPTBIAR,			\
+	  SUNI_REGN_SPTBIAR,	SUNI_REGX_SPTBIAR },			\
+	{ /* 6B */							\
+	  UTP_REGT_INT8,	SUNI_REGO_SPTBIDR,			\
+	  SUNI_REGN_SPTBIDR,	NULL },					\
+	{ /* 6C */							\
+	  UTP_REGT_INT8,	SUNI_REGO_SPTBEPSL,			\
+	  SUNI_REGN_SPTBEPSL,	NULL },					\
+	{ /* 6D */							\
+	  UTP_REGT_BITS,	SUNI_REGO_SPTBPSLS,			\
+	  SUNI_REGN_SPTBPSLS,	SUNI_REGX_SPTBPSLS },			\
+	  /* 6E-6F unused */						\
+	{ /* 70 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_BERMCTRL,			\
+	  SUNI_REGN_BERMCTRL,	SUNI_REGX_BERMCTRL },			\
+	{ /* 71 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_BERMINT,			\
+	  SUNI_REGN_BERMINT,	SUNI_REGX_BERMINT },			\
+	{ /* 72, 73 */							\
+	  UTP_REGT_INT16,	SUNI_REGO_BERMLAP,			\
+	  SUNI_REGN_BERMLAP,	NULL },					\
+	{ /* 74, 75 */							\
+	  UTP_REGT_INT16,	SUNI_REGO_BERMLT,			\
+	  SUNI_REGN_BERMLT,	NULL },					\
+	  /* 76-7f unused */						\
+	{ /* 80 */							\
+	  UTP_REGT_BITS,	SUNI_REGO_MTEST,			\
+	  SUNI_REGN_MTEST,	SUNI_REGX_MTEST_622 }
+
+#endif /* _DEV_UTOPIA_SUNI_H */
diff --git a/sys/dev/utopia/utopia.c b/sys/dev/utopia/utopia.c
new file mode 100644
index 000000000000..ce63186dc0c3
--- /dev/null
+++ b/sys/dev/utopia/utopia.c
@@ -0,0 +1,1082 @@
+/*
+ * Copyright (c) 2003
+ *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * 	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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/proc.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/sysctl.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_media.h>
+#include <net/if_atm.h>
+
+#include <dev/utopia/suni.h>
+#include <dev/utopia/idtphy.h>
+#include <dev/utopia/utopia.h>
+
+#define READREGS(UTOPIA, REG, VALP, NP)				\
+    (UTOPIA)->methods->readregs((UTOPIA)->ifatm, REG, VALP, NP)
+#define WRITEREG(UTOPIA, REG, MASK, VAL)			\
+    (UTOPIA)->methods->writereg((UTOPIA)->ifatm, REG, MASK, VAL)
+
+/*
+ * Global list of all registered interfaces
+ */
+static struct mtx utopia_list_mtx;
+static LIST_HEAD(, utopia) utopia_list = LIST_HEAD_INITIALIZER(utopia_list);
+
+#define UTP_RLOCK_LIST()	mtx_lock(&utopia_list_mtx)
+#define UTP_RUNLOCK_LIST()	mtx_unlock(&utopia_list_mtx)
+#define UTP_WLOCK_LIST()	mtx_lock(&utopia_list_mtx)
+#define UTP_WUNLOCK_LIST()	mtx_unlock(&utopia_list_mtx)
+
+#define UTP_LOCK(UTP)		mtx_lock((UTP)->lock)
+#define UTP_UNLOCK(UTP)		mtx_unlock((UTP)->lock)
+#define UTP_LOCK_ASSERT(UTP)	mtx_assert((UTP)->lock, MA_OWNED)
+
+static struct proc *utopia_kproc;
+
+static void utopia_dump(struct utopia *) __unused;
+
+/*
+ * Debugging - dump all registers.
+ */
+static void
+utopia_dump(struct utopia *utp)
+{
+	uint8_t regs[256];
+	u_int n = 256, i;
+	int err;
+
+	if ((err = READREGS(utp, SUNI_REGO_MRESET, regs, &n)) != 0) {
+		printf("SUNI read error %d\n", err);
+		return;
+	}
+	for (i = 0; i < n; i++) {
+		if (i % 16 == 0)
+			printf("%02x:", i);
+		if (i % 16 == 8)
+			printf(" ");
+		printf(" %02x", regs[i]);
+		if (i % 16 == 15)
+			printf("\n");
+	}
+	if (i % 16 != 0)
+		printf("\n");
+}
+
+/*
+ * Update the carrier status
+ */
+static void
+utopia_check_carrier(struct utopia *utp, u_int carr_ok)
+{
+	int old;
+
+	old = utp->carrier;
+	if (carr_ok) {
+		/* carrier */
+		utp->carrier = UTP_CARR_OK;
+		if (old != UTP_CARR_OK) {
+			if_printf(&utp->ifatm->ifnet, "carrier detected\n");
+		}
+	} else {
+		/* no carrier */
+		utp->carrier = UTP_CARR_LOST;
+		if (old == UTP_CARR_OK) {
+			if_printf(&utp->ifatm->ifnet, "carrier lost\n");
+		}
+	}
+}
+
+static int
+utopia_update_carrier_default(struct utopia *utp)
+{
+	int err;
+	uint8_t reg;
+	u_int n = 1;
+
+	if ((err = READREGS(utp, SUNI_REGO_RSOPSIS, &reg, &n)) != 0) {
+		utp->carrier = UTP_CARR_UNKNOWN;
+		return (err);
+	}
+	utopia_check_carrier(utp, !(reg & SUNI_REGM_RSOPSIS_LOSV));
+	return (0);
+}
+
+/*
+ * enable/disable scrambling
+ */
+static int
+utopia_set_noscramb_default(struct utopia *utp, int noscramb)
+{
+	int err;
+
+	if (noscramb) {
+		err = WRITEREG(utp, SUNI_REGO_TACPCTRL,
+		    SUNI_REGM_TACPCTRL_DSCR, SUNI_REGM_TACPCTRL_DSCR);
+		if (err)
+			return (err);
+		err = WRITEREG(utp, SUNI_REGO_RACPCTRL,
+		    SUNI_REGM_RACPCTRL_DDSCR, SUNI_REGM_RACPCTRL_DDSCR);
+		if (err)
+			return (err);
+		utp->state |= UTP_ST_NOSCRAMB;
+	} else {
+		err = WRITEREG(utp, SUNI_REGO_TACPCTRL,
+		    SUNI_REGM_TACPCTRL_DSCR, 0);
+		if (err)
+			return (err);
+		err = WRITEREG(utp, SUNI_REGO_RACPCTRL,
+		    SUNI_REGM_RACPCTRL_DDSCR, 0);
+		if (err)
+			return (err);
+		utp->state &= ~UTP_ST_NOSCRAMB;
+	}
+	return (0);
+}
+
+/*
+ * set SONET/SDH mode
+ */
+static int
+utopia_set_sdh_default(struct utopia *utp, int sdh)
+{
+	int err;
+
+	if (sdh)
+		err = WRITEREG(utp, SUNI_REGO_TPOPAPTR + 1,
+		    SUNI_REGM_TPOPAPTR_S,
+		    SUNI_REGM_SDH << SUNI_REGS_TPOPAPTR_S);
+	else
+		err = WRITEREG(utp, SUNI_REGO_TPOPAPTR + 1,
+		    SUNI_REGM_TPOPAPTR_S,
+		    SUNI_REGM_SONET << SUNI_REGS_TPOPAPTR_S);
+	if (err != 0)
+		return (err);
+
+	utp->state &= ~UTP_ST_SDH;
+	if (sdh)
+		utp->state |= UTP_ST_SDH;
+
+	return (0);
+}
+
+/*
+ * set idle/unassigned cells
+ */
+static int
+utopia_set_unass_default(struct utopia *utp, int unass)
+{
+	int err;
+
+	if (unass)
+		err = WRITEREG(utp, SUNI_REGO_TACPIDLEH,
+		    0xff, (0 << SUNI_REGS_TACPIDLEH_CLP));
+	else
+		err = WRITEREG(utp, SUNI_REGO_TACPIDLEH,
+		    0xff, (1 << SUNI_REGS_TACPIDLEH_CLP));
+	if (err != 0)
+		return (err);
+
+	utp->state &= ~UTP_ST_UNASS;
+	if (unass)
+		utp->state |= UTP_ST_UNASS;
+
+	return (0);
+}
+
+/*
+ * Set loopback mode for the Lite
+ */
+static int
+utopia_set_loopback_lite(struct utopia *utp, u_int mode)
+{
+	int err;
+	uint32_t val;
+	u_int nmode;
+
+	val = 0;
+	nmode = mode;
+	if (mode & UTP_LOOP_TIME) {
+		nmode &= ~UTP_LOOP_TIME;
+		val |= SUNI_REGM_MCTRL_LOOPT;
+	}
+	if (mode & UTP_LOOP_DIAG) {
+		nmode &= ~UTP_LOOP_DIAG;
+		val |= SUNI_REGM_MCTRL_DLE;
+	}
+	if (mode & UTP_LOOP_LINE) {
+		nmode &= ~UTP_LOOP_LINE;
+		if (val & SUNI_REGM_MCTRL_DLE)
+			return (EINVAL);
+		val |= SUNI_REGM_MCTRL_LLE;
+	}
+	if (nmode != 0)
+		return (EINVAL);
+
+	err = WRITEREG(utp, SUNI_REGO_MCTRL,
+	    SUNI_REGM_MCTRL_LLE | SUNI_REGM_MCTRL_DLE | SUNI_REGM_MCTRL_LOOPT,
+	    val);
+	if (err)
+		return (err);
+	utp->loopback = mode;
+
+	return (0);
+}
+
+/*
+ * Set loopback mode for the Ultra
+ */
+static int
+utopia_set_loopback_ultra(struct utopia *utp, u_int mode)
+{
+	int err;
+	uint32_t val;
+	u_int nmode;
+
+	val = 0;
+	nmode = mode;
+	if (mode & UTP_LOOP_TIME) {
+		nmode &= ~UTP_LOOP_TIME;
+		val |= SUNI_REGM_MCTRL_LOOPT;
+	}
+	if (mode & UTP_LOOP_DIAG) {
+		nmode &= ~UTP_LOOP_DIAG;
+		if (val & SUNI_REGM_MCTRL_LOOPT)
+			return (EINVAL);
+		val |= SUNI_REGM_MCTRL_SDLE;
+	}
+	if (mode & UTP_LOOP_LINE) {
+		nmode &= ~UTP_LOOP_LINE;
+		if (val & (SUNI_REGM_MCTRL_LOOPT | SUNI_REGM_MCTRL_SDLE))
+			return (EINVAL);
+		val |= SUNI_REGM_MCTRL_LLE;
+	}
+	if (mode & UTP_LOOP_PARAL) {
+		nmode &= ~UTP_LOOP_PARAL;
+		val |= SUNI_REGM_MCTRL_PDLE;
+	}
+	if (mode & UTP_LOOP_TWIST) {
+		nmode &= ~UTP_LOOP_TWIST;
+		val |= SUNI_REGM_MCTRL_TPLE;
+	}
+	if (nmode != 0)
+		return (EINVAL);
+
+	err = WRITEREG(utp, SUNI_REGO_MCTRL,
+	    SUNI_REGM_MCTRL_LLE | SUNI_REGM_MCTRL_SDLE | SUNI_REGM_MCTRL_LOOPT |
+	    SUNI_REGM_MCTRL_PDLE | SUNI_REGM_MCTRL_TPLE, val);
+	if (err)
+		return (err);
+	utp->loopback = mode;
+
+	return (0);
+}
+
+/*
+ * Set loopback mode for the Ultra
+ */
+static int
+utopia_set_loopback_622(struct utopia *utp, u_int mode)
+{
+	int err;
+	uint32_t val;
+	uint8_t config;
+	int smode;
+	u_int nmode;
+	u_int n = 1;
+
+	val = 0;
+	nmode = mode;
+	if (mode & UTP_LOOP_PATH) {
+		nmode &= ~UTP_LOOP_PATH;
+		val |= SUNI_REGM_MCTRLM_DPLE;
+	}
+
+	err = READREGS(utp, SUNI_REGO_MCONFIG, &config, &n);
+	if (err != 0)
+		return (err);
+	smode = ((config & SUNI_REGM_MCONFIG_TMODE_622) ==
+	    SUNI_REGM_MCONFIG_TMODE_STS1_BIT &&
+	    (config & SUNI_REGM_MCONFIG_RMODE_622) ==
+	    SUNI_REGM_MCONFIG_RMODE_STS1_BIT);
+
+	if (mode & UTP_LOOP_TIME) {
+		if (!smode)
+			return (EINVAL);
+		nmode &= ~UTP_LOOP_TIME;
+		val |= SUNI_REGM_MCTRLM_LOOPT;
+	}
+	if (mode & UTP_LOOP_DIAG) {
+		nmode &= ~UTP_LOOP_DIAG;
+		if (val & SUNI_REGM_MCTRLM_LOOPT)
+			return (EINVAL);
+		val |= SUNI_REGM_MCTRLM_DLE;
+	}
+	if (mode & UTP_LOOP_LINE) {
+		nmode &= ~UTP_LOOP_LINE;
+		if (val & (SUNI_REGM_MCTRLM_LOOPT | SUNI_REGM_MCTRLM_DLE))
+			return (EINVAL);
+		val |= SUNI_REGM_MCTRLM_LLE;
+	}
+	if (nmode != 0)
+		return (EINVAL);
+
+	err = WRITEREG(utp, SUNI_REGO_MCTRLM,
+	    SUNI_REGM_MCTRLM_LLE | SUNI_REGM_MCTRLM_DLE |
+	    SUNI_REGM_MCTRLM_DPLE | SUNI_REGM_MCTRL_LOOPT, val);
+	if (err)
+		return (err);
+	utp->loopback = mode;
+
+	return (0);
+}
+
+/*
+ * Set the SUNI chip to reflect the current state in utopia.
+ * Assume, that the chip has been reset.
+ */
+static int
+utopia_set_chip(struct utopia *utp)
+{
+	int err = 0;
+
+	/* set sonet/sdh */
+	err |= utopia_set_sdh(utp, utp->state & UTP_ST_SDH);
+
+	/* unassigned or idle cells */
+	err |= utopia_set_unass(utp, utp->state & UTP_ST_UNASS);
+	err |= WRITEREG(utp, SUNI_REGO_TACPIDLEP, 0xff, 0x6a);
+
+	/* loopback */
+	err |= utopia_set_loopback(utp, utp->loopback);
+
+	/* update carrier state */
+	err |= utopia_update_carrier(utp);
+
+	/* enable interrupts on LOS */
+	err |= WRITEREG(utp, SUNI_REGO_RSOPCIE,
+	    SUNI_REGM_RSOPCIE_LOSE, SUNI_REGM_RSOPCIE_LOSE);
+
+	return (err ? EIO : 0);
+}
+
+/*
+ * Reset the SUNI chip to reflect the current state of utopia.
+ */
+static int
+utopia_reset_default(struct utopia *utp)
+{
+	int err = 0;
+
+	if (!(utp->flags & UTP_FL_NORESET)) {
+		err |= WRITEREG(utp, SUNI_REGO_MRESET, SUNI_REGM_MRESET_RESET,
+		    SUNI_REGM_MRESET_RESET);
+		err |= WRITEREG(utp, SUNI_REGO_MRESET, SUNI_REGM_MRESET_RESET,
+		    0);
+	}
+
+	/* disable test mode */
+	err |= WRITEREG(utp, SUNI_REGO_MTEST, 0xff, 0x00);
+
+	err |= utopia_set_chip(utp);
+
+	return (err ? EIO : 0);
+}
+
+/*
+ * Reset the SUNI chip to reflect the current state of utopia.
+ */
+static int
+utopia_reset_622(struct utopia *utp)
+{
+	int err = 0;
+
+	if (!(utp->flags & UTP_FL_NORESET)) {
+		err |= WRITEREG(utp, SUNI_REGO_MRESET, SUNI_REGM_MRESET_RESET,
+		    SUNI_REGM_MRESET_RESET);
+		err |= WRITEREG(utp, SUNI_REGO_MRESET, SUNI_REGM_MRESET_RESET,
+		    0);
+	}
+
+	/* disable test mode */
+	err |= WRITEREG(utp, SUNI_REGO_MTEST, 0xff,
+	    SUNI_REGM_MTEST_DS27_53_622);
+
+	err |= utopia_set_chip(utp);
+
+	return (err ? EIO : 0);
+}
+
+/*
+ * Handle interrupt on lite chip
+ */
+static void
+utopia_intr_default(struct utopia *utp)
+{
+	uint8_t regs[SUNI_REGO_MTEST];
+	u_int n = SUNI_REGO_MTEST;
+	int err;
+
+	/* Read all registers. This acks the interrupts */
+	if ((err = READREGS(utp, SUNI_REGO_MRESET, regs, &n)) != 0) {
+		printf("SUNI read error %d\n", err);
+		return;
+	}
+	if (n <= SUNI_REGO_RSOPSIS) {
+		printf("%s: could not read RSOPSIS", __func__);
+		return;
+	}
+	/* check for LOSI (loss of signal) */
+	if ((regs[SUNI_REGO_MISTATUS] & SUNI_REGM_MISTATUS_RSOPI) &&
+	    (regs[SUNI_REGO_RSOPSIS] & SUNI_REGM_RSOPSIS_LOSI))
+		utopia_check_carrier(utp, !(regs[SUNI_REGO_RSOPSIS]
+		    & SUNI_REGM_RSOPSIS_LOSV));
+}
+
+static const struct utopia_chip chip_622 = {
+	UTP_TYPE_SUNI_622,
+	"Suni/622 (PMC-5355)",
+	256,
+	utopia_reset_622,
+	utopia_set_sdh_default,
+	utopia_set_unass_default,
+	utopia_set_noscramb_default,
+	utopia_update_carrier_default,
+	utopia_set_loopback_622,
+	utopia_intr_default,
+};
+static const struct utopia_chip chip_lite = {
+	UTP_TYPE_SUNI_LITE,
+	"Suni/Lite (PMC-5346)",
+	256,
+	utopia_reset_default,
+	utopia_set_sdh_default,
+	utopia_set_unass_default,
+	utopia_set_noscramb_default,
+	utopia_update_carrier_default,
+	utopia_set_loopback_lite,
+	utopia_intr_default,
+};
+static const struct utopia_chip chip_ultra = {
+	UTP_TYPE_SUNI_ULTRA,
+	"Suni/Ultra (PMC-5350)",
+	256,
+	utopia_reset_default,
+	utopia_set_sdh_default,
+	utopia_set_unass_default,
+	utopia_set_noscramb_default,
+	utopia_update_carrier_default,
+	utopia_set_loopback_ultra,
+	utopia_intr_default,
+};
+
+/*
+ * Reset IDT77105. There is really no way to reset this thing by acessing
+ * the registers. Load the registers with default values.
+ */
+static int
+idt77105_reset(struct utopia *utp)
+{
+	int err = 0;
+	u_int n;
+	uint8_t val[2];
+
+	err |= WRITEREG(utp, IDTPHY_REGO_MCR, 0xff,
+	    IDTPHY_REGM_MCR_DRIC | IDTPHY_REGM_MCR_EI);
+	n = 1;
+	err |= READREGS(utp, IDTPHY_REGO_ISTAT, val, &n);
+	err |= WRITEREG(utp, IDTPHY_REGO_DIAG, 0xff, 0);
+	err |= WRITEREG(utp, IDTPHY_REGO_LHEC, 0xff, 0);
+
+	err |= WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_SEC);
+	n = 2;
+	err |= READREGS(utp, IDTPHY_REGO_CNT, val, &n);
+
+	err |= WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_TX);
+	n = 2;
+	err |= READREGS(utp, IDTPHY_REGO_CNT, val, &n);
+
+	err |= WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_RX);
+	n = 2;
+	err |= READREGS(utp, IDTPHY_REGO_CNT, val, &n);
+
+	err |= WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_HECE);
+	n = 2;
+	err |= READREGS(utp, IDTPHY_REGO_CNT, val, &n);
+
+	err |= WRITEREG(utp, IDTPHY_REGO_MCR, IDTPHY_REGM_MCR_DREC,
+	    IDTPHY_REGM_MCR_DREC);
+	err |= WRITEREG(utp, IDTPHY_REGO_DIAG, IDTPHY_REGM_DIAG_RFLUSH,
+	    IDTPHY_REGM_DIAG_RFLUSH);
+
+	/* loopback */
+	err |= utopia_set_loopback(utp, utp->loopback);
+
+	/* update carrier state */
+	err |= utopia_update_carrier(utp);
+
+	return (err ? EIO : 0);
+}
+
+static int
+unknown_inval(struct utopia *utp, int what __unused)
+{
+	return (EINVAL);
+}
+
+static int
+idt77105_update_carrier(struct utopia *utp)
+{
+	int err;
+	uint8_t reg;
+	u_int n = 1;
+
+	if ((err = READREGS(utp, IDTPHY_REGO_ISTAT, &reg, &n)) != 0) {
+		utp->carrier = UTP_CARR_UNKNOWN;
+		return (err);
+	}
+	utopia_check_carrier(utp, reg & IDTPHY_REGM_ISTAT_GOOD);
+	return (0);
+}
+
+static int
+idt77105_set_loopback(struct utopia *utp, u_int mode)
+{
+	int err;
+
+	switch (mode) {
+	  case UTP_LOOP_NONE:
+		err = WRITEREG(utp, IDTPHY_REGO_DIAG,
+		    IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_NONE);
+		break;
+
+	  case UTP_LOOP_DIAG:
+		err = WRITEREG(utp, IDTPHY_REGO_DIAG,
+		    IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_PHY);
+		break;
+
+	  case UTP_LOOP_LINE:
+		err = WRITEREG(utp, IDTPHY_REGO_DIAG,
+		    IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_LINE);
+		break;
+
+	  default:
+		return (EINVAL);
+	}
+	if (err)
+		return (err);
+	utp->loopback = mode;
+	return (0);
+}
+
+/*
+ * Handle interrupt on IDT77105 chip
+ */
+static void
+idt77105_intr(struct utopia *utp)
+{
+	uint8_t reg;
+	u_int n = 1;
+	int err;
+
+	/* Interrupt status and ack the interrupt */
+	if ((err = READREGS(utp, IDTPHY_REGO_ISTAT, &reg, &n)) != 0) {
+		printf("IDT77105 read error %d\n", err);
+		return;
+	}
+	/* check for signal condition */
+	utopia_check_carrier(utp, reg & IDTPHY_REGM_ISTAT_GOOD);
+}
+
+static const struct utopia_chip chip_idt77105 = {
+	UTP_TYPE_IDT77105,
+	"IDT77105",
+	7,
+	idt77105_reset,
+	unknown_inval,
+	unknown_inval,
+	unknown_inval,
+	idt77105_update_carrier,
+	idt77105_set_loopback,
+	idt77105_intr,
+};
+
+static int
+unknown_reset(struct utopia *utp __unused)
+{
+	return (EIO);
+}
+
+static int
+unknown_update_carrier(struct utopia *utp)
+{
+	utp->carrier = UTP_CARR_UNKNOWN;
+	return (0);
+}
+
+static int
+unknown_set_loopback(struct utopia *utp __unused, u_int mode __unused)
+{
+	return (EINVAL);
+}
+
+static void
+unknown_intr(struct utopia *utp __unused)
+{
+}
+
+static const struct utopia_chip chip_unknown = {
+	UTP_TYPE_UNKNOWN,
+	"unknown",
+	0,
+	unknown_reset,
+	unknown_inval,
+	unknown_inval,
+	unknown_inval,
+	unknown_update_carrier,
+	unknown_set_loopback,
+	unknown_intr,
+};
+
+/*
+ * Callbacks for the ifmedia infrastructure.
+ */
+static int
+utopia_media_change(struct ifnet *ifp)
+{
+	struct ifatm *ifatm = (struct ifatm *)ifp->if_softc;
+	struct utopia *utp = ifatm->phy;
+	int error = 0;
+
+	UTP_LOCK(utp);
+	if (utp->chip->type != UTP_TYPE_UNKNOWN && utp->state & UTP_ST_ACTIVE) {
+		if (utp->media->ifm_media & IFM_ATM_SDH) {
+			if (!(utp->state & UTP_ST_SDH))
+				error = utopia_set_sdh(utp, 1);
+		} else {
+			if (utp->state & UTP_ST_SDH)
+				error = utopia_set_sdh(utp, 0);
+		}
+		if (utp->media->ifm_media & IFM_ATM_UNASSIGNED) {
+			if (!(utp->state & UTP_ST_UNASS))
+				error = utopia_set_unass(utp, 1);
+		} else {
+			if (utp->state & UTP_ST_UNASS)
+				error = utopia_set_unass(utp, 0);
+		}
+		if (utp->media->ifm_media & IFM_ATM_NOSCRAMB) {
+			if (!(utp->state & UTP_ST_NOSCRAMB))
+				error = utopia_set_noscramb(utp, 1);
+		} else {
+			if (utp->state & UTP_ST_NOSCRAMB)
+				error = utopia_set_noscramb(utp, 0);
+		}
+	} else
+		error = EIO;
+	UTP_UNLOCK(utp);
+	return (error);
+}
+
+/*
+ * Look at the carrier status.
+ */
+static void
+utopia_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+	struct utopia *utp = ((struct ifatm *)ifp->if_softc)->phy;
+
+	UTP_LOCK(utp);
+	if (utp->chip->type != UTP_TYPE_UNKNOWN && utp->state & UTP_ST_ACTIVE) {
+		ifmr->ifm_active = IFM_ATM | utp->ifatm->mib.media;
+
+		switch (utp->carrier) {
+
+		  case UTP_CARR_OK:
+			ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
+			break;
+
+		  case UTP_CARR_LOST:
+			ifmr->ifm_status = IFM_AVALID;
+			break;
+
+		  default:
+			ifmr->ifm_status = 0;
+			break;
+		}
+		if (utp->state & UTP_ST_SDH) {
+			ifmr->ifm_active |= IFM_ATM_SDH;
+			ifmr->ifm_current |= IFM_ATM_SDH;
+		}
+		if (utp->state & UTP_ST_UNASS) {
+			ifmr->ifm_active |= IFM_ATM_UNASSIGNED;
+			ifmr->ifm_current |= IFM_ATM_UNASSIGNED;
+		}
+		if (utp->state & UTP_ST_NOSCRAMB) {
+			ifmr->ifm_active |= IFM_ATM_NOSCRAMB;
+			ifmr->ifm_current |= IFM_ATM_NOSCRAMB;
+		}
+	} else {
+		ifmr->ifm_active = 0;
+		ifmr->ifm_status = 0;
+	}
+	UTP_UNLOCK(utp);
+}
+
+/*
+ * Initialize media from the mib
+ */
+void
+utopia_init_media(struct utopia *utp)
+{
+
+	ifmedia_removeall(utp->media);
+	ifmedia_add(utp->media, IFM_ATM | utp->ifatm->mib.media, 0, NULL);
+	ifmedia_set(utp->media, IFM_ATM | utp->ifatm->mib.media);
+}
+
+/*
+ * Reset all media
+ */
+void
+utopia_reset_media(struct utopia *utp)
+{
+
+	ifmedia_removeall(utp->media);
+}
+
+/*
+ * This is called by the driver as soon as the SUNI registers are accessible.
+ * This may be either in the attach routine or the init routine of the driver.
+ */
+int
+utopia_start(struct utopia *utp)
+{
+	uint8_t reg;
+	int err;
+	u_int n = 1;
+
+	if ((err = READREGS(utp, SUNI_REGO_MRESET, &reg, &n)) != 0)
+		return (err);
+
+	switch (reg & SUNI_REGM_MRESET_TYPE) {
+
+	  case SUNI_REGM_MRESET_TYPE_622:
+		utp->chip = &chip_622;
+		break;
+
+	  case SUNI_REGM_MRESET_TYPE_LITE:
+		utp->chip = &chip_lite;
+		break;
+
+	  case SUNI_REGM_MRESET_TYPE_ULTRA:
+		utp->chip = &chip_ultra;
+		break;
+
+	  default:
+		if (reg == (IDTPHY_REGM_MCR_DRIC | IDTPHY_REGM_MCR_EI))
+			utp->chip = &chip_idt77105;
+		else {
+			if_printf(&utp->ifatm->ifnet,
+			    "unknown ATM-PHY chip %#x\n", reg);
+			utp->chip = &chip_unknown;
+		}
+		break;
+	}
+	utp->state |= UTP_ST_ACTIVE;
+	return (0);
+}
+
+/*
+ * Stop the chip
+ */
+void
+utopia_stop(struct utopia *utp)
+{
+	utp->state &= ~UTP_ST_ACTIVE;
+}
+
+/*
+ * Handle the sysctls
+ */
+static int
+utopia_sysctl_regs(SYSCTL_HANDLER_ARGS)
+{
+	struct utopia *utp = (struct utopia *)arg1;
+	int error;
+	u_int n;
+	uint8_t *val;
+	uint8_t new[3];
+
+	if ((n = utp->chip->nregs) == 0)
+		return (EIO);
+	val = malloc(sizeof(uint8_t) * n, M_TEMP, M_WAITOK);
+
+	UTP_LOCK(utp);
+	error = READREGS(utp, 0, val, &n);
+	UTP_UNLOCK(utp);
+
+	if (error) {
+		free(val, M_TEMP);
+		return (error);
+	}
+
+	error = SYSCTL_OUT(req, val, sizeof(uint8_t) * n);
+	free(val, M_TEMP);
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+
+	error = SYSCTL_IN(req, new, sizeof(new));
+	if (error)
+		return (error);
+
+	UTP_LOCK(utp);
+	error = WRITEREG(utp, new[0], new[1], new[2]);
+	UTP_UNLOCK(utp);
+
+	return (error);
+}
+
+/*
+ * Handle the loopback sysctl
+ */
+static int
+utopia_sysctl_loopback(SYSCTL_HANDLER_ARGS)
+{
+	struct utopia *utp = (struct utopia *)arg1;
+	int error;
+	u_int loopback;
+
+	error = SYSCTL_OUT(req, &utp->loopback, sizeof(u_int));
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+
+	error = SYSCTL_IN(req, &loopback, sizeof(u_int));
+	if (error)
+		return (error);
+
+	UTP_LOCK(utp);
+	error = utopia_set_loopback(utp, loopback);
+	UTP_UNLOCK(utp);
+
+	return (error);
+}
+
+/*
+ * Handle the type sysctl
+ */
+static int
+utopia_sysctl_type(SYSCTL_HANDLER_ARGS)
+{
+	struct utopia *utp = (struct utopia *)arg1;
+
+	return (SYSCTL_OUT(req, &utp->chip->type, sizeof(utp->chip->type)));
+}
+
+/*
+ * Handle the name sysctl
+ */
+static int
+utopia_sysctl_name(SYSCTL_HANDLER_ARGS)
+{
+	struct utopia *utp = (struct utopia *)arg1;
+
+	return (SYSCTL_OUT(req, utp->chip->name, strlen(utp->chip->name) + 1));
+}
+
+/*
+ * Initialize the state. This is called from the drivers attach
+ * function. The mutex must be already initialized.
+ */
+int
+utopia_attach(struct utopia *utp, struct ifatm *ifatm, struct ifmedia *media,
+    struct mtx *lock, struct sysctl_ctx_list *ctx,
+    struct sysctl_oid_list *children, const struct utopia_methods *m)
+{
+
+	bzero(utp, sizeof(*utp));
+	utp->ifatm = ifatm;
+	utp->methods = m;
+	utp->media = media;
+	utp->lock = lock;
+	utp->chip = &chip_unknown;
+
+	ifmedia_init(media,
+	    IFM_ATM_SDH | IFM_ATM_UNASSIGNED | IFM_ATM_NOSCRAMB,
+	    utopia_media_change, utopia_media_status);
+
+	if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_regs",
+	    CTLFLAG_RW | CTLTYPE_OPAQUE, utp, 0, utopia_sysctl_regs, "S",
+	    "phy registers") == NULL)
+		return (-1);
+
+	if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_loopback",
+	    CTLFLAG_RW | CTLTYPE_UINT, utp, 0, utopia_sysctl_loopback, "IU",
+	    "phy loopback mode") == NULL)
+		return (-1);
+
+	if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_type",
+	    CTLFLAG_RD | CTLTYPE_UINT, utp, 0, utopia_sysctl_type, "IU",
+	    "phy type") == NULL)
+		return (-1);
+
+	if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_name",
+	    CTLFLAG_RD | CTLTYPE_STRING, utp, 0, utopia_sysctl_name, "A",
+	    "phy name") == NULL)
+		return (-1);
+
+	UTP_WLOCK_LIST();
+	LIST_INSERT_HEAD(&utopia_list, utp, link);
+	UTP_WUNLOCK_LIST();
+
+	utp->state |= UTP_ST_ATTACHED;
+	return (0);
+}
+
+/*
+ * Detach. We set a flag here, wakeup the daemon and let him do it.
+ * Here we need the lock for synchronisation with the daemon.
+ */
+void
+utopia_detach(struct utopia *utp)
+{
+
+	UTP_LOCK_ASSERT(utp);
+	if (utp->state & UTP_ST_ATTACHED) {
+		utp->state |= UTP_ST_DETACH;
+		while (utp->state & UTP_ST_DETACH) {
+			wakeup(&utopia_list);
+			msleep(utp, utp->lock, PZERO, "utopia_detach", hz);
+		}
+	}
+}
+
+/*
+ * The carrier state kernel proc for those adapters that do not interrupt.
+ *
+ * We assume, that utopia_attach can safely add a new utopia while we are going
+ * through the list without disturbing us (we lock the list while getting
+ * the address of the first element, adding is always done at the head).
+ * Removing is entirely handled here.
+ */
+static void
+utopia_daemon(void *arg __unused)
+{
+	struct utopia *utp, *next;
+
+	UTP_RLOCK_LIST();
+	while (utopia_kproc != NULL) {
+		utp = LIST_FIRST(&utopia_list);
+		UTP_RUNLOCK_LIST();
+
+		while (utp != NULL) {
+			mtx_lock(&Giant);	/* XXX depend on MPSAFE */
+			UTP_LOCK(utp);
+			next = LIST_NEXT(utp, link);
+			if (utp->state & UTP_ST_DETACH) {
+				LIST_REMOVE(utp, link);
+				utp->state &= ~UTP_ST_DETACH;
+				wakeup_one(utp);
+			} else if ((utp->state & UTP_ST_ACTIVE) &&
+			    (utp->flags & UTP_FL_POLL_CARRIER)) {
+				utopia_update_carrier(utp);
+			}
+			UTP_UNLOCK(utp);
+			mtx_unlock(&Giant);	/* XXX depend on MPSAFE */
+			utp = next;
+		}
+
+		UTP_RLOCK_LIST();
+		msleep(&utopia_list, &utopia_list_mtx, PZERO, "utopia", hz);
+	}
+	wakeup_one(&utopia_list);
+	UTP_RUNLOCK_LIST();
+	mtx_lock(&Giant);
+	kthread_exit(0);
+}
+
+/*
+ * Module initialisation
+ */
+static int
+utopia_mod_init(module_t mod, int what, void *arg)
+{
+	int err;
+	struct proc *kp;
+
+	switch (what) {
+
+	  case MOD_LOAD:
+		mtx_init(&utopia_list_mtx, "utopia list mutex", NULL, MTX_DEF);
+		err = kthread_create(utopia_daemon, NULL, &utopia_kproc,
+		    RFHIGHPID, 0, "utopia");
+		if (err != 0) {
+			printf("cannot created utopia thread %d\n", err);
+			return (err);
+		}
+		break;
+
+	  case MOD_UNLOAD:
+		UTP_WLOCK_LIST();
+		if ((kp = utopia_kproc) != NULL) {
+			utopia_kproc = NULL;
+			wakeup_one(&utopia_list);
+			PROC_LOCK(kp);
+			UTP_WUNLOCK_LIST();
+			msleep(kp, &kp->p_mtx, PWAIT, "utopia_destroy", 0);
+			PROC_UNLOCK(kp);
+		} else
+			UTP_WUNLOCK_LIST();
+		mtx_destroy(&utopia_list_mtx);
+		break;
+	}
+	return (0);
+}
+
+static moduledata_t utopia_mod = {
+        "utopia",
+        utopia_mod_init,
+        0
+};
+                
+DECLARE_MODULE(utopia, utopia_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
+MODULE_VERSION(utopia, 1);
diff --git a/sys/dev/utopia/utopia.h b/sys/dev/utopia/utopia.h
new file mode 100644
index 000000000000..59db880b4fc8
--- /dev/null
+++ b/sys/dev/utopia/utopia.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2003
+ *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * 	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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * $FreeBSD$
+ */
+#ifndef _DEV_UTOPIA_UTOPIA_H
+#define	_DEV_UTOPIA_UTOPIA_H
+
+/* Structure for user-level register formatting */
+struct utopia_print {
+	uint8_t		type;	/* register type */
+	uint8_t		reg;	/* register number */
+	const char	*name;	/* register name */
+	const char	*fmt;	/* format for printing */
+};
+
+/*
+ * Types of registers
+ */
+#define	UTP_REGT_BITS		0x0	/* use printb to print */
+#define	UTP_REGT_INT8		0x1	/* 8 bit hex number */
+#define	UTP_REGT_INT10BITS	0x2	/* 10 bit hex number + 6 bit printb */
+#define	UTP_REGT_INT12		0x3	/* 12 bit LE hex */
+#define	UTP_REGT_INT16		0x4	/* 16 bit LE hex */
+#define	UTP_REGT_INT19		0x5	/* 19 bit LE hex */
+#define	UTP_REGT_INT20		0x6	/* 20 bit LE hex */
+#define	UTP_REGT_INT21		0x7	/* 21 bit LE hex */
+
+/* number of additional registers per type */
+#define	UTP_REG_ADD	0, 0, 1, 1, 1, 2, 2, 2
+
+/* flags field */
+#define	UTP_FL_NORESET		0x0001	/* cannot write MRESET register */
+#define	UTP_FL_POLL_CARRIER	0x0002	/* need to poll for carrier */
+
+/* state field */
+#define	UTP_ST_ACTIVE		0x0001	/* registers accessible */
+#define	UTP_ST_SDH		0x0002	/* SDH or SONET */
+#define	UTP_ST_UNASS		0x0004	/* produce unassigned cells */
+#define	UTP_ST_NOSCRAMB		0x0008	/* no scrambling */
+#define	UTP_ST_DETACH		0x0010	/* detaching */
+#define	UTP_ST_ATTACHED		0x0020	/* successful attached */
+
+/* carrier field */
+#define	UTP_CARR_UNKNOWN	0
+#define	UTP_CARR_OK		1
+#define	UTP_CARR_LOST		2
+
+/* loopback field */
+#define	UTP_LOOP_NONE		0x0000
+#define	UTP_LOOP_TIME		0x0001	/* timing source loopback */
+#define	UTP_LOOP_DIAG		0x0002	/* diagnostic loopback */
+#define	UTP_LOOP_LINE		0x0004	/* serial line loopback */
+#define	UTP_LOOP_PARAL		0x0008	/* parallel diagnostic loopback */
+#define	UTP_LOOP_TWIST		0x0010	/* twisted pair diagnostic loopback */
+#define	UTP_LOOP_PATH		0x0020	/* diagnostic path loopback */
+
+/* type */
+#define	UTP_TYPE_UNKNOWN	0
+#define	UTP_TYPE_SUNI_LITE	1
+#define	UTP_TYPE_SUNI_ULTRA	2
+#define	UTP_TYPE_SUNI_622	3
+#define	UTP_TYPE_IDT77105	4
+
+#ifdef _KERNEL
+
+#include <sys/queue.h>
+
+/*
+ * These must be implemented by the card driver
+ */
+struct utopia_methods {
+	/* read at most n PHY registers starting at reg into val */
+	int	(*readregs)(struct ifatm *, u_int reg, uint8_t *val, u_int *n);
+
+	/* change the bits given by mask to them in val in register reg */
+	int	(*writereg)(struct ifatm *, u_int reg, u_int mask, u_int val);
+};
+
+/*
+ * Public state
+ */
+struct utopia {
+	struct ifatm	*ifatm;		/* driver data */
+	struct ifmedia	*media;		/* driver supplied */
+	struct mtx	*lock;		/* driver supplied */
+	const struct utopia_methods *methods;
+	LIST_ENTRY(utopia) link;	/* list of these structures */
+	u_int		flags;		/* flags set by the driver */
+	u_int		state;		/* current state */
+	u_int		carrier;	/* carrier state */
+	u_int		loopback;	/* loopback mode */
+	const struct utopia_chip *chip;	/* chip operations */
+};
+
+struct utopia_chip {
+	/* type and name of the chip */
+	u_int	type;
+	const char *const name;
+
+	/* number of registers */
+	u_int	nregs;
+
+	/* reset chip to known state */
+	int	(*reset)(struct utopia *);
+
+	/* set SONET/SDH mode */
+	int	(*set_sdh)(struct utopia *, int sdh);
+
+	/* set idle/unassigned cells */
+	int	(*set_unass)(struct utopia *, int unass);
+
+	/* enable/disable scrambling */
+	int	(*set_noscramb)(struct utopia *, int noscramb);
+
+	/* update carrier status */
+	int	(*update_carrier)(struct utopia *);
+
+	/* set loopback mode */
+	int	(*set_loopback)(struct utopia *, u_int mode);
+
+	/* handle interrupt */
+	void	(*intr)(struct utopia *);
+};
+
+/*
+ * These are implemented in the common utopia code
+ */
+int utopia_attach(struct utopia *, struct ifatm *, struct ifmedia *,
+    struct mtx *, struct sysctl_ctx_list *, struct sysctl_oid_list *,
+    const struct utopia_methods *);
+void utopia_detach(struct utopia *);
+
+int utopia_start(struct utopia *);
+void utopia_stop(struct utopia *);
+
+void utopia_init_media(struct utopia *);
+void utopia_reset_media(struct utopia *);
+
+#define	utopia_reset(S)			((S)->chip->reset((S)))
+#define	utopia_set_sdh(S, SDH)		((S)->chip->set_sdh((S), (SDH)))
+#define	utopia_set_unass(S, U)		((S)->chip->set_unass((S), (U)))
+#define	utopia_set_noscramb(S, N)	((S)->chip->set_noscramb((S), (N)))
+#define	utopia_update_carrier(S)	((S)->chip->update_carrier((S)))
+#define	utopia_set_loopback(S, L)	((S)->chip->set_loopback((S), (L)))
+#define	utopia_intr(S)			((S)->chip->intr((S)))
+
+#endif /* _KERNEL */
+
+#endif	/* _DEV_UTOPIA_UTOPIA_H */
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 4a7fd4bce58d..71644c6a0d6a 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -132,6 +132,7 @@ SUBDIR=	accf_data \
 	urio \
 	usb \
 	uscanner \
+	utopia \
 	uvisor \
 	uvscom \
 	vpo \
diff --git a/sys/modules/utopia/Makefile b/sys/modules/utopia/Makefile
new file mode 100644
index 000000000000..19150cecf498
--- /dev/null
+++ b/sys/modules/utopia/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/utopia
+
+KMOD=	utopia
+SRCS=	utopia.c bus_if.h device_if.h
+
+.include <bsd.kmod.mk>