Home | History | Annotate | Line # | Download | only in ebus
if_le_ebus.c revision 1.13.14.2
      1  1.13.14.2  pgoyette /*	$NetBSD: if_le_ebus.c,v 1.13.14.2 2018/07/28 04:37:30 pgoyette Exp $	*/
      2        1.1     pooka 
      3        1.1     pooka /*-
      4        1.1     pooka  * Copyright (c) 2010 The NetBSD Foundation, Inc.
      5        1.1     pooka  * All rights reserved.
      6        1.1     pooka  *
      7        1.1     pooka  * This code was written by Alessandro Forin and Neil Pittman
      8        1.1     pooka  * at Microsoft Research and contributed to The NetBSD Foundation
      9        1.1     pooka  * by Microsoft Corporation.
     10        1.1     pooka  *
     11        1.1     pooka  * Redistribution and use in source and binary forms, with or without
     12        1.1     pooka  * modification, are permitted provided that the following conditions
     13        1.1     pooka  * are met:
     14        1.1     pooka  * 1. Redistributions of source code must retain the above copyright
     15        1.1     pooka  *    notice, this list of conditions and the following disclaimer.
     16        1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
     17        1.1     pooka  *    notice, this list of conditions and the following disclaimer in the
     18        1.1     pooka  *    documentation and/or other materials provided with the distribution.
     19        1.1     pooka  *
     20        1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21        1.1     pooka  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22        1.1     pooka  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23        1.1     pooka  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24        1.1     pooka  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25        1.1     pooka  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26        1.1     pooka  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27        1.1     pooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28        1.1     pooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29        1.1     pooka  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30        1.1     pooka  * POSSIBILITY OF SUCH DAMAGE.
     31        1.1     pooka  */
     32        1.1     pooka 
     33        1.1     pooka #include <sys/cdefs.h>
     34  1.13.14.2  pgoyette __KERNEL_RCSID(0, "$NetBSD: if_le_ebus.c,v 1.13.14.2 2018/07/28 04:37:30 pgoyette Exp $");
     35        1.1     pooka 
     36        1.1     pooka #include "opt_inet.h"
     37        1.1     pooka 
     38        1.4       tls 
     39        1.1     pooka 
     40        1.1     pooka #include <sys/param.h>
     41        1.1     pooka #include <sys/systm.h>
     42        1.1     pooka #include <sys/mbuf.h>
     43        1.1     pooka #include <sys/syslog.h>
     44        1.1     pooka #include <sys/socket.h>
     45        1.1     pooka #include <sys/device.h>
     46        1.1     pooka #include <sys/malloc.h>
     47        1.1     pooka #include <sys/ioctl.h>
     48        1.1     pooka #include <sys/errno.h>
     49        1.1     pooka 
     50        1.1     pooka #include <net/if.h>
     51        1.1     pooka #include <net/if_dl.h>
     52        1.1     pooka #include <net/if_ether.h>
     53        1.1     pooka #include <net/if_media.h>
     54  1.13.14.1  pgoyette #include <net/bpf.h>
     55        1.1     pooka 
     56        1.1     pooka #ifdef INET
     57        1.1     pooka #include <netinet/in.h>
     58        1.1     pooka #include <netinet/if_inarp.h>
     59        1.1     pooka #endif
     60        1.1     pooka 
     61        1.7  riastrad #include <sys/rndsource.h>
     62        1.1     pooka 
     63        1.1     pooka #include <emips/ebus/ebusvar.h>
     64        1.1     pooka #include <emips/emips/machdep.h>
     65        1.1     pooka #include <machine/emipsreg.h>
     66        1.1     pooka 
     67        1.1     pooka extern paddr_t kvtophys(vaddr_t);
     68        1.1     pooka 
     69        1.1     pooka struct bufmap {
     70        1.2   tsutsui 	struct mbuf *mbuf;
     71        1.2   tsutsui 	paddr_t phys;
     72        1.1     pooka };
     73        1.1     pooka 
     74        1.1     pooka struct enic_softc {
     75        1.1     pooka 	device_t sc_dev;		/* base device glue */
     76        1.1     pooka 	struct	ethercom sc_ethercom;	/* Ethernet common part */
     77        1.1     pooka 	struct	ifmedia sc_media;	/* our supported media */
     78        1.1     pooka 
     79        1.2   tsutsui 	struct _Enic *sc_regs;		/* hw registers */
     80        1.1     pooka 
     81        1.2   tsutsui 	int	sc_havecarrier;		/* carrier status */
     82        1.2   tsutsui 	void	*sc_sh;			/* shutdownhook cookie */
     83        1.2   tsutsui 	int inited;
     84        1.2   tsutsui 
     85        1.2   tsutsui 	int sc_no_rd;
     86        1.2   tsutsui 	int sc_n_recv;
     87        1.2   tsutsui 	int sc_recv_h;
     88        1.2   tsutsui 	/* BUGBUG really should be malloc-ed */
     89        1.1     pooka #define SC_MAX_N_RECV 64
     90        1.2   tsutsui 	struct bufmap sc_recv[SC_MAX_N_RECV];
     91        1.1     pooka 
     92        1.2   tsutsui 	int sc_no_td;
     93        1.2   tsutsui 	int sc_n_xmit;
     94        1.2   tsutsui 	int sc_xmit_h;
     95        1.2   tsutsui 	/* BUGBUG really should be malloc-ed */
     96        1.1     pooka #define SC_MAX_N_XMIT 16
     97        1.2   tsutsui 	struct bufmap sc_xmit[SC_MAX_N_XMIT];
     98        1.1     pooka 
     99        1.1     pooka #if DEBUG
    100        1.2   tsutsui 	int xhit;
    101        1.2   tsutsui 	int xmiss;
    102        1.2   tsutsui 	int tfull;
    103        1.2   tsutsui 	int tfull2;
    104        1.2   tsutsui 	int brh;
    105        1.2   tsutsui 	int rf;
    106        1.2   tsutsui 	int bxh;
    107        1.1     pooka 
    108        1.2   tsutsui 	int it;
    109        1.1     pooka #endif
    110        1.1     pooka 
    111        1.2   tsutsui 	uint8_t sc_enaddr[ETHER_ADDR_LEN];
    112        1.2   tsutsui 	uint8_t sc_pad[2];
    113        1.3       tls 	krndsource_t	rnd_source;
    114        1.1     pooka };
    115        1.1     pooka 
    116        1.1     pooka void enic_reset(struct ifnet *);
    117        1.1     pooka int enic_init(struct ifnet *);
    118        1.2   tsutsui void enic_stop(struct ifnet *, int);
    119        1.2   tsutsui void enic_start(struct ifnet *);
    120        1.1     pooka void enic_shutdown(void *);
    121        1.2   tsutsui void enic_watchdog(struct ifnet *);
    122        1.2   tsutsui int enic_mediachange(struct ifnet *);
    123        1.2   tsutsui void enic_mediastatus(struct ifnet *, struct ifmediareq *);
    124        1.2   tsutsui int enic_ioctl(struct ifnet *, u_long, void *);
    125        1.2   tsutsui int enic_intr(void *, void *);
    126        1.1     pooka void enic_rint(struct enic_softc *, uint32_t, paddr_t);
    127        1.1     pooka void enic_tint(struct enic_softc *, uint32_t, paddr_t);
    128        1.2   tsutsui void enic_kill_xmit(struct enic_softc *);
    129        1.2   tsutsui void enic_post_recv(struct enic_softc *, struct mbuf *);
    130        1.2   tsutsui void enic_refill(struct enic_softc *);
    131        1.2   tsutsui static int enic_gethwinfo(struct enic_softc *);
    132        1.2   tsutsui int enic_put(struct enic_softc *, struct mbuf **);
    133        1.1     pooka 
    134        1.2   tsutsui static int enic_match(device_t, cfdata_t, void *);
    135        1.2   tsutsui static void enic_attach(device_t, device_t, void *);
    136        1.1     pooka 
    137        1.1     pooka CFATTACH_DECL_NEW(enic_emips, sizeof(struct enic_softc),
    138        1.1     pooka     enic_match, enic_attach, NULL, NULL);
    139        1.1     pooka 
    140        1.1     pooka int
    141        1.2   tsutsui enic_match(device_t parent, cfdata_t cf, void *aux)
    142        1.1     pooka {
    143        1.1     pooka 	struct ebus_attach_args *d = aux;
    144        1.1     pooka 	/* donno yet */
    145        1.1     pooka 	struct _Enic *et = (struct _Enic *)d->ia_vaddr;
    146        1.1     pooka 
    147        1.1     pooka 	if (strcmp("enic", d->ia_name) != 0)
    148        1.2   tsutsui 		return 0;
    149        1.1     pooka 	if ((et == NULL) || (et->Tag != PMTTAG_ETHERNET))
    150        1.1     pooka 		return 0;
    151        1.2   tsutsui 	return 1;
    152        1.1     pooka }
    153        1.1     pooka 
    154        1.1     pooka void
    155        1.2   tsutsui enic_attach(device_t parent, device_t self, void *aux)
    156        1.1     pooka {
    157        1.1     pooka 	struct enic_softc *sc = device_private(self);
    158        1.1     pooka 	struct ebus_attach_args *ia = aux;
    159        1.1     pooka 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    160        1.1     pooka 
    161        1.1     pooka 	sc->sc_regs = (struct _Enic *)(ia->ia_vaddr);
    162        1.1     pooka #if DEBUG
    163        1.2   tsutsui 	printf(" virt=%p ", (void *)sc->sc_regs);
    164        1.1     pooka #endif
    165        1.1     pooka 
    166        1.1     pooka 	/* Get the MAC and the depth of the FIFOs */
    167        1.1     pooka 	if (!enic_gethwinfo(sc)) {
    168        1.1     pooka 		printf(" <cannot get hw info> DISABLED.\n");
    169        1.1     pooka 		/*
    170        1.1     pooka 		 * NB: caveat maintainer: make sure what we
    171        1.1     pooka 		 * did NOT do below does not hurt the system
    172        1.1     pooka 		 */
    173        1.1     pooka 		return;
    174        1.1     pooka 	}
    175        1.1     pooka 
    176        1.1     pooka 	sc->sc_dev = self;
    177        1.1     pooka 	sc->sc_no_td = 0;
    178        1.1     pooka 	sc->sc_havecarrier = 1; /* BUGBUG */
    179        1.1     pooka 	sc->sc_recv_h = 0;
    180        1.1     pooka 	sc->sc_xmit_h = 0;
    181        1.1     pooka 	/* uhmm do I need to do this? */
    182        1.2   tsutsui 	memset(sc->sc_recv, 0, sizeof sc->sc_recv);
    183        1.2   tsutsui 	memset(sc->sc_xmit, 0, sizeof sc->sc_xmit);
    184        1.1     pooka 
    185        1.1     pooka 	/* Initialize ifnet structure. */
    186        1.1     pooka 	strcpy(ifp->if_xname, device_xname(sc->sc_dev));
    187        1.1     pooka 	ifp->if_softc = sc;
    188        1.1     pooka 	ifp->if_start = enic_start;
    189        1.1     pooka 	ifp->if_ioctl = enic_ioctl;
    190        1.1     pooka 	ifp->if_watchdog = enic_watchdog;
    191        1.1     pooka 	ifp->if_init = enic_init;
    192        1.1     pooka 	ifp->if_stop = enic_stop;
    193        1.1     pooka 	ifp->if_flags =
    194        1.1     pooka 	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
    195        1.1     pooka 	IFQ_SET_READY(&ifp->if_snd);
    196        1.1     pooka 
    197        1.1     pooka 	/* Initialize ifmedia structures. */
    198        1.1     pooka 	ifmedia_init(&sc->sc_media, 0, enic_mediachange, enic_mediastatus);
    199        1.1     pooka 	ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
    200        1.1     pooka 	ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
    201        1.1     pooka 
    202        1.1     pooka 	/* Make sure the chip is stopped. */
    203        1.1     pooka 	enic_stop(ifp, 0);
    204        1.1     pooka 	sc->inited = 0;
    205        1.1     pooka 
    206        1.1     pooka 	/* Get the mac address and print it */
    207        1.1     pooka 	printf(": eNIC [%d %d], address %s\n",
    208        1.1     pooka 	    sc->sc_n_recv, sc->sc_n_xmit, ether_sprintf(sc->sc_enaddr));
    209        1.1     pooka 
    210        1.1     pooka 	/* claim 802.1q capability */
    211        1.2   tsutsui #if 0
    212        1.2   tsutsui 	sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
    213        1.2   tsutsui #endif
    214        1.1     pooka 
    215        1.1     pooka 	/* Attach the interface. */
    216        1.1     pooka 	if_attach(ifp);
    217       1.12     ozaki 	if_deferred_start_init(ifp, NULL);
    218        1.1     pooka 	ether_ifattach(ifp, sc->sc_enaddr);
    219        1.1     pooka 
    220        1.1     pooka 	sc->sc_sh = shutdownhook_establish(enic_shutdown, ifp);
    221        1.1     pooka 	if (sc->sc_sh == NULL)
    222        1.1     pooka 		panic("enic_attach: cannot establish shutdown hook");
    223        1.1     pooka 
    224        1.1     pooka 	rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
    225        1.6       tls 			  RND_TYPE_NET, RND_FLAG_DEFAULT);
    226        1.1     pooka 
    227        1.2   tsutsui 	ebus_intr_establish(parent, (void *)ia->ia_cookie, IPL_NET,
    228        1.1     pooka 	    enic_intr, sc);
    229        1.1     pooka }
    230        1.1     pooka 
    231        1.2   tsutsui /*
    232        1.2   tsutsui  * Beware: does not work while the nic is running
    233        1.1     pooka  */
    234        1.1     pooka static int enic_gethwinfo(struct enic_softc *sc)
    235        1.1     pooka {
    236        1.2   tsutsui 	uint8_t buffer[8];	/* 64bits max */
    237        1.2   tsutsui 	PENIC_INFO hw = (PENIC_INFO)buffer;
    238        1.2   tsutsui 	paddr_t phys = kvtophys((vaddr_t)&buffer[0]), phys2;
    239        1.2   tsutsui 	int i;
    240        1.2   tsutsui 
    241        1.2   tsutsui 	/*
    242        1.2   tsutsui 	 * First thing first, get the MAC address
    243        1.2   tsutsui 	 */
    244        1.2   tsutsui 	memset(buffer,0,sizeof buffer);
    245        1.2   tsutsui 	buffer[0] = ENIC_CMD_GET_ADDRESS;
    246        1.2   tsutsui 	buffer[3] = ENIC_CMD_GET_ADDRESS;	/* bswap bug */
    247        1.2   tsutsui 	sc->sc_regs->SizeAndFlags = (sizeof buffer) | ES_F_CMD;
    248        1.2   tsutsui 	sc->sc_regs->BufferAddressHi32 = 0;
    249        1.2   tsutsui 	sc->sc_regs->BufferAddressLo32 = phys; /* go! */
    250        1.2   tsutsui 
    251        1.2   tsutsui 	for (i = 0; i < 100; i++) {
    252        1.2   tsutsui 		DELAY(100);
    253        1.2   tsutsui 		if ((sc->sc_regs->Control & EC_OF_EMPTY) == 0)
    254        1.2   tsutsui 			break;
    255        1.2   tsutsui 	}
    256        1.2   tsutsui 	if (i == 100)
    257        1.2   tsutsui 		return 0;
    258        1.1     pooka 
    259        1.2   tsutsui 	phys2 = sc->sc_regs->BufferAddressLo32;
    260        1.2   tsutsui 	if (phys2 != phys) {
    261        1.2   tsutsui 		printf("enic uhu? %llx != %llx?\n",
    262        1.2   tsutsui 		    (long long)phys, (long long)phys2);
    263        1.2   tsutsui 		return 0;
    264        1.2   tsutsui 	}
    265        1.2   tsutsui 	memcpy(sc->sc_enaddr, buffer, ETHER_ADDR_LEN);
    266        1.2   tsutsui 
    267        1.2   tsutsui 	/*
    268        1.2   tsutsui 	 * Next get the HW parameters
    269        1.2   tsutsui 	 */
    270        1.2   tsutsui 	memset(buffer,0,sizeof buffer);
    271        1.2   tsutsui 	buffer[0] = ENIC_CMD_GET_INFO;
    272        1.2   tsutsui 	buffer[3] = ENIC_CMD_GET_INFO;	/* bswap bug */
    273        1.2   tsutsui 	sc->sc_regs->SizeAndFlags = (sizeof buffer) | ES_F_CMD;
    274        1.2   tsutsui 	sc->sc_regs->BufferAddressHi32 = 0;
    275        1.2   tsutsui 	sc->sc_regs->BufferAddressLo32 = phys; /* go! */
    276        1.2   tsutsui 
    277        1.2   tsutsui 	for (i = 0; i < 100; i++) {
    278        1.2   tsutsui 		DELAY(100);
    279        1.2   tsutsui 		if ((sc->sc_regs->Control & EC_OF_EMPTY) == 0)
    280        1.2   tsutsui 			break;
    281        1.2   tsutsui 	}
    282        1.2   tsutsui 	if (i == 100)
    283        1.2   tsutsui 		return 0;
    284        1.2   tsutsui 
    285        1.2   tsutsui 	phys2 = sc->sc_regs->BufferAddressLo32;
    286        1.2   tsutsui 	if (phys2 != phys) {
    287        1.2   tsutsui 		printf("enic uhu2? %llx != %llx?\n",
    288        1.2   tsutsui 		    (long long)phys, (long long)phys2);
    289        1.2   tsutsui 		return 0;
    290        1.2   tsutsui 	}
    291        1.2   tsutsui #if 0
    292        1.2   tsutsui 	printf("enic: hwinfo: %x %x %x %x %x %x \n",
    293        1.2   tsutsui 	    hw->InputFifoSize, hw->OutputFifoSize, hw->CompletionFifoSize,
    294        1.2   tsutsui 	    hw->ErrorCount, hw->FramesDropped, hw->Reserved);
    295        1.2   tsutsui #endif
    296        1.2   tsutsui 
    297        1.2   tsutsui 	/*
    298        1.2   tsutsui 	 * Get FIFO depths and cap them
    299        1.2   tsutsui 	 */
    300        1.2   tsutsui 	sc->sc_n_recv = hw->InputFifoSize;
    301        1.2   tsutsui 	if (sc->sc_n_recv > SC_MAX_N_RECV)
    302        1.2   tsutsui 		sc->sc_n_recv = SC_MAX_N_RECV;
    303        1.2   tsutsui 	if (sc->sc_n_recv == 0) { /* sanity and compat with old hw/simulator */
    304        1.2   tsutsui 		sc->sc_n_recv = 8;
    305        1.2   tsutsui 		sc->sc_n_xmit = 4;
    306        1.2   tsutsui 	} else {
    307        1.2   tsutsui 		sc->sc_n_xmit = hw->OutputFifoSize;
    308        1.2   tsutsui 		if (sc->sc_n_xmit > SC_MAX_N_XMIT)
    309        1.2   tsutsui 			sc->sc_n_xmit = SC_MAX_N_XMIT;
    310        1.2   tsutsui 	}
    311        1.2   tsutsui 
    312        1.2   tsutsui 	return 1;
    313        1.1     pooka }
    314        1.1     pooka 
    315        1.1     pooka void
    316        1.1     pooka enic_reset(struct ifnet *ifp)
    317        1.1     pooka {
    318        1.1     pooka 	int s;
    319        1.1     pooka 
    320        1.1     pooka 	s = splnet();
    321        1.1     pooka 	enic_stop(ifp,0);
    322        1.1     pooka 	enic_init(ifp);
    323        1.1     pooka 	splx(s);
    324        1.1     pooka }
    325        1.1     pooka 
    326        1.1     pooka void
    327        1.1     pooka enic_stop(struct ifnet *ifp, int suspend)
    328        1.1     pooka {
    329        1.1     pooka 	struct enic_softc *sc = ifp->if_softc;
    330        1.1     pooka 
    331        1.2   tsutsui #if 0
    332        1.2   tsutsui 	printf("enic_stop %x\n", sc->sc_regs->Control);
    333        1.2   tsutsui #endif
    334        1.1     pooka 
    335        1.2   tsutsui 	/*
    336        1.2   tsutsui 	 * NB: only "ifconfig down" says suspend=1 (then "up" calls init)
    337        1.2   tsutsui 	 * Could simply set RXDIS in this case
    338        1.2   tsutsui 	 */
    339        1.2   tsutsui 	sc->inited = 2;
    340        1.2   tsutsui 	sc->sc_regs->Control = EC_RESET;
    341        1.2   tsutsui 	sc->sc_no_rd = 0; /* they are gone */
    342        1.2   tsutsui 	sc->sc_no_td = 0; /* they are gone */
    343        1.1     pooka }
    344        1.1     pooka 
    345        1.1     pooka void
    346        1.1     pooka enic_shutdown(void *arg)
    347        1.1     pooka {
    348        1.1     pooka 	struct ifnet *ifp = arg;
    349        1.1     pooka 
    350        1.1     pooka 	enic_stop(ifp, 0);
    351        1.1     pooka }
    352        1.1     pooka 
    353        1.1     pooka void
    354        1.1     pooka enic_kill_xmit(struct enic_softc *sc)
    355        1.1     pooka {
    356        1.2   tsutsui 	int i;
    357        1.2   tsutsui 	struct mbuf *m;
    358        1.1     pooka 
    359        1.2   tsutsui 	for (i = 0; i < sc->sc_n_xmit; i++) {
    360        1.2   tsutsui 		if ((m = sc->sc_xmit[i].mbuf) != NULL) {
    361        1.2   tsutsui 			sc->sc_xmit[i].mbuf = NULL;
    362        1.2   tsutsui 			sc->sc_xmit[i].phys = ~0;
    363        1.2   tsutsui 			m_freem(m);
    364        1.2   tsutsui 		}
    365        1.2   tsutsui 	}
    366        1.1     pooka 	sc->sc_no_td = 0;
    367        1.2   tsutsui 	sc->sc_xmit_h = 0;
    368        1.1     pooka }
    369        1.1     pooka 
    370        1.1     pooka void
    371        1.1     pooka enic_post_recv(struct enic_softc *sc, struct mbuf *m)
    372        1.1     pooka {
    373        1.2   tsutsui 	int i, waitmode = M_DONTWAIT;
    374        1.2   tsutsui 	paddr_t phys;
    375        1.1     pooka 
    376        1.1     pooka #define rpostone(_p_) \
    377        1.1     pooka     sc->sc_regs->SizeAndFlags = ES_F_RECV | MCLBYTES; \
    378        1.1     pooka     sc->sc_regs->BufferAddressHi32 = 0; \
    379        1.1     pooka     sc->sc_regs->BufferAddressLo32 = _p_;
    380        1.1     pooka #define tpostone(_p_,_s_) \
    381        1.1     pooka     sc->sc_regs->SizeAndFlags = ES_F_XMIT | (_s_); \
    382        1.1     pooka     sc->sc_regs->BufferAddressHi32 = 0; \
    383        1.1     pooka     sc->sc_regs->BufferAddressLo32 = _p_;
    384        1.1     pooka 
    385        1.2   tsutsui 	/* Operational reload? */
    386        1.2   tsutsui 	if (m != NULL) {
    387        1.2   tsutsui 		/* But is the hw ready for it */
    388        1.2   tsutsui 		if (sc->sc_regs->Control & EC_IF_FULL)
    389        1.2   tsutsui 			goto no_room;
    390        1.2   tsutsui 		/* Yes, find a spot. Include empty q case. */
    391        1.2   tsutsui 		for (i = sc->sc_recv_h; i < sc->sc_n_recv; i++)
    392        1.2   tsutsui 			if (sc->sc_recv[i].mbuf == NULL)
    393        1.2   tsutsui 				goto found;
    394        1.2   tsutsui 		for (i = 0; i < sc->sc_recv_h; i++)
    395        1.2   tsutsui 			if (sc->sc_recv[i].mbuf == NULL)
    396        1.2   tsutsui 				goto found;
    397        1.2   tsutsui 		/* no spot, drop it (sigh) */
    398        1.2   tsutsui  no_room:
    399        1.2   tsutsui #if DEBUG
    400        1.2   tsutsui 		sc->rf++;
    401        1.2   tsutsui #endif
    402        1.2   tsutsui 		m_freem(m);
    403        1.2   tsutsui 		return;
    404        1.2   tsutsui  found:
    405        1.2   tsutsui 		phys = kvtophys((vaddr_t)m->m_data);
    406        1.2   tsutsui 		sc->sc_recv[i].mbuf = m;
    407        1.2   tsutsui 		sc->sc_recv[i].phys = phys;
    408        1.2   tsutsui 		rpostone(phys);
    409        1.2   tsutsui 		sc->sc_no_rd++;
    410        1.2   tsutsui 		return;
    411        1.2   tsutsui 	}
    412        1.2   tsutsui 
    413        1.2   tsutsui 	/* Repost after reset? */
    414        1.2   tsutsui 	if (sc->inited) {
    415        1.2   tsutsui 		/* order doesnt matter, might as well keep it clean */
    416        1.2   tsutsui 		int j = 0;
    417        1.2   tsutsui 		sc->sc_recv_h = 0;
    418        1.2   tsutsui 		for (i = 0; i < sc->sc_n_recv; i++)
    419        1.2   tsutsui 			if ((m = sc->sc_recv[i].mbuf) != NULL) {
    420        1.2   tsutsui 				phys = sc->sc_recv[i].phys;
    421        1.2   tsutsui 				sc->sc_recv[i].mbuf = NULL;
    422        1.2   tsutsui 				sc->sc_recv[i].phys = ~0;
    423        1.2   tsutsui 				sc->sc_recv[j].mbuf = m;
    424        1.2   tsutsui 				sc->sc_recv[j].phys = phys;
    425        1.2   tsutsui #if DEBUG
    426        1.2   tsutsui 				if (sc->sc_regs->Control & EC_IF_FULL)
    427        1.2   tsutsui 					printf("?uhu? postrecv full? %d\n",
    428        1.2   tsutsui 					    sc->sc_no_rd);
    429        1.2   tsutsui #endif
    430        1.2   tsutsui 				sc->sc_no_rd++;
    431        1.2   tsutsui 				rpostone(phys);
    432        1.2   tsutsui 				j++;
    433        1.2   tsutsui 			}
    434        1.2   tsutsui 		/* Any holes left? */
    435        1.2   tsutsui 		sc->inited = 1;
    436        1.2   tsutsui 		if (j >= sc->sc_n_recv)
    437        1.2   tsutsui 			return;	/* no, we are done */
    438        1.2   tsutsui 		/* continue on with the loop below */
    439        1.2   tsutsui 		i = j; m = NULL;
    440        1.2   tsutsui 		goto fillem;
    441        1.2   tsutsui 	}
    442        1.2   tsutsui 
    443        1.2   tsutsui 	/* Initial refill, we can wait */
    444        1.2   tsutsui 	waitmode = M_WAIT;
    445        1.2   tsutsui 	sc->sc_recv_h = 0;
    446        1.2   tsutsui 	memset(sc->sc_recv, 0, sizeof(sc->sc_recv[0]) * sc->sc_n_recv);
    447        1.2   tsutsui 	i = 0;
    448        1.1     pooka  fillem:
    449        1.2   tsutsui 	for (; i < sc->sc_n_recv; i++) {
    450        1.2   tsutsui 		MGETHDR(m, waitmode, MT_DATA);
    451        1.2   tsutsui 		if (m == 0)
    452        1.2   tsutsui 			break;
    453        1.9     ozaki 		m_set_rcvif(m, &sc->sc_ethercom.ec_if);
    454        1.2   tsutsui 		m->m_pkthdr.len = 0;
    455        1.2   tsutsui 
    456        1.2   tsutsui 		MCLGET(m, waitmode);
    457        1.2   tsutsui 		if ((m->m_flags & M_EXT) == 0)
    458        1.2   tsutsui 			break;
    459        1.1     pooka 
    460        1.2   tsutsui 		/*
    461        1.2   tsutsui 		 * This offset aligns IP/TCP headers and helps performance
    462        1.2   tsutsui 		 */
    463        1.1     pooka #if 1
    464        1.1     pooka #define ADJUST_MBUF_OFFSET(_m_) { \
    465        1.2   tsutsui 	(_m_)->m_data += 2; \
    466        1.2   tsutsui 	(_m_)->m_len -= 2; \
    467        1.1     pooka }
    468        1.1     pooka #else
    469        1.2   tsutsui #define ADJUST_MBUF_OFFSET(_m_)
    470        1.1     pooka #endif
    471        1.1     pooka 
    472        1.1     pooka 		m->m_len = MCLBYTES;
    473        1.1     pooka 
    474        1.2   tsutsui 		ADJUST_MBUF_OFFSET(m);
    475        1.2   tsutsui 		phys = kvtophys((vaddr_t)m->m_data);
    476        1.2   tsutsui 		sc->sc_recv[i].mbuf = m;
    477        1.2   tsutsui 		sc->sc_recv[i].phys = phys;
    478        1.2   tsutsui #if DEBUG
    479        1.2   tsutsui 		if (sc->sc_regs->Control & EC_IF_FULL)
    480        1.2   tsutsui 			printf("?uhu? postrecv2 full? %d\n", sc->sc_no_rd);
    481        1.2   tsutsui #endif
    482        1.2   tsutsui 		sc->sc_no_rd++;
    483        1.2   tsutsui 		rpostone(phys);
    484        1.2   tsutsui 		m = NULL;
    485        1.1     pooka 	}
    486        1.1     pooka 
    487        1.2   tsutsui 	if (m)
    488        1.2   tsutsui 		m_freem(m);
    489        1.2   tsutsui 	sc->inited = 1;
    490        1.1     pooka }
    491        1.1     pooka 
    492        1.1     pooka void enic_refill(struct enic_softc *sc)
    493        1.1     pooka {
    494        1.2   tsutsui 	struct mbuf *m;
    495        1.2   tsutsui 	int waitmode = M_DONTWAIT;
    496        1.1     pooka 
    497        1.2   tsutsui 	MGETHDR(m, waitmode, MT_DATA);
    498        1.2   tsutsui 	if (m == NULL)
    499        1.2   tsutsui 		return;
    500        1.9     ozaki 	m_set_rcvif(m, &sc->sc_ethercom.ec_if);
    501        1.2   tsutsui 	m->m_pkthdr.len = 0;
    502        1.1     pooka 
    503        1.2   tsutsui 	MCLGET(m, waitmode);
    504        1.2   tsutsui 	if ((m->m_flags & M_EXT) == 0) {
    505        1.2   tsutsui 		m_freem(m);
    506        1.2   tsutsui 		return;
    507        1.2   tsutsui 	}
    508        1.2   tsutsui 
    509        1.2   tsutsui 	m->m_len = MCLBYTES;
    510        1.2   tsutsui 	ADJUST_MBUF_OFFSET(m);
    511        1.1     pooka 
    512        1.2   tsutsui 	enic_post_recv(sc,m);
    513        1.1     pooka }
    514        1.1     pooka 
    515        1.1     pooka int
    516        1.1     pooka enic_init(struct ifnet *ifp)
    517        1.1     pooka {
    518        1.1     pooka 	struct enic_softc *sc = ifp->if_softc;
    519        1.2   tsutsui 	uint32_t ctl;
    520        1.2   tsutsui 
    521        1.2   tsutsui 	/* no need to init many times unless we are in reset */
    522        1.2   tsutsui 	if (sc->inited != 1) {
    523        1.1     pooka 
    524        1.2   tsutsui 		/* Cancel all xmit buffers */
    525        1.2   tsutsui 		enic_kill_xmit(sc);
    526        1.1     pooka 
    527        1.2   tsutsui 		/* Re-post all recv buffers */
    528        1.2   tsutsui 		enic_post_recv(sc,NULL);
    529        1.2   tsutsui 	}
    530        1.1     pooka 
    531        1.2   tsutsui 	/* Start the eNIC */
    532        1.2   tsutsui 	ifp->if_flags |= IFF_RUNNING;
    533        1.2   tsutsui 	ifp->if_flags &= ~IFF_OACTIVE;
    534        1.2   tsutsui 	ifp->if_timer = 0;
    535        1.2   tsutsui 	ctl = sc->sc_regs->Control | EC_INTEN;
    536        1.2   tsutsui 	ctl &= ~EC_RXDIS;
    537        1.2   tsutsui 	sc->sc_regs->Control = ctl;
    538        1.2   tsutsui #if 0
    539        1.2   tsutsui 	printf("enic_init <- %x\n",ctl);
    540        1.2   tsutsui #endif
    541        1.1     pooka 
    542       1.12     ozaki 	if_schedule_deferred_start(ifp);
    543        1.1     pooka 
    544        1.2   tsutsui 	return 0;
    545        1.1     pooka }
    546        1.1     pooka 
    547        1.1     pooka 
    548        1.1     pooka void
    549        1.1     pooka enic_watchdog(struct ifnet *ifp)
    550        1.1     pooka {
    551        1.1     pooka 	struct enic_softc *sc = ifp->if_softc;
    552        1.1     pooka 
    553        1.2   tsutsui #if 0
    554        1.2   tsutsui 	printf("enic_watch ctl=%x\n", sc->sc_regs->Control);
    555        1.2   tsutsui #endif
    556        1.1     pooka 	log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
    557        1.1     pooka 	++ifp->if_oerrors;
    558        1.1     pooka 
    559        1.1     pooka 	enic_reset(ifp);
    560        1.1     pooka }
    561        1.1     pooka 
    562        1.1     pooka int
    563        1.1     pooka enic_mediachange(struct ifnet *ifp)
    564        1.1     pooka {
    565        1.2   tsutsui #if 0
    566        1.2   tsutsui 	struct enic_softc *sc = ifp->if_softc;
    567        1.2   tsutsui #endif
    568        1.2   tsutsui 	/* more code here.. */
    569        1.1     pooka 
    570        1.2   tsutsui 	return 0;
    571        1.1     pooka }
    572        1.1     pooka 
    573        1.1     pooka void
    574        1.2   tsutsui enic_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
    575        1.1     pooka {
    576        1.1     pooka 	struct enic_softc *sc = ifp->if_softc;
    577        1.1     pooka 
    578        1.1     pooka 	if ((ifp->if_flags & IFF_UP) == 0)
    579        1.1     pooka 		return;
    580        1.1     pooka 
    581        1.1     pooka 	ifmr->ifm_status = IFM_AVALID;
    582        1.1     pooka 	if (sc->sc_havecarrier)
    583        1.1     pooka 		ifmr->ifm_status |= IFM_ACTIVE;
    584        1.1     pooka 
    585        1.2   tsutsui 	/* more code here someday.. */
    586        1.1     pooka }
    587        1.1     pooka 
    588        1.1     pooka /*
    589        1.1     pooka  * Process an ioctl request.
    590        1.1     pooka  */
    591        1.1     pooka int
    592        1.1     pooka enic_ioctl(struct ifnet *ifp, u_long cmd, void *data)
    593        1.1     pooka {
    594        1.1     pooka 	struct enic_softc *sc = ifp->if_softc;
    595        1.1     pooka 	struct ifreq *ifr = (struct ifreq *)data;
    596        1.1     pooka 	int s, error = 0;
    597        1.1     pooka 
    598        1.1     pooka 	s = splnet();
    599        1.1     pooka 
    600        1.1     pooka 	switch (cmd) {
    601        1.1     pooka 	case SIOCGIFMEDIA:
    602        1.1     pooka 	case SIOCSIFMEDIA:
    603        1.1     pooka #if 0 /*DEBUG*/
    604        1.2   tsutsui 	    {
    605        1.2   tsutsui 		extern int ei_drops[];
    606        1.2   tsutsui 		static int flip = 0;
    607        1.2   tsutsui 		if (flip++ == 2) {
    608        1.2   tsutsui 			int i;
    609        1.2   tsutsui 			flip = 0;
    610        1.2   tsutsui 			printf("enic_ioctl(%x) %qd/%qd %qd/%qd %d/%d %d:%d "
    611        1.2   tsutsui 			    "%d+%d %d/%d/%d\n", ifp->if_flags,
    612        1.2   tsutsui 			    ifp->if_ierrors, ifp->if_oerrors,
    613        1.2   tsutsui 			    ifp->if_ipackets, ifp->if_opackets,
    614        1.2   tsutsui 			    sc->sc_no_rd, sc->sc_no_td,
    615        1.2   tsutsui 			    sc->xhit, sc->xmiss,
    616        1.2   tsutsui 			    sc->tfull, sc->tfull2,
    617        1.2   tsutsui 			    sc->brh, sc->rf, sc->bxh);
    618        1.2   tsutsui 			printf(" Ctl %x lt %x tim %d\n",
    619        1.2   tsutsui 			    sc->sc_regs->Control, sc->it, ifp->if_timer);
    620        1.2   tsutsui 
    621        1.2   tsutsui 			for (i = 0; i < 64; i++)
    622        1.2   tsutsui 				if (ei_drops[i])
    623        1.2   tsutsui 					printf(" %d.%d",i,ei_drops[i]);
    624        1.2   tsutsui 			printf("\n");
    625        1.1     pooka 		}
    626        1.2   tsutsui 	    }
    627        1.1     pooka #endif
    628        1.1     pooka 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
    629        1.1     pooka 		break;
    630        1.1     pooka 
    631        1.1     pooka 	default:
    632        1.1     pooka 		error = ether_ioctl(ifp, cmd, data);
    633        1.1     pooka 		if (cmd == SIOCSIFADDR) {
    634        1.1     pooka 			/*
    635        1.1     pooka 			 * hackattack: NFS does not turn us back
    636        1.1     pooka 			 * on after a stop. So.
    637        1.1     pooka 			 */
    638        1.2   tsutsui #if 0
    639        1.2   tsutsui 			printf("enic_ioctl(%lx)\n",cmd);
    640        1.2   tsutsui #endif
    641        1.1     pooka 			enic_init(ifp);
    642        1.1     pooka 		}
    643        1.1     pooka 		if (error != ENETRESET)
    644        1.1     pooka 			break;
    645        1.1     pooka 		error = 0;
    646        1.1     pooka 		if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
    647        1.1     pooka 			break;
    648        1.1     pooka 		if (ifp->if_flags & IFF_RUNNING) {
    649        1.1     pooka 			enic_reset(ifp);
    650        1.1     pooka 		}
    651        1.1     pooka 		break;
    652        1.1     pooka 	}
    653        1.1     pooka 	splx(s);
    654        1.1     pooka 
    655        1.2   tsutsui 	return error;
    656        1.1     pooka }
    657        1.1     pooka 
    658        1.1     pooka int
    659        1.1     pooka enic_intr(void *cookie, void *f)
    660        1.1     pooka {
    661        1.1     pooka 	struct enic_softc *sc = cookie;
    662        1.2   tsutsui 	uint32_t isr, saf, hi, lo, fl;
    663        1.1     pooka 
    664        1.1     pooka 	isr = sc->sc_regs->Control;
    665        1.1     pooka 
    666        1.2   tsutsui 	/* Make sure there is one and that we should take it */
    667        1.1     pooka 	if ((isr & (EC_INTEN|EC_DONE)) != (EC_INTEN|EC_DONE))
    668        1.2   tsutsui 		return 0;
    669        1.1     pooka 
    670        1.1     pooka 	if (isr & EC_ERROR) {
    671        1.2   tsutsui 		printf("%s: internal error\n", device_xname(sc->sc_dev));
    672        1.2   tsutsui 		enic_reset(&sc->sc_ethercom.ec_if);
    673        1.2   tsutsui 		return 1;
    674        1.2   tsutsui 	}
    675        1.1     pooka 
    676        1.2   tsutsui 	/*
    677        1.2   tsutsui 	 * pull out all completed buffers
    678        1.2   tsutsui 	 */
    679        1.2   tsutsui 	while ((isr & EC_OF_EMPTY) == 0) {
    680        1.2   tsutsui 
    681        1.2   tsutsui 		/* beware, order matters */
    682        1.2   tsutsui 		saf = sc->sc_regs->SizeAndFlags;
    683        1.2   tsutsui 		hi  = sc->sc_regs->BufferAddressHi32; /* BUGBUG 64bit */
    684        1.2   tsutsui 		lo  = sc->sc_regs->BufferAddressLo32; /* this pops the fifo */
    685        1.5  christos 		__USE(hi);
    686        1.2   tsutsui 
    687        1.2   tsutsui 		fl = saf & (ES_F_MASK &~ ES_F_DONE);
    688        1.2   tsutsui 		if (fl == ES_F_RECV)
    689        1.2   tsutsui 			enic_rint(sc,saf,lo);
    690        1.2   tsutsui 		else if (fl == ES_F_XMIT)
    691        1.2   tsutsui 			enic_tint(sc,saf,lo);
    692        1.2   tsutsui 		else {
    693        1.2   tsutsui 			/*
    694        1.2   tsutsui 			 * we do not currently expect or care for
    695        1.2   tsutsui 			 * command completions?
    696        1.2   tsutsui 			 */
    697        1.2   tsutsui 			if (fl != ES_F_CMD)
    698        1.2   tsutsui 				printf("%s: invalid saf=x%x (lo=%x)\n",
    699        1.2   tsutsui 				    device_xname(sc->sc_dev), saf, lo);
    700        1.2   tsutsui 		}
    701        1.2   tsutsui 
    702        1.2   tsutsui 		isr = sc->sc_regs->Control;
    703        1.2   tsutsui 	}
    704        1.1     pooka 
    705        1.1     pooka 	rnd_add_uint32(&sc->rnd_source, isr);
    706        1.1     pooka 
    707        1.2   tsutsui 	return 1;
    708        1.1     pooka }
    709        1.1     pooka 
    710        1.1     pooka void
    711        1.1     pooka enic_rint(struct enic_softc *sc, uint32_t saf, paddr_t phys)
    712        1.1     pooka {
    713        1.1     pooka 	struct mbuf *m;
    714        1.1     pooka 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    715        1.2   tsutsui 	int len = saf & ES_S_MASK, i;
    716        1.1     pooka 
    717        1.2   tsutsui 	/* Find what buffer it is. Should be the first. */
    718        1.2   tsutsui 	for (i = sc->sc_recv_h; i < sc->sc_n_recv; i++)
    719        1.2   tsutsui 		if (sc->sc_recv[i].phys == phys)
    720        1.2   tsutsui 			goto found;
    721        1.2   tsutsui 	for (i = 0; i < sc->sc_recv_h; i++)
    722        1.2   tsutsui 		if (sc->sc_recv[i].phys == phys)
    723        1.2   tsutsui 			goto found;
    724        1.2   tsutsui 
    725        1.2   tsutsui 	/* uhu?? */
    726        1.2   tsutsui 	printf("%s: bad recv phys %llx\n", device_xname(sc->sc_dev),
    727        1.2   tsutsui 	    (long long)phys);
    728        1.2   tsutsui 	ifp->if_ierrors++;
    729        1.2   tsutsui 	return;
    730        1.1     pooka 
    731        1.2   tsutsui 	/* got it, pop it */
    732        1.1     pooka  found:
    733        1.2   tsutsui 	sc->sc_no_rd--;
    734        1.2   tsutsui 	m = sc->sc_recv[i].mbuf;
    735        1.2   tsutsui 	sc->sc_recv[i].mbuf = NULL;
    736        1.2   tsutsui 	sc->sc_recv[i].phys = ~0;
    737        1.2   tsutsui 	if (i == sc->sc_recv_h) { /* should be */
    738        1.2   tsutsui 		sc->sc_recv_h = (++i == sc->sc_n_recv) ? 0 : i;
    739        1.2   tsutsui 	}
    740        1.1     pooka #if DEBUG
    741        1.2   tsutsui 	else
    742        1.2   tsutsui 		sc->brh++;
    743        1.1     pooka #endif
    744        1.1     pooka 
    745        1.1     pooka 	if (len <= sizeof(struct ether_header) ||
    746        1.1     pooka 	    len > ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) ?
    747        1.1     pooka 		ETHER_VLAN_ENCAP_LEN + ETHERMTU + sizeof(struct ether_header) :
    748        1.1     pooka 		ETHERMTU + sizeof(struct ether_header))) {
    749        1.1     pooka 		ifp->if_ierrors++;
    750        1.1     pooka 
    751        1.2   tsutsui 		/* reuse it */
    752        1.2   tsutsui 		enic_post_recv(sc,m);
    753        1.1     pooka 		return;
    754        1.1     pooka 	}
    755        1.1     pooka 
    756        1.1     pooka 	/* Adjust size */
    757        1.1     pooka 	m->m_pkthdr.len = len;
    758        1.1     pooka 	m->m_len = len; /* recheck */
    759        1.1     pooka 
    760        1.1     pooka 	/* Pass the packet up. */
    761        1.8     ozaki 	if_percpuq_enqueue(ifp->if_percpuq, m);
    762        1.1     pooka 
    763        1.1     pooka 	/* Need to refill now */
    764        1.1     pooka 	enic_refill(sc);
    765        1.1     pooka }
    766        1.1     pooka 
    767        1.1     pooka void enic_tint(struct enic_softc *sc, uint32_t saf, paddr_t phys)
    768        1.1     pooka {
    769        1.1     pooka 	struct mbuf *m;
    770        1.1     pooka 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    771        1.2   tsutsui 	int i;
    772        1.1     pooka 
    773        1.1     pooka #if DEBUG
    774        1.2   tsutsui 	sc->it = 1;
    775        1.1     pooka #endif
    776        1.1     pooka 
    777        1.2   tsutsui 	/* BUGBUG should there be a per-buffer error bit in SAF? */
    778        1.1     pooka 
    779        1.2   tsutsui 	/* Find what buffer it is. Should be the first. */
    780        1.2   tsutsui 	for (i = sc->sc_xmit_h; i < sc->sc_n_xmit; i++)
    781        1.2   tsutsui 		if (sc->sc_xmit[i].phys == phys)
    782        1.2   tsutsui 			goto found;
    783        1.2   tsutsui 	for (i = 0; i < sc->sc_xmit_h; i++)
    784        1.2   tsutsui 		if (sc->sc_xmit[i].phys == phys)
    785        1.2   tsutsui 			goto found;
    786        1.1     pooka 
    787        1.2   tsutsui 	/* uhu?? */
    788        1.2   tsutsui 	printf("%s: bad xmit phys %llx\n", device_xname(sc->sc_dev),
    789        1.2   tsutsui 	    (long long)phys);
    790        1.2   tsutsui 	ifp->if_oerrors++;
    791        1.2   tsutsui 	return;
    792        1.1     pooka 
    793        1.2   tsutsui 	/* got it, pop it */
    794        1.1     pooka  found:
    795        1.2   tsutsui 	m = sc->sc_xmit[i].mbuf;
    796        1.2   tsutsui 	sc->sc_xmit[i].mbuf = NULL;
    797        1.2   tsutsui 	sc->sc_xmit[i].phys = ~0;
    798        1.2   tsutsui 	if (i == sc->sc_xmit_h) { /* should be */
    799        1.2   tsutsui 		sc->sc_xmit_h = (++i == sc->sc_n_xmit) ? 0 : i;
    800        1.2   tsutsui 	}
    801        1.1     pooka #if DEBUG
    802        1.2   tsutsui 	else
    803        1.2   tsutsui 		sc->bxh++;
    804        1.1     pooka #endif
    805        1.2   tsutsui 	m_freem(m);
    806        1.2   tsutsui 	ifp->if_opackets++;
    807        1.1     pooka 
    808        1.1     pooka 	if (--sc->sc_no_td == 0)
    809        1.1     pooka 		ifp->if_timer = 0;
    810        1.1     pooka 
    811        1.2   tsutsui 	ifp->if_flags &= ~IFF_OACTIVE;
    812       1.12     ozaki 	if_schedule_deferred_start(ifp);
    813        1.1     pooka #if DEBUG
    814        1.2   tsutsui 	sc->it = 1;
    815        1.1     pooka #endif
    816        1.1     pooka }
    817        1.1     pooka 
    818        1.1     pooka /*
    819        1.1     pooka  * Setup output on interface.
    820        1.1     pooka  * Get another datagram to send off of the interface queue, and map it to the
    821        1.1     pooka  * interface before starting the output.
    822        1.1     pooka  * Called only at splnet or interrupt level.
    823        1.1     pooka  */
    824        1.1     pooka void
    825        1.1     pooka enic_start(struct ifnet *ifp)
    826        1.1     pooka {
    827        1.1     pooka 	struct enic_softc *sc = ifp->if_softc;
    828        1.1     pooka 	struct mbuf *m;
    829        1.1     pooka 	int len, ix, s;
    830        1.2   tsutsui 	paddr_t phys;
    831        1.1     pooka 
    832        1.1     pooka #if DEBUG
    833        1.2   tsutsui 	sc->it = 0;
    834        1.1     pooka #endif
    835        1.1     pooka 
    836        1.2   tsutsui #if 0
    837        1.2   tsutsui 	printf("enic_start(%x)\n", ifp->if_flags);
    838        1.2   tsutsui #endif
    839        1.1     pooka 
    840        1.1     pooka 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
    841        1.1     pooka 		return;
    842        1.1     pooka 
    843        1.2   tsutsui 	s = splnet();	/* I know, I dont trust people.. */
    844        1.1     pooka 
    845        1.2   tsutsui 	ix = sc->sc_xmit_h;
    846        1.1     pooka 	for (;;) {
    847        1.1     pooka 
    848        1.2   tsutsui 		/* Anything to do? */
    849        1.2   tsutsui 		IFQ_POLL(&ifp->if_snd, m);
    850        1.2   tsutsui 		if (m == NULL)
    851        1.1     pooka 			break;
    852        1.1     pooka 
    853        1.2   tsutsui 		/* find a spot, if any */
    854        1.2   tsutsui 		for (; ix < sc->sc_n_xmit; ix++)
    855        1.2   tsutsui 			if (sc->sc_xmit[ix].mbuf == NULL)
    856        1.2   tsutsui 				goto found;
    857        1.2   tsutsui 		for (ix = 0; ix < sc->sc_xmit_h; ix++)
    858        1.2   tsutsui 			if (sc->sc_xmit[ix].mbuf == NULL)
    859        1.2   tsutsui 				goto found;
    860        1.2   tsutsui 		/* oh well */
    861        1.2   tsutsui 		ifp->if_flags |= IFF_OACTIVE;
    862        1.1     pooka #if DEBUG
    863        1.2   tsutsui 		sc->tfull++;
    864        1.1     pooka #endif
    865        1.2   tsutsui 		break;
    866        1.1     pooka 
    867        1.2   tsutsui  found:
    868        1.1     pooka 		IFQ_DEQUEUE(&ifp->if_snd, m);
    869        1.2   tsutsui 		if (m == NULL)
    870        1.1     pooka 			break;
    871        1.1     pooka 
    872        1.1     pooka 		/*
    873        1.1     pooka 		 * If BPF is listening on this interface, let it see the packet
    874        1.1     pooka 		 * before we commit it to the wire.
    875        1.1     pooka 		 */
    876  1.13.14.2  pgoyette 		bpf_mtap(ifp, m, BPF_D_OUT);
    877        1.1     pooka 
    878        1.1     pooka 		/*
    879        1.1     pooka 		 * Copy the mbuf chain into a contiguous transmit buffer.
    880        1.1     pooka 		 */
    881        1.1     pooka 		len = enic_put(sc, &m);
    882        1.2   tsutsui 		if (len == 0)
    883        1.2   tsutsui 			break;	/* sanity */
    884        1.2   tsutsui 		if (len > (ETHERMTU + sizeof(struct ether_header))) {
    885        1.2   tsutsui 			printf("enic? tlen %d > %d\n",
    886        1.2   tsutsui 			    len, ETHERMTU + sizeof(struct ether_header));
    887        1.2   tsutsui 			len = ETHERMTU + sizeof(struct ether_header);
    888        1.2   tsutsui 		}
    889        1.1     pooka 
    890        1.1     pooka 		ifp->if_timer = 5;
    891        1.1     pooka 
    892        1.1     pooka 		/*
    893        1.1     pooka 		 * Remember and post the buffer
    894        1.1     pooka 		 */
    895        1.2   tsutsui 		phys = kvtophys((vaddr_t)m->m_data);
    896        1.2   tsutsui 		sc->sc_xmit[ix].mbuf = m;
    897        1.2   tsutsui 		sc->sc_xmit[ix].phys = phys;
    898        1.1     pooka 
    899        1.2   tsutsui 		sc->sc_no_td++;
    900        1.1     pooka 
    901        1.2   tsutsui 		tpostone(phys,len);
    902        1.1     pooka 
    903        1.1     pooka 		if (sc->sc_regs->Control & EC_IF_FULL) {
    904        1.1     pooka 			ifp->if_flags |= IFF_OACTIVE;
    905        1.1     pooka #if DEBUG
    906        1.2   tsutsui 			sc->tfull2++;
    907        1.1     pooka #endif
    908        1.1     pooka 			break;
    909        1.1     pooka 		}
    910        1.1     pooka 
    911        1.2   tsutsui 		ix++;
    912        1.1     pooka 	}
    913        1.1     pooka 
    914        1.2   tsutsui 	splx(s);
    915        1.1     pooka }
    916        1.1     pooka 
    917        1.1     pooka int enic_put(struct enic_softc *sc, struct mbuf **pm)
    918        1.1     pooka {
    919        1.1     pooka 	struct mbuf *n, *m = *pm, *mm;
    920        1.1     pooka 	int len, tlen = 0, xlen = m->m_pkthdr.len;
    921        1.2   tsutsui 	uint8_t *cp;
    922        1.1     pooka 
    923        1.1     pooka #if 0
    924        1.2   tsutsui 	/* drop garbage */
    925        1.2   tsutsui 	tlen = xlen;
    926        1.1     pooka 	for (; m; m = n) {
    927        1.1     pooka 		len = m->m_len;
    928        1.1     pooka 		if (len == 0) {
    929       1.10  christos 			n = m_free(m);
    930       1.11      maya 			if (m == *pm)
    931       1.11      maya 				*pm = n;
    932        1.1     pooka 			continue;
    933        1.1     pooka 		}
    934        1.1     pooka 		tlen -= len;
    935        1.2   tsutsui 		KASSERT(m != m->m_next);
    936        1.2   tsutsui 		n = m->m_next;
    937        1.2   tsutsui 		if (tlen <= 0)
    938        1.2   tsutsui 			break;
    939        1.2   tsutsui 	}
    940        1.1     pooka 
    941        1.2   tsutsui 	/*
    942        1.2   tsutsui 	 * We might be done:
    943        1.2   tsutsui 	 * (a) empty chain (b) only one segment (c) bad chain
    944        1.2   tsutsui 	 */
    945        1.2   tsutsui 	if (((m = *pm) == NULL) || (tlen > 0))
    946        1.2   tsutsui 		xlen = 0;
    947        1.2   tsutsui #endif
    948        1.2   tsutsui 
    949        1.2   tsutsui 	if ((xlen == 0) || (xlen <= m->m_len)) {
    950        1.2   tsutsui #if DEBUG
    951        1.2   tsutsui 		sc->xhit++;
    952        1.2   tsutsui #endif
    953        1.2   tsutsui 		return xlen;
    954        1.2   tsutsui 	}
    955        1.2   tsutsui 
    956        1.2   tsutsui 	/* Nope, true chain. Copy to contig :-(( */
    957        1.2   tsutsui 	tlen = xlen;
    958        1.2   tsutsui 	MGETHDR(n, M_NOWAIT, MT_DATA);
    959        1.2   tsutsui 	if (n == NULL)
    960        1.2   tsutsui 		goto Bad;
    961        1.9     ozaki 	m_set_rcvif(n, &sc->sc_ethercom.ec_if);
    962        1.2   tsutsui 	n->m_pkthdr.len = tlen;
    963        1.2   tsutsui 
    964        1.2   tsutsui 	MCLGET(n, M_NOWAIT);
    965        1.2   tsutsui 	if ((n->m_flags & M_EXT) == 0) {
    966        1.2   tsutsui 		m_freem(n);
    967        1.2   tsutsui 		goto Bad;
    968        1.2   tsutsui 	}
    969        1.2   tsutsui 
    970        1.2   tsutsui 	n->m_len = tlen;
    971        1.2   tsutsui 	cp = mtod(n, uint8_t *);
    972        1.1     pooka 	for (; m && tlen; m = mm) {
    973        1.1     pooka 
    974        1.2   tsutsui 		len = m->m_len;
    975        1.2   tsutsui 		if (len > tlen)
    976        1.2   tsutsui 			len = tlen;
    977        1.2   tsutsui 		if (len)
    978        1.2   tsutsui 			memcpy(cp, mtod(m, void *), len);
    979        1.1     pooka 
    980        1.1     pooka 		cp += len;
    981        1.2   tsutsui 		tlen -= len;
    982       1.10  christos 		mm = m_free(m);
    983        1.2   tsutsui 
    984        1.1     pooka 	}
    985        1.1     pooka 
    986        1.2   tsutsui 	*pm = n;
    987        1.1     pooka #if DEBUG
    988        1.2   tsutsui 	sc->xmiss++;
    989        1.1     pooka #endif
    990        1.1     pooka 	return (xlen);
    991        1.1     pooka 
    992        1.1     pooka  Bad:
    993        1.2   tsutsui 	printf("enic_put: no mem?\n");
    994        1.2   tsutsui 	m_freem(m);
    995        1.2   tsutsui 	return 0;
    996        1.1     pooka }
    997