mb8795.c revision 1.30 1 /* $NetBSD: mb8795.c,v 1.30 2002/09/11 13:15:58 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 /* Initialize media goo. */
144 ifmedia_init(&sc->sc_media, 0, mb8795_mediachange,
145 mb8795_mediastatus);
146 if (media != NULL) {
147 int i;
148 for (i = 0; i < nmedia; i++)
149 ifmedia_add(&sc->sc_media, media[i], 0, NULL);
150 ifmedia_set(&sc->sc_media, defmedia);
151 } else {
152 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
153 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
154 }
155
156 /* Attach the interface. */
157 if_attach(ifp);
158 ether_ifattach(ifp, sc->sc_enaddr);
159
160 sc->sc_sh = shutdownhook_establish(mb8795_shutdown, sc);
161 if (sc->sc_sh == NULL)
162 panic("mb8795_config: can't establish shutdownhook");
163
164 #if NRND > 0
165 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
166 RND_TYPE_NET, 0);
167 #endif
168
169 DPRINTF(("%s: leaving mb8795_config()\n",sc->sc_dev.dv_xname));
170 }
171
172 /*
173 * Media change callback.
174 */
175 int
176 mb8795_mediachange(ifp)
177 struct ifnet *ifp;
178 {
179 struct mb8795_softc *sc = ifp->if_softc;
180 int data;
181
182 if (turbo)
183 return (0);
184
185 switch IFM_SUBTYPE(sc->sc_media.ifm_media) {
186 case IFM_AUTO:
187 if ((bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, BMAP_DATA) &
188 BMAP_DATA_UTPENABLED_MASK) ||
189 !(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, BMAP_DATA) &
190 BMAP_DATA_UTPCARRIER_MASK)) {
191 data = BMAP_DATA_UTPENABLE;
192 sc->sc_media.ifm_cur->ifm_data = IFM_ETHER|IFM_10_T;
193 } else {
194 data = BMAP_DATA_BNCENABLE;
195 sc->sc_media.ifm_cur->ifm_data = IFM_ETHER|IFM_10_2;
196 }
197 break;
198 case IFM_10_T:
199 data = BMAP_DATA_UTPENABLE;
200 break;
201 case IFM_10_2:
202 data = BMAP_DATA_BNCENABLE;
203 break;
204 default:
205 return (1);
206 break;
207 }
208
209 bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh,
210 BMAP_DDIR, BMAP_DDIR_UTPENABLE_MASK);
211 bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh,
212 BMAP_DATA, data);
213
214 return (0);
215 }
216
217 /*
218 * Media status callback.
219 */
220 void
221 mb8795_mediastatus(ifp, ifmr)
222 struct ifnet *ifp;
223 struct ifmediareq *ifmr;
224 {
225 struct mb8795_softc *sc = ifp->if_softc;
226
227 if (turbo)
228 return;
229
230 if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_AUTO) {
231 ifmr->ifm_active = sc->sc_media.ifm_cur->ifm_data;
232 }
233 if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_10_T) {
234 ifmr->ifm_status = IFM_AVALID;
235 if (!(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, BMAP_DATA) &
236 BMAP_DATA_UTPCARRIER_MASK))
237 ifmr->ifm_status |= IFM_ACTIVE;
238 } else {
239 ifmr->ifm_status &= ~IFM_AVALID; /* don't know for 10_2 */
240 }
241 return;
242 }
243
244 /****************************************************************/
245 #ifdef MB8795_DEBUG
246 #define XCHR(x) "0123456789abcdef"[(x) & 0xf]
247 static void
248 mb8795_hex_dump(unsigned char *pkt, size_t len)
249 {
250 size_t i, j;
251
252 printf("00000000 ");
253 for(i=0; i<len; i++) {
254 printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i]));
255 if ((i+1) % 16 == 8) {
256 printf(" ");
257 }
258 if ((i+1) % 16 == 0) {
259 printf(" %c", '|');
260 for(j=0; j<16; j++) {
261 printf("%c", pkt[i-15+j]>=32 && pkt[i-15+j]<127?pkt[i-15+j]:'.');
262 }
263 printf("%c\n%c%c%c%c%c%c%c%c ", '|',
264 XCHR((i+1)>>28),XCHR((i+1)>>24),XCHR((i+1)>>20),XCHR((i+1)>>16),
265 XCHR((i+1)>>12), XCHR((i+1)>>8), XCHR((i+1)>>4), XCHR(i+1));
266 }
267 }
268 printf("\n");
269 }
270 #undef XCHR
271 #endif
272
273 /*
274 * Controller receive interrupt.
275 */
276 void
277 mb8795_rint(sc)
278 struct mb8795_softc *sc;
279 {
280 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
281 int error = 0;
282 u_char rxstat;
283 u_char rxmask;
284
285 rxstat = MB_READ_REG(sc, MB8795_RXSTAT);
286 rxmask = MB_READ_REG(sc, MB8795_RXMASK);
287
288 MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR);
289
290 if (rxstat & MB8795_RXSTAT_RESET) {
291 DPRINTF(("%s: rx reset packet\n",
292 sc->sc_dev.dv_xname));
293 error++;
294 }
295 if (rxstat & MB8795_RXSTAT_SHORT) {
296 DPRINTF(("%s: rx short packet\n",
297 sc->sc_dev.dv_xname));
298 error++;
299 }
300 if (rxstat & MB8795_RXSTAT_ALIGNERR) {
301 DPRINTF(("%s: rx alignment error\n",
302 sc->sc_dev.dv_xname));
303 #if 0
304 error++;
305 #endif
306 }
307 if (rxstat & MB8795_RXSTAT_CRCERR) {
308 DPRINTF(("%s: rx CRC error\n",
309 sc->sc_dev.dv_xname));
310 #if 0
311 error++;
312 #endif
313 }
314 if (rxstat & MB8795_RXSTAT_OVERFLOW) {
315 DPRINTF(("%s: rx overflow error\n",
316 sc->sc_dev.dv_xname));
317 #if 0
318 error++;
319 #endif
320 }
321
322 if (error) {
323 ifp->if_ierrors++;
324 /* @@@ handle more gracefully, free memory, etc. */
325 }
326
327 if (rxstat & MB8795_RXSTAT_OK) {
328 struct mbuf *m;
329 int s;
330 s = spldma();
331
332 while ((m = MBDMA_RX_MBUF (sc))) {
333 m->m_pkthdr.len = m->m_len;
334 m->m_flags |= M_HASFCS;
335 m->m_pkthdr.rcvif = ifp;
336
337 /* Find receive length, keep crc */
338 /* enable dma interrupts while we process the packet */
339 splx(s);
340
341 #if defined(MB8795_DEBUG)
342 /* Peek at the packet */
343 DPRINTF(("%s: received packet, at VA %p-%p,len %d\n",
344 sc->sc_dev.dv_xname,mtod(m,u_char *),mtod(m,u_char *)+m->m_len,m->m_len));
345 if (mb8795_debug > 3) {
346 mb8795_hex_dump(mtod(m,u_char *), m->m_pkthdr.len);
347 } else if (mb8795_debug > 2) {
348 mb8795_hex_dump(mtod(m,u_char *), m->m_pkthdr.len < 255 ? m->m_pkthdr.len : 128 );
349 }
350 #endif
351
352 #if NBPFILTER > 0
353 /*
354 * Pass packet to bpf if there is a listener.
355 */
356 if (ifp->if_bpf)
357 bpf_mtap(ifp->if_bpf, m);
358 #endif
359
360 {
361 ifp->if_ipackets++;
362
363 /* Pass the packet up. */
364 (*ifp->if_input)(ifp, m);
365 }
366
367 s = spldma();
368
369 }
370
371 splx(s);
372
373 }
374
375 #ifdef MB8795_DEBUG
376 if (mb8795_debug) {
377 char sbuf[256];
378
379 bitmask_snprintf(rxstat, MB8795_RXSTAT_BITS, sbuf, sizeof(sbuf));
380 printf("%s: rx interrupt, rxstat = %s\n",
381 sc->sc_dev.dv_xname, sbuf);
382
383 bitmask_snprintf(MB_READ_REG(sc, MB8795_RXSTAT),
384 MB8795_RXSTAT_BITS, sbuf, sizeof(sbuf));
385 printf("rxstat = 0x%s\n", sbuf);
386
387 bitmask_snprintf(MB_READ_REG(sc, MB8795_RXMASK),
388 MB8795_RXMASK_BITS, sbuf, sizeof(sbuf));
389 printf("rxmask = 0x%s\n", sbuf);
390
391 bitmask_snprintf(MB_READ_REG(sc, MB8795_RXMODE),
392 MB8795_RXMODE_BITS, sbuf, sizeof(sbuf));
393 printf("rxmode = 0x%s\n", sbuf);
394 }
395 #endif
396
397 return;
398 }
399
400 /*
401 * Controller transmit interrupt.
402 */
403 void
404 mb8795_tint(sc)
405 struct mb8795_softc *sc;
406 {
407 u_char txstat;
408 u_char txmask;
409 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
410
411 panic ("tint");
412 txstat = MB_READ_REG(sc, MB8795_TXSTAT);
413 txmask = MB_READ_REG(sc, MB8795_TXMASK);
414
415 if ((txstat & MB8795_TXSTAT_READY) ||
416 (txstat & MB8795_TXSTAT_TXRECV)) {
417 /* printf("X"); */
418 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR);
419 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_READYIE); */
420 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_TXRXIE); */
421 MB_WRITE_REG(sc, MB8795_TXMASK, 0);
422 if ((ifp->if_flags & IFF_RUNNING) && !IF_IS_EMPTY(&sc->sc_tx_snd)) {
423 void mb8795_start_dma __P((struct mb8795_softc *)); /* XXXX */
424 /* printf ("Z"); */
425 mb8795_start_dma(sc);
426 }
427 return;
428 }
429
430 if (txstat & MB8795_TXSTAT_SHORTED) {
431 printf("%s: tx cable shorted\n", sc->sc_dev.dv_xname);
432 ifp->if_oerrors++;
433 }
434 if (txstat & MB8795_TXSTAT_UNDERFLOW) {
435 printf("%s: tx underflow\n", sc->sc_dev.dv_xname);
436 ifp->if_oerrors++;
437 }
438 if (txstat & MB8795_TXSTAT_COLLERR) {
439 DPRINTF(("%s: tx collision\n", sc->sc_dev.dv_xname));
440 ifp->if_collisions++;
441 }
442 if (txstat & MB8795_TXSTAT_COLLERR16) {
443 printf("%s: tx 16th collision\n", sc->sc_dev.dv_xname);
444 ifp->if_oerrors++;
445 ifp->if_collisions += 16;
446 }
447
448 #if 0
449 if (txstat & MB8795_TXSTAT_READY) {
450 char sbuf[256];
451
452 bitmask_snprintf(txstat, MB8795_TXSTAT_BITS, sbuf, sizeof(sbuf));
453 panic("%s: unexpected tx interrupt %s",
454 sc->sc_dev.dv_xname, sbuf);
455
456 /* turn interrupt off */
457 MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_READYIE);
458 }
459 #endif
460
461 return;
462 }
463
464 /****************************************************************/
465
466 void
467 mb8795_reset(sc)
468 struct mb8795_softc *sc;
469 {
470 int s;
471 int i;
472
473 s = splnet();
474
475 DPRINTF (("%s: mb8795_reset()\n",sc->sc_dev.dv_xname));
476
477 sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
478 sc->sc_ethercom.ec_if.if_timer = 0;
479
480 MBDMA_RESET(sc);
481
482 MB_WRITE_REG(sc, MB8795_RESET, MB8795_RESET_MODE);
483
484 mb8795_mediachange(&sc->sc_ethercom.ec_if);
485
486 #if 0 /* This interrupt was sometimes failing to ack correctly
487 * causing a loop @@@
488 */
489 MB_WRITE_REG(sc, MB8795_TXMASK,
490 MB8795_TXMASK_UNDERFLOWIE | MB8795_TXMASK_COLLIE | MB8795_TXMASK_COLL16IE
491 | MB8795_TXMASK_PARERRIE);
492 #else
493 MB_WRITE_REG(sc, MB8795_TXMASK, 0);
494 #endif
495 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR);
496
497 #if 0
498 MB_WRITE_REG(sc, MB8795_RXMASK,
499 MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE | MB8795_RXMASK_SHORTIE |
500 MB8795_RXMASK_ALIGNERRIE | MB8795_RXMASK_CRCERRIE | MB8795_RXMASK_OVERFLOWIE);
501 #else
502 MB_WRITE_REG(sc, MB8795_RXMASK,
503 MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE | MB8795_RXMASK_SHORTIE);
504 #endif
505
506 MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR);
507
508 for(i=0;i<sizeof(sc->sc_enaddr);i++) {
509 MB_WRITE_REG(sc, MB8795_ENADDR+i, sc->sc_enaddr[i]);
510 }
511
512 DPRINTF(("%s: initializing ethernet %02x:%02x:%02x:%02x:%02x:%02x, size=%d\n",
513 sc->sc_dev.dv_xname,
514 sc->sc_enaddr[0],sc->sc_enaddr[1],sc->sc_enaddr[2],
515 sc->sc_enaddr[3],sc->sc_enaddr[4],sc->sc_enaddr[5],
516 sizeof(sc->sc_enaddr)));
517
518 MB_WRITE_REG(sc, MB8795_RESET, 0);
519
520 splx(s);
521 }
522
523 void
524 mb8795_watchdog(ifp)
525 struct ifnet *ifp;
526 {
527 struct mb8795_softc *sc = ifp->if_softc;
528
529 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
530 ++ifp->if_oerrors;
531
532 DPRINTF(("%s: %lld input errors, %lld input packets\n",
533 sc->sc_dev.dv_xname, ifp->if_ierrors, ifp->if_ipackets));
534
535 ifp->if_flags &= ~IFF_RUNNING;
536 mb8795_init(sc);
537 }
538
539 /*
540 * Initialization of interface; set up initialization block
541 * and transmit/receive descriptor rings.
542 */
543 void
544 mb8795_init(sc)
545 struct mb8795_softc *sc;
546 {
547 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
548 int s;
549
550 DPRINTF (("%s: mb8795_init()\n",sc->sc_dev.dv_xname));
551
552 if (ifp->if_flags & IFF_UP) {
553 int rxmode;
554
555 s = spldma();
556 if ((ifp->if_flags & IFF_RUNNING) == 0)
557 mb8795_reset(sc);
558
559 if (ifp->if_flags & IFF_PROMISC)
560 rxmode = MB8795_RXMODE_PROMISCUOUS;
561 else
562 rxmode = MB8795_RXMODE_NORMAL;
563 /* XXX add support for multicast */
564 if (turbo)
565 rxmode |= MB8795_RXMODE_TEST;
566
567 /* switching mode probably borken now with turbo */
568 MB_WRITE_REG(sc, MB8795_TXMODE,
569 turbo ? MB8795_TXMODE_TURBO1 : MB8795_TXMODE_LB_DISABLE);
570 MB_WRITE_REG(sc, MB8795_RXMODE, rxmode);
571
572 if ((ifp->if_flags & IFF_RUNNING) == 0) {
573 MBDMA_RX_SETUP(sc);
574 MBDMA_TX_SETUP(sc);
575
576 ifp->if_flags |= IFF_RUNNING;
577 ifp->if_flags &= ~IFF_OACTIVE;
578 ifp->if_timer = 0;
579
580 MBDMA_RX_GO(sc);
581 }
582 splx(s);
583 #if 0
584 s = spldma();
585 if (! IF_IS_EMPTY(&sc->sc_tx_snd)) {
586 mb8795_start_dma(ifp);
587 }
588 splx(s);
589 #endif
590 } else {
591 mb8795_reset(sc);
592 }
593 }
594
595 void
596 mb8795_shutdown(arg)
597 void *arg;
598 {
599 struct mb8795_softc *sc = (struct mb8795_softc *)arg;
600
601 DPRINTF(("%s: mb8795_shutdown()\n",sc->sc_dev.dv_xname));
602
603 mb8795_reset(sc);
604 }
605
606 /****************************************************************/
607 int
608 mb8795_ioctl(ifp, cmd, data)
609 register struct ifnet *ifp;
610 u_long cmd;
611 caddr_t data;
612 {
613 register struct mb8795_softc *sc = ifp->if_softc;
614 struct ifaddr *ifa = (struct ifaddr *)data;
615 struct ifreq *ifr = (struct ifreq *)data;
616 int s, error = 0;
617
618 s = splnet();
619
620 DPRINTF(("%s: mb8795_ioctl()\n",sc->sc_dev.dv_xname));
621
622 switch (cmd) {
623
624 case SIOCSIFADDR:
625 DPRINTF(("%s: mb8795_ioctl() SIOCSIFADDR\n",sc->sc_dev.dv_xname));
626 ifp->if_flags |= IFF_UP;
627
628 switch (ifa->ifa_addr->sa_family) {
629 #ifdef INET
630 case AF_INET:
631 mb8795_init(sc);
632 arp_ifinit(ifp, ifa);
633 break;
634 #endif
635 #ifdef NS
636 case AF_NS:
637 {
638 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
639
640 if (ns_nullhost(*ina))
641 ina->x_host =
642 *(union ns_host *)LLADDR(ifp->if_sadl);
643 else {
644 bcopy(ina->x_host.c_host,
645 LLADDR(ifp->if_sadl),
646 sizeof(sc->sc_enaddr));
647 }
648 /* Set new address. */
649 mb8795_init(sc);
650 break;
651 }
652 #endif
653 default:
654 mb8795_init(sc);
655 break;
656 }
657 break;
658
659 #if defined(CCITT) && defined(LLC)
660 case SIOCSIFCONF_X25:
661 ifp->if_flags |= IFF_UP;
662 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */
663 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
664 if (error == 0)
665 mb8795_init(sc);
666 break;
667 #endif /* CCITT && LLC */
668
669 case SIOCSIFFLAGS:
670 DPRINTF(("%s: mb8795_ioctl() SIOCSIFFLAGS\n",sc->sc_dev.dv_xname));
671 if ((ifp->if_flags & IFF_UP) == 0 &&
672 (ifp->if_flags & IFF_RUNNING) != 0) {
673 /*
674 * If interface is marked down and it is running, then
675 * stop it.
676 */
677 /* ifp->if_flags &= ~IFF_RUNNING; */
678 mb8795_reset(sc);
679 } else if ((ifp->if_flags & IFF_UP) != 0 &&
680 (ifp->if_flags & IFF_RUNNING) == 0) {
681 /*
682 * If interface is marked up and it is stopped, then
683 * start it.
684 */
685 mb8795_init(sc);
686 } else {
687 /*
688 * Reset the interface to pick up changes in any other
689 * flags that affect hardware registers.
690 */
691 mb8795_init(sc);
692 }
693 #ifdef MB8795_DEBUG
694 if (ifp->if_flags & IFF_DEBUG)
695 sc->sc_debug = 1;
696 else
697 sc->sc_debug = 0;
698 #endif
699 break;
700
701 case SIOCADDMULTI:
702 case SIOCDELMULTI:
703 DPRINTF(("%s: mb8795_ioctl() SIOCADDMULTI\n",sc->sc_dev.dv_xname));
704 error = (cmd == SIOCADDMULTI) ?
705 ether_addmulti(ifr, &sc->sc_ethercom) :
706 ether_delmulti(ifr, &sc->sc_ethercom);
707
708 if (error == ENETRESET) {
709 /*
710 * Multicast list has changed; set the hardware filter
711 * accordingly.
712 */
713 mb8795_init(sc);
714 error = 0;
715 }
716 break;
717
718 case SIOCGIFMEDIA:
719 case SIOCSIFMEDIA:
720 DPRINTF(("%s: mb8795_ioctl() SIOCSIFMEDIA\n",sc->sc_dev.dv_xname));
721 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
722 break;
723
724 default:
725 error = EINVAL;
726 break;
727 }
728
729 splx(s);
730
731 #if 0
732 DPRINTF(("DEBUG: mb8795_ioctl(0x%lx) returning %d\n",
733 cmd,error));
734 #endif
735
736 return (error);
737 }
738
739 /*
740 * Setup output on interface.
741 * Get another datagram to send off of the interface queue, and map it to the
742 * interface before starting the output.
743 * Called only at splnet or interrupt level.
744 */
745 void
746 mb8795_start(ifp)
747 struct ifnet *ifp;
748 {
749 struct mb8795_softc *sc = ifp->if_softc;
750 struct mbuf *m;
751 int s;
752
753 DPRINTF(("%s: mb8795_start()\n",sc->sc_dev.dv_xname));
754
755 #ifdef DIAGNOSTIC
756 IFQ_POLL(&ifp->if_snd, m);
757 if (m == 0) {
758 panic("%s: No packet to start\n",
759 sc->sc_dev.dv_xname);
760 }
761 #endif
762
763 while (1) {
764 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
765 return;
766
767 #if 0
768 return; /* @@@ Turn off xmit for debugging */
769 #endif
770
771 ifp->if_flags |= IFF_OACTIVE;
772
773 IFQ_DEQUEUE(&ifp->if_snd, m);
774 if (m == 0) {
775 ifp->if_flags &= ~IFF_OACTIVE;
776 return;
777 }
778
779 #if NBPFILTER > 0
780 /*
781 * Pass packet to bpf if there is a listener.
782 */
783 if (ifp->if_bpf)
784 bpf_mtap(ifp->if_bpf, m);
785 #endif
786
787 s = spldma();
788 IF_ENQUEUE(&sc->sc_tx_snd, m);
789 if (!MBDMA_TX_ISACTIVE(sc))
790 mb8795_start_dma(sc);
791 splx(s);
792
793 ifp->if_flags &= ~IFF_OACTIVE;
794 }
795
796 }
797
798 void
799 mb8795_start_dma(sc)
800 struct mb8795_softc *sc;
801 {
802 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
803 struct mbuf *m;
804 u_char txmask;
805
806 DPRINTF(("%s: mb8795_start_dma()\n",sc->sc_dev.dv_xname));
807
808 #if (defined(DIAGNOSTIC))
809 {
810 u_char txstat;
811 txstat = MB_READ_REG(sc, MB8795_TXSTAT);
812 if (!turbo && !(txstat & MB8795_TXSTAT_READY)) {
813 /* @@@ I used to panic here, but then it paniced once.
814 * Let's see if I can just reset instead. [ dbj 980706.1900 ]
815 */
816 printf("%s: transmitter not ready\n",
817 sc->sc_dev.dv_xname);
818 ifp->if_flags &= ~IFF_RUNNING;
819 mb8795_init(sc);
820 return;
821 }
822 }
823 #endif
824
825 #if 0
826 return; /* @@@ Turn off xmit for debugging */
827 #endif
828
829 IF_DEQUEUE(&sc->sc_tx_snd, m);
830 if (m == 0) {
831 #ifdef DIAGNOSTIC
832 panic("%s: No packet to start_dma\n",
833 sc->sc_dev.dv_xname);
834 #endif
835 return;
836 }
837
838 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR);
839 txmask = MB_READ_REG(sc, MB8795_TXMASK);
840 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_READYIE); */
841 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_TXRXIE); */
842
843 ifp->if_timer = 5;
844
845 if (MBDMA_TX_MBUF(sc, m))
846 return;
847
848 MBDMA_TX_GO(sc);
849 if (turbo)
850 MB_WRITE_REG(sc, MB8795_TXMODE, MB8795_TXMODE_TURBO1 | MB8795_TXMODE_TURBOSTART);
851
852 ifp->if_opackets++;
853 }
854
855 /****************************************************************/
856