if_el.c revision 1.96 1 /* $NetBSD: if_el.c,v 1.96 2018/06/26 06:48:01 msaitoh Exp $ */
2
3 /*
4 * Copyright (c) 1994, Matthew E. Kimmel. Permission is hereby granted
5 * to use, copy, modify and distribute this software provided that both
6 * the copyright notice and this permission notice appear in all copies
7 * of the software, derivative works or modified versions, and any
8 * portions thereof.
9 */
10
11 /*
12 * 3COM Etherlink 3C501 device driver
13 */
14
15 /*
16 * Bugs/possible improvements:
17 * - Does not currently support DMA
18 * - Does not currently support multicasts
19 */
20
21 #include <sys/cdefs.h>
22 __KERNEL_RCSID(0, "$NetBSD: if_el.c,v 1.96 2018/06/26 06:48:01 msaitoh Exp $");
23
24 #include "opt_inet.h"
25
26 #include <sys/param.h>
27 #include <sys/systm.h>
28 #include <sys/errno.h>
29 #include <sys/ioctl.h>
30 #include <sys/mbuf.h>
31 #include <sys/socket.h>
32 #include <sys/syslog.h>
33 #include <sys/device.h>
34 #include <sys/rndsource.h>
35
36 #include <net/if.h>
37 #include <net/if_dl.h>
38 #include <net/if_types.h>
39 #include <net/bpf.h>
40
41 #include <net/if_ether.h>
42
43 #ifdef INET
44 #include <netinet/in.h>
45 #include <netinet/in_systm.h>
46 #include <netinet/in_var.h>
47 #include <netinet/ip.h>
48 #include <netinet/if_inarp.h>
49 #endif
50
51 #include <sys/cpu.h>
52 #include <sys/intr.h>
53 #include <sys/bus.h>
54
55 #include <dev/isa/isavar.h>
56 #include <dev/isa/if_elreg.h>
57
58 /* for debugging convenience */
59 #ifdef EL_DEBUG
60 #define DPRINTF(x) printf x
61 #else
62 #define DPRINTF(x)
63 #endif
64
65 /*
66 * per-line info and status
67 */
68 struct el_softc {
69 device_t sc_dev;
70 void *sc_ih;
71
72 struct ethercom sc_ethercom; /* ethernet common */
73 bus_space_tag_t sc_iot; /* bus space identifier */
74 bus_space_handle_t sc_ioh; /* i/o handle */
75
76 krndsource_t rnd_source;
77 };
78
79 /*
80 * prototypes
81 */
82 int elintr(void *);
83 void elinit(struct el_softc *);
84 int elioctl(struct ifnet *, u_long, void *);
85 void elstart(struct ifnet *);
86 void elwatchdog(struct ifnet *);
87 void elreset(struct el_softc *);
88 void elstop(struct el_softc *);
89 static int el_xmit(struct el_softc *);
90 void elread(struct el_softc *, int);
91 struct mbuf *elget(struct el_softc *sc, int);
92 static inline void el_hardreset(struct el_softc *);
93
94 int elprobe(device_t, cfdata_t, void *);
95 void elattach(device_t, device_t, void *);
96
97 CFATTACH_DECL_NEW(el, sizeof(struct el_softc),
98 elprobe, elattach, NULL, NULL);
99
100 /*
101 * Probe routine.
102 *
103 * See if the card is there and at the right place.
104 * (XXX - cgd -- needs help)
105 */
106 int
107 elprobe(device_t parent, cfdata_t match, void *aux)
108 {
109 struct isa_attach_args *ia = aux;
110 bus_space_tag_t iot = ia->ia_iot;
111 bus_space_handle_t ioh;
112 int iobase;
113 u_int8_t station_addr[ETHER_ADDR_LEN];
114 u_int8_t i;
115 int rval;
116
117 rval = 0;
118
119 if (ia->ia_nio < 1)
120 return (0);
121 if (ia->ia_nirq < 1)
122 return (0);
123
124 if (ISA_DIRECT_CONFIG(ia))
125 return (0);
126
127 iobase = ia->ia_io[0].ir_addr;
128
129 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
130 return (0);
131 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ)
132 return (0);
133
134 /* First check the base. */
135 if (iobase < 0x200 || iobase > 0x3f0)
136 return 0;
137
138 /* Map i/o space. */
139 if (bus_space_map(iot, iobase, 16, 0, &ioh))
140 return 0;
141
142 /*
143 * Now attempt to grab the station address from the PROM and see if it
144 * contains the 3com vendor code.
145 */
146 DPRINTF(("Probing 3c501 at 0x%x...\n", iobase));
147
148 /* Reset the board. */
149 DPRINTF(("Resetting board...\n"));
150 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RESET);
151 delay(5);
152 bus_space_write_1(iot, ioh, EL_AC, 0);
153
154 /* Now read the address. */
155 DPRINTF(("Reading station address...\n"));
156 for (i = 0; i < ETHER_ADDR_LEN; i++) {
157 bus_space_write_1(iot, ioh, EL_GPBL, i);
158 station_addr[i] = bus_space_read_1(iot, ioh, EL_EAW);
159 }
160 DPRINTF(("Address is %s\n", ether_sprintf(station_addr)));
161
162 /*
163 * If the vendor code is ok, return a 1. We'll assume that whoever
164 * configured this system is right about the IRQ.
165 */
166 if (station_addr[0] != 0x02 || station_addr[1] != 0x60 ||
167 station_addr[2] != 0x8c) {
168 DPRINTF(("Bad vendor code.\n"));
169 goto out;
170 }
171 DPRINTF(("Vendor code ok.\n"));
172
173 ia->ia_nio = 1;
174 ia->ia_io[0].ir_size = 16;
175
176 ia->ia_nirq = 1;
177
178 ia->ia_niomem = 0;
179 ia->ia_ndrq = 0;
180
181 rval = 1;
182
183 out:
184 bus_space_unmap(iot, ioh, 16);
185 return rval;
186 }
187
188 /*
189 * Attach the interface to the kernel data structures. By the time this is
190 * called, we know that the card exists at the given I/O address. We still
191 * assume that the IRQ given is correct.
192 */
193 void
194 elattach(device_t parent, device_t self, void *aux)
195 {
196 struct el_softc *sc = device_private(self);
197 struct isa_attach_args *ia = aux;
198 bus_space_tag_t iot = ia->ia_iot;
199 bus_space_handle_t ioh;
200 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
201 u_int8_t myaddr[ETHER_ADDR_LEN];
202 u_int8_t i;
203
204 sc->sc_dev = self;
205
206 printf("\n");
207
208 DPRINTF(("Attaching %s...\n", device_xname(sc->sc_dev)));
209
210 /* Map i/o space. */
211 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh)) {
212 aprint_error_dev(self, "can't map i/o space\n");
213 return;
214 }
215
216 sc->sc_iot = iot;
217 sc->sc_ioh = ioh;
218
219 /* Reset the board. */
220 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RESET);
221 delay(5);
222 bus_space_write_1(iot, ioh, EL_AC, 0);
223
224 /* Now read the address. */
225 for (i = 0; i < ETHER_ADDR_LEN; i++) {
226 bus_space_write_1(iot, ioh, EL_GPBL, i);
227 myaddr[i] = bus_space_read_1(iot, ioh, EL_EAW);
228 }
229
230 /* Stop the board. */
231 elstop(sc);
232
233 /* Initialize ifnet structure. */
234 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
235 ifp->if_softc = sc;
236 ifp->if_start = elstart;
237 ifp->if_ioctl = elioctl;
238 ifp->if_watchdog = elwatchdog;
239 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
240 IFQ_SET_READY(&ifp->if_snd);
241
242 /* Now we can attach the interface. */
243 DPRINTF(("Attaching interface...\n"));
244 if_attach(ifp);
245 ether_ifattach(ifp, myaddr);
246
247 /* Print out some information for the user. */
248 printf("%s: address %s\n", device_xname(self), ether_sprintf(myaddr));
249
250 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
251 IST_EDGE, IPL_NET, elintr, sc);
252
253 DPRINTF(("Attaching to random...\n"));
254 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
255 RND_TYPE_NET, RND_FLAG_DEFAULT);
256
257 DPRINTF(("elattach() finished.\n"));
258 }
259
260 /*
261 * Reset interface.
262 */
263 void
264 elreset(struct el_softc *sc)
265 {
266 int s;
267
268 DPRINTF(("elreset()\n"));
269 s = splnet();
270 elstop(sc);
271 elinit(sc);
272 splx(s);
273 }
274
275 /*
276 * Stop interface.
277 */
278 void
279 elstop(struct el_softc *sc)
280 {
281
282 bus_space_write_1(sc->sc_iot, sc->sc_ioh, EL_AC, 0);
283 }
284
285 /*
286 * Do a hardware reset of the board, and upload the ethernet address again in
287 * case the board forgets.
288 */
289 static inline void
290 el_hardreset(struct el_softc *sc)
291 {
292 bus_space_tag_t iot = sc->sc_iot;
293 bus_space_handle_t ioh = sc->sc_ioh;
294 int i;
295
296 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RESET);
297 delay(5);
298 bus_space_write_1(iot, ioh, EL_AC, 0);
299
300 for (i = 0; i < ETHER_ADDR_LEN; i++)
301 bus_space_write_1(iot, ioh, i,
302 CLLADDR(sc->sc_ethercom.ec_if.if_sadl)[i]);
303 }
304
305 /*
306 * Initialize interface.
307 */
308 void
309 elinit(struct el_softc *sc)
310 {
311 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
312 bus_space_tag_t iot = sc->sc_iot;
313 bus_space_handle_t ioh = sc->sc_ioh;
314
315 /* First, reset the board. */
316 el_hardreset(sc);
317
318 /* Configure rx. */
319 DPRINTF(("Configuring rx...\n"));
320 if (ifp->if_flags & IFF_PROMISC)
321 bus_space_write_1(iot, ioh, EL_RXC,
322 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB |
323 EL_RXC_DOFLOW | EL_RXC_PROMISC);
324 else
325 bus_space_write_1(iot, ioh, EL_RXC,
326 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB |
327 EL_RXC_DOFLOW | EL_RXC_ABROAD);
328 bus_space_write_1(iot, ioh, EL_RBC, 0);
329
330 /* Configure TX. */
331 DPRINTF(("Configuring tx...\n"));
332 bus_space_write_1(iot, ioh, EL_TXC, 0);
333
334 /* Start reception. */
335 DPRINTF(("Starting reception...\n"));
336 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX);
337
338 /* Set flags appropriately. */
339 ifp->if_flags |= IFF_RUNNING;
340 ifp->if_flags &= ~IFF_OACTIVE;
341
342 /* And start output. */
343 elstart(ifp);
344 }
345
346 /*
347 * Start output on interface. Get datagrams from the queue and output them,
348 * giving the receiver a chance between datagrams. Call only from splnet or
349 * interrupt level!
350 */
351 void
352 elstart(struct ifnet *ifp)
353 {
354 struct el_softc *sc = ifp->if_softc;
355 bus_space_tag_t iot = sc->sc_iot;
356 bus_space_handle_t ioh = sc->sc_ioh;
357 struct mbuf *m, *m0;
358 int s, i, off, retries;
359
360 DPRINTF(("elstart()...\n"));
361 s = splnet();
362
363 /* Don't do anything if output is active. */
364 if ((ifp->if_flags & IFF_OACTIVE) != 0) {
365 splx(s);
366 return;
367 }
368
369 ifp->if_flags |= IFF_OACTIVE;
370
371 /*
372 * The main loop. They warned me against endless loops, but would I
373 * listen? NOOO....
374 */
375 for (;;) {
376 /* Dequeue the next datagram. */
377 IFQ_DEQUEUE(&ifp->if_snd, m0);
378
379 /* If there's nothing to send, return. */
380 if (m0 == 0)
381 break;
382
383 /* Give the packet to the bpf, if any. */
384 bpf_mtap(ifp, m0, BPF_D_OUT);
385
386 /* Disable the receiver. */
387 bus_space_write_1(iot, ioh, EL_AC, EL_AC_HOST);
388 bus_space_write_1(iot, ioh, EL_RBC, 0);
389
390 /* Transfer datagram to board. */
391 DPRINTF(("el: xfr pkt length=%d...\n", m0->m_pkthdr.len));
392 off = EL_BUFSIZ - max(m0->m_pkthdr.len,
393 ETHER_MIN_LEN - ETHER_CRC_LEN);
394 #ifdef DIAGNOSTIC
395 if ((off & 0xffff) != off)
396 printf("%s: bogus off 0x%x\n",
397 device_xname(sc->sc_dev), off);
398 #endif
399 bus_space_write_1(iot, ioh, EL_GPBL, off & 0xff);
400 bus_space_write_1(iot, ioh, EL_GPBH, (off >> 8) & 0xff);
401
402 /* Copy the datagram to the buffer. */
403 for (m = m0; m != 0; m = m->m_next)
404 bus_space_write_multi_1(iot, ioh, EL_BUF,
405 mtod(m, u_int8_t *), m->m_len);
406 for (i = 0;
407 i < ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len; i++)
408 bus_space_write_1(iot, ioh, EL_BUF, 0);
409
410 m_freem(m0);
411
412 /* Now transmit the datagram. */
413 retries = 0;
414 for (;;) {
415 bus_space_write_1(iot, ioh, EL_GPBL, off & 0xff);
416 bus_space_write_1(iot, ioh, EL_GPBH, (off >> 8) & 0xff);
417 if (el_xmit(sc)) {
418 ifp->if_oerrors++;
419 break;
420 }
421 /* Check out status. */
422 i = bus_space_read_1(iot, ioh, EL_TXS);
423 DPRINTF(("tx status=0x%x\n", i));
424 if ((i & EL_TXS_READY) == 0) {
425 DPRINTF(("el: err txs=%x\n", i));
426 if (i & (EL_TXS_COLL | EL_TXS_COLL16)) {
427 ifp->if_collisions++;
428 if ((i & EL_TXC_DCOLL16) == 0 &&
429 retries < 15) {
430 retries++;
431 bus_space_write_1(iot, ioh,
432 EL_AC, EL_AC_HOST);
433 }
434 } else {
435 ifp->if_oerrors++;
436 break;
437 }
438 } else {
439 ifp->if_opackets++;
440 break;
441 }
442 }
443
444 /*
445 * Now give the card a chance to receive.
446 * Gotta love 3c501s...
447 */
448 (void)bus_space_read_1(iot, ioh, EL_AS);
449 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX);
450 splx(s);
451 /* Interrupt here. */
452 s = splnet();
453 }
454
455 (void)bus_space_read_1(iot, ioh, EL_AS);
456 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX);
457 ifp->if_flags &= ~IFF_OACTIVE;
458 splx(s);
459 }
460
461 /*
462 * This function actually attempts to transmit a datagram downloaded to the
463 * board. Call at splnet or interrupt, after downloading data! Returns 0 on
464 * success, non-0 on failure.
465 */
466 static int
467 el_xmit(struct el_softc *sc)
468 {
469 bus_space_tag_t iot = sc->sc_iot;
470 bus_space_handle_t ioh = sc->sc_ioh;
471 int i;
472
473 /*
474 * XXX
475 * This busy-waits for the tx completion. Can we get an interrupt
476 * instead?
477 */
478
479 DPRINTF(("el: xmit..."));
480 bus_space_write_1(iot, ioh, EL_AC, EL_AC_TXFRX);
481 i = 20000;
482 while ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_TXBUSY) && (i > 0))
483 i--;
484 if (i == 0) {
485 DPRINTF(("tx not ready\n"));
486 return -1;
487 }
488 DPRINTF(("%d cycles.\n", 20000 - i));
489 return 0;
490 }
491
492 /*
493 * Controller interrupt.
494 */
495 int
496 elintr(void *arg)
497 {
498 struct el_softc *sc = arg;
499 bus_space_tag_t iot = sc->sc_iot;
500 bus_space_handle_t ioh = sc->sc_ioh;
501 u_int8_t rxstat;
502 int len;
503
504 DPRINTF(("elintr: "));
505
506 /* Check board status. */
507 if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) {
508 (void)bus_space_read_1(iot, ioh, EL_RXC);
509 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX);
510 return 0;
511 }
512
513 for (;;) {
514 rxstat = bus_space_read_1(iot, ioh, EL_RXS);
515 if (rxstat & EL_RXS_STALE)
516 break;
517
518 /* If there's an overflow, reinit the board. */
519 if ((rxstat & EL_RXS_NOFLOW) == 0) {
520 DPRINTF(("overflow.\n"));
521 el_hardreset(sc);
522 /* Put board back into receive mode. */
523 if (sc->sc_ethercom.ec_if.if_flags & IFF_PROMISC)
524 bus_space_write_1(iot, ioh, EL_RXC,
525 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB |
526 EL_RXC_DOFLOW | EL_RXC_PROMISC);
527 else
528 bus_space_write_1(iot, ioh, EL_RXC,
529 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB |
530 EL_RXC_DOFLOW | EL_RXC_ABROAD);
531 (void)bus_space_read_1(iot, ioh, EL_AS);
532 bus_space_write_1(iot, ioh, EL_RBC, 0);
533 break;
534 }
535
536 /* Incoming packet. */
537 len = bus_space_read_1(iot, ioh, EL_RBL);
538 len |= bus_space_read_1(iot, ioh, EL_RBH) << 8;
539 DPRINTF(("receive len=%d rxstat=%x ", len, rxstat));
540 bus_space_write_1(iot, ioh, EL_AC, EL_AC_HOST);
541
542 /* Pass data up to upper levels. */
543 elread(sc, len);
544
545 /* Is there another packet? */
546 if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0)
547 break;
548
549 rnd_add_uint32(&sc->rnd_source, rxstat);
550
551 DPRINTF(("<rescan> "));
552 }
553
554 (void)bus_space_read_1(iot, ioh, EL_RXC);
555 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX);
556 return 1;
557 }
558
559 /*
560 * Pass a packet to the higher levels.
561 */
562 void
563 elread(struct el_softc *sc, int len)
564 {
565 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
566 struct mbuf *m;
567
568 if (len <= sizeof(struct ether_header) ||
569 len > ETHER_MAX_LEN) {
570 printf("%s: invalid packet size %d; dropping\n",
571 device_xname(sc->sc_dev), len);
572 ifp->if_ierrors++;
573 return;
574 }
575
576 /* Pull packet off interface. */
577 m = elget(sc, len);
578 if (m == 0) {
579 ifp->if_ierrors++;
580 return;
581 }
582
583 if_percpuq_enqueue(ifp->if_percpuq, m);
584 }
585
586 /*
587 * Pull read data off a interface. Len is length of data, with local net
588 * header stripped. We copy the data into mbufs. When full cluster sized
589 * units are present we copy into clusters.
590 */
591 struct mbuf *
592 elget(struct el_softc *sc, int totlen)
593 {
594 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
595 bus_space_tag_t iot = sc->sc_iot;
596 bus_space_handle_t ioh = sc->sc_ioh;
597 struct mbuf *m, *m0, *newm;
598 int len;
599
600 MGETHDR(m0, M_DONTWAIT, MT_DATA);
601 if (m0 == 0)
602 return (0);
603 m_set_rcvif(m0, ifp);
604 m0->m_pkthdr.len = totlen;
605 len = MHLEN;
606 m = m0;
607
608 bus_space_write_1(iot, ioh, EL_GPBL, 0);
609 bus_space_write_1(iot, ioh, EL_GPBH, 0);
610
611 while (totlen > 0) {
612 if (totlen >= MINCLSIZE) {
613 MCLGET(m, M_DONTWAIT);
614 if ((m->m_flags & M_EXT) == 0)
615 goto bad;
616 len = MCLBYTES;
617 }
618
619 m->m_len = len = min(totlen, len);
620 bus_space_read_multi_1(iot, ioh, EL_BUF, mtod(m, u_int8_t *), len);
621
622 totlen -= len;
623 if (totlen > 0) {
624 MGET(newm, M_DONTWAIT, MT_DATA);
625 if (newm == 0)
626 goto bad;
627 len = MLEN;
628 m = m->m_next = newm;
629 }
630 }
631
632 bus_space_write_1(iot, ioh, EL_RBC, 0);
633 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RX);
634
635 return (m0);
636
637 bad:
638 m_freem(m0);
639 return (0);
640 }
641
642 /*
643 * Process an ioctl request. This code needs some work - it looks pretty ugly.
644 */
645 int
646 elioctl(struct ifnet *ifp, u_long cmd, void *data)
647 {
648 struct el_softc *sc = ifp->if_softc;
649 struct ifaddr *ifa = (struct ifaddr *)data;
650 int s, error = 0;
651
652 s = splnet();
653
654 switch (cmd) {
655
656 case SIOCINITIFADDR:
657 ifp->if_flags |= IFF_UP;
658
659 elinit(sc);
660 switch (ifa->ifa_addr->sa_family) {
661 #ifdef INET
662 case AF_INET:
663 arp_ifinit(ifp, ifa);
664 break;
665 #endif
666 default:
667 break;
668 }
669 break;
670
671 case SIOCSIFFLAGS:
672 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
673 break;
674 /* XXX re-use ether_ioctl() */
675 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
676 case IFF_RUNNING:
677 /*
678 * If interface is marked down and it is running, then
679 * stop it.
680 */
681 elstop(sc);
682 ifp->if_flags &= ~IFF_RUNNING;
683 break;
684 case IFF_UP:
685 /*
686 * If interface is marked up and it is stopped, then
687 * start it.
688 */
689 elinit(sc);
690 break;
691 default:
692 /*
693 * Some other important flag might have changed, so
694 * reset.
695 */
696 elreset(sc);
697 break;
698 }
699 break;
700
701 default:
702 error = ether_ioctl(ifp, cmd, data);
703 break;
704 }
705
706 splx(s);
707 return error;
708 }
709
710 /*
711 * Device timeout routine.
712 */
713 void
714 elwatchdog(struct ifnet *ifp)
715 {
716 struct el_softc *sc = ifp->if_softc;
717
718 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
719 sc->sc_ethercom.ec_if.if_oerrors++;
720
721 elreset(sc);
722 }
723