xref: /netbsd-src/sys/arch/next68k/dev/mb8795.c (revision e55cffd8e520e9b03f18a1bd98bb04223e79f69f)
1 /*	$NetBSD: mb8795.c,v 1.22 2001/04/16 14:12:12 dbj 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 0x%08x-0x%08x,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: %d input errors, %d 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 = 0x%08x, m->m_len = %d\n",
999 				m->m_data, m->m_len));
1000 		DPRINTF(("DEBUG: MCLBYTES = %d, map->_dm_size = %d\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