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