Home | History | Annotate | Line # | Download | only in ic
dm9000.c revision 1.36
      1  1.36    martin /*	$NetBSD: dm9000.c,v 1.36 2023/07/07 07:22:18 martin Exp $	*/
      2   1.1     ahoka 
      3   1.1     ahoka /*
      4   1.1     ahoka  * Copyright (c) 2009 Paul Fleischer
      5   1.1     ahoka  * All rights reserved.
      6   1.1     ahoka  *
      7   1.1     ahoka  * 1. Redistributions of source code must retain the above copyright
      8   1.1     ahoka  *    notice, this list of conditions and the following disclaimer.
      9   1.1     ahoka  * 2. Redistributions in binary form must reproduce the above copyright
     10   1.1     ahoka  *    notice, this list of conditions and the following disclaimer in the
     11   1.1     ahoka  *    documentation and/or other materials provided with the distribution.
     12   1.1     ahoka  * 3. The name of the company nor the name of the author may be used to
     13   1.1     ahoka  *    endorse or promote products derived from this software without specific
     14   1.1     ahoka  *    prior written permission.
     15   1.1     ahoka  *
     16   1.1     ahoka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17   1.1     ahoka  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18   1.1     ahoka  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19   1.1     ahoka  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     20   1.1     ahoka  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21   1.1     ahoka  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22   1.1     ahoka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23   1.1     ahoka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24   1.1     ahoka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25   1.1     ahoka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26   1.1     ahoka  * SUCH DAMAGE.
     27   1.1     ahoka  */
     28   1.1     ahoka 
     29   1.1     ahoka /* based on sys/dev/ic/cs89x0.c */
     30   1.1     ahoka /*
     31   1.1     ahoka  * Copyright (c) 2004 Christopher Gilbert
     32   1.1     ahoka  * All rights reserved.
     33   1.1     ahoka  *
     34   1.1     ahoka  * 1. Redistributions of source code must retain the above copyright
     35   1.1     ahoka  *    notice, this list of conditions and the following disclaimer.
     36   1.1     ahoka  * 2. Redistributions in binary form must reproduce the above copyright
     37   1.1     ahoka  *    notice, this list of conditions and the following disclaimer in the
     38   1.1     ahoka  *    documentation and/or other materials provided with the distribution.
     39   1.1     ahoka  * 3. The name of the company nor the name of the author may be used to
     40   1.1     ahoka  *    endorse or promote products derived from this software without specific
     41   1.1     ahoka  *    prior written permission.
     42   1.1     ahoka  *
     43   1.1     ahoka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     44   1.1     ahoka  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     45   1.1     ahoka  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     46   1.1     ahoka  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     47   1.1     ahoka  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     48   1.1     ahoka  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     49   1.1     ahoka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     50   1.1     ahoka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     51   1.1     ahoka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     52   1.1     ahoka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     53   1.1     ahoka  * SUCH DAMAGE.
     54   1.1     ahoka  */
     55   1.1     ahoka 
     56   1.1     ahoka /*
     57   1.1     ahoka  * Copyright 1997
     58   1.1     ahoka  * Digital Equipment Corporation. All rights reserved.
     59   1.1     ahoka  *
     60   1.1     ahoka  * This software is furnished under license and may be used and
     61   1.1     ahoka  * copied only in accordance with the following terms and conditions.
     62   1.1     ahoka  * Subject to these conditions, you may download, copy, install,
     63   1.1     ahoka  * use, modify and distribute this software in source and/or binary
     64   1.1     ahoka  * form. No title or ownership is transferred hereby.
     65   1.1     ahoka  *
     66   1.1     ahoka  * 1) Any source code used, modified or distributed must reproduce
     67   1.1     ahoka  *    and retain this copyright notice and list of conditions as
     68   1.1     ahoka  *    they appear in the source file.
     69   1.1     ahoka  *
     70   1.1     ahoka  * 2) No right is granted to use any trade name, trademark, or logo of
     71   1.1     ahoka  *    Digital Equipment Corporation. Neither the "Digital Equipment
     72   1.1     ahoka  *    Corporation" name nor any trademark or logo of Digital Equipment
     73   1.1     ahoka  *    Corporation may be used to endorse or promote products derived
     74   1.1     ahoka  *    from this software without the prior written permission of
     75   1.1     ahoka  *    Digital Equipment Corporation.
     76   1.1     ahoka  *
     77   1.1     ahoka  * 3) This software is provided "AS-IS" and any express or implied
     78   1.1     ahoka  *    warranties, including but not limited to, any implied warranties
     79   1.1     ahoka  *    of merchantability, fitness for a particular purpose, or
     80   1.1     ahoka  *    non-infringement are disclaimed. In no event shall DIGITAL be
     81   1.1     ahoka  *    liable for any damages whatsoever, and in particular, DIGITAL
     82   1.1     ahoka  *    shall not be liable for special, indirect, consequential, or
     83   1.1     ahoka  *    incidental damages or damages for lost profits, loss of
     84   1.1     ahoka  *    revenue or loss of use, whether such damages arise in contract,
     85   1.1     ahoka  *    negligence, tort, under statute, in equity, at law or otherwise,
     86   1.1     ahoka  *    even if advised of the possibility of such damage.
     87   1.1     ahoka  */
     88   1.1     ahoka 
     89   1.1     ahoka #include <sys/cdefs.h>
     90   1.1     ahoka 
     91   1.1     ahoka #include <sys/param.h>
     92  1.24  nisimura #include <sys/bus.h>
     93  1.24  nisimura #include <sys/intr.h>
     94  1.24  nisimura #include <sys/device.h>
     95   1.1     ahoka #include <sys/mbuf.h>
     96  1.24  nisimura #include <sys/sockio.h>
     97   1.1     ahoka #include <sys/errno.h>
     98  1.24  nisimura #include <sys/cprng.h>
     99  1.24  nisimura #include <sys/rndsource.h>
    100  1.24  nisimura #include <sys/kernel.h>
    101  1.24  nisimura #include <sys/systm.h>
    102   1.1     ahoka 
    103   1.1     ahoka #include <net/if.h>
    104  1.24  nisimura #include <net/if_dl.h>
    105   1.1     ahoka #include <net/if_ether.h>
    106   1.1     ahoka #include <net/if_media.h>
    107  1.24  nisimura #include <dev/mii/mii.h>
    108  1.24  nisimura #include <dev/mii/miivar.h>
    109  1.13   msaitoh #include <net/bpf.h>
    110  1.13   msaitoh 
    111   1.1     ahoka #include <dev/ic/dm9000var.h>
    112   1.1     ahoka #include <dev/ic/dm9000reg.h>
    113   1.1     ahoka 
    114   1.1     ahoka #if 1
    115   1.1     ahoka #undef DM9000_DEBUG
    116   1.4  nisimura #undef DM9000_TX_DEBUG
    117   1.1     ahoka #undef DM9000_TX_DATA_DEBUG
    118   1.1     ahoka #undef DM9000_RX_DEBUG
    119   1.1     ahoka #undef  DM9000_RX_DATA_DEBUG
    120   1.1     ahoka #else
    121   1.1     ahoka #define DM9000_DEBUG
    122   1.1     ahoka #define  DM9000_TX_DEBUG
    123   1.1     ahoka #define DM9000_TX_DATA_DEBUG
    124   1.1     ahoka #define DM9000_RX_DEBUG
    125   1.1     ahoka #define  DM9000_RX_DATA_DEBUG
    126   1.1     ahoka #endif
    127   1.1     ahoka 
    128   1.1     ahoka #ifdef DM9000_DEBUG
    129   1.1     ahoka #define DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
    130   1.1     ahoka #else
    131   1.1     ahoka #define DPRINTF(s) do {} while (/*CONSTCOND*/0)
    132   1.1     ahoka #endif
    133   1.1     ahoka 
    134   1.1     ahoka #ifdef DM9000_TX_DEBUG
    135   1.1     ahoka #define TX_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
    136   1.1     ahoka #else
    137   1.1     ahoka #define TX_DPRINTF(s) do {} while (/*CONSTCOND*/0)
    138   1.1     ahoka #endif
    139   1.1     ahoka 
    140   1.1     ahoka #ifdef DM9000_RX_DEBUG
    141   1.1     ahoka #define RX_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
    142   1.1     ahoka #else
    143   1.1     ahoka #define RX_DPRINTF(s) do {} while (/*CONSTCOND*/0)
    144   1.1     ahoka #endif
    145   1.1     ahoka 
    146   1.1     ahoka #ifdef DM9000_RX_DATA_DEBUG
    147   1.1     ahoka #define RX_DATA_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
    148   1.1     ahoka #else
    149   1.1     ahoka #define RX_DATA_DPRINTF(s) do {} while (/*CONSTCOND*/0)
    150   1.1     ahoka #endif
    151   1.1     ahoka 
    152   1.1     ahoka #ifdef DM9000_TX_DATA_DEBUG
    153   1.1     ahoka #define TX_DATA_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
    154   1.1     ahoka #else
    155   1.1     ahoka #define TX_DATA_DPRINTF(s) do {} while (/*CONSTCOND*/0)
    156   1.1     ahoka #endif
    157   1.1     ahoka 
    158  1.24  nisimura static void dme_reset(struct dme_softc *);
    159  1.24  nisimura static int dme_init(struct ifnet *);
    160  1.24  nisimura static void dme_stop(struct ifnet *, int);
    161  1.24  nisimura static void dme_start(struct ifnet *);
    162  1.24  nisimura static int dme_ioctl(struct ifnet *, u_long, void *);
    163  1.24  nisimura 
    164  1.24  nisimura static void dme_set_rcvfilt(struct dme_softc *);
    165  1.24  nisimura static void mii_statchg(struct ifnet *);
    166  1.24  nisimura static void lnkchg(struct dme_softc *);
    167  1.24  nisimura static void phy_tick(void *);
    168  1.24  nisimura static int mii_readreg(device_t, int, int, uint16_t *);
    169  1.24  nisimura static int mii_writereg(device_t, int, int, uint16_t);
    170  1.24  nisimura 
    171  1.24  nisimura static void dme_prepare(struct ifnet *);
    172  1.24  nisimura static void dme_transmit(struct ifnet *);
    173  1.24  nisimura static void dme_receive(struct ifnet *);
    174  1.24  nisimura 
    175  1.24  nisimura static int pkt_read_2(struct dme_softc *, struct mbuf **);
    176  1.24  nisimura static int pkt_write_2(struct dme_softc *, struct mbuf *);
    177  1.24  nisimura static int pkt_read_1(struct dme_softc *, struct mbuf **);
    178  1.24  nisimura static int pkt_write_1(struct dme_softc *, struct mbuf *);
    179  1.24  nisimura #define PKT_READ(ii,m) (*(ii)->sc_pkt_read)((ii),(m))
    180  1.24  nisimura #define PKT_WRITE(ii,m) (*(ii)->sc_pkt_write)((ii),(m))
    181  1.24  nisimura 
    182  1.24  nisimura #define ETHER_IS_ONE(x) \
    183  1.24  nisimura 	   (((x)[0] & (x)[1] & (x)[2] & (x)[3] & (x)[4] & (x)[5]) == 255)
    184  1.24  nisimura #define ETHER_IS_ZERO(x) \
    185  1.24  nisimura 	   (((x)[0] | (x)[1] | (x)[2] | (x)[3] | (x)[4] | (x)[5]) == 0)
    186   1.4  nisimura 
    187   1.4  nisimura int
    188  1.24  nisimura dme_attach(struct dme_softc *sc, const uint8_t *notusedanymore)
    189   1.4  nisimura {
    190  1.24  nisimura 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    191  1.24  nisimura 	struct mii_data *mii = &sc->sc_mii;
    192  1.24  nisimura 	struct ifmedia *ifm = &mii->mii_media;
    193  1.24  nisimura 	uint8_t b[2];
    194  1.24  nisimura 	uint16_t io_mode;
    195  1.24  nisimura 	uint8_t enaddr[ETHER_ADDR_LEN];
    196  1.24  nisimura 	prop_dictionary_t dict;
    197  1.24  nisimura 	prop_data_t ea;
    198   1.1     ahoka 
    199   1.1     ahoka 	dme_read_c(sc, DM9000_VID0, b, 2);
    200  1.24  nisimura 	sc->sc_vendor_id = le16toh((uint16_t)b[1] << 8 | b[0]);
    201   1.1     ahoka 	dme_read_c(sc, DM9000_PID0, b, 2);
    202  1.24  nisimura 	sc->sc_product_id = le16toh((uint16_t)b[1] << 8 | b[0]);
    203  1.24  nisimura 
    204   1.1     ahoka 	/* TODO: Check the vendor ID as well */
    205   1.1     ahoka 	if (sc->sc_product_id != 0x9000) {
    206   1.1     ahoka 		panic("dme_attach: product id mismatch (0x%hx != 0x9000)",
    207   1.1     ahoka 		    sc->sc_product_id);
    208   1.1     ahoka 	}
    209  1.24  nisimura #if 1 || DM9000_DEBUG
    210  1.24  nisimura 	{
    211  1.24  nisimura 		dme_read_c(sc, DM9000_PAB0, enaddr, 6);
    212  1.24  nisimura 		aprint_normal_dev(sc->sc_dev,
    213  1.24  nisimura 		    "DM9000 was configured with MAC address: %s\n",
    214  1.24  nisimura 		    ether_sprintf(enaddr));
    215  1.24  nisimura 	}
    216  1.24  nisimura #endif
    217  1.24  nisimura 	dict = device_properties(sc->sc_dev);
    218  1.24  nisimura 	ea = (dict) ? prop_dictionary_get(dict, "mac-address") : NULL;
    219  1.24  nisimura 	if (ea != NULL) {
    220  1.24  nisimura 	       /*
    221  1.30    andvar 		 * If the MAC address is overridden by a device property,
    222  1.24  nisimura 		 * use that.
    223  1.24  nisimura 		 */
    224  1.24  nisimura 		KASSERT(prop_object_type(ea) == PROP_TYPE_DATA);
    225  1.24  nisimura 		KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN);
    226  1.29  jmcneill 		memcpy(enaddr, prop_data_value(ea), ETHER_ADDR_LEN);
    227  1.28  nisimura 		aprint_debug_dev(sc->sc_dev, "got MAC address!\n");
    228  1.24  nisimura 	} else {
    229  1.24  nisimura 		/*
    230  1.24  nisimura 		 * If we did not get an externaly configure address,
    231  1.24  nisimura 		 * try to read one from the current setup, before
    232  1.24  nisimura 		 * resetting the chip.
    233  1.24  nisimura 		 */
    234  1.24  nisimura 		dme_read_c(sc, DM9000_PAB0, enaddr, 6);
    235  1.24  nisimura 		if (ETHER_IS_ONE(enaddr) || ETHER_IS_ZERO(enaddr)) {
    236  1.24  nisimura 			/* make a random MAC address */
    237  1.24  nisimura 			uint32_t maclo = 0x00f2 | (cprng_strong32() << 16);
    238  1.24  nisimura 			uint32_t machi = cprng_strong32();
    239  1.24  nisimura 			enaddr[0] = maclo;
    240  1.24  nisimura 			enaddr[1] = maclo >> 8;
    241  1.24  nisimura 			enaddr[2] = maclo >> 16;
    242  1.24  nisimura 			enaddr[3] = maclo >> 26;
    243  1.24  nisimura 			enaddr[4] = machi;
    244  1.24  nisimura 			enaddr[5] = machi >> 8;
    245  1.24  nisimura 		}
    246  1.24  nisimura 	}
    247  1.24  nisimura 	/* TODO: perform explicit EEPROM read op if it's availble */
    248  1.24  nisimura 
    249  1.24  nisimura 	dme_reset(sc);
    250  1.24  nisimura 
    251  1.24  nisimura 	mii->mii_ifp = ifp;
    252  1.24  nisimura 	mii->mii_readreg = mii_readreg;
    253  1.24  nisimura 	mii->mii_writereg = mii_writereg;
    254  1.24  nisimura 	mii->mii_statchg = mii_statchg;
    255  1.24  nisimura 
    256  1.25  nisimura 	/* assume davicom PHY at 1. ext PHY could be hooked but only at 0-3 */
    257  1.24  nisimura 	sc->sc_ethercom.ec_mii = mii;
    258  1.24  nisimura 	ifmedia_init(ifm, 0, ether_mediachange, ether_mediastatus);
    259  1.25  nisimura 	mii_attach(sc->sc_dev, mii, 0xffffffff, 1 /* PHY 1 */,
    260  1.25  nisimura 		MII_OFFSET_ANY, 0);
    261  1.24  nisimura 	if (LIST_FIRST(&mii->mii_phys) == NULL) {
    262  1.24  nisimura 		ifmedia_add(ifm, IFM_ETHER | IFM_NONE, 0, NULL);
    263  1.24  nisimura 		ifmedia_set(ifm, IFM_ETHER | IFM_NONE);
    264  1.24  nisimura 	} else
    265  1.24  nisimura 		ifmedia_set(ifm, IFM_ETHER | IFM_AUTO);
    266  1.24  nisimura 	ifm->ifm_media = ifm->ifm_cur->ifm_media;
    267   1.1     ahoka 
    268   1.1     ahoka 	strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
    269   1.1     ahoka 	ifp->if_softc = sc;
    270  1.24  nisimura 	ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
    271   1.1     ahoka 	ifp->if_init = dme_init;
    272  1.24  nisimura 	ifp->if_start = dme_start;
    273  1.24  nisimura 	ifp->if_stop = dme_stop;
    274   1.1     ahoka 	ifp->if_ioctl = dme_ioctl;
    275  1.24  nisimura 	ifp->if_watchdog = NULL; /* no watchdog used */
    276  1.24  nisimura 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
    277   1.1     ahoka 	IFQ_SET_READY(&ifp->if_snd);
    278   1.1     ahoka 
    279  1.24  nisimura 	if_attach(ifp);
    280  1.24  nisimura 	ether_ifattach(ifp, enaddr);
    281  1.24  nisimura 	if_deferred_start_init(ifp, NULL);
    282  1.24  nisimura 
    283  1.24  nisimura 	rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
    284  1.24  nisimura             RND_TYPE_NET, RND_FLAG_DEFAULT);
    285   1.4  nisimura 
    286  1.24  nisimura 	/* might be unnecessary as link change interrupt works well */
    287   1.4  nisimura 	callout_init(&sc->sc_link_callout, 0);
    288  1.24  nisimura 	callout_setfunc(&sc->sc_link_callout, phy_tick, sc);
    289   1.1     ahoka 
    290   1.4  nisimura 	io_mode = (dme_read(sc, DM9000_ISR) &
    291   1.1     ahoka 	    DM9000_IOMODE_MASK) >> DM9000_IOMODE_SHIFT;
    292   1.4  nisimura 
    293  1.25  nisimura 	/* frame body read/write ops in 2 byte quantity or byte-wise. */
    294   1.4  nisimura 	DPRINTF(("DM9000 Operation Mode: "));
    295  1.18   msaitoh 	switch (io_mode) {
    296  1.24  nisimura 	case DM9000_MODE_8BIT:
    297  1.24  nisimura 		DPRINTF(("8-bit mode"));
    298  1.24  nisimura 		sc->sc_data_width = 1;
    299  1.24  nisimura 		sc->sc_pkt_write = pkt_write_1;
    300  1.24  nisimura 		sc->sc_pkt_read = pkt_read_1;
    301  1.24  nisimura 		break;
    302   1.1     ahoka 	case DM9000_MODE_16BIT:
    303   1.4  nisimura 		DPRINTF(("16-bit mode"));
    304   1.4  nisimura 		sc->sc_data_width = 2;
    305  1.24  nisimura 		sc->sc_pkt_write = pkt_write_2;
    306  1.24  nisimura 		sc->sc_pkt_read = pkt_read_2;
    307   1.1     ahoka 		break;
    308   1.1     ahoka 	case DM9000_MODE_32BIT:
    309   1.4  nisimura 		DPRINTF(("32-bit mode"));
    310   1.4  nisimura 		sc->sc_data_width = 4;
    311   1.6  macallan 		panic("32bit mode is unsupported\n");
    312   1.1     ahoka 		break;
    313   1.4  nisimura 	default:
    314   1.4  nisimura 		DPRINTF(("Invalid mode"));
    315   1.1     ahoka 		break;
    316   1.1     ahoka 	}
    317   1.4  nisimura 	DPRINTF(("\n"));
    318   1.4  nisimura 
    319  1.24  nisimura 	return 0;
    320  1.24  nisimura }
    321   1.1     ahoka 
    322  1.24  nisimura int
    323  1.24  nisimura dme_detach(struct dme_softc *sc)
    324  1.24  nisimura {
    325   1.1     ahoka 	return 0;
    326   1.1     ahoka }
    327   1.1     ahoka 
    328  1.24  nisimura /* Software Initialize/Reset of the DM9000 */
    329  1.24  nisimura static void
    330  1.24  nisimura dme_reset(struct dme_softc *sc)
    331   1.1     ahoka {
    332  1.24  nisimura 	uint8_t misc;
    333   1.1     ahoka 
    334  1.24  nisimura 	/* We only re-initialized the PHY in this function the first time it is
    335  1.24  nisimura 	 * called. */
    336  1.24  nisimura 	if (!sc->sc_phy_initialized) {
    337  1.24  nisimura 		/* PHY Reset */
    338  1.24  nisimura 		mii_writereg(sc->sc_dev, 1, MII_BMCR, BMCR_RESET);
    339   1.4  nisimura 
    340  1.24  nisimura 		/* PHY Power Down */
    341  1.24  nisimura 		misc = dme_read(sc, DM9000_GPR);
    342  1.24  nisimura 		dme_write(sc, DM9000_GPR, misc | DM9000_GPR_PHY_PWROFF);
    343   1.1     ahoka 	}
    344   1.1     ahoka 
    345  1.24  nisimura 	/* Reset the DM9000 twice, as described in section 2 of the Programming
    346  1.24  nisimura 	 * Guide.
    347  1.24  nisimura 	 * The PHY is initialized and enabled between those two resets.
    348  1.24  nisimura 	 */
    349   1.1     ahoka 
    350  1.24  nisimura 	/* Software Reset */
    351  1.24  nisimura 	dme_write(sc, DM9000_NCR,
    352  1.24  nisimura 	    DM9000_NCR_RST | DM9000_NCR_LBK_MAC_INTERNAL);
    353  1.24  nisimura 	delay(20);
    354  1.24  nisimura 	dme_write(sc, DM9000_NCR, 0x0);
    355   1.1     ahoka 
    356  1.24  nisimura 	if (!sc->sc_phy_initialized) {
    357  1.24  nisimura 		/* PHY Enable */
    358  1.24  nisimura 		misc = dme_read(sc, DM9000_GPR);
    359  1.24  nisimura 		dme_write(sc, DM9000_GPR, misc & ~DM9000_GPR_PHY_PWROFF);
    360  1.24  nisimura 		misc = dme_read(sc, DM9000_GPCR);
    361  1.24  nisimura 		dme_write(sc, DM9000_GPCR, misc | DM9000_GPCR_GPIO0_OUT);
    362   1.1     ahoka 
    363  1.24  nisimura 		dme_write(sc, DM9000_NCR,
    364  1.24  nisimura 		    DM9000_NCR_RST | DM9000_NCR_LBK_MAC_INTERNAL);
    365  1.24  nisimura 		delay(20);
    366  1.24  nisimura 		dme_write(sc, DM9000_NCR, 0x0);
    367  1.24  nisimura 	}
    368   1.1     ahoka 
    369  1.24  nisimura 	/* Select internal PHY, no wakeup event, no collosion mode,
    370  1.24  nisimura 	 * normal loopback mode.
    371  1.24  nisimura 	 */
    372  1.24  nisimura 	dme_write(sc, DM9000_NCR, DM9000_NCR_LBK_NORMAL);
    373   1.1     ahoka 
    374  1.24  nisimura 	/* Will clear TX1END, TX2END, and WAKEST fields by reading DM9000_NSR*/
    375  1.24  nisimura 	dme_read(sc, DM9000_NSR);
    376   1.1     ahoka 
    377  1.24  nisimura 	/* Enable wraparound of read/write pointer, frame received latch,
    378  1.24  nisimura 	 * and frame transmitted latch.
    379  1.24  nisimura 	 */
    380  1.17   msaitoh 	dme_write(sc, DM9000_IMR,
    381  1.17   msaitoh 	    DM9000_IMR_PAR | DM9000_IMR_PRM | DM9000_IMR_PTM);
    382   1.1     ahoka 
    383  1.24  nisimura 	dme_write(sc, DM9000_RCR,
    384  1.24  nisimura 	    DM9000_RCR_DIS_CRC | DM9000_RCR_DIS_LONG | DM9000_RCR_WTDIS);
    385   1.4  nisimura 
    386  1.24  nisimura 	sc->sc_phy_initialized = 1;
    387   1.1     ahoka }
    388   1.1     ahoka 
    389  1.24  nisimura static int
    390  1.24  nisimura dme_init(struct ifnet *ifp)
    391   1.1     ahoka {
    392  1.24  nisimura 	struct dme_softc *sc = ifp->if_softc;
    393   1.1     ahoka 
    394  1.24  nisimura 	dme_stop(ifp, 0);
    395  1.24  nisimura 	dme_reset(sc);
    396  1.24  nisimura 	dme_write_c(sc, DM9000_PAB0, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
    397  1.24  nisimura 	dme_set_rcvfilt(sc);
    398  1.24  nisimura 	(void)ether_mediachange(ifp);
    399  1.24  nisimura 
    400  1.24  nisimura 	sc->txbusy = sc->txready = 0;
    401  1.24  nisimura 
    402  1.24  nisimura 	ifp->if_flags |= IFF_RUNNING;
    403  1.24  nisimura 	callout_schedule(&sc->sc_link_callout, hz);
    404   1.1     ahoka 
    405  1.24  nisimura 	return 0;
    406  1.24  nisimura }
    407   1.4  nisimura 
    408  1.24  nisimura /* Configure multicast filter */
    409  1.24  nisimura static void
    410  1.24  nisimura dme_set_rcvfilt(struct dme_softc *sc)
    411  1.24  nisimura {
    412  1.24  nisimura 	struct ethercom	*ec = &sc->sc_ethercom;
    413  1.24  nisimura 	struct ifnet *ifp = &ec->ec_if;
    414  1.24  nisimura 	struct ether_multi *enm;
    415  1.24  nisimura 	struct ether_multistep step;
    416  1.24  nisimura 	uint8_t mchash[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* 64bit mchash */
    417  1.24  nisimura 	uint32_t h = 0;
    418  1.24  nisimura 	int rcr;
    419   1.1     ahoka 
    420  1.24  nisimura 	rcr = dme_read(sc, DM9000_RCR);
    421  1.24  nisimura 	rcr &= ~(DM9000_RCR_PRMSC | DM9000_RCR_ALL);
    422  1.24  nisimura 	dme_write(sc, DM9000_RCR, rcr &~ DM9000_RCR_RXEN);
    423   1.1     ahoka 
    424  1.24  nisimura 	ETHER_LOCK(ec);
    425  1.24  nisimura 	if (ifp->if_flags & IFF_PROMISC) {
    426  1.24  nisimura 		ec->ec_flags |= ETHER_F_ALLMULTI;
    427  1.24  nisimura 		ETHER_UNLOCK(ec);
    428  1.24  nisimura 		/* run promisc. mode */
    429  1.24  nisimura 		rcr |= DM9000_RCR_PRMSC;
    430  1.24  nisimura 		goto update;
    431  1.24  nisimura 	}
    432  1.24  nisimura 	ec->ec_flags &= ~ETHER_F_ALLMULTI;
    433  1.24  nisimura 	ETHER_FIRST_MULTI(step, ec, enm);
    434  1.24  nisimura 	while (enm != NULL) {
    435  1.24  nisimura 		if (memcpy(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
    436  1.24  nisimura 			/*
    437  1.24  nisimura 			 * We must listen to a range of multicast addresses.
    438  1.24  nisimura 			 * For now, just accept all multicasts, rather than
    439  1.24  nisimura 			 * trying to set only those filter bits needed to match
    440  1.24  nisimura 			 * the range.  (At this time, the only use of address
    441  1.24  nisimura 			 * ranges is for IP multicast routing, for which the
    442  1.24  nisimura 			 * range is big enough to require all bits set.)
    443  1.24  nisimura 			 */
    444  1.24  nisimura 			ec->ec_flags |= ETHER_F_ALLMULTI;
    445  1.24  nisimura 			ETHER_UNLOCK(ec);
    446  1.24  nisimura 			memset(mchash, 0xff, sizeof(mchash)); /* necessary? */
    447  1.24  nisimura 			/* accept all mulicast frame */
    448  1.24  nisimura 			rcr |= DM9000_RCR_ALL;
    449  1.36    martin 			goto update;
    450  1.24  nisimura 		}
    451  1.24  nisimura 		h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) & 0x3f;
    452  1.24  nisimura 		/* 3(5:3) and 3(2:0) sampling to have uint8_t[8] */
    453  1.24  nisimura 		mchash[h / 8] |= 1 << (h % 8);
    454  1.24  nisimura 		ETHER_NEXT_MULTI(step, enm);
    455   1.1     ahoka 	}
    456  1.24  nisimura 	ETHER_UNLOCK(ec);
    457  1.24  nisimura 	/* DM9000 receive filter is always on */
    458  1.24  nisimura 	mchash[7] |= 0x80; /* to catch bcast frame */
    459  1.24  nisimura  update:
    460  1.24  nisimura 	dme_write_c(sc, DM9000_MAB0, mchash, sizeof(mchash));
    461  1.24  nisimura 	dme_write(sc, DM9000_RCR, rcr | DM9000_RCR_RXEN);
    462  1.24  nisimura 	return;
    463   1.1     ahoka }
    464   1.1     ahoka 
    465   1.1     ahoka void
    466  1.24  nisimura lnkchg(struct dme_softc *sc)
    467   1.1     ahoka {
    468  1.24  nisimura 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    469  1.24  nisimura 	struct ifmediareq ifmr;
    470  1.24  nisimura 
    471  1.24  nisimura 	ether_mediastatus(ifp, &ifmr);
    472  1.24  nisimura }
    473   1.1     ahoka 
    474  1.24  nisimura static void
    475  1.24  nisimura mii_statchg(struct ifnet *ifp)
    476  1.24  nisimura {
    477  1.24  nisimura 	struct dme_softc *sc = ifp->if_softc;
    478  1.24  nisimura 	struct mii_data *mii = &sc->sc_mii;
    479  1.27     skrll 	uint8_t fcr, ncr;
    480  1.27     skrll 
    481  1.27     skrll #if 0
    482  1.24  nisimura 	const uint8_t Mbps[2] = { 10, 100 };
    483  1.27     skrll 	uint8_t nsr = dme_read(sc, DM9000_NSR);
    484  1.27     skrll 	int spd = Mbps[!!(nsr & DM9000_NSR_SPEED)];
    485  1.24  nisimura 	/* speed/duplexity available also in reg 0x11 of internal PHY */
    486  1.24  nisimura 	if (nsr & DM9000_NSR_LINKST)
    487  1.24  nisimura 		printf("link up,spd%d", spd);
    488  1.24  nisimura 	else
    489  1.24  nisimura 		printf("link down");
    490   1.1     ahoka 
    491  1.24  nisimura 	/* show resolved mii(4) parameters */
    492  1.24  nisimura 	printf("MII spd%d",
    493  1.24  nisimura 	    (int)(sc->sc_ethercom.ec_if.if_baudrate / IF_Mbps(1)));
    494  1.24  nisimura 	if (mii->mii_media_active & IFM_FDX)
    495  1.24  nisimura 		printf(",full-duplex");
    496  1.24  nisimura 	printf("\n");
    497  1.24  nisimura #endif
    498   1.1     ahoka 
    499  1.24  nisimura 	/* Adjust duplexity and PAUSE flow control. */
    500  1.24  nisimura 	fcr = dme_read(sc, DM9000_FCR) &~ DM9000_FCR_FLCE;
    501  1.24  nisimura 	ncr = dme_read(sc, DM9000_NCR) &~ DM9000_NCR_FDX;
    502  1.24  nisimura 	if ((mii->mii_media_active & IFM_FDX)
    503  1.24  nisimura 	    && (mii->mii_media_active & IFM_FLOW)) {
    504  1.24  nisimura 		fcr |= DM9000_FCR_FLCE;
    505  1.24  nisimura 		ncr |= DM9000_NCR_FDX;
    506   1.1     ahoka 	}
    507  1.24  nisimura 	dme_write(sc, DM9000_FCR, fcr);
    508  1.24  nisimura 	dme_write(sc, DM9000_NCR, ncr);
    509  1.24  nisimura }
    510   1.1     ahoka 
    511  1.24  nisimura static void
    512  1.24  nisimura phy_tick(void *arg)
    513  1.24  nisimura {
    514  1.24  nisimura 	struct dme_softc *sc = arg;
    515  1.24  nisimura 	struct mii_data *mii = &sc->sc_mii;
    516  1.24  nisimura 	int s;
    517   1.1     ahoka 
    518  1.24  nisimura 	s = splnet();
    519  1.24  nisimura 	mii_tick(mii);
    520  1.24  nisimura 	splx(s);
    521   1.1     ahoka 
    522  1.24  nisimura 	callout_schedule(&sc->sc_link_callout, hz);
    523  1.24  nisimura }
    524   1.1     ahoka 
    525  1.24  nisimura static int
    526  1.24  nisimura mii_readreg(device_t self, int phy, int reg, uint16_t *val)
    527  1.24  nisimura {
    528  1.24  nisimura 	struct dme_softc *sc = device_private(self);
    529   1.1     ahoka 
    530  1.24  nisimura 	if (phy != 1)
    531  1.24  nisimura 		return EINVAL;
    532   1.1     ahoka 
    533  1.24  nisimura 	/* Select Register to read*/
    534  1.24  nisimura 	dme_write(sc, DM9000_EPAR, DM9000_EPAR_INT_PHY +
    535  1.24  nisimura 	    (reg & DM9000_EPAR_EROA_MASK));
    536  1.24  nisimura 	/* Select read operation (DM9000_EPCR_ERPRR) from the PHY */
    537  1.24  nisimura 	dme_write(sc, DM9000_EPCR, DM9000_EPCR_ERPRR + DM9000_EPCR_EPOS_PHY);
    538   1.1     ahoka 
    539  1.24  nisimura 	/* Wait until access to PHY has completed */
    540  1.24  nisimura 	while (dme_read(sc, DM9000_EPCR) & DM9000_EPCR_ERRE)
    541  1.24  nisimura 		;
    542   1.1     ahoka 
    543  1.24  nisimura 	/* Reset ERPRR-bit */
    544  1.24  nisimura 	dme_write(sc, DM9000_EPCR, DM9000_EPCR_EPOS_PHY);
    545   1.1     ahoka 
    546  1.24  nisimura 	*val = dme_read(sc, DM9000_EPDRL) | (dme_read(sc, DM9000_EPDRH) << 8);
    547  1.24  nisimura 	return 0;
    548   1.1     ahoka }
    549   1.1     ahoka 
    550  1.24  nisimura static int
    551  1.24  nisimura mii_writereg(device_t self, int phy, int reg, uint16_t val)
    552   1.1     ahoka {
    553  1.24  nisimura 	struct dme_softc *sc = device_private(self);
    554   1.1     ahoka 
    555  1.24  nisimura 	if (phy != 1)
    556  1.24  nisimura 		return EINVAL;
    557   1.1     ahoka 
    558  1.24  nisimura 	/* Select Register to write */
    559  1.24  nisimura 	dme_write(sc, DM9000_EPAR, DM9000_EPAR_INT_PHY +
    560  1.24  nisimura 	    (reg & DM9000_EPAR_EROA_MASK));
    561   1.1     ahoka 
    562  1.24  nisimura 	/* Write data to the two data registers */
    563  1.24  nisimura 	dme_write(sc, DM9000_EPDRL, val & 0xFF);
    564  1.24  nisimura 	dme_write(sc, DM9000_EPDRH, (val >> 8) & 0xFF);
    565   1.1     ahoka 
    566  1.24  nisimura 	/* Select write operation (DM9000_EPCR_ERPRW) from the PHY */
    567  1.24  nisimura 	dme_write(sc, DM9000_EPCR, DM9000_EPCR_ERPRW + DM9000_EPCR_EPOS_PHY);
    568   1.1     ahoka 
    569  1.24  nisimura 	/* Wait until access to PHY has completed */
    570  1.24  nisimura 	while (dme_read(sc, DM9000_EPCR) & DM9000_EPCR_ERRE)
    571  1.24  nisimura 		;
    572   1.1     ahoka 
    573  1.24  nisimura 	/* Reset ERPRR-bit */
    574  1.24  nisimura 	dme_write(sc, DM9000_EPCR, DM9000_EPCR_EPOS_PHY);
    575   1.1     ahoka 
    576  1.24  nisimura 	return 0;
    577   1.1     ahoka }
    578   1.1     ahoka 
    579   1.1     ahoka void
    580   1.1     ahoka dme_stop(struct ifnet *ifp, int disable)
    581   1.1     ahoka {
    582   1.1     ahoka 	struct dme_softc *sc = ifp->if_softc;
    583   1.1     ahoka 
    584   1.1     ahoka 	/* Not quite sure what to do when called with disable == 0 */
    585   1.1     ahoka 	if (disable) {
    586   1.1     ahoka 		/* Disable RX */
    587   1.1     ahoka 		dme_write(sc, DM9000_RCR, 0x0);
    588   1.1     ahoka 	}
    589  1.24  nisimura 	mii_down(&sc->sc_mii);
    590  1.24  nisimura 	callout_stop(&sc->sc_link_callout);
    591   1.1     ahoka 
    592  1.34   thorpej 	ifp->if_flags &= ~IFF_RUNNING;
    593   1.1     ahoka 	ifp->if_timer = 0;
    594   1.1     ahoka }
    595   1.1     ahoka 
    596  1.24  nisimura static void
    597  1.24  nisimura dme_start(struct ifnet *ifp)
    598   1.1     ahoka {
    599   1.4  nisimura 	struct dme_softc *sc = ifp->if_softc;
    600   1.4  nisimura 
    601  1.34   thorpej 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
    602  1.24  nisimura 		return;
    603  1.24  nisimura 	}
    604  1.34   thorpej 	if (!sc->txready) {
    605  1.34   thorpej 		dme_prepare(ifp);
    606  1.34   thorpej 	}
    607  1.24  nisimura 	if (sc->txbusy) {
    608  1.34   thorpej 		/*
    609  1.34   thorpej 		 * We need to wait until the current frame has
    610  1.24  nisimura 		 * been transmitted.
    611  1.24  nisimura 		 */
    612  1.24  nisimura 		return;
    613  1.24  nisimura 	}
    614  1.34   thorpej 	if (sc->txready) {
    615  1.34   thorpej 		/* We are ready to transmit right away */
    616  1.34   thorpej 		dme_transmit(ifp);
    617  1.34   thorpej 	}
    618  1.24  nisimura 	dme_prepare(ifp); /* Prepare next one */
    619   1.1     ahoka }
    620   1.1     ahoka 
    621  1.24  nisimura /* Prepare data to be transmitted (i.e. dequeue and load it into the DM9000) */
    622  1.24  nisimura static void
    623  1.24  nisimura dme_prepare(struct ifnet *ifp)
    624   1.1     ahoka {
    625   1.1     ahoka 	struct dme_softc *sc = ifp->if_softc;
    626  1.24  nisimura 	uint16_t length;
    627  1.24  nisimura 	struct mbuf *m;
    628  1.24  nisimura 
    629  1.34   thorpej 	KASSERT(!sc->txready);
    630  1.24  nisimura 
    631  1.24  nisimura 	IFQ_DEQUEUE(&ifp->if_snd, m);
    632  1.24  nisimura 	if (m == NULL) {
    633  1.24  nisimura 		TX_DPRINTF(("dme_prepare: Nothing to transmit\n"));
    634  1.24  nisimura 		return; /* Nothing to transmit */
    635  1.24  nisimura 	}
    636  1.24  nisimura 
    637  1.24  nisimura 	/* Element has now been removed from the queue, so we better send it */
    638  1.24  nisimura 
    639  1.24  nisimura 	bpf_mtap(ifp, m, BPF_D_OUT);
    640  1.24  nisimura 
    641  1.24  nisimura 	/* Setup the DM9000 to accept the writes, and then write each buf in
    642  1.24  nisimura 	   the chain. */
    643  1.24  nisimura 
    644  1.24  nisimura 	TX_DATA_DPRINTF(("dme_prepare: Writing data: "));
    645  1.24  nisimura 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->dme_io, DM9000_MWCMD);
    646  1.24  nisimura 	length = PKT_WRITE(sc, m);
    647  1.24  nisimura 	bpf_mtap(ifp, m, BPF_D_OUT);
    648  1.24  nisimura 	TX_DATA_DPRINTF(("\n"));
    649  1.24  nisimura 
    650  1.24  nisimura 	if (length % sc->sc_data_width != 0)
    651  1.24  nisimura 		panic("dme_prepare: length is not compatible with IO_MODE");
    652   1.1     ahoka 
    653  1.24  nisimura 	sc->txready_length = length;
    654  1.24  nisimura 	sc->txready = 1;
    655  1.24  nisimura 	m_freem(m);
    656   1.1     ahoka }
    657   1.1     ahoka 
    658  1.24  nisimura /* Transmit prepared data */
    659  1.24  nisimura static void
    660  1.24  nisimura dme_transmit(struct ifnet *ifp)
    661   1.1     ahoka {
    662  1.24  nisimura 	struct dme_softc *sc = ifp->if_softc;
    663   1.1     ahoka 
    664   1.1     ahoka 	TX_DPRINTF(("dme_transmit: PRE: txready: %d, txbusy: %d\n",
    665   1.1     ahoka 		sc->txready, sc->txbusy));
    666   1.1     ahoka 
    667  1.24  nisimura 	/* prime frame length first */
    668   1.1     ahoka 	dme_write(sc, DM9000_TXPLL, sc->txready_length & 0xff);
    669  1.24  nisimura 	dme_write(sc, DM9000_TXPLH, (sc->txready_length >> 8) & 0xff);
    670  1.24  nisimura 	/* read isr next */
    671   1.5     skrll 	dme_read(sc, DM9000_ISR);
    672  1.24  nisimura 	/* finally issue a request to send */
    673   1.1     ahoka 	dme_write(sc, DM9000_TCR, DM9000_TCR_TXREQ);
    674   1.1     ahoka 	sc->txready = 0;
    675   1.1     ahoka 	sc->txbusy = 1;
    676   1.1     ahoka 	sc->txready_length = 0;
    677   1.1     ahoka }
    678   1.1     ahoka 
    679  1.24  nisimura /* Receive data */
    680  1.24  nisimura static void
    681  1.24  nisimura dme_receive(struct ifnet *ifp)
    682   1.1     ahoka {
    683  1.24  nisimura 	struct dme_softc *sc = ifp->if_softc;
    684  1.24  nisimura 	struct mbuf *m;
    685  1.24  nisimura 	uint8_t avail, rsr;
    686   1.1     ahoka 
    687   1.1     ahoka 	DPRINTF(("inside dme_receive\n"));
    688   1.1     ahoka 
    689  1.24  nisimura 	/* frame has just arrived, retrieve it */
    690  1.24  nisimura 	/* called right after Rx frame available interrupt */
    691  1.24  nisimura 	do {
    692  1.24  nisimura 		/* "no increment" read to get the avail byte without
    693   1.7  macallan 		   moving past it. */
    694  1.24  nisimura 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->dme_io,
    695  1.24  nisimura 			DM9000_MRCMDX);
    696  1.24  nisimura 		/* Read twice */
    697  1.24  nisimura 		avail = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
    698  1.24  nisimura 		avail = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
    699  1.24  nisimura 		avail &= 03;	/* 1:0 we only want these bits */
    700  1.24  nisimura 		if (avail == 01) {
    701   1.1     ahoka 			/* Read with address increment. */
    702  1.24  nisimura 			bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->dme_io,
    703  1.24  nisimura 				DM9000_MRCMD);
    704  1.24  nisimura 			rsr = PKT_READ(sc, &m);
    705   1.8  macallan 			if (m == NULL) {
    706   1.8  macallan 				/* failed to allocate a receive buffer */
    707   1.8  macallan 				RX_DPRINTF(("dme_receive: "
    708   1.8  macallan 					"Error allocating buffer\n"));
    709  1.24  nisimura 				if_statinc(ifp, if_ierrors);
    710  1.24  nisimura 				continue;
    711  1.24  nisimura 			}
    712  1.24  nisimura 			if (rsr & (DM9000_RSR_CE | DM9000_RSR_PLE)) {
    713  1.24  nisimura 				/* Error while receiving the frame,
    714   1.1     ahoka 				 * discard it and keep track of counters
    715   1.1     ahoka 				 */
    716  1.24  nisimura 				RX_DPRINTF(("dme_receive: "
    717  1.24  nisimura 					"Error reciving frame\n"));
    718  1.22   thorpej 				if_statinc(ifp, if_ierrors);
    719  1.24  nisimura 				continue;
    720  1.24  nisimura 			}
    721  1.24  nisimura 			if (rsr & DM9000_RSR_LCS) {
    722  1.22   thorpej 				if_statinc(ifp, if_collisions);
    723  1.24  nisimura 				continue;
    724   1.1     ahoka 			}
    725  1.26  nisimura 			/* pick and forward this frame to ifq */
    726  1.24  nisimura 			if_percpuq_enqueue(ifp->if_percpuq, m);
    727  1.24  nisimura 		} else if (avail != 00) {
    728   1.1     ahoka 			/* Should this be logged somehow? */
    729   1.4  nisimura 			printf("%s: Resetting chip\n",
    730   1.4  nisimura 			       device_xname(sc->sc_dev));
    731   1.1     ahoka 			dme_reset(sc);
    732  1.26  nisimura 			break;
    733   1.1     ahoka 		}
    734  1.26  nisimura 	} while (avail == 01);
    735  1.32   msaitoh 	/* frame received successfully */
    736   1.1     ahoka }
    737   1.1     ahoka 
    738  1.24  nisimura int
    739  1.24  nisimura dme_intr(void *arg)
    740   1.1     ahoka {
    741  1.24  nisimura 	struct dme_softc *sc = arg;
    742  1.24  nisimura 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    743  1.24  nisimura 	uint8_t isr, nsr, tsr;
    744  1.24  nisimura 
    745  1.24  nisimura 	DPRINTF(("dme_intr: Begin\n"));
    746  1.24  nisimura 
    747  1.24  nisimura 	/* Disable interrupts */
    748  1.24  nisimura 	dme_write(sc, DM9000_IMR, DM9000_IMR_PAR);
    749   1.1     ahoka 
    750  1.24  nisimura 	isr = dme_read(sc, DM9000_ISR);
    751  1.24  nisimura 	dme_write(sc, DM9000_ISR, isr); /* write to clear */
    752   1.4  nisimura 
    753  1.24  nisimura 	if (isr & DM9000_ISR_PRS) {
    754  1.24  nisimura 		KASSERT(ifp->if_flags & IFF_RUNNING);
    755  1.24  nisimura 		dme_receive(ifp);
    756   1.4  nisimura 	}
    757  1.24  nisimura 	if (isr & DM9000_ISR_LNKCHNG)
    758  1.24  nisimura 		lnkchg(sc);
    759  1.24  nisimura 	if (isr & DM9000_ISR_PTS) {
    760  1.24  nisimura 		tsr = 0x01; /* Initialize to an error value */
    761   1.1     ahoka 
    762  1.24  nisimura 		/* A frame has been transmitted */
    763  1.24  nisimura 		sc->txbusy = 0;
    764   1.4  nisimura 
    765  1.24  nisimura 		nsr = dme_read(sc, DM9000_NSR);
    766  1.24  nisimura 		if (nsr & DM9000_NSR_TX1END) {
    767  1.24  nisimura 			tsr = dme_read(sc, DM9000_TSR1);
    768  1.24  nisimura 			TX_DPRINTF(("dme_intr: Sent using channel 0\n"));
    769  1.24  nisimura 		} else if (nsr & DM9000_NSR_TX2END) {
    770  1.24  nisimura 			tsr = dme_read(sc, DM9000_TSR2);
    771  1.24  nisimura 			TX_DPRINTF(("dme_intr: Sent using channel 1\n"));
    772  1.24  nisimura 		}
    773   1.4  nisimura 
    774  1.24  nisimura 		if (tsr == 0x0) {
    775  1.24  nisimura 			/* Frame successfully sent */
    776  1.24  nisimura 			if_statinc(ifp, if_opackets);
    777  1.24  nisimura 		} else {
    778  1.24  nisimura 			if_statinc(ifp, if_oerrors);
    779  1.24  nisimura 		}
    780   1.4  nisimura 
    781  1.24  nisimura 		/* If we have nothing ready to transmit, prepare something */
    782  1.24  nisimura 		if (!sc->txready)
    783  1.24  nisimura 			dme_prepare(ifp);
    784   1.4  nisimura 
    785  1.24  nisimura 		if (sc->txready)
    786  1.24  nisimura 			dme_transmit(ifp);
    787   1.1     ahoka 
    788  1.24  nisimura 		/* Prepare the next frame */
    789  1.24  nisimura 		dme_prepare(ifp);
    790   1.1     ahoka 
    791  1.24  nisimura 		if_schedule_deferred_start(ifp);
    792  1.24  nisimura 	}
    793   1.1     ahoka 
    794  1.24  nisimura 	/* Enable interrupts again */
    795   1.1     ahoka 	dme_write(sc, DM9000_IMR,
    796   1.1     ahoka 	    DM9000_IMR_PAR | DM9000_IMR_PRM | DM9000_IMR_PTM);
    797   1.1     ahoka 
    798  1.24  nisimura 	DPRINTF(("dme_intr: End\n"));
    799  1.24  nisimura 
    800  1.24  nisimura 	return (isr != 0);
    801  1.24  nisimura }
    802   1.4  nisimura 
    803  1.24  nisimura static int
    804  1.24  nisimura dme_ioctl(struct ifnet *ifp, u_long cmd, void *data)
    805  1.24  nisimura {
    806  1.24  nisimura 	struct dme_softc *sc = ifp->if_softc;
    807  1.24  nisimura 	struct ifreq *ifr = (struct ifreq *)data;
    808  1.24  nisimura 	struct ifmedia *ifm = &sc->sc_mii.mii_media;
    809  1.24  nisimura 	int s, error;
    810   1.1     ahoka 
    811  1.24  nisimura 	s = splnet();
    812  1.24  nisimura 	switch (cmd) {
    813  1.24  nisimura 	case SIOCSIFMEDIA:
    814  1.24  nisimura 		/* Flow control requires full-duplex mode. */
    815  1.24  nisimura 		if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO ||
    816  1.24  nisimura 		    (ifr->ifr_media & IFM_FDX) == 0)
    817  1.24  nisimura 			ifr->ifr_media &= ~IFM_ETH_FMASK;
    818  1.24  nisimura 		if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) {
    819  1.24  nisimura 			if ((ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) {
    820  1.24  nisimura 				ifr->ifr_media |=
    821  1.24  nisimura 					IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE;
    822  1.24  nisimura 			}
    823  1.24  nisimura 		}
    824  1.24  nisimura 		error = ifmedia_ioctl(ifp, ifr, ifm, cmd);
    825  1.24  nisimura 		break;
    826  1.24  nisimura 	default:
    827  1.24  nisimura 		if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
    828  1.24  nisimura 			break;
    829  1.24  nisimura 		error = 0;
    830  1.24  nisimura 		if (cmd == SIOCSIFCAP)
    831  1.33  riastrad 			error = if_init(ifp);
    832  1.24  nisimura 		else if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
    833  1.24  nisimura 			;
    834  1.24  nisimura 		else if (ifp->if_flags && IFF_RUNNING) {
    835  1.24  nisimura 			/* Address list has changed, reconfigure filter */
    836  1.24  nisimura 			dme_set_rcvfilt(sc);
    837  1.24  nisimura 		}
    838  1.24  nisimura 		break;
    839  1.24  nisimura 	}
    840  1.24  nisimura 	splx(s);
    841  1.24  nisimura 	return error;
    842   1.4  nisimura }
    843   1.4  nisimura 
    844  1.24  nisimura static struct mbuf *
    845  1.24  nisimura dme_alloc_receive_buffer(struct ifnet *ifp, unsigned int frame_length)
    846   1.4  nisimura {
    847  1.24  nisimura 	struct dme_softc *sc = ifp->if_softc;
    848  1.24  nisimura 	struct mbuf *m;
    849  1.24  nisimura 	int pad, quantum;
    850  1.23  nisimura 
    851  1.24  nisimura 	quantum = sc->sc_data_width;
    852  1.24  nisimura 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    853  1.24  nisimura 	if (m == NULL)
    854  1.24  nisimura 		return NULL;
    855   1.4  nisimura 
    856  1.24  nisimura 	m_set_rcvif(m, ifp);
    857  1.24  nisimura 	/* Ensure that we always allocate an even number of
    858  1.24  nisimura 	 * bytes in order to avoid writing beyond the buffer
    859  1.24  nisimura 	 */
    860  1.24  nisimura 	m->m_pkthdr.len = frame_length + (frame_length % quantum);
    861  1.24  nisimura 	pad = ALIGN(sizeof(struct ether_header)) -
    862  1.24  nisimura 		sizeof(struct ether_header);
    863  1.24  nisimura 	/* All our frames have the CRC attached */
    864  1.24  nisimura 	m->m_flags |= M_HASFCS;
    865  1.24  nisimura 	if (m->m_pkthdr.len + pad > MHLEN) {
    866  1.24  nisimura 		MCLGET(m, M_DONTWAIT);
    867  1.24  nisimura 		if ((m->m_flags & M_EXT) == 0) {
    868  1.24  nisimura 			m_freem(m);
    869  1.24  nisimura 			return NULL;
    870   1.4  nisimura 		}
    871   1.4  nisimura 	}
    872  1.24  nisimura 
    873  1.24  nisimura 	m->m_data += pad;
    874  1.24  nisimura 	m->m_len = frame_length + (frame_length % quantum);
    875  1.24  nisimura 
    876  1.24  nisimura 	return m;
    877   1.4  nisimura }
    878   1.4  nisimura 
    879  1.24  nisimura static int
    880  1.24  nisimura pkt_write_2(struct dme_softc *sc, struct mbuf *bufChain)
    881   1.4  nisimura {
    882   1.4  nisimura 	int left_over_count = 0; /* Number of bytes from previous mbuf, which
    883   1.4  nisimura 				    need to be written with the next.*/
    884   1.4  nisimura 	uint16_t left_over_buf = 0;
    885   1.4  nisimura 	int length = 0;
    886   1.4  nisimura 	struct mbuf *buf;
    887   1.4  nisimura 	uint8_t *write_ptr;
    888   1.4  nisimura 
    889   1.4  nisimura 	/* We expect that the DM9000 has been setup to accept writes before
    890   1.4  nisimura 	   this function is called. */
    891   1.4  nisimura 
    892   1.4  nisimura 	for (buf = bufChain; buf != NULL; buf = buf->m_next) {
    893   1.4  nisimura 		int to_write = buf->m_len;
    894   1.4  nisimura 
    895   1.4  nisimura 		length += to_write;
    896   1.4  nisimura 
    897   1.4  nisimura 		write_ptr = buf->m_data;
    898   1.4  nisimura 		while (to_write > 0 ||
    899  1.17   msaitoh 		    (buf->m_next == NULL && left_over_count > 0)) {
    900   1.4  nisimura 			if (left_over_count > 0) {
    901   1.4  nisimura 				uint8_t b = 0;
    902  1.24  nisimura 				DPRINTF(("pkt_write_16: "
    903   1.4  nisimura 					 "Writing left over byte\n"));
    904   1.4  nisimura 
    905   1.4  nisimura 				if (to_write > 0) {
    906   1.4  nisimura 					b = *write_ptr;
    907   1.4  nisimura 					to_write--;
    908   1.4  nisimura 					write_ptr++;
    909   1.4  nisimura 
    910   1.4  nisimura 					DPRINTF(("Took single byte\n"));
    911   1.4  nisimura 				} else {
    912   1.4  nisimura 					DPRINTF(("Leftover in last run\n"));
    913   1.4  nisimura 					length++;
    914   1.4  nisimura 				}
    915   1.4  nisimura 
    916  1.31   msaitoh 				/* Does shift direction depend on endianness? */
    917   1.4  nisimura 				left_over_buf = left_over_buf | (b << 8);
    918   1.4  nisimura 
    919   1.4  nisimura 				bus_space_write_2(sc->sc_iot, sc->sc_ioh,
    920   1.4  nisimura 						  sc->dme_data, left_over_buf);
    921   1.4  nisimura 				TX_DATA_DPRINTF(("%02X ", left_over_buf));
    922   1.4  nisimura 				left_over_count = 0;
    923   1.4  nisimura 			} else if ((long)write_ptr % 2 != 0) {
    924   1.4  nisimura 				/* Misaligned data */
    925  1.24  nisimura 				DPRINTF(("pkt_write_16: "
    926   1.4  nisimura 					 "Detected misaligned data\n"));
    927   1.4  nisimura 				left_over_buf = *write_ptr;
    928   1.4  nisimura 				left_over_count = 1;
    929   1.4  nisimura 				write_ptr++;
    930   1.4  nisimura 				to_write--;
    931   1.4  nisimura 			} else {
    932   1.4  nisimura 				int i;
    933   1.7  macallan 				uint16_t *dptr = (uint16_t *)write_ptr;
    934   1.4  nisimura 
    935   1.4  nisimura 				/* A block of aligned data. */
    936  1.17   msaitoh 				for (i = 0; i < to_write / 2; i++) {
    937   1.4  nisimura 					/* buf will be half-word aligned
    938   1.4  nisimura 					 * all the time
    939   1.4  nisimura 					 */
    940   1.4  nisimura 					bus_space_write_2(sc->sc_iot,
    941   1.7  macallan 					    sc->sc_ioh, sc->dme_data, *dptr);
    942   1.4  nisimura 					TX_DATA_DPRINTF(("%02X %02X ",
    943   1.7  macallan 					    *dptr & 0xFF, (*dptr >> 8) & 0xFF));
    944   1.4  nisimura 					dptr++;
    945   1.4  nisimura 				}
    946   1.4  nisimura 
    947   1.7  macallan 				write_ptr += i * 2;
    948   1.4  nisimura 				if (to_write % 2 != 0) {
    949  1.24  nisimura 					DPRINTF(("pkt_write_16: "
    950   1.4  nisimura 						 "to_write %% 2: %d\n",
    951   1.4  nisimura 						 to_write % 2));
    952   1.4  nisimura 					left_over_count = 1;
    953   1.4  nisimura 					/* XXX: Does this depend on
    954  1.31   msaitoh 					 * the endianness?
    955   1.4  nisimura 					 */
    956   1.4  nisimura 					left_over_buf = *write_ptr;
    957   1.4  nisimura 
    958   1.4  nisimura 					write_ptr++;
    959   1.4  nisimura 					to_write--;
    960  1.24  nisimura 					DPRINTF(("pkt_write_16: "
    961   1.4  nisimura 						 "to_write (after): %d\n",
    962   1.4  nisimura 						 to_write));
    963  1.24  nisimura 					DPRINTF(("pkt_write_16: i * 2: %d\n",
    964   1.4  nisimura 						 i*2));
    965   1.4  nisimura 				}
    966   1.7  macallan 				to_write -= i * 2;
    967   1.4  nisimura 			}
    968  1.18   msaitoh 		} /* while (...) */
    969  1.18   msaitoh 	} /* for (...) */
    970   1.4  nisimura 
    971   1.4  nisimura 	return length;
    972   1.4  nisimura }
    973   1.4  nisimura 
    974  1.24  nisimura static int
    975  1.24  nisimura pkt_read_2(struct dme_softc *sc, struct mbuf **outBuf)
    976   1.4  nisimura {
    977  1.24  nisimura 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    978   1.4  nisimura 	uint8_t rx_status;
    979   1.4  nisimura 	struct mbuf *m;
    980   1.4  nisimura 	uint16_t data;
    981   1.4  nisimura 	uint16_t frame_length;
    982   1.4  nisimura 	uint16_t i;
    983   1.4  nisimura 	uint16_t *buf;
    984   1.4  nisimura 
    985   1.7  macallan 	data = bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->dme_data);
    986  1.24  nisimura 	rx_status = data & 0xFF;
    987   1.4  nisimura 
    988   1.4  nisimura 	frame_length = bus_space_read_2(sc->sc_iot,
    989   1.4  nisimura 					sc->sc_ioh, sc->dme_data);
    990   1.4  nisimura 	if (frame_length > ETHER_MAX_LEN) {
    991   1.4  nisimura 		printf("Got frame of length: %d\n", frame_length);
    992   1.4  nisimura 		printf("ETHER_MAX_LEN is: %d\n", ETHER_MAX_LEN);
    993   1.4  nisimura 		panic("Something is rotten");
    994   1.4  nisimura 	}
    995  1.17   msaitoh 	RX_DPRINTF(("dme_receive: rx_statux: 0x%x, frame_length: %d\n",
    996  1.17   msaitoh 		rx_status, frame_length));
    997   1.4  nisimura 
    998   1.4  nisimura 	m = dme_alloc_receive_buffer(ifp, frame_length);
    999   1.8  macallan 	if (m == NULL) {
   1000   1.8  macallan 		/*
   1001   1.8  macallan 		 * didn't get a receive buffer, so we read the rest of the
   1002  1.24  nisimura 		 * frame, throw it away and return an error
   1003   1.8  macallan 		 */
   1004  1.24  nisimura 		for (i = 0; i < frame_length; i += 2) {
   1005   1.8  macallan 			data = bus_space_read_2(sc->sc_iot,
   1006   1.8  macallan 					sc->sc_ioh, sc->dme_data);
   1007   1.8  macallan 		}
   1008   1.8  macallan 		*outBuf = NULL;
   1009   1.8  macallan 		return 0;
   1010   1.8  macallan 	}
   1011   1.4  nisimura 
   1012   1.4  nisimura 	buf = mtod(m, uint16_t*);
   1013   1.4  nisimura 
   1014   1.4  nisimura 	RX_DPRINTF(("dme_receive: "));
   1015   1.4  nisimura 
   1016  1.24  nisimura 	for (i = 0; i < frame_length; i += 2) {
   1017   1.4  nisimura 		data = bus_space_read_2(sc->sc_iot,
   1018   1.4  nisimura 					sc->sc_ioh, sc->dme_data);
   1019   1.4  nisimura 		if ( (frame_length % 2 != 0) &&
   1020   1.7  macallan 		     (i == frame_length - 1) ) {
   1021   1.4  nisimura 			data = data & 0xff;
   1022   1.4  nisimura 			RX_DPRINTF((" L "));
   1023   1.4  nisimura 		}
   1024   1.4  nisimura 		*buf = data;
   1025   1.4  nisimura 		buf++;
   1026   1.4  nisimura 		RX_DATA_DPRINTF(("%02X %02X ", data & 0xff,
   1027   1.7  macallan 				 (data >> 8) & 0xff));
   1028   1.4  nisimura 	}
   1029   1.4  nisimura 
   1030   1.4  nisimura 	RX_DATA_DPRINTF(("\n"));
   1031   1.4  nisimura 	RX_DPRINTF(("Read %d bytes\n", i));
   1032   1.4  nisimura 
   1033   1.4  nisimura 	*outBuf = m;
   1034   1.4  nisimura 	return rx_status;
   1035   1.4  nisimura }
   1036   1.4  nisimura 
   1037  1.24  nisimura static int
   1038  1.24  nisimura pkt_write_1(struct dme_softc *sc, struct mbuf *bufChain)
   1039   1.6  macallan {
   1040   1.6  macallan 	int length = 0, i;
   1041   1.6  macallan 	struct mbuf *buf;
   1042   1.6  macallan 	uint8_t *write_ptr;
   1043   1.6  macallan 
   1044  1.17   msaitoh 	/*
   1045  1.17   msaitoh 	 * We expect that the DM9000 has been setup to accept writes before
   1046  1.17   msaitoh 	 * this function is called.
   1047  1.17   msaitoh 	 */
   1048   1.6  macallan 
   1049   1.6  macallan 	for (buf = bufChain; buf != NULL; buf = buf->m_next) {
   1050   1.6  macallan 		int to_write = buf->m_len;
   1051   1.6  macallan 
   1052   1.6  macallan 		length += to_write;
   1053   1.6  macallan 
   1054   1.6  macallan 		write_ptr = buf->m_data;
   1055   1.7  macallan 		for (i = 0; i < to_write; i++) {
   1056   1.6  macallan 			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
   1057   1.6  macallan 			    sc->dme_data, *write_ptr);
   1058   1.6  macallan 			write_ptr++;
   1059   1.6  macallan 		}
   1060  1.18   msaitoh 	} /* for (...) */
   1061   1.6  macallan 
   1062   1.6  macallan 	return length;
   1063   1.6  macallan }
   1064   1.6  macallan 
   1065  1.24  nisimura static int
   1066  1.24  nisimura pkt_read_1(struct dme_softc *sc, struct mbuf **outBuf)
   1067   1.6  macallan {
   1068  1.24  nisimura 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1069   1.6  macallan 	uint8_t rx_status;
   1070   1.6  macallan 	struct mbuf *m;
   1071   1.6  macallan 	uint8_t *buf;
   1072   1.6  macallan 	uint16_t frame_length;
   1073   1.6  macallan 	uint16_t i, reg;
   1074   1.6  macallan 	uint8_t data;
   1075   1.6  macallan 
   1076   1.6  macallan 	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
   1077   1.6  macallan 	reg |= bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data) << 8;
   1078   1.6  macallan 	rx_status = reg & 0xFF;
   1079   1.6  macallan 
   1080   1.6  macallan 	reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
   1081   1.6  macallan 	reg |= bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data) << 8;
   1082   1.6  macallan 	frame_length = reg;
   1083   1.7  macallan 
   1084   1.6  macallan 	if (frame_length > ETHER_MAX_LEN) {
   1085   1.6  macallan 		printf("Got frame of length: %d\n", frame_length);
   1086   1.6  macallan 		printf("ETHER_MAX_LEN is: %d\n", ETHER_MAX_LEN);
   1087   1.6  macallan 		panic("Something is rotten");
   1088   1.6  macallan 	}
   1089   1.6  macallan 	RX_DPRINTF(("dme_receive: "
   1090   1.6  macallan 		    "rx_statux: 0x%x, frame_length: %d\n",
   1091   1.6  macallan 		    rx_status, frame_length));
   1092   1.6  macallan 
   1093   1.6  macallan 	m = dme_alloc_receive_buffer(ifp, frame_length);
   1094   1.8  macallan 	if (m == NULL) {
   1095   1.8  macallan 		/*
   1096   1.8  macallan 		 * didn't get a receive buffer, so we read the rest of the
   1097  1.24  nisimura 		 * frame, throw it away and return an error
   1098   1.8  macallan 		 */
   1099   1.8  macallan 		for (i = 0; i < frame_length; i++ ) {
   1100   1.8  macallan 			data = bus_space_read_2(sc->sc_iot,
   1101   1.8  macallan 					sc->sc_ioh, sc->dme_data);
   1102   1.8  macallan 		}
   1103   1.8  macallan 		*outBuf = NULL;
   1104   1.8  macallan 		return 0;
   1105   1.8  macallan 	}
   1106   1.6  macallan 
   1107   1.7  macallan 	buf = mtod(m, uint8_t *);
   1108   1.6  macallan 
   1109   1.6  macallan 	RX_DPRINTF(("dme_receive: "));
   1110  1.24  nisimura 	for (i = 0; i< frame_length; i += 1) {
   1111   1.7  macallan 		data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
   1112   1.6  macallan 		*buf = data;
   1113   1.6  macallan 		buf++;
   1114   1.6  macallan 		RX_DATA_DPRINTF(("%02X ", data));
   1115   1.6  macallan 	}
   1116   1.6  macallan 
   1117   1.6  macallan 	RX_DATA_DPRINTF(("\n"));
   1118   1.6  macallan 	RX_DPRINTF(("Read %d bytes\n", i));
   1119   1.6  macallan 
   1120   1.6  macallan 	*outBuf = m;
   1121   1.6  macallan 	return rx_status;
   1122   1.6  macallan }
   1123