if_sn.c revision 1.1 1 /* $NetBSD: if_sn.c,v 1.1 1997/03/15 20:26:35 briggs Exp $ */
2
3 /*
4 * National Semiconductor SONIC Driver
5 * Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk)
6 * You may use, copy, and modify this program so long as you retain the
7 * copyright line.
8 *
9 * This driver has been substantially modified since Algorithmics donated
10 * it.
11 */
12
13 #include <sys/param.h>
14 #include <sys/systm.h>
15 #include <sys/mbuf.h>
16 #include <sys/buf.h>
17 #include <sys/protosw.h>
18 #include <sys/socket.h>
19 #include <sys/syslog.h>
20 #include <sys/ioctl.h>
21 #include <sys/errno.h>
22 #include <sys/device.h>
23
24 #include <net/if.h>
25 #include <net/netisr.h>
26 #include <net/route.h>
27
28 #ifdef INET
29 #include <netinet/in.h>
30 #include <netinet/in_systm.h>
31 #include <netinet/in_var.h>
32 #include <netinet/ip.h>
33 #include <netinet/if_ether.h>
34 #endif
35
36 #include <vm/vm.h>
37
38 extern int kvtop(caddr_t addr);
39
40 #include "bpfilter.h"
41 #if NBPFILTER > 0
42 #include <net/bpf.h>
43 #include <net/bpfdesc.h>
44 #endif
45
46 typedef unsigned char uchar;
47
48 #include <machine/bus.h>
49 #include <machine/cpu.h>
50 #include <machine/viareg.h>
51 #include <mac68k/dev/if_snreg.h>
52 #include <mac68k/dev/if_snvar.h>
53
54 #include "nubus.h"
55
56 /*
57 * Register access macros:
58 * SWR is "Sonic Write Register"
59 * SRD is "Sonic Read Register"
60 */
61 #define SWR(a, x) (a) = (x)
62 #define SRD(a) ((a) & 0xffff)
63
64 #define wbflush()
65
66 static void snwatchdog __P((struct ifnet *));
67 static int sninit __P((struct sn_softc *sc));
68 static int snstop __P((struct sn_softc *sc));
69 static int sonicput __P((struct sn_softc *sc, struct mbuf *m0));
70 static void snintr __P((void *, int));
71 static int snioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
72 static void snstart __P((struct ifnet *ifp));
73 static void snreset __P((struct sn_softc *sc));
74
75 void camdump __P((struct sn_softc *sc));
76
77 struct cfdriver sn_cd = {
78 NULL, "sn", DV_IFNET
79 };
80
81 #undef assert
82 #undef _assert
83
84 #ifdef NDEBUG
85 #define assert(e) ((void)0)
86 #define _assert(e) ((void)0)
87 #else
88 #define _assert(e) assert(e)
89 #ifdef __STDC__
90 #define assert(e) ((e) ? (void)0 : __assert("sn ", __FILE__, __LINE__, #e))
91 #else /* PCC */
92 #define assert(e) ((e) ? (void)0 : __assert("sn "__FILE__, __LINE__, "e"))
93 #endif
94 #endif
95
96 int ethdebug = 0;
97
98 /*
99 * SONIC buffers need to be aligned 16 or 32 bit aligned.
100 * These macros calculate and verify alignment.
101 */
102 #define ROUNDUP(p, N) (((int) p + N - 1) & ~(N - 1))
103
104 #define SOALIGN(m, array) (m ? (ROUNDUP(array, 4)) : (ROUNDUP(array, 2)))
105
106 #define LOWER(x) ((unsigned)(x) & 0xffff)
107 #define UPPER(x) ((unsigned)(x) >> 16)
108
109 /*
110 * Interface exists: make available by filling in network interface
111 * record. System will initialize the interface when it is ready
112 * to accept packets.
113 */
114 void
115 snsetup(sc)
116 struct sn_softc *sc;
117 {
118 struct ifnet *ifp = &sc->sc_if;
119 unsigned char *p;
120 unsigned char *pp;
121 int i;
122
123 sc->sc_csr = (struct sonic_reg *) sc->sc_regh;
124
125 /*
126 * Disable caching on register and DMA space.
127 */
128 physaccess((caddr_t) sc->sc_csr, (caddr_t) kvtop((caddr_t) sc->sc_csr),
129 SN_REGSIZE, PG_V | PG_RW | PG_CI);
130
131 physaccess((caddr_t) sc->space, (caddr_t) kvtop((caddr_t) sc->space),
132 sizeof(sc->space), PG_V | PG_RW | PG_CI);
133
134 /*
135 * Put the pup in reset mode (sninit() will fix it later)
136 * and clear any interrupts.
137 */
138 sc->sc_csr->s_cr = CR_RST;
139 wbflush();
140 sc->sc_csr->s_isr = 0x7fff;
141 wbflush();
142
143 /*
144 * because the SONIC is basically 16bit device it 'concatenates'
145 * a higher buffer address to a 16 bit offset--this will cause wrap
146 * around problems near the end of 64k !!
147 */
148 p = &sc->space[0];
149 pp = (unsigned char *)ROUNDUP ((int)p, NBPG);
150 p = pp;
151
152 for (i = 0; i < NRRA; i++) {
153 sc->p_rra[i] = (void *)p;
154 sc->v_rra[i] = kvtop(p);
155 p += RXRSRC_SIZE(sc);
156 }
157 sc->v_rea = kvtop(p);
158
159 p = (unsigned char *)SOALIGN(sc, p);
160
161 sc->p_cda = (void *) (p);
162 sc->v_cda = kvtop(p);
163 p += CDA_SIZE(sc);
164
165 p = (unsigned char *)SOALIGN(sc, p);
166
167 for (i = 0; i < NRDA; i++) {
168 sc->p_rda[i] = (void *) p;
169 sc->v_rda[i] = kvtop(p);
170 p += RXPKT_SIZE(sc);
171 }
172
173 p = (unsigned char *)SOALIGN(sc, p);
174
175 for (i = 0; i < NTDA; i++) {
176 struct mtd *mtdp = &sc->mtda[i];
177 mtdp->mtd_txp = (void *)p;
178 mtdp->mtd_vtxp = kvtop(p);
179 p += TXP_SIZE(sc);
180 }
181
182 p = (unsigned char *)SOALIGN(sc, p);
183
184 if ((p - pp) > NBPG) {
185 printf ("sn: sizeof RRA (%ld) + CDA (%ld) +"
186 "RDA (%ld) + TDA (%ld) > NBPG (%d). Punt!\n",
187 (ulong)sc->p_cda - (ulong)sc->p_rra[0],
188 (ulong)sc->p_rda[0] - (ulong)sc->p_cda,
189 (ulong)sc->mtda[0].mtd_txp - (ulong)sc->p_rda[0],
190 (ulong)p - (ulong)sc->mtda[0].mtd_txp,
191 NBPG);
192 return;
193 }
194
195 p = pp + NBPG;
196
197 for (i = 0; i < NRBA; i+=2) {
198 sc->rbuf[i] = (caddr_t) p;
199 sc->rbuf[i+1] = (caddr_t)(p + (NBPG/2));
200 p += NBPG;
201 }
202
203 for (i = 0; i < NTXB; i+=2) {
204 sc->tbuf[i] = (caddr_t) p;
205 sc->tbuf[i+1] = (caddr_t)(p + (NBPG/2));
206 sc->vtbuf[i] = kvtop(sc->tbuf[i]);
207 sc->vtbuf[i+1] = kvtop(sc->tbuf[i+1]);
208 p += NBPG;
209 }
210
211 #if 0
212 camdump(sc);
213 #endif
214 printf(" address %s\n", ether_sprintf(sc->sc_enaddr));
215
216 #if 0
217 printf("sonic buffers: rra=%p cda=0x%x rda=0x%x tda=0x%x\n",
218 sc->p_rra[0], sc->p_cda, sc->p_rda[0], sc->mtda[0].mtd_txp);
219 #endif
220
221 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
222 ifp->if_softc = sc;
223 ifp->if_ioctl = snioctl;
224 ifp->if_start = snstart;
225 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
226 ifp->if_watchdog = snwatchdog;
227 #if NBPFILTER > 0
228 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
229 #endif
230 if_attach(ifp);
231 ether_ifattach(ifp);
232
233 add_nubus_intr(sc->slotno, snintr, (void *) sc);
234 }
235
236 static int
237 snioctl(ifp, cmd, data)
238 struct ifnet *ifp;
239 u_long cmd;
240 caddr_t data;
241 {
242 struct ifaddr *ifa;
243 struct sn_softc *sc = ifp->if_softc;
244 int s = splnet(), err = 0;
245 int temp;
246
247 switch (cmd) {
248
249 case SIOCSIFADDR:
250 ifa = (struct ifaddr *)data;
251 ifp->if_flags |= IFF_UP;
252 switch (ifa->ifa_addr->sa_family) {
253 #ifdef INET
254 case AF_INET:
255 (void)sninit(ifp->if_softc);
256 arp_ifinit(&sc->sc_arpcom, ifa);
257 break;
258 #endif
259 default:
260 (void)sninit(ifp->if_softc);
261 break;
262 }
263 break;
264
265 case SIOCSIFFLAGS:
266 if ((ifp->if_flags & IFF_UP) == 0 &&
267 ifp->if_flags & IFF_RUNNING) {
268 snstop(ifp->if_softc);
269 ifp->if_flags &= ~IFF_RUNNING;
270 } else if (ifp->if_flags & IFF_UP &&
271 (ifp->if_flags & IFF_RUNNING) == 0)
272 (void)sninit(ifp->if_softc);
273 /*
274 * If the state of the promiscuous bit changes, the interface
275 * must be reset to effect the change.
276 */
277 if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) &&
278 (ifp->if_flags & IFF_RUNNING)) {
279 sc->sc_iflags = ifp->if_flags;
280 printf("change in flags\n");
281 temp = sc->sc_if.if_flags & IFF_UP;
282 snreset(sc);
283 sc->sc_if.if_flags |= temp;
284 snstart(ifp);
285 }
286 break;
287
288 case SIOCADDMULTI:
289 case SIOCDELMULTI:
290 if(cmd == SIOCADDMULTI)
291 err = ether_addmulti((struct ifreq *)data,
292 &sc->sc_arpcom);
293 else
294 err = ether_delmulti((struct ifreq *)data,
295 &sc->sc_arpcom);
296
297 if (err == ENETRESET) {
298 /*
299 * Multicast list has changed; set the hardware
300 * filter accordingly. But remember UP flag!
301 */
302 temp = sc->sc_if.if_flags & IFF_UP;
303 snreset(sc);
304 sc->sc_if.if_flags |= temp;
305 err = 0;
306 }
307 break;
308 default:
309 err = EINVAL;
310 }
311 splx(s);
312 return (err);
313 }
314
315 /*
316 * Encapsulate a packet of type family for the local net.
317 * Use trailer local net encapsulation if enough data in first
318 * packet leaves a multiple of 512 bytes of data in remainder.
319 */
320 static void
321 snstart(ifp)
322 struct ifnet *ifp;
323 {
324 struct sn_softc *sc = ifp->if_softc;
325 struct mbuf *m;
326 int len;
327
328 if ((sc->sc_if.if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
329 return;
330
331 outloop:
332 /* Check for room in the xmit buffer. */
333 if (sc->txb_inuse == sc->txb_cnt) {
334 ifp->if_flags |= IFF_OACTIVE;
335 return;
336 }
337
338 if (sc->sc_csr->s_cr & CR_TXP) {
339 return;
340 }
341
342 IF_DEQUEUE(&sc->sc_if.if_snd, m);
343 if (m == 0)
344 return;
345
346 /* We need the header for m_pkthdr.len. */
347 if ((m->m_flags & M_PKTHDR) == 0)
348 panic("snstart: no header mbuf");
349
350 #if NBPFILTER > 0
351 /*
352 * If bpf is listening on this interface, let it
353 * see the packet before we commit it to the wire.
354 */
355 if (sc->sc_if.if_bpf)
356 bpf_mtap(sc->sc_if.if_bpf, m);
357 #endif
358
359 /*
360 * If there is nothing in the o/p queue, and there is room in
361 * the Tx ring, then send the packet directly. Otherwise append
362 * it to the o/p queue.
363 */
364 len = sonicput(sc, m);
365 #if 0
366 if (len != m->m_pkthdr.len) {
367 printf("snstart: len %d != m->m_pkthdr.len %d.\n",
368 len, m->m_pkthdr.len);
369 }
370 #endif
371 len = m->m_pkthdr.len;
372
373 m_freem(m);
374
375 /* Point to next buffer slot and wrap if necessary. */
376 if (++sc->txb_new == sc->txb_cnt)
377 sc->txb_new = 0;
378
379 sc->txb_inuse++;
380
381 sc->sc_if.if_opackets++; /* # of pkts */
382 sc->sc_sum.ls_opacks++; /* # of pkts */
383
384 /* Jump back for possibly more punishment. */
385 goto outloop;
386 }
387
388 /*
389 * This is called from sonicioctl() when /etc/ifconfig is run to set
390 * the address or switch the i/f on.
391 */
392 void caminitialise __P((struct sn_softc *));
393 void camentry __P((struct sn_softc *, int, unsigned char *ea));
394 void camprogram __P((struct sn_softc *));
395 void initialise_tda __P((struct sn_softc *));
396 void initialise_rda __P((struct sn_softc *));
397 void initialise_rra __P((struct sn_softc *));
398 void initialise_tba __P((struct sn_softc *));
399
400 /*
401 * reset and restart the SONIC. Called in case of fatal
402 * hardware/software errors.
403 */
404 static void
405 snreset(sc)
406 struct sn_softc *sc;
407 {
408 printf("snreset\n");
409 snstop(sc);
410 sninit(sc);
411 }
412
413 static int
414 sninit(sc)
415 struct sn_softc *sc;
416 {
417 struct sonic_reg *csr = sc->sc_csr;
418 int s;
419
420 if (sc->sc_if.if_flags & IFF_RUNNING)
421 /* already running */
422 return (0);
423
424 s = splnet();
425
426 csr->s_cr = CR_RST; /* s_dcr only accessable reset mode! */
427
428 /* config it */
429 csr->s_dcr = sc->s_dcr | (sc->bitmode ? DCR_DW32 : DCR_DW16);
430 csr->s_rcr = RCR_BRD | RCR_LBNONE;
431 csr->s_imr = IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN;
432
433 /* clear pending interrupts */
434 csr->s_isr = 0x7fff;
435
436 /* clear tally counters */
437 csr->s_crct = -1;
438 csr->s_faet = -1;
439 csr->s_mpt = -1;
440
441 initialise_tda(sc);
442 initialise_rda(sc);
443 initialise_rra(sc);
444 initialise_tba(sc);
445
446 /* enable the chip */
447 csr->s_cr = 0;
448 wbflush();
449
450 /* program the CAM with our address */
451 caminitialise(sc);
452 camentry(sc, 0, sc->sc_enaddr);
453 camprogram(sc);
454
455 /* get it to read resource descriptors */
456 csr->s_cr = CR_RRRA;
457 wbflush();
458 while (csr->s_cr & CR_RRRA)
459 continue;
460
461 /* enable rx */
462 csr->s_cr = CR_RXEN;
463 wbflush();
464
465 /* flag interface as "running" */
466 sc->sc_if.if_flags |= IFF_RUNNING;
467
468 splx(s);
469 return (0);
470 }
471
472 /*
473 * close down an interface and free its buffers
474 * Called on final close of device, or if sninit() fails
475 * part way through.
476 */
477 static int
478 snstop(sc)
479 struct sn_softc *sc;
480 {
481 struct mtd *mtd;
482 int s = splnet();
483
484 /* stick chip in reset */
485 sc->sc_csr->s_cr = CR_RST;
486 wbflush();
487
488 /* free all receive buffers (currently static so nothing to do) */
489
490 /* free all pending transmit mbufs */
491 while (sc->mtd_hw != sc->mtd_free) {
492 mtd = &sc->mtda[sc->mtd_hw];
493 mtd->mtd_buf = 0;
494 if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0;
495 }
496 sc->txb_inuse = 0;
497
498 sc->sc_if.if_timer = 0;
499 sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP);
500
501 splx(s);
502 return (0);
503 }
504
505 /*
506 * Called if any Tx packets remain unsent after 5 seconds,
507 * In all cases we just reset the chip, and any retransmission
508 * will be handled by higher level protocol timeouts.
509 */
510 static void
511 snwatchdog(ifp)
512 struct ifnet *ifp;
513 {
514 struct sn_softc *sc = ifp->if_softc;
515 struct mtd *mtd;
516 int temp;
517
518 if (sc->mtd_hw != sc->mtd_free) {
519 /* something still pending for transmit */
520 mtd = &sc->mtda[sc->mtd_hw];
521 if (SRO(sc->bitmode, mtd->mtd_txp, TXP_STATUS) == 0)
522 log(LOG_ERR, "%s: Tx - timeout\n",
523 sc->sc_dev.dv_xname);
524 else
525 log(LOG_ERR, "%s: Tx - lost interrupt\n",
526 sc->sc_dev.dv_xname);
527 temp = sc->sc_if.if_flags & IFF_UP;
528 snreset(sc);
529 sc->sc_if.if_flags |= temp;
530 }
531 }
532
533 /*
534 * stuff packet into sonic (at splnet)
535 */
536 static int
537 sonicput(sc, m0)
538 struct sn_softc *sc;
539 struct mbuf *m0;
540 {
541 struct sonic_reg *csr = sc->sc_csr;
542 unsigned char *buff, *buffer;
543 void *txp;
544 struct mtd *mtdp;
545 struct mbuf *m;
546 unsigned int len = 0;
547 unsigned int totlen = 0;
548 int mtd_free = sc->mtd_free;
549 int mtd_next;
550 int txb_new = sc->txb_new;
551
552 /* grab the replacement mtd */
553 mtdp = &sc->mtda[mtd_free];
554
555 if ((mtd_next = mtd_free + 1) == NTDA)
556 mtd_next = 0;
557
558 if (mtd_next == sc->mtd_hw) {
559 return (0);
560 }
561
562 /* We are guaranteed, if we get here, that the xmit buffer is free. */
563 buff = buffer = sc->tbuf[txb_new];
564
565 /* this packet goes to mtdnext fill in the TDA */
566 mtdp->mtd_buf = buffer;
567 txp = mtdp->mtd_txp;
568 SWO(sc->bitmode, txp, TXP_CONFIG, 0);
569
570 for (m = m0; m; m = m->m_next) {
571 unsigned char *data = mtod(m, u_char *);
572 len = m->m_len;
573 totlen += len;
574 bcopy(data, buff, len);
575 buff += len;
576 }
577 if (totlen >= TXBSIZE) {
578 panic("packet overflow in sonicput.");
579 }
580 SWO(sc->bitmode, txp, TXP_FRAGOFF+(0*TXP_FRAGSIZE)+TXP_FPTRLO,
581 LOWER(sc->vtbuf[txb_new]));
582 SWO(sc->bitmode, txp, TXP_FRAGOFF+(0*TXP_FRAGSIZE)+TXP_FPTRHI,
583 UPPER(sc->vtbuf[txb_new]));
584
585 if (totlen < ETHERMIN + sizeof(struct ether_header)) {
586 int pad = ETHERMIN + sizeof(struct ether_header) - totlen;
587 bzero(buffer + totlen, pad);
588 totlen = ETHERMIN + sizeof(struct ether_header);
589 }
590
591 SWO(sc->bitmode, txp, TXP_FRAGOFF+(0*TXP_FRAGSIZE)+TXP_FSIZE,
592 totlen);
593 SWO(sc->bitmode, txp, TXP_FRAGCNT, 1);
594 SWO(sc->bitmode, txp, TXP_PKTSIZE, totlen);
595
596 /* link onto the next mtd that will be used */
597 SWO(sc->bitmode, txp, TXP_FRAGOFF+(1*TXP_FRAGSIZE)+TXP_FPTRLO,
598 LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL);
599
600 /*
601 * The previous txp.tlink currently contains a pointer to
602 * our txp | EOL. Want to clear the EOL, so write our
603 * pointer to the previous txp.
604 */
605 SWO(sc->bitmode, sc->mtda[sc->mtd_prev].mtd_txp, sc->mtd_tlinko,
606 LOWER(mtdp->mtd_vtxp));
607
608 sc->mtd_prev = mtd_free;
609 sc->mtd_free = mtd_next;
610
611 /* make sure chip is running */
612 wbflush();
613 csr->s_cr = CR_TXP;
614 wbflush();
615 sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */
616
617 return (totlen);
618 }
619
620 void sonictxint __P((struct sn_softc *));
621 void sonicrxint __P((struct sn_softc *));
622
623 int sonic_read __P((struct sn_softc *, caddr_t, int));
624 struct mbuf *sonic_get __P((struct sn_softc *, struct ether_header *, int));
625
626 /*
627 * CAM support
628 */
629 void
630 caminitialise(sc)
631 struct sn_softc *sc;
632 {
633 int i;
634 void *p_cda = sc->p_cda;
635 int bitmode = sc->bitmode;
636
637 for (i = 0; i < MAXCAM; i++)
638 SWO(bitmode, p_cda, (CDA_CAMDESC * i + CDA_CAMEP), i);
639 SWO(bitmode, p_cda, CDA_ENABLE, 0);
640 }
641
642 void
643 camentry(sc, entry, ea)
644 int entry;
645 unsigned char *ea;
646 struct sn_softc *sc;
647 {
648 int bitmode = sc->bitmode;
649 void *p_cda = sc->p_cda;
650 int camoffset = entry * CDA_CAMDESC;
651
652 SWO(bitmode, p_cda, camoffset + CDA_CAMEP, entry);
653 SWO(bitmode, p_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]);
654 SWO(bitmode, p_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]);
655 SWO(bitmode, p_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]);
656 SWO(bitmode, p_cda, CDA_ENABLE, (1 << entry));
657 }
658
659 void
660 camprogram(sc)
661 struct sn_softc *sc;
662 {
663 struct sonic_reg *csr;
664 int timeout;
665
666 csr = sc->sc_csr;
667 csr->s_cdp = LOWER(sc->v_cda);
668 csr->s_cdc = MAXCAM;
669 csr->s_cr = CR_LCAM;
670 wbflush();
671
672 timeout = 10000;
673 while (csr->s_cr & CR_LCAM && timeout--)
674 continue;
675 if (timeout == 0) {
676 /* XXX */
677 panic("sonic: CAM initialisation failed\n");
678 }
679 timeout = 10000;
680 while ((csr->s_isr & ISR_LCD) == 0 && timeout--)
681 continue;
682
683 if (csr->s_isr & ISR_LCD)
684 csr->s_isr = ISR_LCD;
685 else
686 printf("sonic: CAM initialisation without interrupt\n");
687 }
688
689 #if 0
690 void
691 camdump(sc)
692 struct sn_softc *sc;
693 {
694 struct sonic_reg *csr = sc->sc_csr;
695 int i;
696
697 printf("CAM entries:\n");
698 csr->s_cr = CR_RST;
699 wbflush();
700
701 for (i = 0; i < 16; i++) {
702 ushort ap2, ap1, ap0;
703 csr->s_cep = i;
704 wbflush();
705 ap2 = csr->s_cap2;
706 ap1 = csr->s_cap1;
707 ap0 = csr->s_cap0;
708 printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0);
709 }
710 printf("CAM enable 0x%lx\n", csr->s_cep);
711
712 csr->s_cr = 0;
713 wbflush();
714 }
715 #endif
716
717 void
718 initialise_tda(sc)
719 struct sn_softc *sc;
720 {
721 struct sonic_reg *csr;
722 struct mtd *mtd;
723 int i;
724
725 csr = sc->sc_csr;
726
727 for (i = 0; i < NTDA; i++) {
728 mtd = &sc->mtda[i];
729 mtd->mtd_buf = 0;
730 }
731
732 sc->mtd_hw = 0;
733 sc->mtd_prev = NTDA-1;
734 sc->mtd_free = 0;
735 sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO;
736
737 csr->s_utda = UPPER(sc->mtda[0].mtd_vtxp);
738 csr->s_ctda = LOWER(sc->mtda[0].mtd_vtxp);
739 }
740
741 void
742 initialise_rda(sc)
743 struct sn_softc *sc;
744 {
745 struct sonic_reg *csr;
746 int bitmode = sc->bitmode;
747 int i;
748
749 csr = sc->sc_csr;
750
751 /* link the RDA's together into a circular list */
752 for (i = 0; i < (NRDA - 1); i++) {
753 SWO(bitmode, sc->p_rda[i], RXPKT_RLINK, LOWER(sc->v_rda[i+1]));
754 SWO(bitmode, sc->p_rda[i], RXPKT_INUSE, 1);
755 }
756 SWO(bitmode, sc->p_rda[NRDA - 1], RXPKT_RLINK, LOWER(sc->v_rda[0]) | EOL);
757 SWO(bitmode, sc->p_rda[NRDA - 1], RXPKT_INUSE, 1);
758
759 /* mark end of receive descriptor list */
760 sc->sc_rdamark = NRDA - 1;
761
762 sc->sc_rxmark = 0;
763
764 SWR(csr->s_urda, UPPER(sc->v_rda[0]));
765 SWR(csr->s_crda, LOWER(sc->v_rda[0]));
766 wbflush();
767 }
768
769 void
770 initialise_rra(sc)
771 struct sn_softc *sc;
772 {
773 struct sonic_reg *csr;
774 int i;
775 unsigned int v;
776 int bitmode = sc->bitmode;
777
778 csr = sc->sc_csr;
779
780 if (bitmode)
781 csr->s_eobc = RBASIZE(sc) / 2 - 2; /* must be >= MAXETHERPKT */
782 else
783 csr->s_eobc = RBASIZE(sc) / 2 - 1; /* must be >= MAXETHERPKT */
784 csr->s_urra = UPPER(sc->v_rra[0]);
785 csr->s_rsa = LOWER(sc->v_rra[0]);
786 /* rea must point just past the end of the rra space */
787 csr->s_rea = LOWER(sc->v_rea);
788 csr->s_rrp = LOWER(sc->v_rra[0]);
789
790 /* fill up SOME of the rra with buffers */
791 for (i = 0; i < NRBA; i++) {
792 v = kvtop(sc->rbuf[i]);
793 SWO(bitmode, sc->p_rra[i], RXRSRC_PTRHI, UPPER(v));
794 SWO(bitmode, sc->p_rra[i], RXRSRC_PTRLO, LOWER(v));
795 SWO(bitmode, sc->p_rra[i], RXRSRC_WCHI, UPPER(RBASIZE(sc) / 2));
796 SWO(bitmode, sc->p_rra[i], RXRSRC_WCLO, LOWER(RBASIZE(sc) / 2));
797 }
798 sc->sc_rramark = NRBA;
799 csr->s_rwp = LOWER(sc->v_rra[sc->sc_rramark]);
800 wbflush();
801 }
802
803 void
804 initialise_tba(sc)
805 struct sn_softc *sc;
806 {
807 sc->txb_cnt = NTXB;
808 sc->txb_inuse = 0;
809 sc->txb_new = 0;
810 }
811
812 static void
813 snintr(arg, slot)
814 void *arg;
815 int slot;
816 {
817 struct sn_softc *sc = (struct sn_softc *)arg;
818 struct sonic_reg *csr = sc->sc_csr;
819 int isr;
820
821 while ((isr = (csr->s_isr & ISR_ALL)) != 0) {
822 /* scrub the interrupts that we are going to service */
823 csr->s_isr = isr;
824 wbflush();
825
826 if (isr & (ISR_BR | ISR_LCD | ISR_PINT | ISR_TC))
827 printf("sonic: unexpected interrupt status 0x%x\n", isr);
828
829 if (isr & (ISR_TXDN | ISR_TXER))
830 sonictxint(sc);
831
832 if (isr & ISR_PKTRX)
833 sonicrxint(sc);
834
835 if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
836 if (isr & ISR_HBL)
837 /*
838 * The repeater is not providing a heartbeat.
839 * In itself this isn't harmful, lots of the
840 * cheap repeater hubs don't supply a heartbeat.
841 * So ignore the lack of heartbeat. Its only
842 * if we can't detect a carrier that we have a
843 * problem.
844 */
845 if (isr & ISR_RDE)
846 printf("sonic: receive descriptors exhausted\n");
847 if (isr & ISR_RBE)
848 printf("sonic: receive buffers exhausted\n");
849 if (isr & ISR_RBAE)
850 printf("sonic: receive buffer area exhausted\n");
851 if (isr & ISR_RFO)
852 printf("sonic: receive FIFO overrun\n");
853 }
854 if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) {
855 #ifdef notdef
856 if (isr & ISR_CRC)
857 sc->sc_crctally++;
858 if (isr & ISR_FAE)
859 sc->sc_faetally++;
860 if (isr & ISR_MP)
861 sc->sc_mptally++;
862 #endif
863 }
864 snstart(&sc->sc_if);
865 }
866 return;
867 }
868
869 /*
870 * Transmit interrupt routine
871 */
872 void
873 sonictxint(sc)
874 struct sn_softc *sc;
875 {
876 void *txp;
877 struct sonic_reg *csr;
878 struct mtd *mtd;
879 /* XXX DG make mtd_hw a local var */
880
881 if (sc->mtd_hw == sc->mtd_free)
882 return;
883
884 csr = sc->sc_csr;
885
886 while (sc->mtd_hw != sc->mtd_free) {
887 mtd = &sc->mtda[sc->mtd_hw];
888 if (mtd->mtd_buf == 0)
889 break;
890
891 txp = mtd->mtd_txp;
892
893 if (SRO(sc->bitmode, txp, TXP_STATUS) == 0)
894 return; /* it hasn't really gone yet */
895
896 if (ethdebug) {
897 struct ether_header *eh;
898
899 eh = (struct ether_header *) mtd->mtd_buf;
900 printf("xmit status=0x%x len=%d type=0x%x from %s",
901 SRO(sc->bitmode, txp, TXP_STATUS),
902 SRO(sc->bitmode, txp, TXP_PKTSIZE),
903 htons(eh->ether_type),
904 ether_sprintf(eh->ether_shost));
905 printf(" (to %s)\n", ether_sprintf(eh->ether_dhost));
906 }
907 sc->txb_inuse--;
908 mtd->mtd_buf = 0;
909 if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0;
910
911 /* XXX - Do stats here. */
912
913 if ((SRO(sc->bitmode, txp, TXP_STATUS) & TCR_PTX) == 0) {
914 printf("sonic: Tx packet status=0x%x\n",
915 SRO(sc->bitmode, txp, TXP_STATUS));
916
917 /* XXX - DG This looks bogus */
918 if (sc->mtd_hw != sc->mtd_free) {
919 printf("resubmitting remaining packets\n");
920 mtd = &sc->mtda[sc->mtd_hw];
921 csr->s_ctda = LOWER(mtd->mtd_vtxp);
922 csr->s_cr = CR_TXP;
923 wbflush();
924 return;
925 }
926 }
927 }
928 }
929
930 /*
931 * Receive interrupt routine
932 */
933 void
934 sonicrxint(sc)
935 struct sn_softc *sc;
936 {
937 struct sonic_reg *csr = sc->sc_csr;
938 void *rda;
939 int orra;
940 int len;
941 int rramark;
942 int rdamark;
943 int bitmode = sc->bitmode;
944 void *tmp1;
945 void *tmp2;
946
947 rda = sc->p_rda[sc->sc_rxmark];
948
949 while (SRO(bitmode, rda, RXPKT_INUSE) == 0) {
950 unsigned status = SRO(bitmode, rda, RXPKT_STATUS);
951 if ((status & RCR_LPKT) == 0)
952 printf("sonic: more than one packet in RBA!\n");
953
954 orra = RBASEQ(SRO(bitmode, rda, RXPKT_SEQNO)) & RRAMASK;
955 len = SRO(bitmode, rda, RXPKT_BYTEC) -
956 sizeof(struct ether_header) - FCSSIZE;
957 if (status & RCR_PRX) {
958 if (sonic_read(sc, sc->rbuf[orra & RBAMASK], len)) {
959 sc->sc_if.if_ipackets++;
960 sc->sc_sum.ls_ipacks++;
961 sc->sc_missed = 0;
962 }
963 } else
964 sc->sc_if.if_ierrors++;
965
966 /*
967 * give receive buffer area back to chip.
968 *
969 * orra is now empty of packets and can be freed if
970 * sonic read didnt copy it out then we would have to
971 * wait !!
972 * (dont bother add it back in again straight away)
973 *
974 * Really, we're doing p_rra[rramark] = p_rra[orra] but
975 * we have to use the macros because SONIC might be in
976 * 16 or 32 bit mode.
977 */
978 rramark = sc->sc_rramark;
979 tmp1 = sc->p_rra[rramark];
980 tmp2 = sc->p_rra[orra];
981 SWO(bitmode, tmp1, RXRSRC_PTRLO,
982 SRO(bitmode, tmp2, RXRSRC_PTRLO));
983 SWO(bitmode, tmp1, RXRSRC_PTRHI,
984 SRO(bitmode, tmp2, RXRSRC_PTRHI));
985 SWO(bitmode, tmp1, RXRSRC_WCLO,
986 SRO(bitmode, tmp2, RXRSRC_WCLO));
987 SWO(bitmode, tmp1, RXRSRC_WCHI,
988 SRO(bitmode, tmp2, RXRSRC_WCHI));
989
990 /* zap old rra for fun */
991 SWO(bitmode, tmp2, RXRSRC_WCHI, 0);
992 SWO(bitmode, tmp2, RXRSRC_WCLO, 0);
993
994 sc->sc_rramark = (++rramark) & RRAMASK;
995 csr->s_rwp = LOWER(sc->v_rra[rramark]);
996 wbflush();
997
998 /*
999 * give receive descriptor back to chip simple
1000 * list is circular
1001 */
1002 rdamark = sc->sc_rdamark;
1003 SWO(bitmode, rda, RXPKT_INUSE, 1);
1004 SWO(bitmode, rda, RXPKT_RLINK,
1005 SRO(bitmode, rda, RXPKT_RLINK) | EOL);
1006 SWO(bitmode, sc->p_rda[rdamark], RXPKT_RLINK,
1007 SRO(bitmode, sc->p_rda[rdamark], RXPKT_RLINK) & ~EOL);
1008 sc->sc_rdamark = sc->sc_rxmark;
1009
1010 if (++sc->sc_rxmark >= NRDA)
1011 sc->sc_rxmark = 0;
1012 rda = sc->p_rda[sc->sc_rxmark];
1013 }
1014 }
1015
1016 /*
1017 * sonic_read -- pull packet off interface and forward to
1018 * appropriate protocol handler
1019 */
1020 int
1021 sonic_read(sc, pkt, len)
1022 struct sn_softc *sc;
1023 caddr_t pkt;
1024 int len;
1025 {
1026 struct ifnet *ifp = &sc->sc_if;
1027 struct ether_header *et;
1028 struct mbuf *m;
1029
1030 /*
1031 * Get pointer to ethernet header (in input buffer).
1032 * Deal with trailer protocol: if type is PUP trailer
1033 * get true type from first 16-bit word past data.
1034 * Remember that type was trailer by setting off.
1035 */
1036 et = (struct ether_header *)pkt;
1037
1038 if (ethdebug) {
1039 printf("rcvd 0x%p len=%d type=0x%x from %s",
1040 et, len, htons(et->ether_type),
1041 ether_sprintf(et->ether_shost));
1042 printf(" (to %s)\n", ether_sprintf(et->ether_dhost));
1043 }
1044 if (len < ETHERMIN || len > ETHERMTU) {
1045 printf("sonic: invalid packet length %d bytes\n", len);
1046 return (0);
1047 }
1048
1049 #if NBPFILTER > 0
1050 /*
1051 * Check if there's a bpf filter listening on this interface.
1052 * If so, hand off the raw packet to enet, then discard things
1053 * not destined for us (but be sure to keep broadcast/multicast).
1054 */
1055 if (sc->sc_if.if_bpf) {
1056 bpf_tap(sc->sc_if.if_bpf, pkt,
1057 len + sizeof(struct ether_header));
1058 if ((ifp->if_flags & IFF_PROMISC) != 0 &&
1059 (et->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1060 bcmp(et->ether_dhost, sc->sc_enaddr,
1061 sizeof(et->ether_dhost)) != 0)
1062 return (0);
1063 }
1064 #endif
1065 m = sonic_get(sc, et, len);
1066 if (m == NULL)
1067 return (0);
1068 ether_input(ifp, et, m);
1069 return(1);
1070 }
1071
1072 #define sonicdataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
1073
1074 /*
1075 * munge the received packet into an mbuf chain
1076 * because we are using stupid buffer management this
1077 * is slow.
1078 */
1079 struct mbuf *
1080 sonic_get(sc, eh, datalen)
1081 struct sn_softc *sc;
1082 struct ether_header *eh;
1083 int datalen;
1084 {
1085 struct mbuf *m;
1086 struct mbuf *top = 0, **mp = ⊤
1087 int len;
1088 char *spkt = sonicdataaddr(eh, 0, caddr_t);
1089 char *epkt = spkt + datalen;
1090 char *cp = spkt;
1091
1092 epkt = cp + datalen;
1093 MGETHDR(m, M_DONTWAIT, MT_DATA);
1094 if (m == 0)
1095 return (0);
1096 m->m_pkthdr.rcvif = &sc->sc_if;
1097 m->m_pkthdr.len = datalen;
1098 m->m_len = MHLEN;
1099
1100 while (datalen > 0) {
1101 if (top) {
1102 MGET(m, M_DONTWAIT, MT_DATA);
1103 if (m == 0) {
1104 m_freem(top);
1105 return (0);
1106 }
1107 m->m_len = MLEN;
1108 }
1109 len = min(datalen, epkt - cp);
1110 if (len >= MINCLSIZE) {
1111 MCLGET(m, M_DONTWAIT);
1112 if (m->m_flags & M_EXT)
1113 m->m_len = len = min(len, MCLBYTES);
1114 else
1115 len = m->m_len;
1116 } else {
1117 /*
1118 * Place initial small packet/header at end of mbuf.
1119 */
1120 if (len < m->m_len) {
1121 if (top == 0 && len + max_linkhdr <= m->m_len)
1122 m->m_data += max_linkhdr;
1123 m->m_len = len;
1124 } else
1125 len = m->m_len;
1126 }
1127 bcopy(cp, mtod(m, caddr_t), (unsigned) len);
1128 cp += len;
1129 *mp = m;
1130 mp = &m->m_next;
1131 datalen -= len;
1132 if (cp == epkt)
1133 cp = spkt;
1134 }
1135 return (top);
1136 }
1137