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$");
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/idtphy.h>
53142384Sharti#include <dev/utopia/utopia.h>
54142384Sharti#include <dev/utopia/utopia_priv.h>
55142384Sharti
56142384Sharti/*
57142384Sharti * Reset IDT77105. There is really no way to reset this thing by acessing
58142384Sharti * the registers. Load the registers with default values.
59142384Sharti */
60142384Shartistatic int
61142384Shartiidt77105_reset(struct utopia *utp)
62142384Sharti{
63142384Sharti	int err = 0;
64142384Sharti	u_int n;
65142384Sharti	uint8_t val[2];
66142384Sharti
67142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_MCR, 0xff,
68142384Sharti	    IDTPHY_REGM_MCR_DRIC | IDTPHY_REGM_MCR_EI);
69142384Sharti	n = 1;
70142384Sharti	err |= UTP_READREGS(utp, IDTPHY_REGO_ISTAT, val, &n);
71142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_DIAG, 0xff, 0);
72142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_LHEC, 0xff, 0);
73142384Sharti
74142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_SEC);
75142384Sharti	n = 2;
76142384Sharti	err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
77142384Sharti
78142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_TX);
79142384Sharti	n = 2;
80142384Sharti	err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
81142384Sharti
82142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_RX);
83142384Sharti	n = 2;
84142384Sharti	err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
85142384Sharti
86142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_HECE);
87142384Sharti	n = 2;
88142384Sharti	err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
89142384Sharti
90142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_MCR, IDTPHY_REGM_MCR_DREC,
91142384Sharti	    IDTPHY_REGM_MCR_DREC);
92142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_DIAG, IDTPHY_REGM_DIAG_RFLUSH,
93142384Sharti	    IDTPHY_REGM_DIAG_RFLUSH);
94142384Sharti
95142384Sharti	/* loopback */
96142384Sharti	err |= utopia_set_loopback(utp, utp->loopback);
97142384Sharti
98142384Sharti	/* update carrier state */
99142384Sharti	err |= utopia_update_carrier(utp);
100142384Sharti
101142384Sharti	return (err ? EIO : 0);
102142384Sharti}
103142384Sharti
104142384Shartistatic int
105142384Shartiidt77105_inval(struct utopia *utp, int what __unused)
106142384Sharti{
107142384Sharti
108142384Sharti	return (EINVAL);
109142384Sharti}
110142384Sharti
111142384Shartistatic int
112142384Shartiidt77105_update_carrier(struct utopia *utp)
113142384Sharti{
114142384Sharti	int err;
115142384Sharti	uint8_t reg;
116142384Sharti	u_int n = 1;
117142384Sharti
118142384Sharti	if ((err = UTP_READREGS(utp, IDTPHY_REGO_ISTAT, &reg, &n)) != 0) {
119142384Sharti		utp->carrier = UTP_CARR_UNKNOWN;
120142384Sharti		return (err);
121142384Sharti	}
122142384Sharti	utopia_check_carrier(utp, reg & IDTPHY_REGM_ISTAT_GOOD);
123142384Sharti	return (0);
124142384Sharti}
125142384Sharti
126142384Shartistatic int
127142384Shartiidt77105_set_loopback(struct utopia *utp, u_int mode)
128142384Sharti{
129142384Sharti	int err;
130142384Sharti
131142384Sharti	switch (mode) {
132142384Sharti	  case UTP_LOOP_NONE:
133142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
134142384Sharti		    IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_NONE);
135142384Sharti		break;
136142384Sharti
137142384Sharti	  case UTP_LOOP_DIAG:
138142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
139142384Sharti		    IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_PHY);
140142384Sharti		break;
141142384Sharti
142142384Sharti	  case UTP_LOOP_LINE:
143142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
144142384Sharti		    IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_LINE);
145142384Sharti		break;
146142384Sharti
147142384Sharti	  default:
148142384Sharti		return (EINVAL);
149142384Sharti	}
150142384Sharti	if (err)
151142384Sharti		return (err);
152142384Sharti	utp->loopback = mode;
153142384Sharti	return (0);
154142384Sharti}
155142384Sharti
156142384Sharti/*
157142384Sharti * Handle interrupt on IDT77105 chip
158142384Sharti */
159142384Shartistatic void
160142384Shartiidt77105_intr(struct utopia *utp)
161142384Sharti{
162142384Sharti	uint8_t reg;
163142384Sharti	u_int n = 1;
164142384Sharti	int err;
165142384Sharti
166142384Sharti	/* Interrupt status and ack the interrupt */
167142384Sharti	if ((err = UTP_READREGS(utp, IDTPHY_REGO_ISTAT, &reg, &n)) != 0) {
168142384Sharti		printf("IDT77105 read error %d\n", err);
169142384Sharti		return;
170142384Sharti	}
171142384Sharti	/* check for signal condition */
172142384Sharti	utopia_check_carrier(utp, reg & IDTPHY_REGM_ISTAT_GOOD);
173142384Sharti}
174142384Sharti
175142384Shartistatic void
176142384Shartiidt77105_update_stats(struct utopia *utp)
177142384Sharti{
178142384Sharti	int err = 0;
179142384Sharti	uint8_t regs[2];
180142384Sharti	u_int n;
181142384Sharti
182142384Sharti#ifdef DIAGNOSTIC
183142384Sharti#define UDIAG(F,A,B)	printf(F, A, B)
184142384Sharti#else
185142384Sharti#define	UDIAG(F,A,B)	do { } while (0)
186142384Sharti#endif
187142384Sharti
188142384Sharti#define	UPD(FIELD, CODE, N, MASK)					\
189142384Sharti	err = UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, CODE);		\
190142384Sharti	if (err != 0) {							\
191142384Sharti		UDIAG("%s: cannot write CNTS: %d\n", __func__, err);	\
192142384Sharti		return;							\
193142384Sharti	}								\
194142384Sharti	n = N;								\
195142384Sharti	err = UTP_READREGS(utp, IDTPHY_REGO_CNT, regs, &n);		\
196142384Sharti	if (err != 0) {							\
197142384Sharti		UDIAG("%s: cannot read CNT: %d\n", __func__, err);	\
198142384Sharti		return;							\
199142384Sharti	}								\
200142384Sharti	if (n != N) {							\
201142384Sharti		UDIAG("%s: got only %u registers\n", __func__, n);	\
202142384Sharti		return;							\
203142384Sharti	}								\
204142384Sharti	if (N == 1)							\
205142384Sharti		utp->stats.FIELD += (regs[0] & MASK);			\
206142384Sharti	else								\
207142384Sharti		utp->stats.FIELD += (regs[0] | (regs[1] << 8)) & MASK;
208142384Sharti
209142384Sharti	UPD(rx_symerr, IDTPHY_REGM_CNTS_SEC, 1, 0xff);
210142384Sharti	UPD(tx_cells, IDTPHY_REGM_CNTS_TX, 2, 0xffff);
211142384Sharti	UPD(rx_cells, IDTPHY_REGM_CNTS_RX, 2, 0xffff);
212142384Sharti	UPD(rx_uncorr, IDTPHY_REGM_CNTS_HECE, 1, 0x1f);
213142384Sharti
214142384Sharti#undef	UDIAG
215142384Sharti#undef	UPD
216142384Sharti}
217142384Sharti
218142384Shartistruct utopia_chip utopia_chip_idt77105 = {
219142384Sharti	UTP_TYPE_IDT77105,
220142384Sharti	"IDT77105",
221142384Sharti	7,
222142384Sharti	idt77105_reset,
223142384Sharti	idt77105_inval,
224142384Sharti	idt77105_inval,
225142384Sharti	idt77105_inval,
226142384Sharti	idt77105_update_carrier,
227142384Sharti	idt77105_set_loopback,
228142384Sharti	idt77105_intr,
229142384Sharti	idt77105_update_stats,
230142384Sharti};
231142384Sharti
232142384Sharti/*
233142384Sharti * Update the carrier status
234142384Sharti */
235142384Shartistatic int
236142384Shartiidt77155_update_carrier(struct utopia *utp)
237142384Sharti{
238142384Sharti	int err;
239142384Sharti	uint8_t reg;
240142384Sharti	u_int n = 1;
241142384Sharti
242142384Sharti	if ((err = UTP_READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
243142384Sharti		utp->carrier = UTP_CARR_UNKNOWN;
244142384Sharti		return (err);
245142384Sharti	}
246142384Sharti	utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
247142384Sharti	return (0);
248142384Sharti}
249142384Sharti
250142384Sharti/*
251142384Sharti * Handle interrupt on IDT77155 chip
252142384Sharti */
253142384Shartistatic void
254142384Shartiidt77155_intr(struct utopia *utp)
255142384Sharti{
256142384Sharti	uint8_t reg;
257142384Sharti	u_int n = 1;
258142384Sharti	int err;
259142384Sharti
260142384Sharti	if ((err = UTP_READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
261142384Sharti		printf("IDT77105 read error %d\n", err);
262142384Sharti		return;
263142384Sharti	}
264142384Sharti	utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
265142384Sharti}
266142384Sharti
267142384Sharti/*
268142384Sharti * set SONET/SDH mode
269142384Sharti */
270142384Shartistatic int
271142384Shartiidt77155_set_sdh(struct utopia *utp, int sdh)
272142384Sharti{
273142384Sharti	int err;
274142384Sharti
275142384Sharti	if (sdh)
276142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_PTRM,
277142384Sharti		    IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SDH);
278142384Sharti	else
279142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_PTRM,
280142384Sharti		    IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SONET);
281142384Sharti	if (err != 0)
282142384Sharti		return (err);
283142384Sharti
284142384Sharti	utp->state &= ~UTP_ST_SDH;
285142384Sharti	if (sdh)
286142384Sharti		utp->state |= UTP_ST_SDH;
287142384Sharti
288142384Sharti	return (0);
289142384Sharti}
290142384Sharti
291142384Sharti/*
292142384Sharti * set idle/unassigned cells
293142384Sharti */
294142384Shartistatic int
295142384Shartiidt77155_set_unass(struct utopia *utp, int unass)
296142384Sharti{
297142384Sharti	int err;
298142384Sharti
299142384Sharti	if (unass)
300142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 0);
301142384Sharti	else
302142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 1);
303142384Sharti	if (err != 0)
304142384Sharti		return (err);
305142384Sharti
306142384Sharti	utp->state &= ~UTP_ST_UNASS;
307142384Sharti	if (unass)
308142384Sharti		utp->state |= UTP_ST_UNASS;
309142384Sharti
310142384Sharti	return (0);
311142384Sharti}
312142384Sharti
313142384Sharti/*
314142384Sharti * enable/disable scrambling
315142384Sharti */
316142384Shartistatic int
317142384Shartiidt77155_set_noscramb(struct utopia *utp, int noscramb)
318142384Sharti{
319142384Sharti	int err;
320142384Sharti
321142384Sharti	if (noscramb) {
322142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_TCC,
323142384Sharti		    IDTPHY_REGM_TCC_DSCR, IDTPHY_REGM_TCC_DSCR);
324142384Sharti		if (err)
325142384Sharti			return (err);
326142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_RCC,
327142384Sharti		    IDTPHY_REGM_RCC_DSCR, IDTPHY_REGM_RCC_DSCR);
328142384Sharti		if (err)
329142384Sharti			return (err);
330142384Sharti		utp->state |= UTP_ST_NOSCRAMB;
331142384Sharti	} else {
332142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_TCC,
333142384Sharti		    IDTPHY_REGM_TCC_DSCR, 0);
334142384Sharti		if (err)
335142384Sharti			return (err);
336142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_RCC,
337142384Sharti		    IDTPHY_REGM_RCC_DSCR, 0);
338142384Sharti		if (err)
339142384Sharti			return (err);
340142384Sharti		utp->state &= ~UTP_ST_NOSCRAMB;
341142384Sharti	}
342142384Sharti	return (0);
343142384Sharti}
344142384Sharti
345142384Sharti/*
346142384Sharti * Set loopback mode for the 77155
347142384Sharti */
348142384Shartistatic int
349142384Shartiidt77155_set_loopback(struct utopia *utp, u_int mode)
350142384Sharti{
351142384Sharti	int err;
352142384Sharti	uint32_t val;
353142384Sharti	u_int nmode;
354142384Sharti
355142384Sharti	val = 0;
356142384Sharti	nmode = mode;
357142384Sharti	if (mode & UTP_LOOP_TIME) {
358142384Sharti		nmode &= ~UTP_LOOP_TIME;
359142384Sharti		val |= IDTPHY_REGM_MCTL_TLOOP;
360142384Sharti	}
361142384Sharti	if (mode & UTP_LOOP_DIAG) {
362142384Sharti		nmode &= ~UTP_LOOP_DIAG;
363142384Sharti		val |= IDTPHY_REGM_MCTL_DLOOP;
364142384Sharti	}
365142384Sharti	if (mode & UTP_LOOP_LINE) {
366142384Sharti		nmode &= ~UTP_LOOP_LINE;
367142384Sharti		val |= IDTPHY_REGM_MCTL_LLOOP;
368142384Sharti	}
369142384Sharti	if (nmode != 0)
370142384Sharti		return (EINVAL);
371142384Sharti
372142384Sharti	err = UTP_WRITEREG(utp, IDTPHY_REGO_MCTL, IDTPHY_REGM_MCTL_TLOOP |
373142384Sharti	    IDTPHY_REGM_MCTL_DLOOP | IDTPHY_REGM_MCTL_LLOOP, val);
374142384Sharti	if (err)
375142384Sharti		return (err);
376142384Sharti	utp->loopback = mode;
377142384Sharti
378142384Sharti	return (0);
379142384Sharti}
380142384Sharti
381142384Sharti/*
382142384Sharti * Set the chip to reflect the current state in utopia.
383142384Sharti * Assume, that the chip has been reset.
384142384Sharti */
385142384Shartistatic int
386142384Shartiidt77155_set_chip(struct utopia *utp)
387142384Sharti{
388142384Sharti	int err = 0;
389142384Sharti
390142384Sharti	/* set sonet/sdh */
391142384Sharti	err |= idt77155_set_sdh(utp, utp->state & UTP_ST_SDH);
392142384Sharti
393142384Sharti	/* unassigned or idle cells */
394142384Sharti	err |= idt77155_set_unass(utp, utp->state & UTP_ST_UNASS);
395142384Sharti
396142384Sharti	/* loopback */
397142384Sharti	err |= idt77155_set_loopback(utp, utp->loopback);
398142384Sharti
399142384Sharti	/* update carrier state */
400142384Sharti	err |= idt77155_update_carrier(utp);
401142384Sharti
402142384Sharti	/* enable interrupts on LOS */
403142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_INT,
404142384Sharti	    IDTPHY_REGM_INT_RXSOHI, IDTPHY_REGM_INT_RXSOHI);
405142384Sharti	err |= UTP_WRITEREG(utp, IDTPHY_REGO_RSOC,
406142384Sharti	    IDTPHY_REGM_RSOC_LOSI, IDTPHY_REGM_RSOC_LOSI);
407142384Sharti
408142384Sharti	return (err ? EIO : 0);
409142384Sharti}
410142384Sharti
411142384Sharti/*
412142384Sharti * Reset the chip to reflect the current state of utopia.
413142384Sharti */
414142384Shartistatic int
415142384Shartiidt77155_reset(struct utopia *utp)
416142384Sharti{
417142384Sharti	int err = 0;
418142384Sharti
419142384Sharti	if (!(utp->flags & UTP_FL_NORESET)) {
420142384Sharti		err |= UTP_WRITEREG(utp, IDTPHY_REGO_MRID,
421142384Sharti		    IDTPHY_REGM_MRID_RESET, IDTPHY_REGM_MRID_RESET);
422142384Sharti		err |= UTP_WRITEREG(utp, IDTPHY_REGO_MRID,
423142384Sharti		    IDTPHY_REGM_MRID_RESET, 0);
424142384Sharti	}
425142384Sharti
426142384Sharti	err |= idt77155_set_chip(utp);
427142384Sharti
428142384Sharti	return (err ? EIO : 0);
429142384Sharti}
430142384Sharti
431142384Sharti/*
432142384Sharti * Update statistics from a IDT77155
433142384Sharti * This appears to be the same as for the Suni/Lite and Ultra. IDT however
434142384Sharti * makes no assessment about the transfer time. Assume 7us.
435142384Sharti */
436142384Shartistatic void
437142384Shartiidt77155_update_stats(struct utopia *utp)
438142384Sharti{
439142384Sharti	int err;
440142384Sharti
441142384Sharti	/* write to the master if we can */
442142384Sharti	if (!(utp->flags & UTP_FL_NORESET)) {
443142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_MRID, 0, 0);
444142384Sharti	} else {
445142384Sharti		err = UTP_WRITEREG(utp, IDTPHY_REGO_BIPC, 0, 0);
446142384Sharti		err |= UTP_WRITEREG(utp, IDTPHY_REGO_B2EC, 0, 0);
447142384Sharti		err |= UTP_WRITEREG(utp, IDTPHY_REGO_B3EC, 0, 0);
448142384Sharti		err |= UTP_WRITEREG(utp, IDTPHY_REGO_CEC, 0, 0);
449142384Sharti		err |= UTP_WRITEREG(utp, IDTPHY_REGO_TXCNT, 0, 0);
450142384Sharti
451142384Sharti	}
452142384Sharti	if (err) {
453142384Sharti#ifdef DIAGNOSTIC
454142384Sharti		printf("%s: register write error %s: %d\n", __func__,
455142384Sharti		    utp->chip->name, err);
456142384Sharti#endif
457142384Sharti		return;
458142384Sharti	}
459142384Sharti
460142384Sharti	DELAY(8);
461142384Sharti
462142384Sharti	utp->stats.rx_sbip += utopia_update(utp,
463142384Sharti	    IDTPHY_REGO_BIPC, 2, 0xffff);
464142384Sharti	utp->stats.rx_lbip += utopia_update(utp,
465142384Sharti	    IDTPHY_REGO_B2EC, 3, 0xfffff);
466142384Sharti	utp->stats.rx_lfebe += utopia_update(utp,
467142384Sharti	    IDTPHY_REGO_FEBEC, 3, 0xfffff);
468142384Sharti	utp->stats.rx_pbip += utopia_update(utp,
469142384Sharti	    IDTPHY_REGO_B3EC, 2, 0xffff);
470142384Sharti	utp->stats.rx_pfebe += utopia_update(utp,
471142384Sharti	    IDTPHY_REGO_PFEBEC, 2, 0xffff);
472142384Sharti	utp->stats.rx_corr += utopia_update(utp,
473142384Sharti	    IDTPHY_REGO_CEC, 1, 0xff);
474142384Sharti	utp->stats.rx_uncorr += utopia_update(utp,
475142384Sharti	    IDTPHY_REGO_UEC, 1, 0xff);
476142384Sharti	utp->stats.rx_cells += utopia_update(utp,
477142384Sharti	    IDTPHY_REGO_RCCNT, 3, 0x7ffff);
478142384Sharti	utp->stats.tx_cells += utopia_update(utp,
479142384Sharti	    IDTPHY_REGO_TXCNT, 3, 0x7ffff);
480142384Sharti}
481142384Sharti
482142384Sharticonst struct utopia_chip utopia_chip_idt77155 = {
483142384Sharti	UTP_TYPE_IDT77155,
484142384Sharti	"IDT77155",
485142384Sharti	0x80,
486142384Sharti	idt77155_reset,
487142384Sharti	idt77155_set_sdh,
488142384Sharti	idt77155_set_unass,
489142384Sharti	idt77155_set_noscramb,
490142384Sharti	idt77155_update_carrier,
491142384Sharti	idt77155_set_loopback,
492142384Sharti	idt77155_intr,
493142384Sharti	idt77155_update_stats,
494142384Sharti};
495