mb8795.c revision 1.28 1 /* $NetBSD: mb8795.c,v 1.28 2002/09/11 01:46:31 mycroft Exp $ */
2 /*
3 * Copyright (c) 1998 Darrin B. Jewell
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Darrin B. Jewell
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "opt_inet.h"
33 #include "opt_ccitt.h"
34 #include "opt_llc.h"
35 #include "opt_ns.h"
36 #include "bpfilter.h"
37 #include "rnd.h"
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/mbuf.h>
42 #include <sys/syslog.h>
43 #include <sys/socket.h>
44 #include <sys/device.h>
45 #include <sys/malloc.h>
46 #include <sys/ioctl.h>
47 #include <sys/errno.h>
48 #if NRND > 0
49 #include <sys/rnd.h>
50 #endif
51
52 #include <net/if.h>
53 #include <net/if_dl.h>
54 #include <net/if_ether.h>
55
56 #include <net/if_media.h>
57
58 #ifdef INET
59 #include <netinet/in.h>
60 #include <netinet/if_inarp.h>
61 #include <netinet/in_systm.h>
62 #include <netinet/in_var.h>
63 #include <netinet/ip.h>
64 #endif
65
66 #ifdef NS
67 #include <netns/ns.h>
68 #include <netns/ns_if.h>
69 #endif
70
71 #if defined(CCITT) && defined(LLC)
72 #include <sys/socketvar.h>
73 #include <netccitt/x25.h>
74 #include <netccitt/pk.h>
75 #include <netccitt/pk_var.h>
76 #include <netccitt/pk_extern.h>
77 #endif
78
79 #if NBPFILTER > 0
80 #include <net/bpf.h>
81 #include <net/bpfdesc.h>
82 #endif
83
84 #include <machine/cpu.h>
85 #include <machine/bus.h>
86 #include <machine/intr.h>
87
88 /* @@@ this is here for the REALIGN_DMABUF hack below */
89 #include "nextdmareg.h"
90 #include "nextdmavar.h"
91
92 #include "mb8795reg.h"
93 #include "mb8795var.h"
94
95 #include "bmapreg.h"
96
97 #ifdef DEBUG
98 #define MB8795_DEBUG
99 #endif
100
101 #define PRINTF(x) printf x;
102 #ifdef MB8795_DEBUG
103 int mb8795_debug = 0;
104 #define DPRINTF(x) if (mb8795_debug) printf x;
105 #else
106 #define DPRINTF(x)
107 #endif
108
109 extern int turbo;
110
111 /*
112 * Support for
113 * Fujitsu Ethernet Data Link Controller (MB8795)
114 * and the Fujitsu Manchester Encoder/Decoder (MB502).
115 */
116
117 void mb8795_shutdown __P((void *));
118
119 bus_dmamap_t mb8795_txdma_restart __P((bus_dmamap_t,void *));
120 void mb8795_start_dma __P((struct mb8795_softc *));
121
122 int mb8795_mediachange __P((struct ifnet *));
123 void mb8795_mediastatus __P((struct ifnet *, struct ifmediareq *));
124
125 void
126 mb8795_config(sc, media, nmedia, defmedia)
127 struct mb8795_softc *sc;
128 int *media, nmedia, defmedia;
129 {
130 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
131
132 DPRINTF(("%s: mb8795_config()\n",sc->sc_dev.dv_xname));
133
134 /* Initialize ifnet structure. */
135 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
136 ifp->if_softc = sc;
137 ifp->if_start = mb8795_start;
138 ifp->if_ioctl = mb8795_ioctl;
139 ifp->if_watchdog = mb8795_watchdog;
140 ifp->if_flags =
141 IFF_BROADCAST | IFF_NOTRAILERS;
142
143 #ifndef NEXT_TURBO
144 /* Initialize media goo. */
145 ifmedia_init(&sc->sc_media, 0, mb8795_mediachange,
146 mb8795_mediastatus);
147 if (media != NULL) {
148 int i;
149 for (i = 0; i < nmedia; i++)
150 ifmedia_add(&sc->sc_media, media[i], 0, NULL);
151 ifmedia_set(&sc->sc_media, defmedia);
152 } else {
153 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
154 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
155 }
156 #endif
157
158 /* Attach the interface. */
159 if_attach(ifp);
160 ether_ifattach(ifp, sc->sc_enaddr);
161
162 sc->sc_sh = shutdownhook_establish(mb8795_shutdown, sc);
163 if (sc->sc_sh == NULL)
164 panic("mb8795_config: can't establish shutdownhook");
165
166 #if NRND > 0
167 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
168 RND_TYPE_NET, 0);
169 #endif
170
171 DPRINTF(("%s: leaving mb8795_config()\n",sc->sc_dev.dv_xname));
172 }
173
174 /*
175 * Media change callback.
176 */
177 int
178 mb8795_mediachange(ifp)
179 struct ifnet *ifp;
180 {
181 struct mb8795_softc *sc = ifp->if_softc;
182 int data;
183
184 if (turbo)
185 return (0);
186
187 switch IFM_SUBTYPE(sc->sc_media.ifm_media) {
188 case IFM_AUTO:
189 if ((bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, BMAP_DATA) &
190 BMAP_DATA_UTPENABLED_MASK) ||
191 !(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, BMAP_DATA) &
192 BMAP_DATA_UTPCARRIER_MASK)) {
193 data = BMAP_DATA_UTPENABLE;
194 sc->sc_media.ifm_cur->ifm_data = IFM_ETHER|IFM_10_T;
195 } else {
196 data = BMAP_DATA_BNCENABLE;
197 sc->sc_media.ifm_cur->ifm_data = IFM_ETHER|IFM_10_2;
198 }
199 break;
200 case IFM_10_T:
201 data = BMAP_DATA_UTPENABLE;
202 break;
203 case IFM_10_2:
204 data = BMAP_DATA_BNCENABLE;
205 break;
206 default:
207 return (1);
208 break;
209 }
210
211 bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh,
212 BMAP_DDIR, BMAP_DDIR_UTPENABLE_MASK);
213 bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh,
214 BMAP_DATA, data);
215
216 return (0);
217 }
218
219 /*
220 * Media status callback.
221 */
222 void
223 mb8795_mediastatus(ifp, ifmr)
224 struct ifnet *ifp;
225 struct ifmediareq *ifmr;
226 {
227 struct mb8795_softc *sc = ifp->if_softc;
228
229 if (turbo)
230 return;
231
232 if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_AUTO) {
233 ifmr->ifm_active = sc->sc_media.ifm_cur->ifm_data;
234 }
235 if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_10_T) {
236 ifmr->ifm_status = IFM_AVALID;
237 if (!(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, BMAP_DATA) &
238 BMAP_DATA_UTPCARRIER_MASK))
239 ifmr->ifm_status |= IFM_ACTIVE;
240 } else {
241 ifmr->ifm_status &= ~IFM_AVALID; /* don't know for 10_2 */
242 }
243 return;
244 }
245
246 /****************************************************************/
247 #ifdef MB8795_DEBUG
248 #define XCHR(x) "0123456789abcdef"[(x) & 0xf]
249 static void
250 mb8795_hex_dump(unsigned char *pkt, size_t len)
251 {
252 size_t i, j;
253
254 printf("00000000 ");
255 for(i=0; i<len; i++) {
256 printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i]));
257 if ((i+1) % 16 == 8) {
258 printf(" ");
259 }
260 if ((i+1) % 16 == 0) {
261 printf(" %c", '|');
262 for(j=0; j<16; j++) {
263 printf("%c", pkt[i-15+j]>=32 && pkt[i-15+j]<127?pkt[i-15+j]:'.');
264 }
265 printf("%c\n%c%c%c%c%c%c%c%c ", '|',
266 XCHR((i+1)>>28),XCHR((i+1)>>24),XCHR((i+1)>>20),XCHR((i+1)>>16),
267 XCHR((i+1)>>12), XCHR((i+1)>>8), XCHR((i+1)>>4), XCHR(i+1));
268 }
269 }
270 printf("\n");
271 }
272 #undef XCHR
273 #endif
274
275 /*
276 * Controller receive interrupt.
277 */
278 void
279 mb8795_rint(sc)
280 struct mb8795_softc *sc;
281 {
282 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
283 int error = 0;
284 u_char rxstat;
285 u_char rxmask;
286
287 rxstat = MB_READ_REG(sc, MB8795_RXSTAT);
288 rxmask = MB_READ_REG(sc, MB8795_RXMASK);
289
290 MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR);
291
292 if (rxstat & MB8795_RXSTAT_RESET) {
293 DPRINTF(("%s: rx reset packet\n",
294 sc->sc_dev.dv_xname));
295 error++;
296 }
297 if (rxstat & MB8795_RXSTAT_SHORT) {
298 DPRINTF(("%s: rx short packet\n",
299 sc->sc_dev.dv_xname));
300 error++;
301 }
302 if (rxstat & MB8795_RXSTAT_ALIGNERR) {
303 DPRINTF(("%s: rx alignment error\n",
304 sc->sc_dev.dv_xname));
305 #if 0
306 error++;
307 #endif
308 }
309 if (rxstat & MB8795_RXSTAT_CRCERR) {
310 DPRINTF(("%s: rx CRC error\n",
311 sc->sc_dev.dv_xname));
312 #if 0
313 error++;
314 #endif
315 }
316 if (rxstat & MB8795_RXSTAT_OVERFLOW) {
317 DPRINTF(("%s: rx overflow error\n",
318 sc->sc_dev.dv_xname));
319 #if 0
320 error++;
321 #endif
322 }
323
324 if (error) {
325 ifp->if_ierrors++;
326 /* @@@ handle more gracefully, free memory, etc. */
327 }
328
329 if (rxstat & MB8795_RXSTAT_OK) {
330 struct mbuf *m;
331 int s;
332 s = spldma();
333
334 while ((m = MBDMA_RX_MBUF (sc))) {
335 m->m_pkthdr.len = m->m_len;
336 m->m_flags |= M_HASFCS;
337 m->m_pkthdr.rcvif = ifp;
338
339 /* Find receive length, keep crc */
340 /* enable dma interrupts while we process the packet */
341 splx(s);
342
343 #if defined(MB8795_DEBUG)
344 /* Peek at the packet */
345 DPRINTF(("%s: received packet, at VA %p-%p,len %d\n",
346 sc->sc_dev.dv_xname,mtod(m,u_char *),mtod(m,u_char *)+m->m_len,m->m_len));
347 if (mb8795_debug > 3) {
348 mb8795_hex_dump(mtod(m,u_char *), m->m_pkthdr.len);
349 } else if (mb8795_debug > 2) {
350 mb8795_hex_dump(mtod(m,u_char *), m->m_pkthdr.len < 255 ? m->m_pkthdr.len : 128 );
351 }
352 #endif
353
354 #if NBPFILTER > 0
355 /*
356 * Pass packet to bpf if there is a listener.
357 */
358 if (ifp->if_bpf)
359 bpf_mtap(ifp->if_bpf, m);
360 #endif
361
362 {
363 ifp->if_ipackets++;
364
365 /* Pass the packet up. */
366 (*ifp->if_input)(ifp, m);
367 }
368
369 s = spldma();
370
371 }
372
373 splx(s);
374
375 }
376
377 #ifdef MB8795_DEBUG
378 if (mb8795_debug) {
379 char sbuf[256];
380
381 bitmask_snprintf(rxstat, MB8795_RXSTAT_BITS, sbuf, sizeof(sbuf));
382 printf("%s: rx interrupt, rxstat = %s\n",
383 sc->sc_dev.dv_xname, sbuf);
384
385 bitmask_snprintf(MB_READ_REG(sc, MB8795_RXSTAT),
386 MB8795_RXSTAT_BITS, sbuf, sizeof(sbuf));
387 printf("rxstat = 0x%s\n", sbuf);
388
389 bitmask_snprintf(MB_READ_REG(sc, MB8795_RXMASK),
390 MB8795_RXMASK_BITS, sbuf, sizeof(sbuf));
391 printf("rxmask = 0x%s\n", sbuf);
392
393 bitmask_snprintf(MB_READ_REG(sc, MB8795_RXMODE),
394 MB8795_RXMODE_BITS, sbuf, sizeof(sbuf));
395 printf("rxmode = 0x%s\n", sbuf);
396 }
397 #endif
398
399 return;
400 }
401
402 /*
403 * Controller transmit interrupt.
404 */
405 void
406 mb8795_tint(sc)
407 struct mb8795_softc *sc;
408 {
409 u_char txstat;
410 u_char txmask;
411 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
412
413 panic ("tint");
414 txstat = MB_READ_REG(sc, MB8795_TXSTAT);
415 txmask = MB_READ_REG(sc, MB8795_TXMASK);
416
417 if ((txstat & MB8795_TXSTAT_READY) ||
418 (txstat & MB8795_TXSTAT_TXRECV)) {
419 /* printf("X"); */
420 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR);
421 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_READYIE); */
422 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_TXRXIE); */
423 MB_WRITE_REG(sc, MB8795_TXMASK, 0);
424 if ((ifp->if_flags & IFF_RUNNING) && !IF_IS_EMPTY(&sc->sc_tx_snd)) {
425 void mb8795_start_dma __P((struct mb8795_softc *)); /* XXXX */
426 /* printf ("Z"); */
427 mb8795_start_dma(sc);
428 }
429 return;
430 }
431
432 if (txstat & MB8795_TXSTAT_SHORTED) {
433 printf("%s: tx cable shorted\n", sc->sc_dev.dv_xname);
434 ifp->if_oerrors++;
435 }
436 if (txstat & MB8795_TXSTAT_UNDERFLOW) {
437 printf("%s: tx underflow\n", sc->sc_dev.dv_xname);
438 ifp->if_oerrors++;
439 }
440 if (txstat & MB8795_TXSTAT_COLLERR) {
441 DPRINTF(("%s: tx collision\n", sc->sc_dev.dv_xname));
442 ifp->if_collisions++;
443 }
444 if (txstat & MB8795_TXSTAT_COLLERR16) {
445 printf("%s: tx 16th collision\n", sc->sc_dev.dv_xname);
446 ifp->if_oerrors++;
447 ifp->if_collisions += 16;
448 }
449
450 #if 0
451 if (txstat & MB8795_TXSTAT_READY) {
452 char sbuf[256];
453
454 bitmask_snprintf(txstat, MB8795_TXSTAT_BITS, sbuf, sizeof(sbuf));
455 panic("%s: unexpected tx interrupt %s",
456 sc->sc_dev.dv_xname, sbuf);
457
458 /* turn interrupt off */
459 MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_READYIE);
460 }
461 #endif
462
463 return;
464 }
465
466 /****************************************************************/
467
468 void
469 mb8795_reset(sc)
470 struct mb8795_softc *sc;
471 {
472 int s;
473 int i;
474
475 s = splnet();
476
477 DPRINTF (("%s: mb8795_reset()\n",sc->sc_dev.dv_xname));
478
479 sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
480 sc->sc_ethercom.ec_if.if_timer = 0;
481
482 MBDMA_RESET(sc);
483
484 MB_WRITE_REG(sc, MB8795_RESET, MB8795_RESET_MODE);
485
486 #ifndef NEXT_TURBO
487 mb8795_mediachange(&sc->sc_ethercom.ec_if);
488 #endif
489
490 #if 0 /* This interrupt was sometimes failing to ack correctly
491 * causing a loop @@@
492 */
493 MB_WRITE_REG(sc, MB8795_TXMASK,
494 MB8795_TXMASK_UNDERFLOWIE | MB8795_TXMASK_COLLIE | MB8795_TXMASK_COLL16IE
495 | MB8795_TXMASK_PARERRIE);
496 #else
497 MB_WRITE_REG(sc, MB8795_TXMASK, 0);
498 #endif
499 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR);
500
501 #if 0
502 MB_WRITE_REG(sc, MB8795_RXMASK,
503 MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE | MB8795_RXMASK_SHORTIE |
504 MB8795_RXMASK_ALIGNERRIE | MB8795_RXMASK_CRCERRIE | MB8795_RXMASK_OVERFLOWIE);
505 #else
506 MB_WRITE_REG(sc, MB8795_RXMASK,
507 MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE | MB8795_RXMASK_SHORTIE);
508 #endif
509
510 MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR);
511
512 for(i=0;i<sizeof(sc->sc_enaddr);i++) {
513 MB_WRITE_REG(sc, MB8795_ENADDR+i, sc->sc_enaddr[i]);
514 }
515
516 DPRINTF(("%s: initializing ethernet %02x:%02x:%02x:%02x:%02x:%02x, size=%d\n",
517 sc->sc_dev.dv_xname,
518 sc->sc_enaddr[0],sc->sc_enaddr[1],sc->sc_enaddr[2],
519 sc->sc_enaddr[3],sc->sc_enaddr[4],sc->sc_enaddr[5],
520 sizeof(sc->sc_enaddr)));
521
522 MB_WRITE_REG(sc, MB8795_RESET, 0);
523
524 splx(s);
525 }
526
527 void
528 mb8795_watchdog(ifp)
529 struct ifnet *ifp;
530 {
531 struct mb8795_softc *sc = ifp->if_softc;
532
533 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
534 ++ifp->if_oerrors;
535
536 DPRINTF(("%s: %lld input errors, %lld input packets\n",
537 sc->sc_dev.dv_xname, ifp->if_ierrors, ifp->if_ipackets));
538
539 ifp->if_flags &= ~IFF_RUNNING;
540 mb8795_init(sc);
541 }
542
543 /*
544 * Initialization of interface; set up initialization block
545 * and transmit/receive descriptor rings.
546 */
547 void
548 mb8795_init(sc)
549 struct mb8795_softc *sc;
550 {
551 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
552 int s;
553
554 DPRINTF (("%s: mb8795_init()\n",sc->sc_dev.dv_xname));
555
556 if (ifp->if_flags & IFF_UP) {
557 int rxmode;
558
559 s = spldma ();
560 if ((ifp->if_flags & IFF_RUNNING) == 0) {
561 mb8795_reset(sc);
562 }
563 if (ifp->if_flags & IFF_PROMISC) {
564 rxmode = MB8795_RXMODE_PROMISCUOUS;
565 panic ("promisc");
566 } else {
567 /* XXX add support for multicast */
568 rxmode = turbo ? MB8795_RXMODE_TEST | MB8795_RXMODE_MULTICAST : MB8795_RXMODE_NORMAL;
569 }
570
571 if ((ifp->if_flags & IFF_RUNNING) == 0) {
572 /* switching mode probably borken now with turbo */
573 MB_WRITE_REG(sc, MB8795_TXMODE,
574 turbo ? MB8795_TXMODE_TURBO1 : MB8795_TXMODE_LB_DISABLE);
575 MB_WRITE_REG(sc, MB8795_RXMODE, rxmode);
576
577 MBDMA_RX_SETUP(sc);
578 MBDMA_TX_SETUP(sc);
579
580 ifp->if_flags |= IFF_RUNNING;
581 ifp->if_flags &= ~IFF_OACTIVE;
582 ifp->if_timer = 0;
583
584 MBDMA_RX_GO(sc);
585 if (turbo)
586 MB_WRITE_REG(sc, MB8795_RXMODE, rxmode | MB8795_RXMODE_MULTICAST);
587 }
588 splx(s);
589 #if 0
590 s = spldma();
591 if (! IF_IS_EMPTY(&sc->sc_tx_snd)) {
592 mb8795_start_dma(ifp);
593 }
594 splx(s);
595 #endif
596 } else {
597 mb8795_reset(sc);
598 }
599 }
600
601 void
602 mb8795_shutdown(arg)
603 void *arg;
604 {
605 struct mb8795_softc *sc = (struct mb8795_softc *)arg;
606
607 DPRINTF(("%s: mb8795_shutdown()\n",sc->sc_dev.dv_xname));
608
609 mb8795_reset(sc);
610 }
611
612 /****************************************************************/
613 int
614 mb8795_ioctl(ifp, cmd, data)
615 register struct ifnet *ifp;
616 u_long cmd;
617 caddr_t data;
618 {
619 register struct mb8795_softc *sc = ifp->if_softc;
620 struct ifaddr *ifa = (struct ifaddr *)data;
621 struct ifreq *ifr = (struct ifreq *)data;
622 int s, error = 0;
623
624 s = splnet();
625
626 DPRINTF(("%s: mb8795_ioctl()\n",sc->sc_dev.dv_xname));
627
628 switch (cmd) {
629
630 case SIOCSIFADDR:
631 DPRINTF(("%s: mb8795_ioctl() SIOCSIFADDR\n",sc->sc_dev.dv_xname));
632 ifp->if_flags |= IFF_UP;
633
634 switch (ifa->ifa_addr->sa_family) {
635 #ifdef INET
636 case AF_INET:
637 mb8795_init(sc);
638 arp_ifinit(ifp, ifa);
639 break;
640 #endif
641 #ifdef NS
642 case AF_NS:
643 {
644 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
645
646 if (ns_nullhost(*ina))
647 ina->x_host =
648 *(union ns_host *)LLADDR(ifp->if_sadl);
649 else {
650 bcopy(ina->x_host.c_host,
651 LLADDR(ifp->if_sadl),
652 sizeof(sc->sc_enaddr));
653 }
654 /* Set new address. */
655 mb8795_init(sc);
656 break;
657 }
658 #endif
659 default:
660 mb8795_init(sc);
661 break;
662 }
663 break;
664
665 #if defined(CCITT) && defined(LLC)
666 case SIOCSIFCONF_X25:
667 ifp->if_flags |= IFF_UP;
668 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */
669 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
670 if (error == 0)
671 mb8795_init(sc);
672 break;
673 #endif /* CCITT && LLC */
674
675 case SIOCSIFFLAGS:
676 DPRINTF(("%s: mb8795_ioctl() SIOCSIFFLAGS\n",sc->sc_dev.dv_xname));
677 if ((ifp->if_flags & IFF_UP) == 0 &&
678 (ifp->if_flags & IFF_RUNNING) != 0) {
679 /*
680 * If interface is marked down and it is running, then
681 * stop it.
682 */
683 /* ifp->if_flags &= ~IFF_RUNNING; */
684 mb8795_reset(sc);
685 } else if ((ifp->if_flags & IFF_UP) != 0 &&
686 (ifp->if_flags & IFF_RUNNING) == 0) {
687 /*
688 * If interface is marked up and it is stopped, then
689 * start it.
690 */
691 mb8795_init(sc);
692 } else {
693 /*
694 * Reset the interface to pick up changes in any other
695 * flags that affect hardware registers.
696 */
697 mb8795_init(sc);
698 }
699 #ifdef MB8795_DEBUG
700 if (ifp->if_flags & IFF_DEBUG)
701 sc->sc_debug = 1;
702 else
703 sc->sc_debug = 0;
704 #endif
705 break;
706
707 case SIOCADDMULTI:
708 case SIOCDELMULTI:
709 DPRINTF(("%s: mb8795_ioctl() SIOCADDMULTI\n",sc->sc_dev.dv_xname));
710 error = (cmd == SIOCADDMULTI) ?
711 ether_addmulti(ifr, &sc->sc_ethercom) :
712 ether_delmulti(ifr, &sc->sc_ethercom);
713
714 if (error == ENETRESET) {
715 /*
716 * Multicast list has changed; set the hardware filter
717 * accordingly.
718 */
719 mb8795_init(sc);
720 error = 0;
721 }
722 break;
723
724 case SIOCGIFMEDIA:
725 case SIOCSIFMEDIA:
726 DPRINTF(("%s: mb8795_ioctl() SIOCSIFMEDIA\n",sc->sc_dev.dv_xname));
727 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
728 break;
729
730 default:
731 error = EINVAL;
732 break;
733 }
734
735 splx(s);
736
737 #if 0
738 DPRINTF(("DEBUG: mb8795_ioctl(0x%lx) returning %d\n",
739 cmd,error));
740 #endif
741
742 return (error);
743 }
744
745 /*
746 * Setup output on interface.
747 * Get another datagram to send off of the interface queue, and map it to the
748 * interface before starting the output.
749 * Called only at splnet or interrupt level.
750 */
751 void
752 mb8795_start(ifp)
753 struct ifnet *ifp;
754 {
755 struct mb8795_softc *sc = ifp->if_softc;
756 struct mbuf *m;
757 int s;
758
759 DPRINTF(("%s: mb8795_start()\n",sc->sc_dev.dv_xname));
760
761 #ifdef DIAGNOSTIC
762 IFQ_POLL(&ifp->if_snd, m);
763 if (m == 0) {
764 panic("%s: No packet to start\n",
765 sc->sc_dev.dv_xname);
766 }
767 #endif
768
769 while (1) {
770 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
771 return;
772
773 #if 0
774 return; /* @@@ Turn off xmit for debugging */
775 #endif
776
777 ifp->if_flags |= IFF_OACTIVE;
778
779 IFQ_DEQUEUE(&ifp->if_snd, m);
780 if (m == 0) {
781 ifp->if_flags &= ~IFF_OACTIVE;
782 return;
783 }
784
785 #if NBPFILTER > 0
786 /*
787 * Pass packet to bpf if there is a listener.
788 */
789 if (ifp->if_bpf)
790 bpf_mtap(ifp->if_bpf, m);
791 #endif
792
793 s = spldma();
794 IF_ENQUEUE(&sc->sc_tx_snd, m);
795 if (!MBDMA_TX_ISACTIVE(sc))
796 mb8795_start_dma(sc);
797 splx(s);
798
799 ifp->if_flags &= ~IFF_OACTIVE;
800 }
801
802 }
803
804 void
805 mb8795_start_dma(sc)
806 struct mb8795_softc *sc;
807 {
808 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
809 struct mbuf *m;
810 u_char txmask;
811
812 DPRINTF(("%s: mb8795_start_dma()\n",sc->sc_dev.dv_xname));
813
814 #if (defined(DIAGNOSTIC))
815 {
816 u_char txstat;
817 txstat = MB_READ_REG(sc, MB8795_TXSTAT);
818 if (!turbo && !(txstat & MB8795_TXSTAT_READY)) {
819 /* @@@ I used to panic here, but then it paniced once.
820 * Let's see if I can just reset instead. [ dbj 980706.1900 ]
821 */
822 printf("%s: transmitter not ready\n",
823 sc->sc_dev.dv_xname);
824 ifp->if_flags &= ~IFF_RUNNING;
825 mb8795_init(sc);
826 return;
827 }
828 }
829 #endif
830
831 #if 0
832 return; /* @@@ Turn off xmit for debugging */
833 #endif
834
835 IF_DEQUEUE(&sc->sc_tx_snd, m);
836 if (m == 0) {
837 #ifdef DIAGNOSTIC
838 panic("%s: No packet to start_dma\n",
839 sc->sc_dev.dv_xname);
840 #endif
841 return;
842 }
843
844 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR);
845 txmask = MB_READ_REG(sc, MB8795_TXMASK);
846 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_READYIE); */
847 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_TXRXIE); */
848
849 ifp->if_timer = 5;
850
851 if (MBDMA_TX_MBUF(sc, m))
852 return;
853
854 MBDMA_TX_GO(sc);
855 if (turbo)
856 MB_WRITE_REG(sc, MB8795_TXMODE, MB8795_TXMODE_TURBO1 | MB8795_TXMODE_TURBOSTART);
857
858 ifp->if_opackets++;
859 }
860
861 /****************************************************************/
862