/* * Read a multi-register value. */ uint32_t utopia_update(struct utopia *utp, u_int reg, u_int nreg, uint32_t mask) { int err; u_int n; uint8_t regs[4]; uint32_t val; n = nreg; 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); #endif return (0); } if (n < nreg) { #ifdef DIAGNOSTIC printf("%s: got only %u regs %s(%u,%u): %d\n", __func__, n, utp->chip->name, reg, nreg, err); #endif return (0); } val = 0; for (n = nreg; n > 0; n--) { val <<= 8; val |= regs[n - 1]; } return (val & mask); }
/* * 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); }
/* * 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, ®, &n)) != 0) { utp->carrier = UTP_CARR_UNKNOWN; return (err); } utopia_check_carrier(utp, !(reg & SUNI_REGM_RSOPSIS_LOSV)); return (0); }
/* * 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)); }
/* * Debugging - dump all registers. */ static void utopia_dump(struct utopia *utp) { uint8_t regs[256]; u_int n = 256, i; int 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++) { 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"); }