1142384Sharti/*-
2142384Sharti * Copyright (c) 2003
3142384Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4142384Sharti * 	All rights reserved.
5142384Sharti *
6142384Sharti * Author: Hartmut Brandt <harti@freebsd.org>
7142384Sharti *
8142384Sharti * Redistribution and use in source and binary forms, with or without
9142384Sharti * modification, are permitted provided that the following conditions
10142384Sharti * are met:
11142384Sharti * 1. Redistributions of source code must retain the above copyright
12142384Sharti *    notice, this list of conditions and the following disclaimer.
13142384Sharti * 2. Redistributions in binary form must reproduce the above copyright
14142384Sharti *    notice, this list of conditions and the following disclaimer in the
15142384Sharti *    documentation and/or other materials provided with the distribution.
16142384Sharti *
17142384Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18142384Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19142384Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20142384Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21142384Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22142384Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23142384Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24142384Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25142384Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26142384Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27142384Sharti * SUCH DAMAGE.
28142384Sharti */
29142384Sharti
30142384Sharti#include <sys/cdefs.h>
31142384Sharti__FBSDID("$FreeBSD: releng/11.0/sys/dev/utopia/suni.c 142384 2005-02-24 16:56:36Z harti $");
32142384Sharti
33142384Sharti#include <sys/param.h>
34142384Sharti#include <sys/systm.h>
35142384Sharti#include <sys/unistd.h>
36142384Sharti#include <sys/kernel.h>
37142384Sharti#include <sys/kthread.h>
38142384Sharti#include <sys/proc.h>
39142384Sharti#include <sys/bus.h>
40142384Sharti#include <sys/malloc.h>
41142384Sharti#include <sys/module.h>
42142384Sharti#include <sys/sysctl.h>
43142384Sharti#include <sys/lock.h>
44142384Sharti#include <sys/mutex.h>
45142384Sharti#include <sys/socket.h>
46142384Sharti
47142384Sharti#include <net/if.h>
48142384Sharti#include <net/if_var.h>
49142384Sharti#include <net/if_media.h>
50142384Sharti#include <net/if_atm.h>
51142384Sharti
52142384Sharti#include <dev/utopia/suni.h>
53142384Sharti#include <dev/utopia/utopia.h>
54142384Sharti#include <dev/utopia/utopia_priv.h>
55142384Sharti
56142384Sharti/*
57142384Sharti * set SONET/SDH mode
58142384Sharti */
59142384Shartistatic int
60142384Shartisuni_set_sdh(struct utopia *utp, int sdh)
61142384Sharti{
62142384Sharti	int err;
63142384Sharti
64142384Sharti	if (sdh)
65142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_TPOPAPTR + 1,
66142384Sharti		    SUNI_REGM_TPOPAPTR_S,
67142384Sharti		    SUNI_REGM_SDH << SUNI_REGS_TPOPAPTR_S);
68142384Sharti	else
69142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_TPOPAPTR + 1,
70142384Sharti		    SUNI_REGM_TPOPAPTR_S,
71142384Sharti		    SUNI_REGM_SONET << SUNI_REGS_TPOPAPTR_S);
72142384Sharti	if (err != 0)
73142384Sharti		return (err);
74142384Sharti
75142384Sharti	utp->state &= ~UTP_ST_SDH;
76142384Sharti	if (sdh)
77142384Sharti		utp->state |= UTP_ST_SDH;
78142384Sharti
79142384Sharti	return (0);
80142384Sharti}
81142384Sharti
82142384Sharti/*
83142384Sharti * set idle/unassigned cells
84142384Sharti */
85142384Shartistatic int
86142384Shartisuni_set_unass(struct utopia *utp, int unass)
87142384Sharti{
88142384Sharti	int err;
89142384Sharti
90142384Sharti	if (unass)
91142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_TACPIDLEH,
92142384Sharti		    0xff, (0 << SUNI_REGS_TACPIDLEH_CLP));
93142384Sharti	else
94142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_TACPIDLEH,
95142384Sharti		    0xff, (1 << SUNI_REGS_TACPIDLEH_CLP));
96142384Sharti	if (err != 0)
97142384Sharti		return (err);
98142384Sharti
99142384Sharti	utp->state &= ~UTP_ST_UNASS;
100142384Sharti	if (unass)
101142384Sharti		utp->state |= UTP_ST_UNASS;
102142384Sharti
103142384Sharti	return (0);
104142384Sharti}
105142384Sharti
106142384Sharti/*
107142384Sharti * enable/disable scrambling
108142384Sharti */
109142384Shartistatic int
110142384Shartisuni_set_noscramb(struct utopia *utp, int noscramb)
111142384Sharti{
112142384Sharti	int err;
113142384Sharti
114142384Sharti	if (noscramb) {
115142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_TACPCTRL,
116142384Sharti		    SUNI_REGM_TACPCTRL_DSCR, SUNI_REGM_TACPCTRL_DSCR);
117142384Sharti		if (err)
118142384Sharti			return (err);
119142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_RACPCTRL,
120142384Sharti		    SUNI_REGM_RACPCTRL_DDSCR, SUNI_REGM_RACPCTRL_DDSCR);
121142384Sharti		if (err)
122142384Sharti			return (err);
123142384Sharti		utp->state |= UTP_ST_NOSCRAMB;
124142384Sharti	} else {
125142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_TACPCTRL,
126142384Sharti		    SUNI_REGM_TACPCTRL_DSCR, 0);
127142384Sharti		if (err)
128142384Sharti			return (err);
129142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_RACPCTRL,
130142384Sharti		    SUNI_REGM_RACPCTRL_DDSCR, 0);
131142384Sharti		if (err)
132142384Sharti			return (err);
133142384Sharti		utp->state &= ~UTP_ST_NOSCRAMB;
134142384Sharti	}
135142384Sharti	return (0);
136142384Sharti}
137142384Sharti
138142384Sharti/*
139142384Sharti * Get current carrier state
140142384Sharti */
141142384Shartistatic int
142142384Shartisuni_update_carrier(struct utopia *utp)
143142384Sharti{
144142384Sharti	int err;
145142384Sharti	uint8_t reg;
146142384Sharti	u_int n = 1;
147142384Sharti
148142384Sharti	if ((err = UTP_READREGS(utp, SUNI_REGO_RSOPSIS, &reg, &n)) != 0) {
149142384Sharti		utp->carrier = UTP_CARR_UNKNOWN;
150142384Sharti		return (err);
151142384Sharti	}
152142384Sharti	utopia_check_carrier(utp, !(reg & SUNI_REGM_RSOPSIS_LOSV));
153142384Sharti	return (0);
154142384Sharti}
155142384Sharti
156142384Sharti/*
157142384Sharti * Set the SUNI chip to reflect the current state in utopia.
158142384Sharti * Assume, that the chip has been reset.
159142384Sharti */
160142384Shartistatic int
161142384Shartisuni_set_chip(struct utopia *utp)
162142384Sharti{
163142384Sharti	int err = 0;
164142384Sharti
165142384Sharti	/* set sonet/sdh */
166142384Sharti	err |= utopia_set_sdh(utp, utp->state & UTP_ST_SDH);
167142384Sharti
168142384Sharti	/* unassigned or idle cells */
169142384Sharti	err |= utopia_set_unass(utp, utp->state & UTP_ST_UNASS);
170142384Sharti	err |= UTP_WRITEREG(utp, SUNI_REGO_TACPIDLEP, 0xff, 0x6a);
171142384Sharti
172142384Sharti	/* set scrambling */
173142384Sharti	err |= utopia_set_noscramb(utp, utp->state & UTP_ST_NOSCRAMB);
174142384Sharti
175142384Sharti	/* loopback */
176142384Sharti	err |= utopia_set_loopback(utp, utp->loopback);
177142384Sharti
178142384Sharti	/* update carrier state */
179142384Sharti	err |= utopia_update_carrier(utp);
180142384Sharti
181142384Sharti	/* enable interrupts on LOS */
182142384Sharti	err |= UTP_WRITEREG(utp, SUNI_REGO_RSOPCIE,
183142384Sharti	    SUNI_REGM_RSOPCIE_LOSE, SUNI_REGM_RSOPCIE_LOSE);
184142384Sharti
185142384Sharti	return (err ? EIO : 0);
186142384Sharti}
187142384Sharti
188142384Sharti/*
189142384Sharti * Reset the SUNI chip to reflect the current state of utopia.
190142384Sharti */
191142384Shartistatic int
192142384Shartisuni_reset_default(struct utopia *utp)
193142384Sharti{
194142384Sharti	int err = 0;
195142384Sharti
196142384Sharti	if (!(utp->flags & UTP_FL_NORESET)) {
197142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
198142384Sharti		    SUNI_REGM_MRESET_RESET, SUNI_REGM_MRESET_RESET);
199142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
200142384Sharti		    SUNI_REGM_MRESET_RESET, 0);
201142384Sharti	}
202142384Sharti
203142384Sharti	/* disable test mode */
204142384Sharti	err |= UTP_WRITEREG(utp, SUNI_REGO_MTEST, 0xff, 0x00);
205142384Sharti
206142384Sharti	err |= suni_set_chip(utp);
207142384Sharti
208142384Sharti	return (err ? EIO : 0);
209142384Sharti}
210142384Sharti
211142384Sharti/*
212142384Sharti * Set loopback mode for the Lite
213142384Sharti */
214142384Shartistatic int
215142384Shartisuni_set_loopback_lite(struct utopia *utp, u_int mode)
216142384Sharti{
217142384Sharti	int err;
218142384Sharti	uint32_t val;
219142384Sharti	u_int nmode;
220142384Sharti
221142384Sharti	val = 0;
222142384Sharti	nmode = mode;
223142384Sharti	if (mode & UTP_LOOP_TIME) {
224142384Sharti		nmode &= ~UTP_LOOP_TIME;
225142384Sharti		val |= SUNI_REGM_MCTRL_LOOPT;
226142384Sharti	}
227142384Sharti	if (mode & UTP_LOOP_DIAG) {
228142384Sharti		nmode &= ~UTP_LOOP_DIAG;
229142384Sharti		val |= SUNI_REGM_MCTRL_DLE;
230142384Sharti	}
231142384Sharti	if (mode & UTP_LOOP_LINE) {
232142384Sharti		nmode &= ~UTP_LOOP_LINE;
233142384Sharti		if (val & SUNI_REGM_MCTRL_DLE)
234142384Sharti			return (EINVAL);
235142384Sharti		val |= SUNI_REGM_MCTRL_LLE;
236142384Sharti	}
237142384Sharti	if (nmode != 0)
238142384Sharti		return (EINVAL);
239142384Sharti
240142384Sharti	err = UTP_WRITEREG(utp, SUNI_REGO_MCTRL,
241142384Sharti	    SUNI_REGM_MCTRL_LLE | SUNI_REGM_MCTRL_DLE | SUNI_REGM_MCTRL_LOOPT,
242142384Sharti	    val);
243142384Sharti	if (err)
244142384Sharti		return (err);
245142384Sharti	utp->loopback = mode;
246142384Sharti
247142384Sharti	return (0);
248142384Sharti}
249142384Sharti
250142384Sharti/*
251142384Sharti * Update statistics from a SUNI/LITE or SUNI/ULTRA
252142384Sharti */
253142384Shartistatic void
254142384Shartisuni_lite_update_stats(struct utopia *utp)
255142384Sharti{
256142384Sharti	int err;
257142384Sharti
258142384Sharti	/* write to the master if we can */
259142384Sharti	if (!(utp->flags & UTP_FL_NORESET)) {
260142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_MRESET, 0, 0);
261142384Sharti	} else {
262142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_RSOP_BIP8, 0, 0);
263142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_RLOPBIP8_24, 0, 0);
264142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_RPOPBIP8, 0, 0);
265142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_RACPCHCS, 0, 0);
266142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_TACPCNT, 0, 0);
267142384Sharti
268142384Sharti	}
269142384Sharti	if (err) {
270142384Sharti#ifdef DIAGNOSTIC
271142384Sharti		printf("%s: register write error %s: %d\n", __func__,
272142384Sharti		    utp->chip->name, err);
273142384Sharti#endif
274142384Sharti		return;
275142384Sharti	}
276142384Sharti
277142384Sharti	DELAY(8);
278142384Sharti
279142384Sharti	utp->stats.rx_sbip += utopia_update(utp,
280142384Sharti	    SUNI_REGO_RSOP_BIP8, 2, 0xffff);
281142384Sharti	utp->stats.rx_lbip += utopia_update(utp,
282142384Sharti	    SUNI_REGO_RLOPBIP8_24, 3, 0xfffff);
283142384Sharti	utp->stats.rx_lfebe += utopia_update(utp,
284142384Sharti	    SUNI_REGO_RLOPFEBE, 3, 0xfffff);
285142384Sharti	utp->stats.rx_pbip += utopia_update(utp,
286142384Sharti	    SUNI_REGO_RPOPBIP8, 2, 0xffff);
287142384Sharti	utp->stats.rx_pfebe += utopia_update(utp,
288142384Sharti	    SUNI_REGO_RPOPFEBE, 2, 0xffff);
289142384Sharti	utp->stats.rx_corr += utopia_update(utp,
290142384Sharti	    SUNI_REGO_RACPCHCS, 1, 0xff);
291142384Sharti	utp->stats.rx_uncorr += utopia_update(utp,
292142384Sharti	    SUNI_REGO_RACPUHCS, 1, 0xff);
293142384Sharti	utp->stats.rx_cells += utopia_update(utp,
294142384Sharti	    SUNI_REGO_RACPCNT, 3, 0x7ffff);
295142384Sharti	utp->stats.tx_cells += utopia_update(utp,
296142384Sharti	    SUNI_REGO_TACPCNT, 3, 0x7ffff);
297142384Sharti}
298142384Sharti
299142384Sharti/*
300142384Sharti * Handle interrupt on SUNI chip
301142384Sharti */
302142384Shartistatic void
303142384Shartisuni_intr_default(struct utopia *utp)
304142384Sharti{
305142384Sharti	uint8_t regs[SUNI_REGO_MTEST];
306142384Sharti	u_int n = SUNI_REGO_MTEST;
307142384Sharti	int err;
308142384Sharti
309142384Sharti	/* Read all registers. This acks the interrupts */
310142384Sharti	if ((err = UTP_READREGS(utp, SUNI_REGO_MRESET, regs, &n)) != 0) {
311142384Sharti		printf("SUNI read error %d\n", err);
312142384Sharti		return;
313142384Sharti	}
314142384Sharti	if (n <= SUNI_REGO_RSOPSIS) {
315142384Sharti		printf("%s: could not read RSOPSIS", __func__);
316142384Sharti		return;
317142384Sharti	}
318142384Sharti	/* check for LOSI (loss of signal) */
319142384Sharti	if ((regs[SUNI_REGO_MISTATUS] & SUNI_REGM_MISTATUS_RSOPI) &&
320142384Sharti	    (regs[SUNI_REGO_RSOPSIS] & SUNI_REGM_RSOPSIS_LOSI))
321142384Sharti		utopia_check_carrier(utp, !(regs[SUNI_REGO_RSOPSIS]
322142384Sharti		    & SUNI_REGM_RSOPSIS_LOSV));
323142384Sharti}
324142384Sharti
325142384Sharticonst struct utopia_chip utopia_chip_lite = {
326142384Sharti	UTP_TYPE_SUNI_LITE,
327142384Sharti	"Suni/Lite (PMC-5346)",
328142384Sharti	256,
329142384Sharti	suni_reset_default,
330142384Sharti	suni_set_sdh,
331142384Sharti	suni_set_unass,
332142384Sharti	suni_set_noscramb,
333142384Sharti	suni_update_carrier,
334142384Sharti	suni_set_loopback_lite,
335142384Sharti	suni_intr_default,
336142384Sharti	suni_lite_update_stats,
337142384Sharti};
338142384Sharti
339142384Sharti/*
340142384Sharti * Set loopback mode for the Ultra
341142384Sharti */
342142384Shartistatic int
343142384Shartisuni_set_loopback_ultra(struct utopia *utp, u_int mode)
344142384Sharti{
345142384Sharti	int err;
346142384Sharti	uint32_t val;
347142384Sharti	u_int nmode;
348142384Sharti
349142384Sharti	val = 0;
350142384Sharti	nmode = mode;
351142384Sharti	if (mode & UTP_LOOP_TIME) {
352142384Sharti		nmode &= ~UTP_LOOP_TIME;
353142384Sharti		val |= SUNI_REGM_MCTRL_LOOPT;
354142384Sharti	}
355142384Sharti	if (mode & UTP_LOOP_DIAG) {
356142384Sharti		nmode &= ~UTP_LOOP_DIAG;
357142384Sharti		if (val & SUNI_REGM_MCTRL_LOOPT)
358142384Sharti			return (EINVAL);
359142384Sharti		val |= SUNI_REGM_MCTRL_SDLE;
360142384Sharti	}
361142384Sharti	if (mode & UTP_LOOP_LINE) {
362142384Sharti		nmode &= ~UTP_LOOP_LINE;
363142384Sharti		if (val & (SUNI_REGM_MCTRL_LOOPT | SUNI_REGM_MCTRL_SDLE))
364142384Sharti			return (EINVAL);
365142384Sharti		val |= SUNI_REGM_MCTRL_LLE;
366142384Sharti	}
367142384Sharti	if (mode & UTP_LOOP_PARAL) {
368142384Sharti		nmode &= ~UTP_LOOP_PARAL;
369142384Sharti		val |= SUNI_REGM_MCTRL_PDLE;
370142384Sharti	}
371142384Sharti	if (mode & UTP_LOOP_TWIST) {
372142384Sharti		nmode &= ~UTP_LOOP_TWIST;
373142384Sharti		val |= SUNI_REGM_MCTRL_TPLE;
374142384Sharti	}
375142384Sharti	if (nmode != 0)
376142384Sharti		return (EINVAL);
377142384Sharti
378142384Sharti	err = UTP_WRITEREG(utp, SUNI_REGO_MCTRL,
379142384Sharti	    SUNI_REGM_MCTRL_LLE | SUNI_REGM_MCTRL_SDLE | SUNI_REGM_MCTRL_LOOPT |
380142384Sharti	    SUNI_REGM_MCTRL_PDLE | SUNI_REGM_MCTRL_TPLE, val);
381142384Sharti	if (err)
382142384Sharti		return (err);
383142384Sharti	utp->loopback = mode;
384142384Sharti
385142384Sharti	return (0);
386142384Sharti}
387142384Sharti
388142384Sharticonst struct utopia_chip utopia_chip_ultra = {
389142384Sharti	UTP_TYPE_SUNI_ULTRA,
390142384Sharti	"Suni/Ultra (PMC-5350)",
391142384Sharti	256,
392142384Sharti	suni_reset_default,
393142384Sharti	suni_set_sdh,
394142384Sharti	suni_set_unass,
395142384Sharti	suni_set_noscramb,
396142384Sharti	suni_update_carrier,
397142384Sharti	suni_set_loopback_ultra,
398142384Sharti	suni_intr_default,
399142384Sharti	suni_lite_update_stats,
400142384Sharti};
401142384Sharti
402142384Sharti/*
403142384Sharti * Set loopback mode for the 622
404142384Sharti */
405142384Shartistatic int
406142384Shartisuni_set_loopback_622(struct utopia *utp, u_int mode)
407142384Sharti{
408142384Sharti	int err;
409142384Sharti	uint32_t val;
410142384Sharti	uint8_t config;
411142384Sharti	int smode;
412142384Sharti	u_int nmode;
413142384Sharti	u_int n = 1;
414142384Sharti
415142384Sharti	val = 0;
416142384Sharti	nmode = mode;
417142384Sharti	if (mode & UTP_LOOP_PATH) {
418142384Sharti		nmode &= ~UTP_LOOP_PATH;
419142384Sharti		val |= SUNI_REGM_MCTRLM_DPLE;
420142384Sharti	}
421142384Sharti
422142384Sharti	err = UTP_READREGS(utp, SUNI_REGO_MCONFIG, &config, &n);
423142384Sharti	if (err != 0)
424142384Sharti		return (err);
425142384Sharti	smode = ((config & SUNI_REGM_MCONFIG_TMODE_622) ==
426142384Sharti	    SUNI_REGM_MCONFIG_TMODE_STS1_BIT &&
427142384Sharti	    (config & SUNI_REGM_MCONFIG_RMODE_622) ==
428142384Sharti	    SUNI_REGM_MCONFIG_RMODE_STS1_BIT);
429142384Sharti
430142384Sharti	if (mode & UTP_LOOP_TIME) {
431142384Sharti		if (!smode)
432142384Sharti			return (EINVAL);
433142384Sharti		nmode &= ~UTP_LOOP_TIME;
434142384Sharti		val |= SUNI_REGM_MCTRLM_LOOPT;
435142384Sharti	}
436142384Sharti	if (mode & UTP_LOOP_DIAG) {
437142384Sharti		nmode &= ~UTP_LOOP_DIAG;
438142384Sharti		if (val & SUNI_REGM_MCTRLM_LOOPT)
439142384Sharti			return (EINVAL);
440142384Sharti		val |= SUNI_REGM_MCTRLM_DLE;
441142384Sharti	}
442142384Sharti	if (mode & UTP_LOOP_LINE) {
443142384Sharti		nmode &= ~UTP_LOOP_LINE;
444142384Sharti		if (val & (SUNI_REGM_MCTRLM_LOOPT | SUNI_REGM_MCTRLM_DLE))
445142384Sharti			return (EINVAL);
446142384Sharti		val |= SUNI_REGM_MCTRLM_LLE;
447142384Sharti	}
448142384Sharti	if (nmode != 0)
449142384Sharti		return (EINVAL);
450142384Sharti
451142384Sharti	err = UTP_WRITEREG(utp, SUNI_REGO_MCTRLM,
452142384Sharti	    SUNI_REGM_MCTRLM_LLE | SUNI_REGM_MCTRLM_DLE |
453142384Sharti	    SUNI_REGM_MCTRLM_DPLE | SUNI_REGM_MCTRL_LOOPT, val);
454142384Sharti	if (err)
455142384Sharti		return (err);
456142384Sharti	utp->loopback = mode;
457142384Sharti
458142384Sharti	return (0);
459142384Sharti}
460142384Sharti
461142384Sharti/*
462142384Sharti * Reset the SUNI chip to reflect the current state of utopia.
463142384Sharti */
464142384Shartistatic int
465142384Shartisuni_reset_622(struct utopia *utp)
466142384Sharti{
467142384Sharti	int err = 0;
468142384Sharti
469142384Sharti	if (!(utp->flags & UTP_FL_NORESET)) {
470142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
471142384Sharti		    SUNI_REGM_MRESET_RESET, SUNI_REGM_MRESET_RESET);
472142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
473142384Sharti		    SUNI_REGM_MRESET_RESET, 0);
474142384Sharti	}
475142384Sharti
476142384Sharti	/* disable test mode */
477142384Sharti	err |= UTP_WRITEREG(utp, SUNI_REGO_MTEST, 0xff,
478142384Sharti	    SUNI_REGM_MTEST_DS27_53_622);
479142384Sharti
480142384Sharti	err |= suni_set_chip(utp);
481142384Sharti
482142384Sharti	return (err ? EIO : 0);
483142384Sharti}
484142384Sharti
485142384Sharti/*
486142384Sharti * Update statistics from a SUNI/622
487142384Sharti */
488142384Shartistatic void
489142384Shartisuni_622_update_stats(struct utopia *utp)
490142384Sharti{
491142384Sharti	int err;
492142384Sharti
493142384Sharti	/* write to the master if we can */
494142384Sharti	if (!(utp->flags & UTP_FL_NORESET)) {
495142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_MRESET, 0, 0);
496142384Sharti	} else {
497142384Sharti		err = UTP_WRITEREG(utp, SUNI_REGO_RSOP_BIP8, 0, 0);
498142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_RLOPBIP8_24, 0, 0);
499142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_RPOPBIP8, 0, 0);
500142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_RACPCHCS, 0, 0);
501142384Sharti		err |= UTP_WRITEREG(utp, SUNI_REGO_TACPCNT, 0, 0);
502142384Sharti	}
503142384Sharti	if (err) {
504142384Sharti#ifdef DIAGNOSTIC
505142384Sharti		printf("%s: register write error %s: %d\n", __func__,
506142384Sharti		    utp->chip->name, err);
507142384Sharti#endif
508142384Sharti		return;
509142384Sharti	}
510142384Sharti
511142384Sharti	DELAY(8);
512142384Sharti
513142384Sharti	utp->stats.rx_sbip += utopia_update(utp,
514142384Sharti	    SUNI_REGO_RSOP_BIP8, 2, 0xffff);
515142384Sharti	utp->stats.rx_lbip += utopia_update(utp,
516142384Sharti	    SUNI_REGO_RLOPBIP8_24, 3, 0xfffff);
517142384Sharti	utp->stats.rx_lfebe += utopia_update(utp,
518142384Sharti	    SUNI_REGO_RLOPFEBE, 3, 0xfffff);
519142384Sharti	utp->stats.rx_pbip += utopia_update(utp,
520142384Sharti	    SUNI_REGO_RPOPBIP8, 2, 0xffff);
521142384Sharti	utp->stats.rx_pfebe += utopia_update(utp,
522142384Sharti	    SUNI_REGO_RPOPFEBE, 2, 0xffff);
523142384Sharti	utp->stats.rx_corr += utopia_update(utp,
524142384Sharti	    SUNI_REGO_RACPCHCS_622, 2, 0xfff);
525142384Sharti	utp->stats.rx_uncorr += utopia_update(utp,
526142384Sharti	    SUNI_REGO_RACPUHCS_622, 2, 0xfff);
527142384Sharti	utp->stats.rx_cells += utopia_update(utp,
528142384Sharti	    SUNI_REGO_RACPCNT_622, 3, 0x1fffff);
529142384Sharti	utp->stats.tx_cells += utopia_update(utp,
530142384Sharti	    SUNI_REGO_TACPCNT, 3, 0x1fffff);
531142384Sharti}
532142384Sharti
533142384Sharticonst struct utopia_chip utopia_chip_622 = {
534142384Sharti	UTP_TYPE_SUNI_622,
535142384Sharti	"Suni/622 (PMC-5355)",
536142384Sharti	256,
537142384Sharti	suni_reset_622,
538142384Sharti	suni_set_sdh,
539142384Sharti	suni_set_unass,
540142384Sharti	suni_set_noscramb,
541142384Sharti	suni_update_carrier,
542142384Sharti	suni_set_loopback_622,
543142384Sharti	suni_intr_default,
544142384Sharti	suni_622_update_stats,
545142384Sharti};
546