mb8795.c revision 1.23 1 /* $NetBSD: mb8795.c,v 1.23 2001/05/13 16:55:38 chs 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 #if 0
57 #include <net/if_media.h>
58 #endif
59
60 #ifdef INET
61 #include <netinet/in.h>
62 #include <netinet/if_inarp.h>
63 #include <netinet/in_systm.h>
64 #include <netinet/in_var.h>
65 #include <netinet/ip.h>
66 #endif
67
68 #ifdef NS
69 #include <netns/ns.h>
70 #include <netns/ns_if.h>
71 #endif
72
73 #if defined(CCITT) && defined(LLC)
74 #include <sys/socketvar.h>
75 #include <netccitt/x25.h>
76 #include <netccitt/pk.h>
77 #include <netccitt/pk_var.h>
78 #include <netccitt/pk_extern.h>
79 #endif
80
81 #if NBPFILTER > 0
82 #include <net/bpf.h>
83 #include <net/bpfdesc.h>
84 #endif
85
86 #include <machine/cpu.h>
87 #include <machine/bus.h>
88 #include <machine/intr.h>
89
90 /* @@@ this is here for the REALIGN_DMABUF hack below */
91 #include "nextdmareg.h"
92 #include "nextdmavar.h"
93
94 #include "mb8795reg.h"
95 #include "mb8795var.h"
96
97 #if 1
98 #define XE_DEBUG
99 #endif
100
101 #ifdef XE_DEBUG
102 int xe_debug = 0;
103 #define DPRINTF(x) if (xe_debug) printf x;
104 #else
105 #define DPRINTF(x)
106 #endif
107
108
109 /*
110 * Support for
111 * Fujitsu Ethernet Data Link Controller (MB8795)
112 * and the Fujitsu Manchester Encoder/Decoder (MB502).
113 */
114
115 void mb8795_shutdown __P((void *));
116
117 struct mbuf * mb8795_rxdmamap_load __P((struct mb8795_softc *,
118 bus_dmamap_t map));
119
120 bus_dmamap_t mb8795_rxdma_continue __P((void *));
121 void mb8795_rxdma_completed __P((bus_dmamap_t,void *));
122 bus_dmamap_t mb8795_txdma_continue __P((void *));
123 void mb8795_txdma_completed __P((bus_dmamap_t,void *));
124 void mb8795_rxdma_shutdown __P((void *));
125 void mb8795_txdma_shutdown __P((void *));
126 bus_dmamap_t mb8795_txdma_restart __P((bus_dmamap_t,void *));
127
128 void
129 mb8795_config(sc)
130 struct mb8795_softc *sc;
131 {
132 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
133
134 DPRINTF(("%s: mb8795_config()\n",sc->sc_dev.dv_xname));
135
136 /* Initialize ifnet structure. */
137 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
138 ifp->if_softc = sc;
139 ifp->if_start = mb8795_start;
140 ifp->if_ioctl = mb8795_ioctl;
141 ifp->if_watchdog = mb8795_watchdog;
142 ifp->if_flags =
143 IFF_BROADCAST | IFF_NOTRAILERS;
144
145 /* Attach the interface. */
146 if_attach(ifp);
147 ether_ifattach(ifp, sc->sc_enaddr);
148
149 /* decrease the mtu on this interface to deal with
150 * alignment problems
151 */
152 ifp->if_mtu -= 16;
153
154 sc->sc_sh = shutdownhook_establish(mb8795_shutdown, sc);
155 if (sc->sc_sh == NULL)
156 panic("mb8795_config: can't establish shutdownhook");
157
158 #if NRND > 0
159 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
160 RND_TYPE_NET, 0);
161 #endif
162
163 /* Initialize the dma maps */
164 {
165 int error;
166 if ((error = bus_dmamap_create(sc->sc_tx_dmat, MCLBYTES,
167 (MCLBYTES/MSIZE), MCLBYTES, 0, BUS_DMA_ALLOCNOW,
168 &sc->sc_tx_dmamap)) != 0) {
169 panic("%s: can't create tx DMA map, error = %d\n",
170 sc->sc_dev.dv_xname, error);
171 }
172 {
173 int i;
174 for(i=0;i<MB8795_NRXBUFS;i++) {
175 if ((error = bus_dmamap_create(sc->sc_rx_dmat, MCLBYTES,
176 (MCLBYTES/MSIZE), MCLBYTES, 0, BUS_DMA_ALLOCNOW,
177 &sc->sc_rx_dmamap[i])) != 0) {
178 panic("%s: can't create rx DMA map, error = %d\n",
179 sc->sc_dev.dv_xname, error);
180 }
181 sc->sc_rx_mb_head[i] = NULL;
182 }
183 sc->sc_rx_loaded_idx = 0;
184 sc->sc_rx_completed_idx = 0;
185 sc->sc_rx_handled_idx = 0;
186 }
187 }
188
189 /* @@@ more next hacks
190 * the 2000 covers at least a 1500 mtu + headers
191 * + DMA_BEGINALIGNMENT+ DMA_ENDALIGNMENT
192 */
193 sc->sc_txbuf = malloc(2000, M_DEVBUF, M_NOWAIT);
194 if (!sc->sc_txbuf) panic("%s: can't malloc tx DMA buffer",
195 sc->sc_dev.dv_xname);
196
197 sc->sc_tx_mb_head = NULL;
198 sc->sc_tx_loaded = 0;
199
200 sc->sc_tx_nd->nd_shutdown_cb = mb8795_txdma_shutdown;
201 sc->sc_tx_nd->nd_continue_cb = mb8795_txdma_continue;
202 sc->sc_tx_nd->nd_completed_cb = mb8795_txdma_completed;
203 sc->sc_tx_nd->nd_cb_arg = sc;
204
205 sc->sc_rx_nd->nd_shutdown_cb = mb8795_rxdma_shutdown;
206 sc->sc_rx_nd->nd_continue_cb = mb8795_rxdma_continue;
207 sc->sc_rx_nd->nd_completed_cb = mb8795_rxdma_completed;
208 sc->sc_rx_nd->nd_cb_arg = sc;
209
210 DPRINTF(("%s: leaving mb8795_config()\n",sc->sc_dev.dv_xname));
211 }
212
213
214 /****************************************************************/
215 #ifdef XE_DEBUG
216 #define XCHR(x) "0123456789abcdef"[(x) & 0xf]
217 static void
218 xe_hex_dump(unsigned char *pkt, size_t len)
219 {
220 size_t i, j;
221
222 printf("00000000 ");
223 for(i=0; i<len; i++) {
224 printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i]));
225 if ((i+1) % 16 == 8) {
226 printf(" ");
227 }
228 if ((i+1) % 16 == 0) {
229 printf(" %c", '|');
230 for(j=0; j<16; j++) {
231 printf("%c", pkt[i-15+j]>=32 && pkt[i-15+j]<127?pkt[i-15+j]:'.');
232 }
233 printf("%c\n%c%c%c%c%c%c%c%c ", '|',
234 XCHR((i+1)>>28),XCHR((i+1)>>24),XCHR((i+1)>>20),XCHR((i+1)>>16),
235 XCHR((i+1)>>12), XCHR((i+1)>>8), XCHR((i+1)>>4), XCHR(i+1));
236 }
237 }
238 printf("\n");
239 }
240 #undef XCHR
241 #endif
242
243 /*
244 * Controller receive interrupt.
245 */
246 void
247 mb8795_rint(sc)
248 struct mb8795_softc *sc;
249 {
250 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
251 int error = 0;
252 u_char rxstat;
253 u_char rxmask;
254
255 rxstat = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT);
256 rxmask = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK);
257
258 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT, XE_RXSTAT_CLEAR);
259
260 if (rxstat & XE_RXSTAT_RESET) {
261 DPRINTF(("%s: rx reset packet\n",
262 sc->sc_dev.dv_xname));
263 error++;
264 }
265 if (rxstat & XE_RXSTAT_SHORT) {
266 DPRINTF(("%s: rx short packet\n",
267 sc->sc_dev.dv_xname));
268 error++;
269 }
270 if (rxstat & XE_RXSTAT_ALIGNERR) {
271 DPRINTF(("%s: rx alignment error\n",
272 sc->sc_dev.dv_xname));
273 #if 0
274 error++;
275 #endif
276 }
277 if (rxstat & XE_RXSTAT_CRCERR) {
278 DPRINTF(("%s: rx CRC error\n",
279 sc->sc_dev.dv_xname));
280 #if 0
281 error++;
282 #endif
283 }
284 if (rxstat & XE_RXSTAT_OVERFLOW) {
285 DPRINTF(("%s: rx overflow error\n",
286 sc->sc_dev.dv_xname));
287 #if 0
288 error++;
289 #endif
290 }
291
292 if (error) {
293 ifp->if_ierrors++;
294 /* @@@ handle more gracefully, free memory, etc. */
295 }
296
297 if (rxstat & XE_RXSTAT_OK) {
298 int s;
299 s = spldma();
300
301 while(sc->sc_rx_handled_idx != sc->sc_rx_completed_idx) {
302 struct mbuf *m;
303 bus_dmamap_t map;
304
305 sc->sc_rx_handled_idx++;
306 sc->sc_rx_handled_idx %= MB8795_NRXBUFS;
307
308 /* Should probably not do this much while interrupts
309 * are disabled, but for now we will.
310 */
311
312 map = sc->sc_rx_dmamap[sc->sc_rx_handled_idx];
313 m = sc->sc_rx_mb_head[sc->sc_rx_handled_idx];
314
315 m->m_pkthdr.len = m->m_len = map->dm_xfer_len;
316 m->m_flags |= M_HASFCS;
317 m->m_pkthdr.rcvif = ifp;
318
319 bus_dmamap_sync(sc->sc_rx_dmat, map,
320 0, map->dm_mapsize, BUS_DMASYNC_POSTREAD);
321
322 bus_dmamap_unload(sc->sc_rx_dmat, map);
323
324 /* Install a fresh mbuf for next packet */
325
326 sc->sc_rx_mb_head[sc->sc_rx_handled_idx] =
327 mb8795_rxdmamap_load(sc,map);
328
329 /* Punt runt packets
330 * dma restarts create 0 length packets for example
331 */
332 if (m->m_len < ETHER_MIN_LEN) {
333 m_freem(m);
334 continue;
335 }
336
337 /* Find receive length, keep crc */
338 /* enable dma interrupts while we process the packet */
339 splx(s);
340
341 #if defined(XE_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 (xe_debug > 3) {
346 xe_hex_dump(mtod(m,u_char *), m->m_pkthdr.len);
347 } else if (xe_debug > 2) {
348 xe_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 XE_DEBUG
376 if (xe_debug) {
377 char sbuf[256];
378
379 bitmask_snprintf(rxstat, XE_RXSTAT_BITS, sbuf, sizeof(sbuf));
380 printf("%s: rx interrupt, rxstat = %s\n",
381 sc->sc_dev.dv_xname, sbuf);
382
383 bitmask_snprintf(bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT),
384 XE_RXSTAT_BITS, sbuf, sizeof(sbuf));
385 printf("rxstat = 0x%s\n", sbuf);
386
387 bitmask_snprintf(bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK),
388 XE_RXMASK_BITS, sbuf, sizeof(sbuf));
389 printf("rxmask = 0x%s\n", sbuf);
390
391 bitmask_snprintf(bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXMODE),
392 XE_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 {
408 u_char txstat;
409 u_char txmask;
410 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
411
412 txstat = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXSTAT);
413 txmask = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK);
414
415 if (txstat & XE_TXSTAT_SHORTED) {
416 printf("%s: tx cable shorted\n", sc->sc_dev.dv_xname);
417 ifp->if_oerrors++;
418 }
419 if (txstat & XE_TXSTAT_UNDERFLOW) {
420 printf("%s: tx underflow\n", sc->sc_dev.dv_xname);
421 ifp->if_oerrors++;
422 }
423 if (txstat & XE_TXSTAT_COLLERR) {
424 DPRINTF(("%s: tx collision\n", sc->sc_dev.dv_xname));
425 ifp->if_collisions++;
426 }
427 if (txstat & XE_TXSTAT_COLLERR16) {
428 printf("%s: tx 16th collision\n", sc->sc_dev.dv_xname);
429 ifp->if_oerrors++;
430 ifp->if_collisions += 16;
431 }
432
433 #if 0
434 if (txstat & XE_TXSTAT_READY) {
435 char sbuf[256];
436
437 bitmask_snprintf(txstat, XE_TXSTAT_BITS, sbuf, sizeof(sbuf));
438 panic("%s: unexpected tx interrupt %s",
439 sc->sc_dev.dv_xname, sbuf);
440
441 /* turn interrupt off */
442 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK,
443 txmask & ~XE_TXMASK_READYIE);
444 }
445 #endif
446
447 return;
448 }
449
450 /****************************************************************/
451
452 void
453 mb8795_reset(sc)
454 struct mb8795_softc *sc;
455 {
456 int s;
457
458 s = splnet();
459 mb8795_init(sc);
460 splx(s);
461 }
462
463 void
464 mb8795_watchdog(ifp)
465 struct ifnet *ifp;
466 {
467 struct mb8795_softc *sc = ifp->if_softc;
468
469 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
470 ++ifp->if_oerrors;
471
472 DPRINTF(("%s: %lld input errors, %lld input packets\n",
473 sc->sc_dev.dv_xname, ifp->if_ierrors, ifp->if_ipackets));
474
475 mb8795_reset(sc);
476 }
477
478 /*
479 * Initialization of interface; set up initialization block
480 * and transmit/receive descriptor rings.
481 * @@@ error handling is bogus in here. memory leaks
482 */
483 void
484 mb8795_init(sc)
485 struct mb8795_softc *sc;
486 {
487 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
488
489 m_freem(sc->sc_tx_mb_head);
490 sc->sc_tx_mb_head = NULL;
491 sc->sc_tx_loaded = 0;
492
493 {
494 int i;
495 for(i=0;i<MB8795_NRXBUFS;i++) {
496 if (sc->sc_rx_mb_head[i]) {
497 bus_dmamap_unload(sc->sc_rx_dmat, sc->sc_rx_dmamap[i]);
498 m_freem(sc->sc_rx_mb_head[i]);
499 }
500 sc->sc_rx_mb_head[i] =
501 mb8795_rxdmamap_load(sc, sc->sc_rx_dmamap[i]);
502 }
503 sc->sc_rx_loaded_idx = 0;
504 sc->sc_rx_completed_idx = 0;
505 sc->sc_rx_handled_idx = 0;
506 }
507
508 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RESET, XE_RESET_MODE);
509
510 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMODE, XE_TXMODE_LB_DISABLE);
511 #if 0 /* This interrupt was sometimes failing to ack correctly
512 * causing a loop @@@
513 */
514 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK,
515 XE_TXMASK_UNDERFLOWIE | XE_TXMASK_COLLIE | XE_TXMASK_COLL16IE
516 | XE_TXMASK_PARERRIE);
517 #else
518 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK, 0);
519 #endif
520 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXSTAT, XE_TXSTAT_CLEAR);
521
522 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXMODE, XE_RXMODE_NORMAL);
523
524 #if 0
525 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK,
526 XE_RXMASK_OKIE | XE_RXMASK_RESETIE | XE_RXMASK_SHORTIE |
527 XE_RXMASK_ALIGNERRIE | XE_RXMASK_CRCERRIE | XE_RXMASK_OVERFLOWIE);
528 #else
529 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK,
530 XE_RXMASK_OKIE | XE_RXMASK_RESETIE | XE_RXMASK_SHORTIE);
531 #endif
532
533 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT, XE_RXSTAT_CLEAR);
534
535 {
536 int i;
537 for(i=0;i<sizeof(sc->sc_enaddr);i++) {
538 bus_space_write_1(sc->sc_bst,sc->sc_bsh,XE_ENADDR+i,sc->sc_enaddr[i]);
539 }
540 }
541
542 DPRINTF(("%s: initializing ethernet %02x:%02x:%02x:%02x:%02x:%02x, size=%d\n",
543 sc->sc_dev.dv_xname,
544 sc->sc_enaddr[0],sc->sc_enaddr[1],sc->sc_enaddr[2],
545 sc->sc_enaddr[3],sc->sc_enaddr[4],sc->sc_enaddr[5],
546 sizeof(sc->sc_enaddr)));
547
548 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RESET, 0);
549
550 ifp->if_flags |= IFF_RUNNING;
551 ifp->if_flags &= ~IFF_OACTIVE;
552 ifp->if_timer = 0;
553
554 nextdma_init(sc->sc_tx_nd);
555 nextdma_init(sc->sc_rx_nd);
556
557 nextdma_start(sc->sc_rx_nd, DMACSR_SETREAD);
558
559 if (ifp->if_snd.ifq_head != NULL) {
560 mb8795_start(ifp);
561 }
562 }
563
564 void
565 mb8795_stop(sc)
566 struct mb8795_softc *sc;
567 {
568 printf("%s: stop not implemented\n", sc->sc_dev.dv_xname);
569 }
570
571
572 void
573 mb8795_shutdown(arg)
574 void *arg;
575 {
576 struct mb8795_softc *sc = (struct mb8795_softc *)arg;
577 mb8795_stop(sc);
578 }
579
580 /****************************************************************/
581 int
582 mb8795_ioctl(ifp, cmd, data)
583 register struct ifnet *ifp;
584 u_long cmd;
585 caddr_t data;
586 {
587 register struct mb8795_softc *sc = ifp->if_softc;
588 struct ifaddr *ifa = (struct ifaddr *)data;
589 struct ifreq *ifr = (struct ifreq *)data;
590 int s, error = 0;
591
592 s = splnet();
593
594 switch (cmd) {
595
596 case SIOCSIFADDR:
597 ifp->if_flags |= IFF_UP;
598
599 switch (ifa->ifa_addr->sa_family) {
600 #ifdef INET
601 case AF_INET:
602 mb8795_init(sc);
603 arp_ifinit(ifp, ifa);
604 break;
605 #endif
606 #ifdef NS
607 case AF_NS:
608 {
609 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
610
611 if (ns_nullhost(*ina))
612 ina->x_host =
613 *(union ns_host *)LLADDR(ifp->if_sadl);
614 else {
615 bcopy(ina->x_host.c_host,
616 LLADDR(ifp->if_sadl),
617 sizeof(sc->sc_enaddr));
618 }
619 /* Set new address. */
620 mb8795_init(sc);
621 break;
622 }
623 #endif
624 default:
625 mb8795_init(sc);
626 break;
627 }
628 break;
629
630 #if defined(CCITT) && defined(LLC)
631 case SIOCSIFCONF_X25:
632 ifp->if_flags |= IFF_UP;
633 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */
634 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
635 if (error == 0)
636 mb8795_init(sc);
637 break;
638 #endif /* CCITT && LLC */
639
640 case SIOCSIFFLAGS:
641 if ((ifp->if_flags & IFF_UP) == 0 &&
642 (ifp->if_flags & IFF_RUNNING) != 0) {
643 /*
644 * If interface is marked down and it is running, then
645 * stop it.
646 */
647 mb8795_stop(sc);
648 ifp->if_flags &= ~IFF_RUNNING;
649 } else if ((ifp->if_flags & IFF_UP) != 0 &&
650 (ifp->if_flags & IFF_RUNNING) == 0) {
651 /*
652 * If interface is marked up and it is stopped, then
653 * start it.
654 */
655 mb8795_init(sc);
656 } else {
657 /*
658 * Reset the interface to pick up changes in any other
659 * flags that affect hardware registers.
660 */
661 /*mb8795_stop(sc);*/
662 mb8795_init(sc);
663 }
664 #ifdef XE_DEBUG
665 if (ifp->if_flags & IFF_DEBUG)
666 sc->sc_debug = 1;
667 else
668 sc->sc_debug = 0;
669 #endif
670 break;
671
672 case SIOCADDMULTI:
673 case SIOCDELMULTI:
674 error = (cmd == SIOCADDMULTI) ?
675 ether_addmulti(ifr, &sc->sc_ethercom) :
676 ether_delmulti(ifr, &sc->sc_ethercom);
677
678 if (error == ENETRESET) {
679 /*
680 * Multicast list has changed; set the hardware filter
681 * accordingly.
682 */
683 mb8795_reset(sc);
684 error = 0;
685 }
686 break;
687
688 #if 0
689 case SIOCGIFMEDIA:
690 case SIOCSIFMEDIA:
691 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
692 break;
693 #endif
694
695 default:
696 error = EINVAL;
697 break;
698 }
699
700 splx(s);
701
702 #if 0
703 DPRINTF(("DEBUG: mb8795_ioctl(0x%lx) returning %d\n",
704 cmd,error));
705 #endif
706
707 return (error);
708 }
709
710 /*
711 * Setup output on interface.
712 * Get another datagram to send off of the interface queue, and map it to the
713 * interface before starting the output.
714 * Called only at splnet or interrupt level.
715 */
716 void
717 mb8795_start(ifp)
718 struct ifnet *ifp;
719 {
720 int error;
721 struct mb8795_softc *sc = ifp->if_softc;
722
723 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
724 return;
725
726 DPRINTF(("%s: mb8795_start()\n",sc->sc_dev.dv_xname));
727
728 #if (defined(DIAGNOSTIC))
729 {
730 u_char txstat;
731 txstat = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXSTAT);
732 if (!(txstat & XE_TXSTAT_READY)) {
733 /* @@@ I used to panic here, but then it paniced once.
734 * Let's see if I can just reset instead. [ dbj 980706.1900 ]
735 */
736 printf("%s: transmitter not ready\n", sc->sc_dev.dv_xname);
737 mb8795_reset(sc);
738 return;
739 }
740 }
741 #endif
742
743 #if 0
744 return; /* @@@ Turn off xmit for debugging */
745 #endif
746
747 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXSTAT, XE_TXSTAT_CLEAR);
748
749 IF_DEQUEUE(&ifp->if_snd, sc->sc_tx_mb_head);
750 if (sc->sc_tx_mb_head == 0) {
751 printf("%s: No packet to start\n",
752 sc->sc_dev.dv_xname);
753 return;
754 }
755
756 ifp->if_timer = 5;
757
758 /* The following is a next specific hack that should
759 * probably be moved out of MI code.
760 * This macro assumes it can move forward as needed
761 * in the buffer. Perhaps it should zero the extra buffer.
762 */
763 #define REALIGN_DMABUF(s,l) \
764 { (s) = ((u_char *)(((unsigned)(s)+DMA_BEGINALIGNMENT-1) \
765 &~(DMA_BEGINALIGNMENT-1))); \
766 (l) = ((u_char *)(((unsigned)((s)+(l))+DMA_ENDALIGNMENT-1) \
767 &~(DMA_ENDALIGNMENT-1)))-(s);}
768
769 #if 0
770 error = bus_dmamap_load_mbuf(sc->sc_tx_dmat,
771 sc->sc_tx_dmamap,
772 sc->sc_tx_mb_head,
773 BUS_DMA_NOWAIT);
774 #else
775 {
776 u_char *buf = sc->sc_txbuf;
777 int buflen = 0;
778 struct mbuf *m = sc->sc_tx_mb_head;
779 buflen = m->m_pkthdr.len;
780
781 /* Fix runt packets, @@@ memory overrun */
782 if (buflen < ETHERMIN+sizeof(struct ether_header)) {
783 buflen = ETHERMIN+sizeof(struct ether_header);
784 }
785
786 buflen += 15;
787 REALIGN_DMABUF(buf,buflen);
788 if (buflen > 1520) {
789 panic("%s: packet too long\n",sc->sc_dev.dv_xname);
790 }
791
792 {
793 u_char *p = buf;
794 for (m=sc->sc_tx_mb_head; m; m = m->m_next) {
795 if (m->m_len == 0) continue;
796 bcopy(mtod(m, u_char *), p, m->m_len);
797 p += m->m_len;
798 }
799 }
800
801 error = bus_dmamap_load(sc->sc_tx_dmat, sc->sc_tx_dmamap,
802 buf,buflen,NULL,BUS_DMA_NOWAIT);
803 }
804 #endif
805 if (error) {
806 printf("%s: can't load mbuf chain, error = %d\n",
807 sc->sc_dev.dv_xname, error);
808 m_freem(sc->sc_tx_mb_head);
809 sc->sc_tx_mb_head = NULL;
810 return;
811 }
812
813 #ifdef DIAGNOSTIC
814 if (sc->sc_tx_loaded != 0) {
815 panic("%s: sc->sc_tx_loaded is %d",sc->sc_dev.dv_xname,
816 sc->sc_tx_loaded);
817 }
818 #endif
819
820 ifp->if_flags |= IFF_OACTIVE;
821
822 bus_dmamap_sync(sc->sc_tx_dmat, sc->sc_tx_dmamap, 0,
823 sc->sc_tx_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
824
825 nextdma_start(sc->sc_tx_nd, DMACSR_SETWRITE);
826
827 #if NBPFILTER > 0
828 /*
829 * Pass packet to bpf if there is a listener.
830 */
831 if (ifp->if_bpf)
832 bpf_mtap(ifp->if_bpf, sc->sc_tx_mb_head);
833 #endif
834
835 }
836
837 /****************************************************************/
838
839 void
840 mb8795_txdma_completed(map, arg)
841 bus_dmamap_t map;
842 void *arg;
843 {
844 struct mb8795_softc *sc = arg;
845
846 DPRINTF(("%s: mb8795_txdma_completed()\n",sc->sc_dev.dv_xname));
847
848 #ifdef DIAGNOSTIC
849 if (!sc->sc_tx_loaded) {
850 panic("%s: tx completed never loaded ",sc->sc_dev.dv_xname);
851 }
852 if (map != sc->sc_tx_dmamap) {
853 panic("%s: unexpected tx completed map",sc->sc_dev.dv_xname);
854 }
855
856 #endif
857 }
858
859 void
860 mb8795_txdma_shutdown(arg)
861 void *arg;
862 {
863 struct mb8795_softc *sc = arg;
864 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
865
866 DPRINTF(("%s: mb8795_txdma_shutdown()\n",sc->sc_dev.dv_xname));
867
868 #ifdef DIAGNOSTIC
869 if (!sc->sc_tx_loaded) {
870 panic("%s: tx shutdown never loaded ",sc->sc_dev.dv_xname);
871 }
872 #endif
873
874 {
875
876 if (sc->sc_tx_loaded) {
877 bus_dmamap_sync(sc->sc_tx_dmat, sc->sc_tx_dmamap,
878 0, sc->sc_tx_dmamap->dm_mapsize,
879 BUS_DMASYNC_POSTWRITE);
880 bus_dmamap_unload(sc->sc_tx_dmat, sc->sc_tx_dmamap);
881 m_freem(sc->sc_tx_mb_head);
882 sc->sc_tx_mb_head = NULL;
883
884 sc->sc_tx_loaded--;
885 }
886
887 #ifdef DIAGNOSTIC
888 if (sc->sc_tx_loaded != 0) {
889 panic("%s: sc->sc_tx_loaded is %d",sc->sc_dev.dv_xname,
890 sc->sc_tx_loaded);
891 }
892 #endif
893
894 ifp->if_flags &= ~IFF_OACTIVE;
895
896 ifp->if_timer = 0;
897
898 if (ifp->if_snd.ifq_head != NULL) {
899 mb8795_start(ifp);
900 }
901
902 }
903
904 #if 0
905 /* Enable ready interrupt */
906 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK,
907 bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK)
908 | XE_TXMASK_READYIE);
909 #endif
910 }
911
912
913 void
914 mb8795_rxdma_completed(map, arg)
915 bus_dmamap_t map;
916 void *arg;
917 {
918 struct mb8795_softc *sc = arg;
919
920 sc->sc_rx_completed_idx++;
921 sc->sc_rx_completed_idx %= MB8795_NRXBUFS;
922
923 DPRINTF(("%s: mb8795_rxdma_completed(), sc->sc_rx_completed_idx = %d\n",
924 sc->sc_dev.dv_xname, sc->sc_rx_completed_idx));
925
926 #if (defined(DIAGNOSTIC))
927 if (map != sc->sc_rx_dmamap[sc->sc_rx_completed_idx]) {
928 panic("%s: Unexpected rx dmamap completed\n",
929 sc->sc_dev.dv_xname);
930 }
931 #endif
932 }
933
934 void
935 mb8795_rxdma_shutdown(arg)
936 void *arg;
937 {
938 struct mb8795_softc *sc = arg;
939
940 DPRINTF(("%s: mb8795_rxdma_shutdown(), restarting.\n",sc->sc_dev.dv_xname));
941
942 nextdma_start(sc->sc_rx_nd, DMACSR_SETREAD);
943 }
944
945
946 /*
947 * load a dmamap with a freshly allocated mbuf
948 */
949 struct mbuf *
950 mb8795_rxdmamap_load(sc,map)
951 struct mb8795_softc *sc;
952 bus_dmamap_t map;
953 {
954 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
955 struct mbuf *m;
956 int error;
957
958 MGETHDR(m, M_DONTWAIT, MT_DATA);
959 if (m) {
960 MCLGET(m, M_DONTWAIT);
961 if ((m->m_flags & M_EXT) == 0) {
962 m_freem(m);
963 m = NULL;
964 } else {
965 m->m_len = MCLBYTES;
966 }
967 }
968 if (!m) {
969 /* @@@ Handle this gracefully by reusing a scratch buffer
970 * or something.
971 */
972 panic("Unable to get memory for incoming ethernet\n");
973 }
974
975 /* Align buffer, @@@ next specific.
976 * perhaps should be using M_ALIGN here instead?
977 * First we give us a little room to align with.
978 */
979 {
980 u_char *buf = m->m_data;
981 int buflen = m->m_len;
982 buflen -= DMA_ENDALIGNMENT+DMA_BEGINALIGNMENT;
983 REALIGN_DMABUF(buf, buflen);
984 m->m_data = buf;
985 m->m_len = buflen;
986 }
987
988 m->m_pkthdr.rcvif = ifp;
989 m->m_pkthdr.len = m->m_len;
990
991 error = bus_dmamap_load_mbuf(sc->sc_rx_dmat,
992 map, m, BUS_DMA_NOWAIT);
993
994 bus_dmamap_sync(sc->sc_rx_dmat, map, 0,
995 map->dm_mapsize, BUS_DMASYNC_PREREAD);
996
997 if (error) {
998 DPRINTF(("DEBUG: m->m_data = %p, m->m_len = %d\n",
999 m->m_data, m->m_len));
1000 DPRINTF(("DEBUG: MCLBYTES = %d, map->_dm_size = %ld\n",
1001 MCLBYTES, map->_dm_size));
1002
1003 panic("%s: can't load rx mbuf chain, error = %d\n",
1004 sc->sc_dev.dv_xname, error);
1005 m_freem(m);
1006 m = NULL;
1007 }
1008
1009 return(m);
1010 }
1011
1012 bus_dmamap_t
1013 mb8795_rxdma_continue(arg)
1014 void *arg;
1015 {
1016 struct mb8795_softc *sc = arg;
1017 bus_dmamap_t map = NULL;
1018
1019 /*
1020 * Currently, starts dumping new packets if the buffers
1021 * fill up. This should probably reclaim unhandled
1022 * buffers instead so we drop older packets instead
1023 * of newer ones.
1024 */
1025 if (((sc->sc_rx_loaded_idx+1)%MB8795_NRXBUFS) != sc->sc_rx_handled_idx) {
1026 sc->sc_rx_loaded_idx++;
1027 sc->sc_rx_loaded_idx %= MB8795_NRXBUFS;
1028 map = sc->sc_rx_dmamap[sc->sc_rx_loaded_idx];
1029
1030 DPRINTF(("%s: mb8795_rxdma_continue() sc->sc_rx_loaded_idx = %d\nn",
1031 sc->sc_dev.dv_xname,sc->sc_rx_loaded_idx));
1032 }
1033 #if (defined(DIAGNOSTIC))
1034 else {
1035 panic("%s: out of receive DMA buffers\n",sc->sc_dev.dv_xname);
1036 }
1037 #endif
1038
1039 return(map);
1040 }
1041
1042 bus_dmamap_t
1043 mb8795_txdma_continue(arg)
1044 void *arg;
1045 {
1046 struct mb8795_softc *sc = arg;
1047 bus_dmamap_t map;
1048
1049 DPRINTF(("%s: mb8795_txdma_continue()\n",sc->sc_dev.dv_xname));
1050
1051 if (sc->sc_tx_loaded) {
1052 map = NULL;
1053 } else {
1054 map = sc->sc_tx_dmamap;
1055 sc->sc_tx_loaded++;
1056 }
1057
1058 #ifdef DIAGNOSTIC
1059 if (sc->sc_tx_loaded != 1) {
1060 panic("%s: sc->sc_tx_loaded is %d",sc->sc_dev.dv_xname,
1061 sc->sc_tx_loaded);
1062 }
1063 #endif
1064
1065 return(map);
1066 }
1067
1068 /****************************************************************/
1069