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