1 /* $OpenBSD: if_ef_isapnp.c,v 1.42 2023/09/11 08:41:26 mvs Exp $ */
2
3 /*
4 * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "bpfilter.h"
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/mbuf.h>
34 #include <sys/socket.h>
35 #include <sys/ioctl.h>
36 #include <sys/errno.h>
37 #include <sys/syslog.h>
38 #include <sys/device.h>
39 #include <sys/queue.h>
40 #include <sys/kernel.h>
41 #include <sys/timeout.h>
42
43 #include <net/if.h>
44 #include <net/if_media.h>
45
46 #include <netinet/in.h>
47 #include <netinet/if_ether.h>
48
49 #if NBPFILTER > 0
50 #include <net/bpf.h>
51 #endif
52
53 #include <machine/cpu.h>
54 #include <machine/bus.h>
55 #include <machine/intr.h>
56
57 #include <dev/mii/mii.h>
58 #include <dev/mii/miivar.h>
59 #include <dev/isa/isavar.h>
60 #include <dev/isa/isadmavar.h>
61 #include <dev/ic/elink3reg.h>
62
63 #undef EF_DEBUG
64
65 struct ef_softc {
66 struct device sc_dv;
67 bus_space_tag_t sc_iot;
68 bus_space_handle_t sc_ioh;
69 struct arpcom sc_arpcom;
70 struct mii_data sc_mii;
71 struct timeout sc_tick_tmo;
72 void * sc_ih;
73 int sc_tx_start_thresh;
74 int sc_tx_succ_ok;
75 int sc_busmaster;
76 };
77
78 #define EF_W0_EEPROM_COMMAND 0x200a
79 #define EF_EEPROM_BUSY (1 << 9)
80 #define EF_EEPROM_READ (1 << 7)
81 #define EF_W0_EEPROM_DATA 0x200c
82
83 #define EF_W1_TX_PIO_WR_1 0x10
84 #define EF_W1_RX_PIO_RR_1 0x10
85 #define EF_W1_RX_ERRORS 0x14
86 #define EF_W1_RX_STATUS 0x18
87 #define EF_W1_TX_STATUS 0x1b
88 #define EF_W1_FREE_TX 0x1c
89
90 #define EF_W4_MEDIA 0x0a
91 #define EF_MEDIA_SQE 0x0008 /* sqe error for aui */
92 #define EF_MEDIA_TP 0x00c0 /* link/jabber, 10baseT */
93 #define EF_MEDIA_LNK 0x0080 /* linkbeat, 100baseTX/FX */
94 #define EF_MEDIA_LNKBEAT 0x0800
95
96 /* Window 4: EP_W4_CTRLR_STATUS: mii manipulation */
97 #define EF_MII_CLK 0x01 /* clock bit */
98 #define EF_MII_DATA 0x02 /* data bit */
99 #define EF_MII_DIR 0x04 /* direction */
100
101 int ef_isapnp_match(struct device *, void *, void *);
102 void ef_isapnp_attach(struct device *, struct device *, void *);
103
104 void efstart(struct ifnet *);
105 int efioctl(struct ifnet *, u_long, caddr_t);
106 void efwatchdog(struct ifnet *);
107 void efreset(struct ef_softc *);
108 void efstop(struct ef_softc *);
109 void efsetmulti(struct ef_softc *);
110 int efbusyeeprom(struct ef_softc *);
111 int efintr(void *);
112 void efinit(struct ef_softc *);
113 void efcompletecmd(struct ef_softc *, u_int, u_int);
114 void eftxstat(struct ef_softc *);
115 void efread(struct ef_softc *);
116 struct mbuf *efget(struct ef_softc *, int totlen);
117
118 void ef_miibus_writereg(struct device *, int, int, int);
119 void ef_miibus_statchg(struct device *);
120 int ef_miibus_readreg(struct device *, int, int);
121 void ef_mii_writeb(struct ef_softc *, int);
122 void ef_mii_sync(struct ef_softc *);
123 int ef_ifmedia_upd(struct ifnet *);
124 void ef_ifmedia_sts(struct ifnet *, struct ifmediareq *);
125 void ef_tick(void *);
126
127 struct cfdriver ef_cd = {
128 NULL, "ef", DV_IFNET
129 };
130
131 const struct cfattach ef_isapnp_ca = {
132 sizeof(struct ef_softc), ef_isapnp_match, ef_isapnp_attach
133 };
134
135 int
ef_isapnp_match(struct device * parent,void * match,void * aux)136 ef_isapnp_match(struct device *parent, void *match, void *aux)
137 {
138 return (1);
139 }
140
141 void
ef_isapnp_attach(struct device * parent,struct device * self,void * aux)142 ef_isapnp_attach(struct device *parent, struct device *self, void *aux)
143 {
144 struct ef_softc *sc = (void *)self;
145 struct isa_attach_args *ia = aux;
146 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
147 bus_space_tag_t iot;
148 bus_space_handle_t ioh;
149 int i;
150 u_int16_t x;
151 u_int32_t cfg;
152
153 sc->sc_iot = iot = ia->ia_iot;
154 sc->sc_ioh = ioh = ia->ipa_io[0].h;
155
156 efcompletecmd(sc, EP_COMMAND, GLOBAL_RESET);
157 DELAY(1500);
158
159 for (i = 0; i < 3; i++) {
160 if (efbusyeeprom(sc))
161 return;
162
163 bus_space_write_2(iot, ioh, EF_W0_EEPROM_COMMAND,
164 EF_EEPROM_READ | i);
165
166 if (efbusyeeprom(sc))
167 return;
168
169 x = bus_space_read_2(iot, ioh, EF_W0_EEPROM_DATA);
170
171 sc->sc_arpcom.ac_enaddr[(i << 1)] = x >> 8;
172 sc->sc_arpcom.ac_enaddr[(i << 1) + 1] = x;
173 }
174
175 printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
176
177 GO_WINDOW(3);
178 cfg = bus_space_read_4(iot, ioh, EP_W3_INTERNAL_CONFIG);
179 cfg &= ~(0x00f00000);
180 cfg |= (0x06 << 20);
181 bus_space_write_4(iot, ioh, EP_W3_INTERNAL_CONFIG, cfg);
182
183 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
184 IPL_NET, efintr, sc, sc->sc_dv.dv_xname);
185
186 if (ia->ia_drq != DRQUNK)
187 isadma_cascade(ia->ia_drq);
188
189 timeout_set(&sc->sc_tick_tmo, ef_tick, sc);
190
191 bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
192 ifp->if_softc = sc;
193 ifp->if_start = efstart;
194 ifp->if_ioctl = efioctl;
195 ifp->if_watchdog = efwatchdog;
196 ifp->if_flags =
197 IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
198
199 sc->sc_mii.mii_ifp = ifp;
200 sc->sc_mii.mii_readreg = ef_miibus_readreg;
201 sc->sc_mii.mii_writereg = ef_miibus_writereg;
202 sc->sc_mii.mii_statchg = ef_miibus_statchg;
203 ifmedia_init(&sc->sc_mii.mii_media, 0, ef_ifmedia_upd, ef_ifmedia_sts);
204 mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
205 0);
206 if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
207 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
208 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
209 } else
210 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
211
212 if_attach(ifp);
213 ether_ifattach(ifp);
214
215 sc->sc_tx_start_thresh = 20;
216
217 efcompletecmd(sc, EP_COMMAND, RX_RESET);
218 efcompletecmd(sc, EP_COMMAND, TX_RESET);
219 }
220
221 void
efstart(struct ifnet * ifp)222 efstart(struct ifnet *ifp)
223 {
224 struct ef_softc *sc = ifp->if_softc;
225 bus_space_tag_t iot = sc->sc_iot;
226 bus_space_handle_t ioh = sc->sc_ioh;
227 struct mbuf *m, *m0;
228 int s, len, pad, i;
229 int fillcnt = 0;
230 u_int32_t filler = 0;
231
232 if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
233 return;
234
235 startagain:
236 m0 = ifq_deq_begin(&ifp->if_snd);
237 if (m0 == NULL)
238 return;
239
240 if ((m0->m_flags & M_PKTHDR) == 0)
241 panic("efstart: no header mbuf");
242 len = m0->m_pkthdr.len;
243 pad = (4 - len) & 3;
244
245 if (len + pad > ETHER_MAX_LEN) {
246 ifp->if_oerrors++;
247 ifq_deq_commit(&ifp->if_snd, m0);
248 m_freem(m0);
249 goto startagain;
250 }
251
252 if (bus_space_read_2(iot, ioh, EF_W1_FREE_TX) < len + pad + 4) {
253 bus_space_write_2(iot, ioh, EP_COMMAND,
254 SET_TX_AVAIL_THRESH | ((len + pad) >> 2));
255 ifq_deq_rollback(&ifp->if_snd, m0);
256 ifq_set_oactive(&ifp->if_snd);
257 return;
258 } else {
259 bus_space_write_2(iot, ioh, EP_COMMAND,
260 SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE);
261 }
262
263 bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
264 ((len / 4 + sc->sc_tx_start_thresh)));
265
266 #if NBPFILTER
267 if (ifp->if_bpf)
268 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
269 #endif
270
271 ifq_deq_commit(&ifp->if_snd, m0);
272 if (m0 == NULL) /* XXX not needed */
273 return;
274
275 s = splhigh();
276
277 bus_space_write_4(iot, ioh, EF_W1_TX_PIO_WR_1, len);
278 for (m = m0; m; ) {
279 if (fillcnt) {
280 while (m->m_len && fillcnt < 4) {
281 fillcnt++;
282 filler >>= 8;
283 filler |= m->m_data[0] << 24;
284 m->m_data++;
285 m->m_len--;
286 }
287 if (fillcnt == 4) {
288 bus_space_write_4(iot, ioh,
289 EF_W1_TX_PIO_WR_1, filler);
290 filler = 0;
291 fillcnt = 0;
292 }
293 }
294
295 if (m->m_len & ~3)
296 bus_space_write_multi_4(iot, ioh,
297 EF_W1_TX_PIO_WR_1, (u_int32_t *)m->m_data,
298 m->m_len >> 2);
299 for (i = 0; i < (m->m_len & 3); i++) {
300 fillcnt++;
301 filler >>= 8;
302 filler |= m->m_data[(m->m_len & ~3) + i] << 24;
303 }
304 m0 = m_free(m);
305 m = m0;
306 }
307
308 if (fillcnt) {
309 bus_space_write_4(iot, ioh, EF_W1_TX_PIO_WR_1,
310 filler >> (32 - (8 * fillcnt)));
311 fillcnt = 0;
312 filler = 0;
313 }
314
315 splx(s);
316
317 goto startagain;
318 }
319
320 int
efioctl(struct ifnet * ifp,u_long cmd,caddr_t data)321 efioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
322 {
323 struct ef_softc *sc = ifp->if_softc;
324 struct ifreq *ifr = (struct ifreq *)data;
325 int s, error = 0;
326
327 s = splnet();
328
329 switch (cmd) {
330 case SIOCSIFADDR:
331 ifp->if_flags |= IFF_UP;
332 efinit(sc);
333 break;
334 case SIOCSIFMEDIA:
335 case SIOCGIFMEDIA:
336 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
337 break;
338 case SIOCSIFFLAGS:
339 if ((ifp->if_flags & IFF_UP) == 0 &&
340 (ifp->if_flags & IFF_RUNNING) != 0) {
341 efstop(sc);
342 ifp->if_flags &= ~IFF_RUNNING;
343 } else if ((ifp->if_flags & IFF_UP) != 0 &&
344 (ifp->if_flags & IFF_RUNNING) == 0) {
345 efinit(sc);
346 }
347 efsetmulti(sc);
348 break;
349
350 default:
351 error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data);
352 }
353
354 if (error == ENETRESET) {
355 if (ifp->if_flags & IFF_RUNNING) {
356 efreset(sc);
357 efsetmulti(sc);
358 }
359 error = 0;
360 }
361
362 splx(s);
363 return (error);
364 }
365
366 void
efinit(struct ef_softc * sc)367 efinit(struct ef_softc *sc)
368 {
369 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
370 bus_space_tag_t iot = sc->sc_iot;
371 bus_space_handle_t ioh = sc->sc_ioh;
372 int i, s;
373
374 s = splnet();
375
376 efstop(sc);
377
378 while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
379 ;
380
381 GO_WINDOW(2);
382 for (i = 0; i < 6; i++)
383 bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i,
384 sc->sc_arpcom.ac_enaddr[i]);
385 for (i = 0; i < 3; i += 2)
386 bus_space_write_2(iot, ioh, EP_W2_RECVMASK_0 + (i * 2), 0);
387
388 efcompletecmd(sc, EP_COMMAND, RX_RESET);
389 efcompletecmd(sc, EP_COMMAND, TX_RESET);
390
391 bus_space_write_2(iot, ioh, EP_COMMAND,
392 SET_TX_AVAIL_THRESH | (ETHER_MAX_DIX_LEN >> 2));
393
394 efsetmulti(sc);
395
396 bus_space_write_2(iot, ioh, EP_COMMAND, STATUS_ENABLE | 0);
397
398 GO_WINDOW(6);
399 for (i = 0; i < 10; i++)
400 (void)bus_space_read_1(iot, ioh, i);
401 (void)bus_space_read_2(iot, ioh, 10);
402 (void)bus_space_read_2(iot, ioh, 12);
403 GO_WINDOW(4);
404 (void)bus_space_read_1(iot, ioh, 12);
405 bus_space_write_2(iot, ioh, EP_W4_NET_DIAG, 0x0040);
406
407 GO_WINDOW(7);
408
409 efsetmulti(sc);
410
411 bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
412 bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
413
414 bus_space_write_2(iot, ioh, EP_COMMAND, STATUS_ENABLE |
415 S_CARD_FAILURE | S_INT_RQD | S_UPD_STATS | S_TX_COMPLETE |
416 S_TX_AVAIL | S_RX_COMPLETE |
417 (sc->sc_busmaster ? S_DMA_DONE : 0));
418 bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR |
419 S_INTR_LATCH | S_TX_AVAIL | S_RX_EARLY | S_INT_RQD);
420 bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK |
421 S_INTR_LATCH | S_TX_AVAIL | S_RX_COMPLETE | S_UPD_STATS |
422 (sc->sc_busmaster ? S_DMA_DONE : 0) | S_UP_COMPLETE |
423 S_DOWN_COMPLETE | S_CARD_FAILURE | S_TX_COMPLETE);
424
425 mii_mediachg(&sc->sc_mii);
426
427 ifp->if_flags |= IFF_RUNNING;
428 ifq_clr_oactive(&ifp->if_snd);
429
430 splx(s);
431
432 timeout_add_sec(&sc->sc_tick_tmo, 1);
433
434 efstart(ifp);
435 }
436
437 void
efreset(struct ef_softc * sc)438 efreset(struct ef_softc *sc)
439 {
440 int s;
441
442 s = splnet();
443 efstop(sc);
444 efinit(sc);
445 splx(s);
446 }
447
448 void
efstop(struct ef_softc * sc)449 efstop(struct ef_softc *sc)
450 {
451 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
452 bus_space_tag_t iot = sc->sc_iot;
453 bus_space_handle_t ioh = sc->sc_ioh;
454
455 ifp->if_timer = 0;
456 ifp->if_flags &= ~IFF_RUNNING;
457 ifq_clr_oactive(&ifp->if_snd);
458
459 timeout_del(&sc->sc_tick_tmo);
460
461 bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
462 efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
463
464 bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
465 bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
466
467 efcompletecmd(sc, EP_COMMAND, RX_RESET);
468 efcompletecmd(sc, EP_COMMAND, TX_RESET);
469
470 bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
471 bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
472 bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
473 bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
474 }
475
476 void
efcompletecmd(struct ef_softc * sc,u_int cmd,u_int arg)477 efcompletecmd(struct ef_softc *sc, u_int cmd, u_int arg)
478 {
479 bus_space_tag_t iot = sc->sc_iot;
480 bus_space_handle_t ioh = sc->sc_ioh;
481
482 bus_space_write_2(iot, ioh, cmd, arg);
483 while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
484 ;
485 }
486
487 int
efintr(void * vsc)488 efintr(void *vsc)
489 {
490 struct ef_softc *sc = vsc;
491 bus_space_tag_t iot = sc->sc_iot;
492 bus_space_handle_t ioh = sc->sc_ioh;
493 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
494 u_int16_t status;
495 int r = 0;
496
497 status = bus_space_read_2(iot, ioh, EP_STATUS);
498
499 do {
500 if (status & S_RX_COMPLETE) {
501 r = 1;
502 bus_space_write_2(iot, ioh, EP_STATUS, C_RX_COMPLETE);
503 efread(sc);
504 }
505 if (status & S_TX_AVAIL) {
506 bus_space_write_2(iot, ioh, EP_STATUS, C_TX_AVAIL);
507 r = 1;
508 ifq_clr_oactive(&sc->sc_arpcom.ac_if.if_snd);
509 efstart(&sc->sc_arpcom.ac_if);
510 }
511 if (status & S_CARD_FAILURE) {
512 r = 1;
513 efreset(sc);
514 printf("%s: adapter failure (%x)\n",
515 sc->sc_dv.dv_xname, status);
516 bus_space_write_2(iot, ioh, EP_COMMAND,
517 C_CARD_FAILURE);
518 return (1);
519 }
520 if (status & S_TX_COMPLETE) {
521 r = 1;
522 eftxstat(sc);
523 efstart(ifp);
524 }
525 bus_space_write_2(iot, ioh, EP_COMMAND,
526 C_INTR_LATCH | C_INT_RQD);
527 } while ((status = bus_space_read_2(iot, ioh, EP_STATUS)) &
528 (S_INT_RQD | S_RX_COMPLETE));
529
530 return (r);
531 }
532
533 void
eftxstat(struct ef_softc * sc)534 eftxstat(struct ef_softc *sc)
535 {
536 bus_space_tag_t iot = sc->sc_iot;
537 bus_space_handle_t ioh = sc->sc_ioh;
538 int i;
539
540 while ((i = bus_space_read_1(iot, ioh, EF_W1_TX_STATUS)) &
541 TXS_COMPLETE) {
542 bus_space_write_1(iot, ioh, EF_W1_TX_STATUS, 0);
543
544 if (i & TXS_JABBER) {
545 sc->sc_arpcom.ac_if.if_oerrors++;
546 #ifdef EF_DEBUG
547 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
548 printf("%s: jabber (%x)\n",
549 sc->sc_dv.dv_xname, i);
550 #endif
551 efreset(sc);
552 }
553 else if (i & TXS_UNDERRUN) {
554 sc->sc_arpcom.ac_if.if_oerrors++;
555 #ifdef EF_DEBUG
556 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
557 printf("%s: fifo underrun (%x) @%d\n",
558 sc->sc_dv.dv_xname, i,
559 sc->sc_tx_start_thresh);
560 #endif
561 if (sc->sc_tx_succ_ok < 100)
562 sc->sc_tx_start_thresh = min(ETHER_MAX_LEN,
563 sc->sc_tx_start_thresh + 20);
564 sc->sc_tx_succ_ok = 0;
565 efreset(sc);
566 }
567 else if (i & TXS_MAX_COLLISION) {
568 sc->sc_arpcom.ac_if.if_collisions++;
569 bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
570 ifq_clr_oactive(&sc->sc_arpcom.ac_if.if_snd);
571 }
572 else
573 sc->sc_tx_succ_ok = (sc->sc_tx_succ_ok + 1) & 127;
574 }
575 }
576
577 int
efbusyeeprom(struct ef_softc * sc)578 efbusyeeprom(struct ef_softc *sc)
579 {
580 int i = 100, j;
581
582 while (i--) {
583 j = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
584 EF_W0_EEPROM_COMMAND);
585 if (j & EF_EEPROM_BUSY)
586 delay(100);
587 else
588 break;
589 }
590 if (i == 0) {
591 printf("%s: eeprom failed to come ready\n",
592 sc->sc_dv.dv_xname);
593 return (1);
594 }
595
596 return (0);
597 }
598
599 void
efwatchdog(struct ifnet * ifp)600 efwatchdog(struct ifnet *ifp)
601 {
602 struct ef_softc *sc = ifp->if_softc;
603
604 printf("%s: device timeout\n", sc->sc_dv.dv_xname);
605 sc->sc_arpcom.ac_if.if_oerrors++;
606 efreset(sc);
607 }
608
609 void
efsetmulti(struct ef_softc * sc)610 efsetmulti(struct ef_softc *sc)
611 {
612 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
613 struct arpcom *ac = &sc->sc_arpcom;
614 bus_space_tag_t iot = sc->sc_iot;
615 bus_space_handle_t ioh = sc->sc_ioh;
616 struct ether_multi *enm;
617 struct ether_multistep step;
618 u_int16_t cmd = SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST;
619 int mcnt = 0;
620
621 ETHER_FIRST_MULTI(step, ac, enm);
622 while (enm != NULL) {
623 mcnt++;
624 ETHER_NEXT_MULTI(step, enm);
625 }
626 if (mcnt || ifp->if_flags & IFF_ALLMULTI)
627 cmd |= FIL_MULTICAST;
628
629 if (ifp->if_flags & IFF_PROMISC)
630 cmd |= FIL_PROMISC;
631
632 bus_space_write_2(iot, ioh, EP_COMMAND, cmd);
633 }
634
635 void
efread(struct ef_softc * sc)636 efread(struct ef_softc *sc)
637 {
638 bus_space_tag_t iot = sc->sc_iot;
639 bus_space_handle_t ioh = sc->sc_ioh;
640 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
641 struct mbuf_list ml = MBUF_LIST_INITIALIZER();
642 struct mbuf *m;
643 int len;
644
645 len = bus_space_read_2(iot, ioh, EF_W1_RX_STATUS);
646
647 #ifdef EF_DEBUG
648 if (ifp->if_flags & IFF_DEBUG) {
649 int err = len & ERR_MASK;
650 char *s = NULL;
651
652 if (len & ERR_INCOMPLETE)
653 s = "incomplete packet";
654 else if (err == ERR_OVERRUN)
655 s = "packet overrun";
656 else if (err == ERR_RUNT)
657 s = "runt packet";
658 else if (err == ERR_ALIGNMENT)
659 s = "bad alignment";
660 else if (err == ERR_CRC)
661 s = "bad crc";
662 else if (err == ERR_OVERSIZE)
663 s = "oversized packet";
664 else if (err == ERR_DRIBBLE)
665 s = "dribble bits";
666
667 if (s)
668 printf("%s: %s\n", sc->sc_dv.dv_xname, s);
669 }
670 #endif
671
672 if (len & ERR_INCOMPLETE)
673 return;
674
675 if (len & ERR_RX) {
676 ifp->if_ierrors++;
677 efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
678 return;
679 }
680
681 len &= RX_BYTES_MASK;
682 m = efget(sc, len);
683 if (m == NULL) {
684 ifp->if_ierrors++;
685 efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
686 return;
687 }
688
689 ml_enqueue(&ml, m);
690 if_input(ifp, &ml);
691 }
692
693 struct mbuf *
efget(struct ef_softc * sc,int totlen)694 efget(struct ef_softc *sc, int totlen)
695 {
696 bus_space_tag_t iot = sc->sc_iot;
697 bus_space_handle_t ioh = sc->sc_ioh;
698 struct mbuf *top, **mp, *m;
699 int len, pad, s;
700
701 MGETHDR(m, M_DONTWAIT, MT_DATA);
702 if (m == NULL)
703 return (NULL);
704 m->m_pkthdr.len = totlen;
705 pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
706 m->m_data += pad;
707 len = MHLEN -pad;
708 top = 0;
709 mp = ⊤
710
711 s = splhigh();
712
713 while (totlen > 0) {
714 if (top) {
715 MGET(m, M_DONTWAIT, MT_DATA);
716 if (m == NULL) {
717 m_freem(top);
718 splx(s);
719 return (NULL);
720 }
721 len = MLEN;
722 }
723 if (top && totlen >= MINCLSIZE) {
724 MCLGET(m, M_DONTWAIT);
725 if (m->m_flags & M_EXT)
726 len = MCLBYTES;
727 }
728 len = min(totlen, len);
729 if (len > 1) {
730 len &= ~1;
731 bus_space_read_raw_multi_2(iot, ioh,
732 EF_W1_RX_PIO_RR_1, mtod(m, u_int8_t *),
733 len);
734 } else
735 *(mtod(m, u_int8_t *)) =
736 bus_space_read_1(iot, ioh, EF_W1_RX_PIO_RR_1);
737
738 m->m_len = len;
739 totlen -= len;
740 *mp = m;
741 mp = &m->m_next;
742 }
743
744 efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
745
746 splx(s);
747
748 return (top);
749 }
750
751 #define MII_SET(sc, x) \
752 bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS, \
753 bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS) \
754 | (x))
755
756 #define MII_CLR(sc, x) \
757 bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS, \
758 bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS) \
759 & (~(x)))
760
761 void
ef_mii_writeb(struct ef_softc * sc,int b)762 ef_mii_writeb(struct ef_softc *sc, int b)
763 {
764 MII_CLR(sc, EF_MII_CLK);
765
766 if (b)
767 MII_SET(sc, EF_MII_DATA);
768 else
769 MII_CLR(sc, EF_MII_DATA);
770
771 MII_CLR(sc, EF_MII_CLK);
772 DELAY(1);
773 MII_SET(sc, EF_MII_CLK);
774 DELAY(1);
775 }
776
777 void
ef_mii_sync(struct ef_softc * sc)778 ef_mii_sync(struct ef_softc *sc)
779 {
780 int i;
781
782 for (i = 0; i < 32; i++)
783 ef_mii_writeb(sc, 1);
784 }
785
786 int
ef_miibus_readreg(struct device * dev,int phy,int reg)787 ef_miibus_readreg(struct device *dev, int phy, int reg)
788 {
789 struct ef_softc *sc = (struct ef_softc *)dev;
790 int i, ack, s, val = 0;
791
792 s = splnet();
793
794 GO_WINDOW(4);
795 bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS, 0);
796
797 /* Turn on xmit */
798 MII_SET(sc, EF_MII_DIR);
799 MII_CLR(sc, EF_MII_CLK);
800
801 ef_mii_sync(sc);
802
803 /* Transmit start sequence */
804 ef_mii_writeb(sc, 0);
805 ef_mii_writeb(sc, 1);
806
807 /* Transmit read sequence */
808 ef_mii_writeb(sc, 1);
809 ef_mii_writeb(sc, 0);
810
811 /* Transmit phy addr */
812 for (i = 0x10; i; i >>= 1)
813 ef_mii_writeb(sc, (phy & i) ? 1 : 0);
814
815 /* Transmit reg addr */
816 for (i = 0x10; i; i >>= 1)
817 ef_mii_writeb(sc, (reg & i) ? 1 : 0);
818
819 /* First cycle of turnaround */
820 MII_CLR(sc, EF_MII_CLK | EF_MII_DATA);
821 DELAY(1);
822 MII_SET(sc, EF_MII_CLK);
823 DELAY(1);
824
825 /* Turn off xmit */
826 MII_CLR(sc, EF_MII_DIR);
827
828 /* Second cycle of turnaround */
829 MII_CLR(sc, EF_MII_CLK);
830 DELAY(1);
831 MII_SET(sc, EF_MII_CLK);
832 DELAY(1);
833 ack = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS) &
834 EF_MII_DATA;
835
836 /* Read 16bit data */
837 for (i = 0x8000; i; i >>= 1) {
838 MII_CLR(sc, EF_MII_CLK);
839 DELAY(1);
840 if (bus_space_read_2(sc->sc_iot, sc->sc_ioh,
841 EP_W4_CTRLR_STATUS) & EF_MII_DATA)
842 val |= i;
843 MII_SET(sc, EF_MII_CLK);
844 DELAY(1);
845 }
846
847 MII_CLR(sc, EF_MII_CLK);
848 DELAY(1);
849 MII_SET(sc, EF_MII_CLK);
850 DELAY(1);
851
852 splx(s);
853
854 return (val);
855 }
856
857 void
ef_miibus_writereg(struct device * dev,int phy,int reg,int val)858 ef_miibus_writereg(struct device *dev, int phy, int reg, int val)
859 {
860 struct ef_softc *sc = (struct ef_softc *)dev;
861 int s, i;
862
863 s = splnet();
864
865 GO_WINDOW(4);
866 bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS, 0);
867
868 /* Turn on xmit */
869 MII_SET(sc, EF_MII_DIR);
870
871 ef_mii_sync(sc);
872
873 ef_mii_writeb(sc, 0);
874 ef_mii_writeb(sc, 1);
875 ef_mii_writeb(sc, 0);
876 ef_mii_writeb(sc, 1);
877
878 for (i = 0x10; i; i >>= 1)
879 ef_mii_writeb(sc, (phy & i) ? 1 : 0);
880
881 for (i = 0x10; i; i >>= 1)
882 ef_mii_writeb(sc, (reg & i) ? 1 : 0);
883
884 ef_mii_writeb(sc, 1);
885 ef_mii_writeb(sc, 0);
886
887 for (i = 0x8000; i; i >>= 1)
888 ef_mii_writeb(sc, (val & i) ? 1 : 0);
889
890 splx(s);
891 }
892
893 int
ef_ifmedia_upd(struct ifnet * ifp)894 ef_ifmedia_upd(struct ifnet *ifp)
895 {
896 struct ef_softc *sc = ifp->if_softc;
897
898 mii_mediachg(&sc->sc_mii);
899 return (0);
900 }
901
902 void
ef_ifmedia_sts(struct ifnet * ifp,struct ifmediareq * ifmr)903 ef_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
904 {
905 struct ef_softc *sc = ifp->if_softc;
906
907 mii_pollstat(&sc->sc_mii);
908 ifmr->ifm_status = sc->sc_mii.mii_media_status;
909 ifmr->ifm_active = sc->sc_mii.mii_media_active;
910 }
911
912 void
ef_miibus_statchg(struct device * self)913 ef_miibus_statchg(struct device *self)
914 {
915 struct ef_softc *sc = (struct ef_softc *)self;
916 int s;
917
918 s = splnet();
919 GO_WINDOW(3);
920 /* Set duplex bit appropriately */
921 if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
922 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
923 EP_W3_MAC_CONTROL, 0x20);
924 else
925 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
926 EP_W3_MAC_CONTROL, 0x00);
927 GO_WINDOW(7);
928 splx(s);
929 }
930
931 void
ef_tick(void * v)932 ef_tick(void *v)
933 {
934 struct ef_softc *sc = v;
935 int s;
936
937 s = splnet();
938 mii_tick(&sc->sc_mii);
939 splx(s);
940 timeout_add_sec(&sc->sc_tick_tmo, 1);
941 }
942