1*1735e5d4Sandvar /* $NetBSD: emac3.c,v 1.16 2024/05/24 20:09:09 andvar Exp $ */
2aad6ef8bSmartin
3aad6ef8bSmartin /*-
4aad6ef8bSmartin * Copyright (c) 2001 The NetBSD Foundation, Inc.
5aad6ef8bSmartin * All rights reserved.
6aad6ef8bSmartin *
7aad6ef8bSmartin * This code is derived from software contributed to The NetBSD Foundation
8aad6ef8bSmartin * by UCHIYAMA Yasushi.
9aad6ef8bSmartin *
10aad6ef8bSmartin * Redistribution and use in source and binary forms, with or without
11aad6ef8bSmartin * modification, are permitted provided that the following conditions
12aad6ef8bSmartin * are met:
13aad6ef8bSmartin * 1. Redistributions of source code must retain the above copyright
14aad6ef8bSmartin * notice, this list of conditions and the following disclaimer.
15aad6ef8bSmartin * 2. Redistributions in binary form must reproduce the above copyright
16aad6ef8bSmartin * notice, this list of conditions and the following disclaimer in the
17aad6ef8bSmartin * documentation and/or other materials provided with the distribution.
18aad6ef8bSmartin *
19aad6ef8bSmartin * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20aad6ef8bSmartin * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21aad6ef8bSmartin * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22aad6ef8bSmartin * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23aad6ef8bSmartin * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24aad6ef8bSmartin * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25aad6ef8bSmartin * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26aad6ef8bSmartin * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27aad6ef8bSmartin * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28aad6ef8bSmartin * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29aad6ef8bSmartin * POSSIBILITY OF SUCH DAMAGE.
30aad6ef8bSmartin */
31aad6ef8bSmartin
32aad6ef8bSmartin /*
33aad6ef8bSmartin * EMAC3 (Ethernet Media Access Controller)
34aad6ef8bSmartin */
35aad6ef8bSmartin
36aad6ef8bSmartin #include <sys/cdefs.h>
37*1735e5d4Sandvar __KERNEL_RCSID(0, "$NetBSD: emac3.c,v 1.16 2024/05/24 20:09:09 andvar Exp $");
38aad6ef8bSmartin
39aad6ef8bSmartin #include "debug_playstation2.h"
40aad6ef8bSmartin
41aad6ef8bSmartin #include <sys/param.h>
42aad6ef8bSmartin #include <sys/systm.h>
43aad6ef8bSmartin
44d6d2ce55Smartin #include <sys/device.h>
45aad6ef8bSmartin #include <sys/socket.h>
46d6d2ce55Smartin #include <sys/pmf.h>
47aad6ef8bSmartin
48aad6ef8bSmartin #include <net/if.h>
49aad6ef8bSmartin #include <net/if_ether.h>
50aad6ef8bSmartin #include <net/if_media.h>
51aad6ef8bSmartin
52aad6ef8bSmartin #include <dev/mii/mii.h>
53aad6ef8bSmartin #include <dev/mii/miivar.h>
54aad6ef8bSmartin
55aad6ef8bSmartin #include <playstation2/ee/eevar.h>
56aad6ef8bSmartin #include <playstation2/dev/emac3reg.h>
57aad6ef8bSmartin #include <playstation2/dev/emac3var.h>
58aad6ef8bSmartin
59aad6ef8bSmartin #ifdef EMAC3_DEBUG
60aad6ef8bSmartin #define STATIC
61aad6ef8bSmartin int emac3_debug = 0;
62aad6ef8bSmartin #define DPRINTF(fmt, args...) \
63aad6ef8bSmartin if (emac3_debug) \
64aad6ef8bSmartin printf("%s: " fmt, __func__ , ##args)
65aad6ef8bSmartin #define DPRINTFN(n, arg) \
66aad6ef8bSmartin if (emac3_debug > (n)) \
67d6d2ce55Smartin printf("%s: " fmt, __func__ , ##args)
68aad6ef8bSmartin #else
69aad6ef8bSmartin #define STATIC static
70aad6ef8bSmartin #define DPRINTF(arg...) ((void)0)
71aad6ef8bSmartin #define DPRINTFN(n, arg...) ((void)0)
72aad6ef8bSmartin #endif
73aad6ef8bSmartin
74aad6ef8bSmartin /* SMAP specific EMAC3 define */
75aad6ef8bSmartin #define EMAC3_BASE MIPS_PHYS_TO_KSEG1(0x14002000)
76aad6ef8bSmartin static inline u_int32_t
_emac3_reg_read_4(int ofs)77aad6ef8bSmartin _emac3_reg_read_4(int ofs)
78aad6ef8bSmartin {
79aad6ef8bSmartin bus_addr_t a_ = EMAC3_BASE + ofs;
80aad6ef8bSmartin
81aad6ef8bSmartin return (_reg_read_2(a_) << 16) | _reg_read_2(a_ + 2);
82aad6ef8bSmartin }
83aad6ef8bSmartin
84aad6ef8bSmartin static inline void
_emac3_reg_write_4(int ofs,u_int32_t v)85aad6ef8bSmartin _emac3_reg_write_4(int ofs, u_int32_t v)
86aad6ef8bSmartin {
87aad6ef8bSmartin bus_addr_t a_ = EMAC3_BASE + ofs;
88aad6ef8bSmartin
89aad6ef8bSmartin _reg_write_2(a_, (v >> 16) & 0xffff);
90aad6ef8bSmartin _reg_write_2(a_ + 2, v & 0xffff);
91aad6ef8bSmartin }
92aad6ef8bSmartin
93aad6ef8bSmartin STATIC int emac3_phy_ready(void);
94aad6ef8bSmartin STATIC int emac3_soft_reset(void);
95aad6ef8bSmartin STATIC void emac3_config(const u_int8_t *);
96aad6ef8bSmartin
97aad6ef8bSmartin int
emac3_init(struct emac3_softc * sc)98aad6ef8bSmartin emac3_init(struct emac3_softc *sc)
99aad6ef8bSmartin {
100aad6ef8bSmartin u_int32_t r;
101aad6ef8bSmartin
102aad6ef8bSmartin /* save current mode before reset */
103aad6ef8bSmartin r = _emac3_reg_read_4(EMAC3_MR1);
104aad6ef8bSmartin
105aad6ef8bSmartin if (emac3_soft_reset() != 0) {
1061e2880f2Sriastradh printf("%s: reset failed.\n", device_xname(sc->dev));
107aad6ef8bSmartin return (1);
108aad6ef8bSmartin }
109aad6ef8bSmartin
110aad6ef8bSmartin /* set operation mode */
111aad6ef8bSmartin r |= MR1_RFS_2KB | MR1_TFS_1KB | MR1_TR0_SINGLE | MR1_TR1_SINGLE;
112aad6ef8bSmartin _emac3_reg_write_4(EMAC3_MR1, r);
113aad6ef8bSmartin
114aad6ef8bSmartin sc->mode1_reg = _emac3_reg_read_4(EMAC3_MR1);
115aad6ef8bSmartin
116aad6ef8bSmartin emac3_intr_clear();
117aad6ef8bSmartin emac3_intr_disable();
118aad6ef8bSmartin
119aad6ef8bSmartin emac3_config(sc->eaddr);
120aad6ef8bSmartin
121aad6ef8bSmartin return (0);
122aad6ef8bSmartin }
123aad6ef8bSmartin
124aad6ef8bSmartin void
emac3_exit(struct emac3_softc * sc)125aad6ef8bSmartin emac3_exit(struct emac3_softc *sc)
126aad6ef8bSmartin {
127aad6ef8bSmartin int retry = 10000;
128aad6ef8bSmartin
129aad6ef8bSmartin /* wait for kicked transmission */
130aad6ef8bSmartin while (((_emac3_reg_read_4(EMAC3_TMR0) & TMR0_GNP0) != 0) &&
131aad6ef8bSmartin --retry > 0)
132aad6ef8bSmartin ;
133aad6ef8bSmartin
134aad6ef8bSmartin if (retry == 0)
1351e2880f2Sriastradh printf("%s: still running.\n", device_xname(sc->dev));
136aad6ef8bSmartin }
137aad6ef8bSmartin
138aad6ef8bSmartin int
emac3_reset(struct emac3_softc * sc)139aad6ef8bSmartin emac3_reset(struct emac3_softc *sc)
140aad6ef8bSmartin {
141aad6ef8bSmartin
142aad6ef8bSmartin if (emac3_soft_reset() != 0) {
1431e2880f2Sriastradh printf("%s: reset failed.\n", device_xname(sc->dev));
144aad6ef8bSmartin return (1);
145aad6ef8bSmartin }
146aad6ef8bSmartin
147aad6ef8bSmartin /* restore previous mode */
148aad6ef8bSmartin _emac3_reg_write_4(EMAC3_MR1, sc->mode1_reg);
149aad6ef8bSmartin
150aad6ef8bSmartin emac3_config(sc->eaddr);
151aad6ef8bSmartin
152aad6ef8bSmartin return (0);
153aad6ef8bSmartin }
154aad6ef8bSmartin
155aad6ef8bSmartin void
emac3_enable(void)156d6d2ce55Smartin emac3_enable(void)
157aad6ef8bSmartin {
158aad6ef8bSmartin
159aad6ef8bSmartin _emac3_reg_write_4(EMAC3_MR0, MR0_TXE | MR0_RXE);
160aad6ef8bSmartin }
161aad6ef8bSmartin
162aad6ef8bSmartin void
emac3_disable(void)163d6d2ce55Smartin emac3_disable(void)
164aad6ef8bSmartin {
165aad6ef8bSmartin int retry = 10000;
166aad6ef8bSmartin
167aad6ef8bSmartin _emac3_reg_write_4(EMAC3_MR0,
168aad6ef8bSmartin _emac3_reg_read_4(EMAC3_MR0) & ~(MR0_TXE | MR0_RXE));
169aad6ef8bSmartin
170aad6ef8bSmartin /* wait for idling state */
171aad6ef8bSmartin while (((_emac3_reg_read_4(EMAC3_MR0) & (MR0_RXI | MR0_TXI)) !=
172aad6ef8bSmartin (MR0_RXI | MR0_TXI)) && --retry > 0)
173aad6ef8bSmartin ;
174aad6ef8bSmartin
175aad6ef8bSmartin if (retry == 0)
176aad6ef8bSmartin printf("emac3 running.\n");
177aad6ef8bSmartin }
178aad6ef8bSmartin
179aad6ef8bSmartin void
emac3_intr_enable(void)180d6d2ce55Smartin emac3_intr_enable(void)
181aad6ef8bSmartin {
182aad6ef8bSmartin
183aad6ef8bSmartin _emac3_reg_write_4(EMAC3_ISER, ~0);
184aad6ef8bSmartin }
185aad6ef8bSmartin
186aad6ef8bSmartin void
emac3_intr_disable(void)187d6d2ce55Smartin emac3_intr_disable(void)
188aad6ef8bSmartin {
189aad6ef8bSmartin
190aad6ef8bSmartin _emac3_reg_write_4(EMAC3_ISER, 0);
191aad6ef8bSmartin }
192aad6ef8bSmartin
193aad6ef8bSmartin void
emac3_intr_clear(void)194d6d2ce55Smartin emac3_intr_clear(void)
195aad6ef8bSmartin {
196aad6ef8bSmartin
197aad6ef8bSmartin _emac3_reg_write_4(EMAC3_ISR, _emac3_reg_read_4(EMAC3_ISR));
198aad6ef8bSmartin }
199aad6ef8bSmartin
200aad6ef8bSmartin int
emac3_intr(void * arg)201aad6ef8bSmartin emac3_intr(void *arg)
202aad6ef8bSmartin {
203aad6ef8bSmartin u_int32_t r = _emac3_reg_read_4(EMAC3_ISR);
204aad6ef8bSmartin
205aad6ef8bSmartin DPRINTF("%08x\n", r);
206aad6ef8bSmartin _emac3_reg_write_4(EMAC3_ISR, r);
207aad6ef8bSmartin
208aad6ef8bSmartin return (1);
209aad6ef8bSmartin }
210aad6ef8bSmartin
211aad6ef8bSmartin void
emac3_tx_kick(void)212d6d2ce55Smartin emac3_tx_kick(void)
213aad6ef8bSmartin {
214aad6ef8bSmartin
215aad6ef8bSmartin _emac3_reg_write_4(EMAC3_TMR0, TMR0_GNP0);
216aad6ef8bSmartin }
217aad6ef8bSmartin
218aad6ef8bSmartin int
emac3_tx_done(void)219d6d2ce55Smartin emac3_tx_done(void)
220aad6ef8bSmartin {
221aad6ef8bSmartin
222aad6ef8bSmartin return (_emac3_reg_read_4(EMAC3_TMR0) & TMR0_GNP0);
223aad6ef8bSmartin }
224aad6ef8bSmartin
225aad6ef8bSmartin void
emac3_setmulti(struct emac3_softc * sc,struct ethercom * ec)226aad6ef8bSmartin emac3_setmulti(struct emac3_softc *sc, struct ethercom *ec)
227aad6ef8bSmartin {
228aad6ef8bSmartin struct ether_multi *enm;
229aad6ef8bSmartin struct ether_multistep step;
230aad6ef8bSmartin struct ifnet *ifp = &ec->ec_if;
231aad6ef8bSmartin u_int32_t r;
232aad6ef8bSmartin
233aad6ef8bSmartin r = _emac3_reg_read_4(EMAC3_RMR);
234aad6ef8bSmartin r &= ~(RMR_PME | RMR_PMME | RMR_MIAE);
235aad6ef8bSmartin
236aad6ef8bSmartin if (ifp->if_flags & IFF_PROMISC) {
237aad6ef8bSmartin allmulti:
238aad6ef8bSmartin ifp->if_flags |= IFF_ALLMULTI;
239aad6ef8bSmartin r |= RMR_PME;
240aad6ef8bSmartin _emac3_reg_write_4(EMAC3_RMR, r);
241aad6ef8bSmartin
242aad6ef8bSmartin return;
243aad6ef8bSmartin }
244aad6ef8bSmartin
24583759283Smsaitoh ETHER_LOCK(ec);
246aad6ef8bSmartin ETHER_FIRST_MULTI(step, ec, enm);
247aad6ef8bSmartin while (enm != NULL) {
248aad6ef8bSmartin if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
24983759283Smsaitoh ETHER_ADDR_LEN) != 0) {
25083759283Smsaitoh ETHER_UNLOCK(ec);
251aad6ef8bSmartin goto allmulti;
25283759283Smsaitoh }
253aad6ef8bSmartin
2548bd396a3Smsaitoh ETHER_NEXT_MULTI(step, enm);
255aad6ef8bSmartin }
25683759283Smsaitoh ETHER_UNLOCK(ec);
257aad6ef8bSmartin
258aad6ef8bSmartin /* XXX always multicast promiscuous mode. XXX use hash table.. */
259aad6ef8bSmartin ifp->if_flags |= IFF_ALLMULTI;
260aad6ef8bSmartin r |= RMR_PMME;
261aad6ef8bSmartin _emac3_reg_write_4(EMAC3_RMR, r);
262aad6ef8bSmartin }
263aad6ef8bSmartin
264aad6ef8bSmartin int
emac3_soft_reset(void)265d6d2ce55Smartin emac3_soft_reset(void)
266aad6ef8bSmartin {
267aad6ef8bSmartin int retry = 10000;
268aad6ef8bSmartin
269aad6ef8bSmartin _emac3_reg_write_4(EMAC3_MR0, MR0_SRST);
270aad6ef8bSmartin
271aad6ef8bSmartin while ((_emac3_reg_read_4(EMAC3_MR0) & MR0_SRST) == MR0_SRST &&
272aad6ef8bSmartin --retry > 0)
273aad6ef8bSmartin ;
274aad6ef8bSmartin
275aad6ef8bSmartin return (retry == 0);
276aad6ef8bSmartin }
277aad6ef8bSmartin
278aad6ef8bSmartin void
emac3_config(const u_int8_t * eaddr)279aad6ef8bSmartin emac3_config(const u_int8_t *eaddr)
280aad6ef8bSmartin {
281aad6ef8bSmartin
282aad6ef8bSmartin /* set ethernet address */
283aad6ef8bSmartin _emac3_reg_write_4(EMAC3_IAHR, (eaddr[0] << 8) | eaddr[1]);
284aad6ef8bSmartin _emac3_reg_write_4(EMAC3_IALR, (eaddr[2] << 24) | (eaddr[3] << 16) |
285aad6ef8bSmartin (eaddr[4] << 8) | eaddr[5]);
286aad6ef8bSmartin
287aad6ef8bSmartin /* inter-frame GAP */
288aad6ef8bSmartin _emac3_reg_write_4(EMAC3_IPGVR, 4);
289aad6ef8bSmartin
290aad6ef8bSmartin /* RX mode */
291aad6ef8bSmartin _emac3_reg_write_4(EMAC3_RMR,
292aad6ef8bSmartin RMR_SP | /* strip padding */
293aad6ef8bSmartin RMR_SFCS | /* strip FCS */
294aad6ef8bSmartin RMR_IAE | /* individual address enable */
295*1735e5d4Sandvar RMR_BAE); /* broadcast address enable */
296aad6ef8bSmartin
297aad6ef8bSmartin /* TX mode */
298aad6ef8bSmartin _emac3_reg_write_4(EMAC3_TMR1,
299aad6ef8bSmartin ((7 << TMR1_TLR_SHIFT) & TMR1_TLR_MASK) | /* 16 word burst */
300aad6ef8bSmartin ((15 << TMR1_TUR_SHIFT) & TMR1_TUR_MASK));
301aad6ef8bSmartin
302aad6ef8bSmartin /* TX threshold */
303aad6ef8bSmartin _emac3_reg_write_4(EMAC3_TRTR,
304aad6ef8bSmartin (12 << TRTR_SHIFT) & TRTR_MASK); /* 832 bytes */
305aad6ef8bSmartin
306aad6ef8bSmartin /* RX watermark */
307aad6ef8bSmartin _emac3_reg_write_4(EMAC3_RWMR,
308aad6ef8bSmartin ((16 << RWMR_RLWM_SHIFT) & RWMR_RLWM_MASK) |
309aad6ef8bSmartin ((128 << RWMR_RHWM_SHIFT) & RWMR_RHWM_MASK));
310aad6ef8bSmartin }
311aad6ef8bSmartin
312aad6ef8bSmartin /*
313aad6ef8bSmartin * PHY/MII
314aad6ef8bSmartin */
315a5cdd4b4Smsaitoh int
emac3_phy_writereg(device_t self,int phy,int reg,uint16_t val)316a5cdd4b4Smsaitoh emac3_phy_writereg(device_t self, int phy, int reg, uint16_t val)
317aad6ef8bSmartin {
318a5cdd4b4Smsaitoh int rv;
319aad6ef8bSmartin
320a5cdd4b4Smsaitoh if ((rv = emac3_phy_ready()) != 0)
321a5cdd4b4Smsaitoh return rv;
322aad6ef8bSmartin
323aad6ef8bSmartin _emac3_reg_write_4(EMAC3_STACR, STACR_WRITE |
324aad6ef8bSmartin ((phy << STACR_PCDASHIFT) & STACR_PCDA) | /* command dest addr*/
325aad6ef8bSmartin ((reg << STACR_PRASHIFT) & STACR_PRA) | /* register addr */
326a5cdd4b4Smsaitoh ((val << STACR_PHYDSHIFT) & STACR_PHYD)); /* data */
327aad6ef8bSmartin
328a5cdd4b4Smsaitoh return emac3_phy_ready();
329aad6ef8bSmartin }
330aad6ef8bSmartin
331aad6ef8bSmartin int
emac3_phy_readreg(device_t self,int phy,int reg,uint16_t * val)332a5cdd4b4Smsaitoh emac3_phy_readreg(device_t self, int phy, int reg, uint16_t *val)
333aad6ef8bSmartin {
334a5cdd4b4Smsaitoh int rv;
335aad6ef8bSmartin
336a5cdd4b4Smsaitoh if ((rv = emac3_phy_ready()) != 0)
337a5cdd4b4Smsaitoh return rv;
338aad6ef8bSmartin
339aad6ef8bSmartin _emac3_reg_write_4(EMAC3_STACR, STACR_READ |
340aad6ef8bSmartin ((phy << STACR_PCDASHIFT) & STACR_PCDA) | /* command dest addr*/
341aad6ef8bSmartin ((reg << STACR_PRASHIFT) & STACR_PRA)); /* register addr */
342aad6ef8bSmartin
343a5cdd4b4Smsaitoh if ((rv = emac3_phy_ready()) != 0)
344a5cdd4b4Smsaitoh return rv;
345aad6ef8bSmartin
346a5cdd4b4Smsaitoh *val =(_emac3_reg_read_4(EMAC3_STACR) >> STACR_PHYDSHIFT) & 0xffff;
347a5cdd4b4Smsaitoh return 0;
348aad6ef8bSmartin }
349aad6ef8bSmartin
350aad6ef8bSmartin void
emac3_phy_statchg(struct ifnet * ifp)351117132e6Smartin emac3_phy_statchg(struct ifnet *ifp)
352aad6ef8bSmartin {
353aad6ef8bSmartin #define EMAC3_FDX (MR1_FDE | MR1_EIFC | MR1_APP)
354117132e6Smartin struct emac3_softc *sc = ifp->if_softc;
355aad6ef8bSmartin int media;
356aad6ef8bSmartin u_int32_t r;
357aad6ef8bSmartin
358aad6ef8bSmartin media = sc->mii.mii_media_active;
359aad6ef8bSmartin
360aad6ef8bSmartin r = _emac3_reg_read_4(EMAC3_MR1);
361aad6ef8bSmartin
362aad6ef8bSmartin r &= ~(MR1_MF_MASK | MR1_IST | EMAC3_FDX);
363aad6ef8bSmartin
364aad6ef8bSmartin switch (media & 0x1f) {
365aad6ef8bSmartin default:
366aad6ef8bSmartin printf("unknown media type. %08x", media);
367aad6ef8bSmartin /* FALLTHROUGH */
368aad6ef8bSmartin case IFM_100_TX:
369aad6ef8bSmartin r |= (MR1_MF_100MBS | MR1_IST);
370aad6ef8bSmartin if (media & IFM_FDX)
371aad6ef8bSmartin r |= EMAC3_FDX;
372aad6ef8bSmartin
373aad6ef8bSmartin break;
374aad6ef8bSmartin case IFM_10_T:
375aad6ef8bSmartin r |= MR1_MF_10MBS;
376aad6ef8bSmartin if (media & IFM_FDX)
377aad6ef8bSmartin r |= (EMAC3_FDX | MR1_IST);
378aad6ef8bSmartin break;
379aad6ef8bSmartin }
380aad6ef8bSmartin
381aad6ef8bSmartin _emac3_reg_write_4(EMAC3_MR1, r);
382aad6ef8bSmartin
383aad6ef8bSmartin /* store current state for re-initialize */
384aad6ef8bSmartin sc->mode1_reg = _emac3_reg_read_4(EMAC3_MR1);
385aad6ef8bSmartin #undef EMAC3_FDX
386aad6ef8bSmartin }
387aad6ef8bSmartin
388aad6ef8bSmartin int
emac3_phy_ready(void)389d6d2ce55Smartin emac3_phy_ready(void)
390aad6ef8bSmartin {
391aad6ef8bSmartin int retry = 10000;
392aad6ef8bSmartin
393aad6ef8bSmartin while ((_emac3_reg_read_4(EMAC3_STACR) & STACR_OC) == 0 &&
394aad6ef8bSmartin --retry > 0)
395aad6ef8bSmartin ;
396aad6ef8bSmartin if (retry == 0) {
397aad6ef8bSmartin printf("emac3: phy busy.\n");
398a5cdd4b4Smsaitoh return ETIMEDOUT;
399aad6ef8bSmartin }
400aad6ef8bSmartin
401aad6ef8bSmartin return (0);
402aad6ef8bSmartin }
403aad6ef8bSmartin
404