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