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