summaryrefslogtreecommitdiffstats
path: root/sys/dev/utopia
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2005-02-24 16:56:36 +0000
committerharti <harti@FreeBSD.org>2005-02-24 16:56:36 +0000
commit272c3271b3f9a21aa6a10e9806830288c1eb6212 (patch)
tree27b47f463c4b5d81ff79ac7ac9f4cde9d20fecd7 /sys/dev/utopia
parent6dcf0684c3043439d042d3d2fb729f21b4523655 (diff)
downloadFreeBSD-src-272c3271b3f9a21aa6a10e9806830288c1eb6212.zip
FreeBSD-src-272c3271b3f9a21aa6a10e9806830288c1eb6212.tar.gz
Split the chip-specific code from the generic Utopia code. This simplifies
adding of new physical chips. Now one just needs to add a .h and a .c file for the new chip and add one line to utopia.c for that chip.
Diffstat (limited to 'sys/dev/utopia')
-rw-r--r--sys/dev/utopia/idtphy.c494
-rw-r--r--sys/dev/utopia/suni.c545
-rw-r--r--sys/dev/utopia/utopia.c954
-rw-r--r--sys/dev/utopia/utopia.h4
-rw-r--r--sys/dev/utopia/utopia_priv.h46
5 files changed, 1120 insertions, 923 deletions
diff --git a/sys/dev/utopia/idtphy.c b/sys/dev/utopia/idtphy.c
new file mode 100644
index 0000000..5aaa576
--- /dev/null
+++ b/sys/dev/utopia/idtphy.c
@@ -0,0 +1,494 @@
+/*-
+ * Copyright (c) 2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * 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.
+ */
+
+#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/module.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/idtphy.h>
+#include <dev/utopia/utopia.h>
+#include <dev/utopia/utopia_priv.h>
+
+/*
+ * 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 |= UTP_WRITEREG(utp, IDTPHY_REGO_MCR, 0xff,
+ IDTPHY_REGM_MCR_DRIC | IDTPHY_REGM_MCR_EI);
+ n = 1;
+ err |= UTP_READREGS(utp, IDTPHY_REGO_ISTAT, val, &n);
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_DIAG, 0xff, 0);
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_LHEC, 0xff, 0);
+
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_SEC);
+ n = 2;
+ err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
+
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_TX);
+ n = 2;
+ err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
+
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_RX);
+ n = 2;
+ err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
+
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_HECE);
+ n = 2;
+ err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
+
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_MCR, IDTPHY_REGM_MCR_DREC,
+ IDTPHY_REGM_MCR_DREC);
+ err |= UTP_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
+idt77105_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 = UTP_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 = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
+ IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_NONE);
+ break;
+
+ case UTP_LOOP_DIAG:
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
+ IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_PHY);
+ break;
+
+ case UTP_LOOP_LINE:
+ err = UTP_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 = UTP_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 void
+idt77105_update_stats(struct utopia *utp)
+{
+ int err = 0;
+ uint8_t regs[2];
+ u_int n;
+
+#ifdef DIAGNOSTIC
+#define UDIAG(F,A,B) printf(F, A, B)
+#else
+#define UDIAG(F,A,B) do { } while (0)
+#endif
+
+#define UPD(FIELD, CODE, N, MASK) \
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, CODE); \
+ if (err != 0) { \
+ UDIAG("%s: cannot write CNTS: %d\n", __func__, err); \
+ return; \
+ } \
+ n = N; \
+ err = UTP_READREGS(utp, IDTPHY_REGO_CNT, regs, &n); \
+ if (err != 0) { \
+ UDIAG("%s: cannot read CNT: %d\n", __func__, err); \
+ return; \
+ } \
+ if (n != N) { \
+ UDIAG("%s: got only %u registers\n", __func__, n); \
+ return; \
+ } \
+ if (N == 1) \
+ utp->stats.FIELD += (regs[0] & MASK); \
+ else \
+ utp->stats.FIELD += (regs[0] | (regs[1] << 8)) & MASK;
+
+ UPD(rx_symerr, IDTPHY_REGM_CNTS_SEC, 1, 0xff);
+ UPD(tx_cells, IDTPHY_REGM_CNTS_TX, 2, 0xffff);
+ UPD(rx_cells, IDTPHY_REGM_CNTS_RX, 2, 0xffff);
+ UPD(rx_uncorr, IDTPHY_REGM_CNTS_HECE, 1, 0x1f);
+
+#undef UDIAG
+#undef UPD
+}
+
+struct utopia_chip utopia_chip_idt77105 = {
+ UTP_TYPE_IDT77105,
+ "IDT77105",
+ 7,
+ idt77105_reset,
+ idt77105_inval,
+ idt77105_inval,
+ idt77105_inval,
+ idt77105_update_carrier,
+ idt77105_set_loopback,
+ idt77105_intr,
+ idt77105_update_stats,
+};
+
+/*
+ * Update the carrier status
+ */
+static int
+idt77155_update_carrier(struct utopia *utp)
+{
+ int err;
+ uint8_t reg;
+ u_int n = 1;
+
+ if ((err = UTP_READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
+ utp->carrier = UTP_CARR_UNKNOWN;
+ return (err);
+ }
+ utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
+ return (0);
+}
+
+/*
+ * Handle interrupt on IDT77155 chip
+ */
+static void
+idt77155_intr(struct utopia *utp)
+{
+ uint8_t reg;
+ u_int n = 1;
+ int err;
+
+ if ((err = UTP_READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
+ printf("IDT77105 read error %d\n", err);
+ return;
+ }
+ utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
+}
+
+/*
+ * set SONET/SDH mode
+ */
+static int
+idt77155_set_sdh(struct utopia *utp, int sdh)
+{
+ int err;
+
+ if (sdh)
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_PTRM,
+ IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SDH);
+ else
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_PTRM,
+ IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SONET);
+ 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
+idt77155_set_unass(struct utopia *utp, int unass)
+{
+ int err;
+
+ if (unass)
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 0);
+ else
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 1);
+ if (err != 0)
+ return (err);
+
+ utp->state &= ~UTP_ST_UNASS;
+ if (unass)
+ utp->state |= UTP_ST_UNASS;
+
+ return (0);
+}
+
+/*
+ * enable/disable scrambling
+ */
+static int
+idt77155_set_noscramb(struct utopia *utp, int noscramb)
+{
+ int err;
+
+ if (noscramb) {
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_TCC,
+ IDTPHY_REGM_TCC_DSCR, IDTPHY_REGM_TCC_DSCR);
+ if (err)
+ return (err);
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_RCC,
+ IDTPHY_REGM_RCC_DSCR, IDTPHY_REGM_RCC_DSCR);
+ if (err)
+ return (err);
+ utp->state |= UTP_ST_NOSCRAMB;
+ } else {
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_TCC,
+ IDTPHY_REGM_TCC_DSCR, 0);
+ if (err)
+ return (err);
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_RCC,
+ IDTPHY_REGM_RCC_DSCR, 0);
+ if (err)
+ return (err);
+ utp->state &= ~UTP_ST_NOSCRAMB;
+ }
+ return (0);
+}
+
+/*
+ * Set loopback mode for the 77155
+ */
+static int
+idt77155_set_loopback(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 |= IDTPHY_REGM_MCTL_TLOOP;
+ }
+ if (mode & UTP_LOOP_DIAG) {
+ nmode &= ~UTP_LOOP_DIAG;
+ val |= IDTPHY_REGM_MCTL_DLOOP;
+ }
+ if (mode & UTP_LOOP_LINE) {
+ nmode &= ~UTP_LOOP_LINE;
+ val |= IDTPHY_REGM_MCTL_LLOOP;
+ }
+ if (nmode != 0)
+ return (EINVAL);
+
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_MCTL, IDTPHY_REGM_MCTL_TLOOP |
+ IDTPHY_REGM_MCTL_DLOOP | IDTPHY_REGM_MCTL_LLOOP, val);
+ if (err)
+ return (err);
+ utp->loopback = mode;
+
+ return (0);
+}
+
+/*
+ * Set the chip to reflect the current state in utopia.
+ * Assume, that the chip has been reset.
+ */
+static int
+idt77155_set_chip(struct utopia *utp)
+{
+ int err = 0;
+
+ /* set sonet/sdh */
+ err |= idt77155_set_sdh(utp, utp->state & UTP_ST_SDH);
+
+ /* unassigned or idle cells */
+ err |= idt77155_set_unass(utp, utp->state & UTP_ST_UNASS);
+
+ /* loopback */
+ err |= idt77155_set_loopback(utp, utp->loopback);
+
+ /* update carrier state */
+ err |= idt77155_update_carrier(utp);
+
+ /* enable interrupts on LOS */
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_INT,
+ IDTPHY_REGM_INT_RXSOHI, IDTPHY_REGM_INT_RXSOHI);
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_RSOC,
+ IDTPHY_REGM_RSOC_LOSI, IDTPHY_REGM_RSOC_LOSI);
+
+ return (err ? EIO : 0);
+}
+
+/*
+ * Reset the chip to reflect the current state of utopia.
+ */
+static int
+idt77155_reset(struct utopia *utp)
+{
+ int err = 0;
+
+ if (!(utp->flags & UTP_FL_NORESET)) {
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_MRID,
+ IDTPHY_REGM_MRID_RESET, IDTPHY_REGM_MRID_RESET);
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_MRID,
+ IDTPHY_REGM_MRID_RESET, 0);
+ }
+
+ err |= idt77155_set_chip(utp);
+
+ return (err ? EIO : 0);
+}
+
+/*
+ * Update statistics from a IDT77155
+ * This appears to be the same as for the Suni/Lite and Ultra. IDT however
+ * makes no assessment about the transfer time. Assume 7us.
+ */
+static void
+idt77155_update_stats(struct utopia *utp)
+{
+ int err;
+
+ /* write to the master if we can */
+ if (!(utp->flags & UTP_FL_NORESET)) {
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_MRID, 0, 0);
+ } else {
+ err = UTP_WRITEREG(utp, IDTPHY_REGO_BIPC, 0, 0);
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_B2EC, 0, 0);
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_B3EC, 0, 0);
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_CEC, 0, 0);
+ err |= UTP_WRITEREG(utp, IDTPHY_REGO_TXCNT, 0, 0);
+
+ }
+ if (err) {
+#ifdef DIAGNOSTIC
+ printf("%s: register write error %s: %d\n", __func__,
+ utp->chip->name, err);
+#endif
+ return;
+ }
+
+ DELAY(8);
+
+ utp->stats.rx_sbip += utopia_update(utp,
+ IDTPHY_REGO_BIPC, 2, 0xffff);
+ utp->stats.rx_lbip += utopia_update(utp,
+ IDTPHY_REGO_B2EC, 3, 0xfffff);
+ utp->stats.rx_lfebe += utopia_update(utp,
+ IDTPHY_REGO_FEBEC, 3, 0xfffff);
+ utp->stats.rx_pbip += utopia_update(utp,
+ IDTPHY_REGO_B3EC, 2, 0xffff);
+ utp->stats.rx_pfebe += utopia_update(utp,
+ IDTPHY_REGO_PFEBEC, 2, 0xffff);
+ utp->stats.rx_corr += utopia_update(utp,
+ IDTPHY_REGO_CEC, 1, 0xff);
+ utp->stats.rx_uncorr += utopia_update(utp,
+ IDTPHY_REGO_UEC, 1, 0xff);
+ utp->stats.rx_cells += utopia_update(utp,
+ IDTPHY_REGO_RCCNT, 3, 0x7ffff);
+ utp->stats.tx_cells += utopia_update(utp,
+ IDTPHY_REGO_TXCNT, 3, 0x7ffff);
+}
+
+const struct utopia_chip utopia_chip_idt77155 = {
+ UTP_TYPE_IDT77155,
+ "IDT77155",
+ 0x80,
+ idt77155_reset,
+ idt77155_set_sdh,
+ idt77155_set_unass,
+ idt77155_set_noscramb,
+ idt77155_update_carrier,
+ idt77155_set_loopback,
+ idt77155_intr,
+ idt77155_update_stats,
+};
diff --git a/sys/dev/utopia/suni.c b/sys/dev/utopia/suni.c
new file mode 100644
index 0000000..ffc49e8
--- /dev/null
+++ b/sys/dev/utopia/suni.c
@@ -0,0 +1,545 @@
+/*-
+ * Copyright (c) 2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
+ * 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.
+ */
+
+#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/module.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/utopia.h>
+#include <dev/utopia/utopia_priv.h>
+
+/*
+ * set SONET/SDH mode
+ */
+static int
+suni_set_sdh(struct utopia *utp, int sdh)
+{
+ int err;
+
+ if (sdh)
+ err = UTP_WRITEREG(utp, SUNI_REGO_TPOPAPTR + 1,
+ SUNI_REGM_TPOPAPTR_S,
+ SUNI_REGM_SDH << SUNI_REGS_TPOPAPTR_S);
+ else
+ err = UTP_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
+suni_set_unass(struct utopia *utp, int unass)
+{
+ int err;
+
+ if (unass)
+ err = UTP_WRITEREG(utp, SUNI_REGO_TACPIDLEH,
+ 0xff, (0 << SUNI_REGS_TACPIDLEH_CLP));
+ else
+ err = UTP_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);
+}
+
+/*
+ * enable/disable scrambling
+ */
+static int
+suni_set_noscramb(struct utopia *utp, int noscramb)
+{
+ int err;
+
+ if (noscramb) {
+ err = UTP_WRITEREG(utp, SUNI_REGO_TACPCTRL,
+ SUNI_REGM_TACPCTRL_DSCR, SUNI_REGM_TACPCTRL_DSCR);
+ if (err)
+ return (err);
+ err = UTP_WRITEREG(utp, SUNI_REGO_RACPCTRL,
+ SUNI_REGM_RACPCTRL_DDSCR, SUNI_REGM_RACPCTRL_DDSCR);
+ if (err)
+ return (err);
+ utp->state |= UTP_ST_NOSCRAMB;
+ } else {
+ err = UTP_WRITEREG(utp, SUNI_REGO_TACPCTRL,
+ SUNI_REGM_TACPCTRL_DSCR, 0);
+ if (err)
+ return (err);
+ err = UTP_WRITEREG(utp, SUNI_REGO_RACPCTRL,
+ SUNI_REGM_RACPCTRL_DDSCR, 0);
+ if (err)
+ return (err);
+ utp->state &= ~UTP_ST_NOSCRAMB;
+ }
+ return (0);
+}
+
+/*
+ * Get current carrier state
+ */
+static int
+suni_update_carrier(struct utopia *utp)
+{
+ int err;
+ uint8_t reg;
+ u_int n = 1;
+
+ if ((err = UTP_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);
+}
+
+/*
+ * Set the SUNI chip to reflect the current state in utopia.
+ * Assume, that the chip has been reset.
+ */
+static int
+suni_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 |= UTP_WRITEREG(utp, SUNI_REGO_TACPIDLEP, 0xff, 0x6a);
+
+ /* set scrambling */
+ err |= utopia_set_noscramb(utp, utp->state & UTP_ST_NOSCRAMB);
+
+ /* loopback */
+ err |= utopia_set_loopback(utp, utp->loopback);
+
+ /* update carrier state */
+ err |= utopia_update_carrier(utp);
+
+ /* enable interrupts on LOS */
+ err |= UTP_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
+suni_reset_default(struct utopia *utp)
+{
+ int err = 0;
+
+ if (!(utp->flags & UTP_FL_NORESET)) {
+ err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
+ SUNI_REGM_MRESET_RESET, SUNI_REGM_MRESET_RESET);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
+ SUNI_REGM_MRESET_RESET, 0);
+ }
+
+ /* disable test mode */
+ err |= UTP_WRITEREG(utp, SUNI_REGO_MTEST, 0xff, 0x00);
+
+ err |= suni_set_chip(utp);
+
+ return (err ? EIO : 0);
+}
+
+/*
+ * Set loopback mode for the Lite
+ */
+static int
+suni_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 = UTP_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);
+}
+
+/*
+ * Update statistics from a SUNI/LITE or SUNI/ULTRA
+ */
+static void
+suni_lite_update_stats(struct utopia *utp)
+{
+ int err;
+
+ /* write to the master if we can */
+ if (!(utp->flags & UTP_FL_NORESET)) {
+ err = UTP_WRITEREG(utp, SUNI_REGO_MRESET, 0, 0);
+ } else {
+ err = UTP_WRITEREG(utp, SUNI_REGO_RSOP_BIP8, 0, 0);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_RLOPBIP8_24, 0, 0);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_RPOPBIP8, 0, 0);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_RACPCHCS, 0, 0);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_TACPCNT, 0, 0);
+
+ }
+ if (err) {
+#ifdef DIAGNOSTIC
+ printf("%s: register write error %s: %d\n", __func__,
+ utp->chip->name, err);
+#endif
+ return;
+ }
+
+ DELAY(8);
+
+ utp->stats.rx_sbip += utopia_update(utp,
+ SUNI_REGO_RSOP_BIP8, 2, 0xffff);
+ utp->stats.rx_lbip += utopia_update(utp,
+ SUNI_REGO_RLOPBIP8_24, 3, 0xfffff);
+ utp->stats.rx_lfebe += utopia_update(utp,
+ SUNI_REGO_RLOPFEBE, 3, 0xfffff);
+ utp->stats.rx_pbip += utopia_update(utp,
+ SUNI_REGO_RPOPBIP8, 2, 0xffff);
+ utp->stats.rx_pfebe += utopia_update(utp,
+ SUNI_REGO_RPOPFEBE, 2, 0xffff);
+ utp->stats.rx_corr += utopia_update(utp,
+ SUNI_REGO_RACPCHCS, 1, 0xff);
+ utp->stats.rx_uncorr += utopia_update(utp,
+ SUNI_REGO_RACPUHCS, 1, 0xff);
+ utp->stats.rx_cells += utopia_update(utp,
+ SUNI_REGO_RACPCNT, 3, 0x7ffff);
+ utp->stats.tx_cells += utopia_update(utp,
+ SUNI_REGO_TACPCNT, 3, 0x7ffff);
+}
+
+/*
+ * Handle interrupt on SUNI chip
+ */
+static void
+suni_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 = UTP_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));
+}
+
+const struct utopia_chip utopia_chip_lite = {
+ UTP_TYPE_SUNI_LITE,
+ "Suni/Lite (PMC-5346)",
+ 256,
+ suni_reset_default,
+ suni_set_sdh,
+ suni_set_unass,
+ suni_set_noscramb,
+ suni_update_carrier,
+ suni_set_loopback_lite,
+ suni_intr_default,
+ suni_lite_update_stats,
+};
+
+/*
+ * Set loopback mode for the Ultra
+ */
+static int
+suni_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 = UTP_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);
+}
+
+const struct utopia_chip utopia_chip_ultra = {
+ UTP_TYPE_SUNI_ULTRA,
+ "Suni/Ultra (PMC-5350)",
+ 256,
+ suni_reset_default,
+ suni_set_sdh,
+ suni_set_unass,
+ suni_set_noscramb,
+ suni_update_carrier,
+ suni_set_loopback_ultra,
+ suni_intr_default,
+ suni_lite_update_stats,
+};
+
+/*
+ * Set loopback mode for the 622
+ */
+static int
+suni_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 = UTP_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 = UTP_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);
+}
+
+/*
+ * Reset the SUNI chip to reflect the current state of utopia.
+ */
+static int
+suni_reset_622(struct utopia *utp)
+{
+ int err = 0;
+
+ if (!(utp->flags & UTP_FL_NORESET)) {
+ err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
+ SUNI_REGM_MRESET_RESET, SUNI_REGM_MRESET_RESET);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
+ SUNI_REGM_MRESET_RESET, 0);
+ }
+
+ /* disable test mode */
+ err |= UTP_WRITEREG(utp, SUNI_REGO_MTEST, 0xff,
+ SUNI_REGM_MTEST_DS27_53_622);
+
+ err |= suni_set_chip(utp);
+
+ return (err ? EIO : 0);
+}
+
+/*
+ * Update statistics from a SUNI/622
+ */
+static void
+suni_622_update_stats(struct utopia *utp)
+{
+ int err;
+
+ /* write to the master if we can */
+ if (!(utp->flags & UTP_FL_NORESET)) {
+ err = UTP_WRITEREG(utp, SUNI_REGO_MRESET, 0, 0);
+ } else {
+ err = UTP_WRITEREG(utp, SUNI_REGO_RSOP_BIP8, 0, 0);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_RLOPBIP8_24, 0, 0);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_RPOPBIP8, 0, 0);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_RACPCHCS, 0, 0);
+ err |= UTP_WRITEREG(utp, SUNI_REGO_TACPCNT, 0, 0);
+ }
+ if (err) {
+#ifdef DIAGNOSTIC
+ printf("%s: register write error %s: %d\n", __func__,
+ utp->chip->name, err);
+#endif
+ return;
+ }
+
+ DELAY(8);
+
+ utp->stats.rx_sbip += utopia_update(utp,
+ SUNI_REGO_RSOP_BIP8, 2, 0xffff);
+ utp->stats.rx_lbip += utopia_update(utp,
+ SUNI_REGO_RLOPBIP8_24, 3, 0xfffff);
+ utp->stats.rx_lfebe += utopia_update(utp,
+ SUNI_REGO_RLOPFEBE, 3, 0xfffff);
+ utp->stats.rx_pbip += utopia_update(utp,
+ SUNI_REGO_RPOPBIP8, 2, 0xffff);
+ utp->stats.rx_pfebe += utopia_update(utp,
+ SUNI_REGO_RPOPFEBE, 2, 0xffff);
+ utp->stats.rx_corr += utopia_update(utp,
+ SUNI_REGO_RACPCHCS_622, 2, 0xfff);
+ utp->stats.rx_uncorr += utopia_update(utp,
+ SUNI_REGO_RACPUHCS_622, 2, 0xfff);
+ utp->stats.rx_cells += utopia_update(utp,
+ SUNI_REGO_RACPCNT_622, 3, 0x1fffff);
+ utp->stats.tx_cells += utopia_update(utp,
+ SUNI_REGO_TACPCNT, 3, 0x1fffff);
+}
+
+const struct utopia_chip utopia_chip_622 = {
+ UTP_TYPE_SUNI_622,
+ "Suni/622 (PMC-5355)",
+ 256,
+ suni_reset_622,
+ suni_set_sdh,
+ suni_set_unass,
+ suni_set_noscramb,
+ suni_update_carrier,
+ suni_set_loopback_622,
+ suni_intr_default,
+ suni_622_update_stats,
+};
diff --git a/sys/dev/utopia/utopia.c b/sys/dev/utopia/utopia.c
index e4a7c01..1a9f353 100644
--- a/sys/dev/utopia/utopia.c
+++ b/sys/dev/utopia/utopia.c
@@ -3,6 +3,8 @@
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
+ * Author: Hartmut Brandt <harti@freebsd.org>
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -23,8 +25,6 @@
* 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>
@@ -52,11 +52,14 @@ __FBSDID("$FreeBSD$");
#include <dev/utopia/suni.h>
#include <dev/utopia/idtphy.h>
#include <dev/utopia/utopia.h>
+#include <dev/utopia/utopia_priv.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)
+/* known chips */
+extern const struct utopia_chip utopia_chip_idt77155;
+extern const struct utopia_chip utopia_chip_idt77105;
+extern const struct utopia_chip utopia_chip_lite;
+extern const struct utopia_chip utopia_chip_ultra;
+extern const struct utopia_chip utopia_chip_622;
/*
* Global list of all registered interfaces
@@ -78,10 +81,10 @@ static struct proc *utopia_kproc;
static void utopia_dump(struct utopia *) __unused;
/*
- * Statistics update inlines
+ * Read a multi-register value.
*/
-static uint32_t
-utp_update(struct utopia *utp, u_int reg, u_int nreg, uint32_t mask)
+uint32_t
+utopia_update(struct utopia *utp, u_int reg, u_int nreg, uint32_t mask)
{
int err;
u_int n;
@@ -89,7 +92,7 @@ utp_update(struct utopia *utp, u_int reg, u_int nreg, uint32_t mask)
uint32_t val;
n = nreg;
- if ((err = READREGS(utp, reg, regs, &n)) != 0) {
+ if ((err = UTP_READREGS(utp, reg, regs, &n)) != 0) {
#ifdef DIAGNOSTIC
printf("%s: register read error %s(%u,%u): %d\n", __func__,
utp->chip->name, reg, nreg, err);
@@ -111,13 +114,6 @@ utp_update(struct utopia *utp, u_int reg, u_int nreg, uint32_t mask)
return (val & mask);
}
-#define UPDATE8(UTP, REG) utp_update(UTP, REG, 1, 0xff)
-#define UPDATE12(UTP, REG) utp_update(UTP, REG, 2, 0xfff)
-#define UPDATE16(UTP, REG) utp_update(UTP, REG, 2, 0xffff)
-#define UPDATE19(UTP, REG) utp_update(UTP, REG, 3, 0x7ffff)
-#define UPDATE20(UTP, REG) utp_update(UTP, REG, 3, 0xfffff)
-#define UPDATE21(UTP, REG) utp_update(UTP, REG, 3, 0x1fffff)
-
/*
* Debugging - dump all registers.
*/
@@ -128,8 +124,8 @@ utopia_dump(struct utopia *utp)
u_int n = 256, i;
int err;
- if ((err = READREGS(utp, SUNI_REGO_MRESET, regs, &n)) != 0) {
- printf("SUNI read error %d\n", err);
+ if ((err = UTP_READREGS(utp, 0, regs, &n)) != 0) {
+ printf("UTOPIA reg read error %d\n", err);
return;
}
for (i = 0; i < n; i++) {
@@ -148,7 +144,7 @@ utopia_dump(struct utopia *utp)
/*
* Update the carrier status
*/
-static void
+void
utopia_check_carrier(struct utopia *utp, u_int carr_ok)
{
int old;
@@ -172,901 +168,12 @@ utopia_check_carrier(struct utopia *utp, u_int carr_ok)
}
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));
-}
-
-/*
- * Update statistics from a SUNI/LITE or SUNI/ULTRA
- */
-static void
-suni_lite_update_stats(struct utopia *utp)
-{
- int err;
-
- /* write to the master if we can */
- if (!(utp->flags & UTP_FL_NORESET)) {
- err = WRITEREG(utp, SUNI_REGO_MRESET, 0, 0);
- } else {
- err = WRITEREG(utp, SUNI_REGO_RSOP_BIP8, 0, 0);
- err |= WRITEREG(utp, SUNI_REGO_RLOPBIP8_24, 0, 0);
- err |= WRITEREG(utp, SUNI_REGO_RPOPBIP8, 0, 0);
- err |= WRITEREG(utp, SUNI_REGO_RACPCHCS, 0, 0);
- err |= WRITEREG(utp, SUNI_REGO_TACPCNT, 0, 0);
-
- }
- if (err) {
-#ifdef DIAGNOSTIC
- printf("%s: register write error %s: %d\n", __func__,
- utp->chip->name, err);
-#endif
- return;
- }
-
- DELAY(8);
-
- utp->stats.rx_sbip += UPDATE16(utp, SUNI_REGO_RSOP_BIP8);
- utp->stats.rx_lbip += UPDATE20(utp, SUNI_REGO_RLOPBIP8_24);
- utp->stats.rx_lfebe += UPDATE20(utp, SUNI_REGO_RLOPFEBE);
- utp->stats.rx_pbip += UPDATE16(utp, SUNI_REGO_RPOPBIP8);
- utp->stats.rx_pfebe += UPDATE16(utp, SUNI_REGO_RPOPFEBE);
- utp->stats.rx_corr += UPDATE8(utp, SUNI_REGO_RACPCHCS);
- utp->stats.rx_uncorr += UPDATE8(utp, SUNI_REGO_RACPUHCS);
- utp->stats.rx_cells += UPDATE19(utp, SUNI_REGO_RACPCNT);
- utp->stats.tx_cells += UPDATE19(utp, SUNI_REGO_TACPCNT);
-}
-
-/*
- * Update statistics from a SUNI/622
- */
-static void
-suni_622_update_stats(struct utopia *utp)
-{
- int err;
-
- /* write to the master if we can */
- if (!(utp->flags & UTP_FL_NORESET)) {
- err = WRITEREG(utp, SUNI_REGO_MRESET, 0, 0);
- } else {
- err = WRITEREG(utp, SUNI_REGO_RSOP_BIP8, 0, 0);
- err |= WRITEREG(utp, SUNI_REGO_RLOPBIP8_24, 0, 0);
- err |= WRITEREG(utp, SUNI_REGO_RPOPBIP8, 0, 0);
- err |= WRITEREG(utp, SUNI_REGO_RACPCHCS, 0, 0);
- err |= WRITEREG(utp, SUNI_REGO_TACPCNT, 0, 0);
- }
- if (err) {
-#ifdef DIAGNOSTIC
- printf("%s: register write error %s: %d\n", __func__,
- utp->chip->name, err);
-#endif
- return;
- }
-
- DELAY(8);
-
- utp->stats.rx_sbip += UPDATE16(utp, SUNI_REGO_RSOP_BIP8);
- utp->stats.rx_lbip += UPDATE20(utp, SUNI_REGO_RLOPBIP8_24);
- utp->stats.rx_lfebe += UPDATE20(utp, SUNI_REGO_RLOPFEBE);
- utp->stats.rx_pbip += UPDATE16(utp, SUNI_REGO_RPOPBIP8);
- utp->stats.rx_pfebe += UPDATE16(utp, SUNI_REGO_RPOPFEBE);
- utp->stats.rx_corr += UPDATE12(utp, SUNI_REGO_RACPCHCS_622);
- utp->stats.rx_uncorr += UPDATE12(utp, SUNI_REGO_RACPUHCS_622);
- utp->stats.rx_cells += UPDATE21(utp, SUNI_REGO_RACPCNT_622);
- utp->stats.tx_cells += UPDATE21(utp, SUNI_REGO_TACPCNT);
-}
-
-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,
- suni_622_update_stats,
-};
-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,
- suni_lite_update_stats,
-};
-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,
- suni_lite_update_stats,
-};
-
-/*
- * 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 void
-idt77105_update_stats(struct utopia *utp)
-{
- int err = 0;
- uint8_t regs[2];
- u_int n;
-
-#ifdef DIAGNOSTIC
-#define UDIAG(F,A,B) printf(F, A, B)
-#else
-#define UDIAG(F,A,B) do { } while (0)
-#endif
-
-#define UPD(FIELD, CODE, N, MASK) \
- err = WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, CODE); \
- if (err != 0) { \
- UDIAG("%s: cannot write CNTS: %d\n", __func__, err); \
- return; \
- } \
- n = N; \
- err = READREGS(utp, IDTPHY_REGO_CNT, regs, &n); \
- if (err != 0) { \
- UDIAG("%s: cannot read CNT: %d\n", __func__, err); \
- return; \
- } \
- if (n != N) { \
- UDIAG("%s: got only %u registers\n", __func__, n); \
- return; \
- } \
- if (N == 1) \
- utp->stats.FIELD += (regs[0] & MASK); \
- else \
- utp->stats.FIELD += (regs[0] | (regs[1] << 8)) & MASK;
-
- UPD(rx_symerr, IDTPHY_REGM_CNTS_SEC, 1, 0xff);
- UPD(tx_cells, IDTPHY_REGM_CNTS_TX, 2, 0xffff);
- UPD(rx_cells, IDTPHY_REGM_CNTS_RX, 2, 0xffff);
- UPD(rx_uncorr, IDTPHY_REGM_CNTS_HECE, 1, 0x1f);
-
-#undef UDIAG
-#undef UPD
-}
-
-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,
- idt77105_update_stats,
-};
-
-/*
- * Update the carrier status
- */
-static int
-idt77155_update_carrier(struct utopia *utp)
-{
- int err;
- uint8_t reg;
- u_int n = 1;
-
- if ((err = READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
- utp->carrier = UTP_CARR_UNKNOWN;
- return (err);
- }
- utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
- return (0);
-}
-
-/*
- * Handle interrupt on IDT77155 chip
- */
-static void
-idt77155_intr(struct utopia *utp)
-{
- uint8_t reg;
- u_int n = 1;
- int err;
-
- if ((err = READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
- printf("IDT77105 read error %d\n", err);
- return;
- }
- utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
-}
-
-/*
- * set SONET/SDH mode
- */
-static int
-idt77155_set_sdh(struct utopia *utp, int sdh)
-{
- int err;
-
- if (sdh)
- err = WRITEREG(utp, IDTPHY_REGO_PTRM,
- IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SDH);
- else
- err = WRITEREG(utp, IDTPHY_REGO_PTRM,
- IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SONET);
- 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
-idt77155_set_unass(struct utopia *utp, int unass)
-{
- int err;
-
- if (unass)
- err = WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 0);
- else
- err = WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 1);
- if (err != 0)
- return (err);
-
- utp->state &= ~UTP_ST_UNASS;
- if (unass)
- utp->state |= UTP_ST_UNASS;
-
- return (0);
-}
-/*
- * enable/disable scrambling
- */
-static int
-idt77155_set_noscramb(struct utopia *utp, int noscramb)
-{
- int err;
-
- if (noscramb) {
- err = WRITEREG(utp, IDTPHY_REGO_TCC,
- IDTPHY_REGM_TCC_DSCR, IDTPHY_REGM_TCC_DSCR);
- if (err)
- return (err);
- err = WRITEREG(utp, IDTPHY_REGO_RCC,
- IDTPHY_REGM_RCC_DSCR, IDTPHY_REGM_RCC_DSCR);
- if (err)
- return (err);
- utp->state |= UTP_ST_NOSCRAMB;
- } else {
- err = WRITEREG(utp, IDTPHY_REGO_TCC,
- IDTPHY_REGM_TCC_DSCR, 0);
- if (err)
- return (err);
- err = WRITEREG(utp, IDTPHY_REGO_RCC,
- IDTPHY_REGM_RCC_DSCR, 0);
- if (err)
- return (err);
- utp->state &= ~UTP_ST_NOSCRAMB;
- }
- return (0);
-}
-
-/*
- * Set loopback mode for the 77155
- */
-static int
-idt77155_set_loopback(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 |= IDTPHY_REGM_MCTL_TLOOP;
- }
- if (mode & UTP_LOOP_DIAG) {
- nmode &= ~UTP_LOOP_DIAG;
- val |= IDTPHY_REGM_MCTL_DLOOP;
- }
- if (mode & UTP_LOOP_LINE) {
- nmode &= ~UTP_LOOP_LINE;
- val |= IDTPHY_REGM_MCTL_LLOOP;
- }
- if (nmode != 0)
- return (EINVAL);
-
- err = WRITEREG(utp, IDTPHY_REGO_MCTL, IDTPHY_REGM_MCTL_TLOOP |
- IDTPHY_REGM_MCTL_DLOOP | IDTPHY_REGM_MCTL_LLOOP, val);
- if (err)
- return (err);
- utp->loopback = mode;
-
- return (0);
-}
-
-/*
- * Set the chip to reflect the current state in utopia.
- * Assume, that the chip has been reset.
- */
-static int
-idt77155_set_chip(struct utopia *utp)
-{
- int err = 0;
-
- /* set sonet/sdh */
- err |= idt77155_set_sdh(utp, utp->state & UTP_ST_SDH);
-
- /* unassigned or idle cells */
- err |= idt77155_set_unass(utp, utp->state & UTP_ST_UNASS);
-
- /* loopback */
- err |= idt77155_set_loopback(utp, utp->loopback);
-
- /* update carrier state */
- err |= idt77155_update_carrier(utp);
-
- /* enable interrupts on LOS */
- err |= WRITEREG(utp, IDTPHY_REGO_INT,
- IDTPHY_REGM_INT_RXSOHI, IDTPHY_REGM_INT_RXSOHI);
- err |= WRITEREG(utp, IDTPHY_REGO_RSOC,
- IDTPHY_REGM_RSOC_LOSI, IDTPHY_REGM_RSOC_LOSI);
-
- return (err ? EIO : 0);
-}
-
-/*
- * Reset the chip to reflect the current state of utopia.
- */
-static int
-idt77155_reset(struct utopia *utp)
-{
- int err = 0;
-
- if (!(utp->flags & UTP_FL_NORESET)) {
- err |= WRITEREG(utp, IDTPHY_REGO_MRID, IDTPHY_REGM_MRID_RESET,
- IDTPHY_REGM_MRID_RESET);
- err |= WRITEREG(utp, IDTPHY_REGO_MRID, IDTPHY_REGM_MRID_RESET,
- 0);
- }
-
- err |= idt77155_set_chip(utp);
-
- return (err ? EIO : 0);
-}
-
-/*
- * Update statistics from a IDT77155
- * This appears to be the same as for the Suni/Lite and Ultra. IDT however
- * makes no assessment about the transfer time. Assume 7us.
- */
-static void
-idt77155_update_stats(struct utopia *utp)
-{
- int err;
-
- /* write to the master if we can */
- if (!(utp->flags & UTP_FL_NORESET)) {
- err = WRITEREG(utp, IDTPHY_REGO_MRID, 0, 0);
- } else {
- err = WRITEREG(utp, IDTPHY_REGO_BIPC, 0, 0);
- err |= WRITEREG(utp, IDTPHY_REGO_B2EC, 0, 0);
- err |= WRITEREG(utp, IDTPHY_REGO_B3EC, 0, 0);
- err |= WRITEREG(utp, IDTPHY_REGO_CEC, 0, 0);
- err |= WRITEREG(utp, IDTPHY_REGO_TXCNT, 0, 0);
-
- }
- if (err) {
-#ifdef DIAGNOSTIC
- printf("%s: register write error %s: %d\n", __func__,
- utp->chip->name, err);
-#endif
- return;
- }
-
- DELAY(8);
-
- utp->stats.rx_sbip += UPDATE16(utp, IDTPHY_REGO_BIPC);
- utp->stats.rx_lbip += UPDATE20(utp, IDTPHY_REGO_B2EC);
- utp->stats.rx_lfebe += UPDATE20(utp, IDTPHY_REGO_FEBEC);
- utp->stats.rx_pbip += UPDATE16(utp, IDTPHY_REGO_B3EC);
- utp->stats.rx_pfebe += UPDATE16(utp, IDTPHY_REGO_PFEBEC);
- utp->stats.rx_corr += UPDATE8(utp, IDTPHY_REGO_CEC);
- utp->stats.rx_uncorr += UPDATE8(utp, IDTPHY_REGO_UEC);
- utp->stats.rx_cells += UPDATE19(utp, IDTPHY_REGO_RCCNT);
- utp->stats.tx_cells += UPDATE19(utp, IDTPHY_REGO_TXCNT);
+ return (EINVAL);
}
-
-static const struct utopia_chip chip_idt77155 = {
- UTP_TYPE_IDT77155,
- "IDT77155",
- 0x80,
- idt77155_reset,
- idt77155_set_sdh,
- idt77155_set_unass,
- idt77155_set_noscramb,
- idt77155_update_carrier,
- idt77155_set_loopback,
- idt77155_intr,
- idt77155_update_stats,
-};
-
static int
unknown_reset(struct utopia *utp __unused)
{
@@ -1096,7 +203,7 @@ unknown_update_stats(struct utopia *utp __unused)
{
}
-static const struct utopia_chip chip_unknown = {
+static const struct utopia_chip utopia_chip_unknown = {
UTP_TYPE_UNKNOWN,
"unknown",
0,
@@ -1227,39 +334,42 @@ utopia_start(struct utopia *utp)
int err;
u_int n = 1;
- if ((err = READREGS(utp, SUNI_REGO_MRESET, &reg, &n)) != 0)
+ /*
+ * Try to find out what chip we have
+ */
+ if ((err = UTP_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;
+ utp->chip = &utopia_chip_622;
break;
case SUNI_REGM_MRESET_TYPE_LITE:
/* this may be either a SUNI LITE or a IDT77155 *
* Read register 0x70. The SUNI doesn't have it */
n = 1;
- if ((err = READREGS(utp, IDTPHY_REGO_RBER, &reg, &n)) != 0)
+ if ((err = UTP_READREGS(utp, IDTPHY_REGO_RBER, &reg, &n)) != 0)
return (err);
if ((reg & ~IDTPHY_REGM_RBER_RESV) ==
(IDTPHY_REGM_RBER_FAIL | IDTPHY_REGM_RBER_WARN))
- utp->chip = &chip_idt77155;
+ utp->chip = &utopia_chip_idt77155;
else
- utp->chip = &chip_lite;
+ utp->chip = &utopia_chip_lite;
break;
case SUNI_REGM_MRESET_TYPE_ULTRA:
- utp->chip = &chip_ultra;
+ utp->chip = &utopia_chip_ultra;
break;
default:
if (reg == (IDTPHY_REGM_MCR_DRIC | IDTPHY_REGM_MCR_EI))
- utp->chip = &chip_idt77105;
+ utp->chip = &utopia_chip_idt77105;
else {
if_printf(&utp->ifatm->ifnet,
"unknown ATM-PHY chip %#x\n", reg);
- utp->chip = &chip_unknown;
+ utp->chip = &utopia_chip_unknown;
}
break;
}
@@ -1293,7 +403,7 @@ utopia_sysctl_regs(SYSCTL_HANDLER_ARGS)
val = malloc(sizeof(uint8_t) * n, M_TEMP, M_WAITOK);
UTP_LOCK(utp);
- error = READREGS(utp, 0, val, &n);
+ error = UTP_READREGS(utp, 0, val, &n);
UTP_UNLOCK(utp);
if (error) {
@@ -1311,7 +421,7 @@ utopia_sysctl_regs(SYSCTL_HANDLER_ARGS)
return (error);
UTP_LOCK(utp);
- error = WRITEREG(utp, new[0], new[1], new[2]);
+ error = UTP_WRITEREG(utp, new[0], new[1], new[2]);
UTP_UNLOCK(utp);
return (error);
@@ -1406,7 +516,7 @@ utopia_attach(struct utopia *utp, struct ifatm *ifatm, struct ifmedia *media,
utp->methods = m;
utp->media = media;
utp->lock = lock;
- utp->chip = &chip_unknown;
+ utp->chip = &utopia_chip_unknown;
utp->stats.version = 1;
ifmedia_init(media,
diff --git a/sys/dev/utopia/utopia.h b/sys/dev/utopia/utopia.h
index 0c95aa3..6e42e99 100644
--- a/sys/dev/utopia/utopia.h
+++ b/sys/dev/utopia/utopia.h
@@ -50,9 +50,10 @@ struct utopia_print {
#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 */
+#define UTP_REGT_INT18 0x8 /* 18 bit LE hex */
/* number of additional registers per type */
-#define UTP_REG_ADD 0, 0, 1, 1, 1, 2, 2, 2
+#define UTP_REG_ADD 0, 0, 1, 1, 1, 2, 2, 2, 2
/* flags field */
#define UTP_FL_NORESET 0x0001 /* cannot write MRESET register */
@@ -87,6 +88,7 @@ struct utopia_print {
#define UTP_TYPE_SUNI_622 3
#define UTP_TYPE_IDT77105 4
#define UTP_TYPE_IDT77155 5
+#define UTP_TYPE_CX28250 6
/*
* Statistics. These structures are versioned.
diff --git a/sys/dev/utopia/utopia_priv.h b/sys/dev/utopia/utopia_priv.h
new file mode 100644
index 0000000..cbb242c
--- /dev/null
+++ b/sys/dev/utopia/utopia_priv.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2005
+ * Hartmut Brandt.
+ * 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$
+ *
+ * Private include file for the interface between chip files and
+ * the utopia main stuff.
+ */
+
+#ifndef _DEV_UTOPIA_UTOPIA_PRIV_H
+#define _DEV_UTOPIA_UTOPIA_PRIV_H
+
+#define UTP_READREGS(UTOPIA, REG, VALP, NP) \
+ (UTOPIA)->methods->readregs((UTOPIA)->ifatm, REG, VALP, NP)
+#define UTP_WRITEREG(UTOPIA, REG, MASK, VAL) \
+ (UTOPIA)->methods->writereg((UTOPIA)->ifatm, REG, MASK, VAL)
+
+uint32_t utopia_update(struct utopia *, u_int, u_int, uint32_t);
+void utopia_check_carrier(struct utopia *, u_int);
+
+#endif /* _DEV_UTOPIA_UTOPIA_PRIV_H */
OpenPOWER on IntegriCloud