Home | History | Annotate | Line # | Download | only in usb
if_axe.c revision 1.102
      1  1.102       mrg /*	$NetBSD: if_axe.c,v 1.102 2019/07/21 10:27:56 mrg Exp $	*/
      2   1.76     skrll /*	$OpenBSD: if_axe.c,v 1.137 2016/04/13 11:03:37 mpi Exp $ */
      3   1.35  pgoyette 
      4   1.35  pgoyette /*
      5   1.35  pgoyette  * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg (at) openbsd.org>
      6   1.35  pgoyette  *
      7   1.35  pgoyette  * Permission to use, copy, modify, and distribute this software for any
      8   1.35  pgoyette  * purpose with or without fee is hereby granted, provided that the above
      9   1.35  pgoyette  * copyright notice and this permission notice appear in all copies.
     10   1.35  pgoyette  *
     11   1.35  pgoyette  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12   1.35  pgoyette  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13   1.35  pgoyette  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14   1.35  pgoyette  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15   1.35  pgoyette  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16   1.35  pgoyette  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17   1.35  pgoyette  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18   1.35  pgoyette  */
     19    1.1  augustss 
     20    1.1  augustss /*
     21    1.1  augustss  * Copyright (c) 1997, 1998, 1999, 2000-2003
     22    1.1  augustss  *	Bill Paul <wpaul (at) windriver.com>.  All rights reserved.
     23    1.1  augustss  *
     24    1.1  augustss  * Redistribution and use in source and binary forms, with or without
     25    1.1  augustss  * modification, are permitted provided that the following conditions
     26    1.1  augustss  * are met:
     27    1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     28    1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     29    1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     30    1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     31    1.1  augustss  *    documentation and/or other materials provided with the distribution.
     32    1.1  augustss  * 3. All advertising materials mentioning features or use of this software
     33    1.1  augustss  *    must display the following acknowledgement:
     34    1.1  augustss  *	This product includes software developed by Bill Paul.
     35    1.1  augustss  * 4. Neither the name of the author nor the names of any co-contributors
     36    1.1  augustss  *    may be used to endorse or promote products derived from this software
     37    1.1  augustss  *    without specific prior written permission.
     38    1.1  augustss  *
     39    1.1  augustss  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
     40    1.1  augustss  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     41    1.1  augustss  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     42    1.1  augustss  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
     43    1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     44    1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     45    1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     46    1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     47    1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     48    1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     49    1.1  augustss  * THE POSSIBILITY OF SUCH DAMAGE.
     50    1.1  augustss  */
     51    1.1  augustss 
     52    1.1  augustss /*
     53   1.76     skrll  * ASIX Electronics AX88172/AX88178/AX88778 USB 2.0 ethernet driver.
     54   1.76     skrll  * Used in the LinkSys USB200M and various other adapters.
     55    1.1  augustss  *
     56    1.1  augustss  * Written by Bill Paul <wpaul (at) windriver.com>
     57    1.1  augustss  * Senior Engineer
     58    1.1  augustss  * Wind River Systems
     59    1.1  augustss  */
     60    1.1  augustss 
     61    1.1  augustss /*
     62    1.1  augustss  * The AX88172 provides USB ethernet supports at 10 and 100Mbps.
     63    1.1  augustss  * It uses an external PHY (reference designs use a RealTek chip),
     64    1.1  augustss  * and has a 64-bit multicast hash filter. There is some information
     65    1.1  augustss  * missing from the manual which one needs to know in order to make
     66    1.1  augustss  * the chip function:
     67    1.1  augustss  *
     68    1.1  augustss  * - You must set bit 7 in the RX control register, otherwise the
     69    1.1  augustss  *   chip won't receive any packets.
     70    1.1  augustss  * - You must initialize all 3 IPG registers, or you won't be able
     71    1.1  augustss  *   to send any packets.
     72    1.1  augustss  *
     73    1.1  augustss  * Note that this device appears to only support loading the station
     74   1.76     skrll  * address via autoload from the EEPROM (i.e. there's no way to manually
     75    1.1  augustss  * set it).
     76    1.1  augustss  *
     77    1.1  augustss  * (Adam Weinberger wanted me to name this driver if_gir.c.)
     78    1.1  augustss  */
     79    1.1  augustss 
     80    1.1  augustss /*
     81   1.76     skrll  * Ax88178 and Ax88772 support backported from the OpenBSD driver.
     82   1.76     skrll  * 2007/02/12, J.R. Oldroyd, fbsd (at) opal.com
     83   1.76     skrll  *
     84   1.76     skrll  * Manual here:
     85   1.76     skrll  * http://www.asix.com.tw/FrootAttach/datasheet/AX88178_datasheet_Rev10.pdf
     86   1.76     skrll  * http://www.asix.com.tw/FrootAttach/datasheet/AX88772_datasheet_Rev10.pdf
     87    1.1  augustss  */
     88    1.1  augustss 
     89    1.1  augustss #include <sys/cdefs.h>
     90  1.102       mrg __KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.102 2019/07/21 10:27:56 mrg Exp $");
     91    1.1  augustss 
     92   1.62  christos #ifdef _KERNEL_OPT
     93    1.1  augustss #include "opt_inet.h"
     94   1.75     skrll #include "opt_usb.h"
     95   1.81   msaitoh #include "opt_net_mpsafe.h"
     96    1.1  augustss #endif
     97    1.1  augustss 
     98    1.1  augustss #include <sys/param.h>
     99   1.35  pgoyette #include <sys/bus.h>
    100   1.35  pgoyette #include <sys/device.h>
    101   1.35  pgoyette #include <sys/kernel.h>
    102   1.35  pgoyette #include <sys/mbuf.h>
    103   1.48  pgoyette #include <sys/module.h>
    104   1.21        ad #include <sys/mutex.h>
    105    1.1  augustss #include <sys/socket.h>
    106   1.35  pgoyette #include <sys/sockio.h>
    107   1.35  pgoyette #include <sys/systm.h>
    108    1.1  augustss 
    109   1.69  riastrad #include <sys/rndsource.h>
    110    1.1  augustss 
    111    1.1  augustss #include <net/if.h>
    112    1.1  augustss #include <net/if_dl.h>
    113   1.35  pgoyette #include <net/if_ether.h>
    114    1.1  augustss #include <net/if_media.h>
    115    1.1  augustss 
    116    1.1  augustss #include <net/bpf.h>
    117    1.1  augustss 
    118    1.1  augustss #include <dev/mii/mii.h>
    119    1.1  augustss #include <dev/mii/miivar.h>
    120    1.1  augustss 
    121    1.1  augustss #include <dev/usb/usb.h>
    122   1.76     skrll #include <dev/usb/usbhist.h>
    123    1.1  augustss #include <dev/usb/usbdi.h>
    124    1.1  augustss #include <dev/usb/usbdi_util.h>
    125   1.35  pgoyette #include <dev/usb/usbdivar.h>
    126    1.1  augustss #include <dev/usb/usbdevs.h>
    127    1.1  augustss 
    128    1.1  augustss #include <dev/usb/if_axereg.h>
    129    1.1  augustss 
    130   1.99       mrg struct axe_type {
    131   1.99       mrg 	struct usb_devno	axe_dev;
    132   1.99       mrg 	uint16_t		axe_flags;
    133   1.99       mrg };
    134   1.99       mrg 
    135   1.99       mrg struct axe_softc;
    136   1.99       mrg 
    137   1.99       mrg struct axe_chain {
    138   1.99       mrg 	struct axe_softc	*axe_sc;
    139   1.99       mrg 	struct usbd_xfer	*axe_xfer;
    140   1.99       mrg 	uint8_t			*axe_buf;
    141   1.99       mrg };
    142   1.99       mrg 
    143   1.99       mrg struct axe_cdata {
    144   1.99       mrg 	struct axe_chain	axe_tx_chain[AXE_TX_LIST_CNT];
    145   1.99       mrg 	struct axe_chain	axe_rx_chain[AXE_RX_LIST_CNT];
    146   1.99       mrg 	int			axe_tx_prod;
    147   1.99       mrg 	int			axe_tx_cnt;
    148   1.99       mrg };
    149   1.99       mrg 
    150   1.99       mrg struct axe_softc {
    151   1.99       mrg 	device_t axe_dev;
    152   1.99       mrg 	struct ethercom		axe_ec;
    153   1.99       mrg 	struct mii_data		axe_mii;
    154   1.99       mrg 	krndsource_t	rnd_source;
    155   1.99       mrg 	struct usbd_device *	axe_udev;
    156   1.99       mrg 	struct usbd_interface *	axe_iface;
    157   1.99       mrg 
    158   1.99       mrg 	uint16_t		axe_vendor;
    159   1.99       mrg 	uint16_t		axe_product;
    160  1.100       mrg 	uint16_t		axe_timer;
    161   1.99       mrg 	uint32_t		axe_flags;	/* copied from axe_type */
    162   1.99       mrg #define AX178		__BIT(0)	/* AX88178 */
    163   1.99       mrg #define AX772		__BIT(1)	/* AX88772 */
    164   1.99       mrg #define AX772A		__BIT(2)	/* AX88772A */
    165   1.99       mrg #define AX772B		__BIT(3)	/* AX88772B */
    166   1.99       mrg #define	AXSTD_FRAME	__BIT(12)
    167   1.99       mrg #define	AXCSUM_FRAME	__BIT(13)
    168   1.99       mrg 
    169   1.99       mrg 	int			axe_ed[AXE_ENDPT_MAX];
    170   1.99       mrg 	struct usbd_pipe *	axe_ep[AXE_ENDPT_MAX];
    171   1.99       mrg 	int			axe_if_flags;
    172   1.99       mrg 	int			axe_phyno;
    173   1.99       mrg 	struct axe_cdata	axe_cdata;
    174  1.100       mrg 	struct callout		axe_stat_ch;
    175   1.99       mrg 
    176   1.99       mrg 	uint8_t			axe_enaddr[ETHER_ADDR_LEN];
    177   1.99       mrg 
    178   1.99       mrg 	int			axe_refcnt;
    179   1.99       mrg 	bool			axe_dying;
    180  1.100       mrg 	bool			axe_stopping;
    181   1.99       mrg 	bool			axe_attached;
    182   1.99       mrg 
    183   1.99       mrg 	struct usb_task		axe_tick_task;
    184   1.99       mrg 
    185  1.100       mrg 	kmutex_t		axe_lock;
    186   1.99       mrg 	kmutex_t		axe_mii_lock;
    187  1.100       mrg 	kmutex_t		axe_rxlock;
    188  1.100       mrg 	kmutex_t		axe_txlock;
    189  1.100       mrg 	kcondvar_t		axe_detachcv;
    190   1.99       mrg 
    191   1.99       mrg 	int			axe_link;
    192   1.99       mrg 
    193   1.99       mrg 	uint8_t			axe_ipgs[3];
    194   1.99       mrg 	uint8_t 		axe_phyaddrs[2];
    195   1.99       mrg 	uint16_t		sc_pwrcfg;
    196   1.99       mrg 	uint16_t		sc_lenmask;
    197   1.99       mrg 
    198   1.99       mrg 	struct timeval		axe_rx_notice;
    199  1.100       mrg 	struct timeval		axe_tx_notice;
    200   1.99       mrg 	int			axe_bufsz;
    201   1.99       mrg 
    202   1.99       mrg #define sc_if	axe_ec.ec_if
    203   1.99       mrg };
    204   1.99       mrg 
    205   1.99       mrg #define	AXE_IS_178_FAMILY(sc)						  \
    206   1.99       mrg 	((sc)->axe_flags & (AX772 | AX772A | AX772B | AX178))
    207   1.99       mrg 
    208   1.99       mrg #define	AXE_IS_772(sc)							  \
    209   1.99       mrg 	((sc)->axe_flags & (AX772 | AX772A | AX772B))
    210   1.99       mrg 
    211   1.99       mrg #define AX_RXCSUM					\
    212   1.99       mrg     (IFCAP_CSUM_IPv4_Rx | 				\
    213   1.99       mrg      IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx |	\
    214   1.99       mrg      IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx)
    215   1.99       mrg 
    216   1.99       mrg #define AX_TXCSUM					\
    217   1.99       mrg     (IFCAP_CSUM_IPv4_Tx | 				\
    218   1.99       mrg      IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx |	\
    219   1.99       mrg      IFCAP_CSUM_TCPv6_Tx | IFCAP_CSUM_UDPv6_Tx)
    220   1.99       mrg 
    221   1.76     skrll /*
    222   1.76     skrll  * AXE_178_MAX_FRAME_BURST
    223   1.76     skrll  * max frame burst size for Ax88178 and Ax88772
    224   1.76     skrll  *	0	2048 bytes
    225   1.76     skrll  *	1	4096 bytes
    226   1.76     skrll  *	2	8192 bytes
    227   1.76     skrll  *	3	16384 bytes
    228   1.76     skrll  * use the largest your system can handle without USB stalling.
    229   1.76     skrll  *
    230   1.76     skrll  * NB: 88772 parts appear to generate lots of input errors with
    231   1.76     skrll  * a 2K rx buffer and 8K is only slightly faster than 4K on an
    232   1.76     skrll  * EHCI port on a T42 so change at your own risk.
    233   1.76     skrll  */
    234   1.76     skrll #define AXE_178_MAX_FRAME_BURST	1
    235   1.76     skrll 
    236   1.76     skrll 
    237   1.76     skrll #ifdef USB_DEBUG
    238   1.76     skrll #ifndef AXE_DEBUG
    239   1.76     skrll #define axedebug 0
    240    1.1  augustss #else
    241   1.76     skrll static int axedebug = 20;
    242   1.76     skrll 
    243   1.76     skrll SYSCTL_SETUP(sysctl_hw_axe_setup, "sysctl hw.axe setup")
    244   1.76     skrll {
    245   1.76     skrll 	int err;
    246   1.76     skrll 	const struct sysctlnode *rnode;
    247   1.76     skrll 	const struct sysctlnode *cnode;
    248   1.76     skrll 
    249   1.76     skrll 	err = sysctl_createv(clog, 0, NULL, &rnode,
    250   1.76     skrll 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "axe",
    251   1.76     skrll 	    SYSCTL_DESCR("axe global controls"),
    252   1.76     skrll 	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
    253   1.76     skrll 
    254   1.76     skrll 	if (err)
    255   1.76     skrll 		goto fail;
    256   1.76     skrll 
    257   1.76     skrll 	/* control debugging printfs */
    258   1.76     skrll 	err = sysctl_createv(clog, 0, &rnode, &cnode,
    259   1.96   msaitoh 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
    260   1.76     skrll 	    "debug", SYSCTL_DESCR("Enable debugging output"),
    261   1.76     skrll 	    NULL, 0, &axedebug, sizeof(axedebug), CTL_CREATE, CTL_EOL);
    262   1.76     skrll 	if (err)
    263   1.76     skrll 		goto fail;
    264   1.76     skrll 
    265   1.76     skrll 	return;
    266   1.76     skrll fail:
    267   1.76     skrll 	aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err);
    268   1.76     skrll }
    269   1.76     skrll 
    270   1.76     skrll #endif /* AXE_DEBUG */
    271   1.76     skrll #endif /* USB_DEBUG */
    272   1.76     skrll 
    273   1.76     skrll #define DPRINTF(FMT,A,B,C,D)	USBHIST_LOGN(axedebug,1,FMT,A,B,C,D)
    274   1.76     skrll #define DPRINTFN(N,FMT,A,B,C,D)	USBHIST_LOGN(axedebug,N,FMT,A,B,C,D)
    275   1.76     skrll #define AXEHIST_FUNC()		USBHIST_FUNC()
    276   1.76     skrll #define AXEHIST_CALLED(name)	USBHIST_CALLED(axedebug)
    277    1.1  augustss 
    278    1.1  augustss /*
    279    1.1  augustss  * Various supported device vendors/products.
    280    1.1  augustss  */
    281   1.35  pgoyette static const struct axe_type axe_devs[] = {
    282   1.35  pgoyette 	{ { USB_VENDOR_ABOCOM,		USB_PRODUCT_ABOCOM_UFE2000}, 0 },
    283   1.35  pgoyette 	{ { USB_VENDOR_ACERCM,		USB_PRODUCT_ACERCM_EP1427X2}, 0 },
    284   1.35  pgoyette 	{ { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_ETHERNET }, AX772 },
    285    1.1  augustss 	{ { USB_VENDOR_ASIX,		USB_PRODUCT_ASIX_AX88172}, 0 },
    286   1.35  pgoyette 	{ { USB_VENDOR_ASIX,		USB_PRODUCT_ASIX_AX88772}, AX772 },
    287   1.35  pgoyette 	{ { USB_VENDOR_ASIX,		USB_PRODUCT_ASIX_AX88772A}, AX772 },
    288   1.76     skrll 	{ { USB_VENDOR_ASIX,		USB_PRODUCT_ASIX_AX88772B}, AX772B },
    289   1.76     skrll 	{ { USB_VENDOR_ASIX,		USB_PRODUCT_ASIX_AX88772B_1}, AX772B },
    290   1.35  pgoyette 	{ { USB_VENDOR_ASIX,		USB_PRODUCT_ASIX_AX88178}, AX178 },
    291   1.35  pgoyette 	{ { USB_VENDOR_ATEN,		USB_PRODUCT_ATEN_UC210T}, 0 },
    292   1.35  pgoyette 	{ { USB_VENDOR_BELKIN,		USB_PRODUCT_BELKIN_F5D5055 }, AX178 },
    293   1.35  pgoyette 	{ { USB_VENDOR_BILLIONTON,	USB_PRODUCT_BILLIONTON_USB2AR}, 0},
    294   1.76     skrll 	{ { USB_VENDOR_CISCOLINKSYS,	USB_PRODUCT_CISCOLINKSYS_USB200MV2}, AX772A },
    295    1.1  augustss 	{ { USB_VENDOR_COREGA,		USB_PRODUCT_COREGA_FETHER_USB2_TX }, 0},
    296    1.1  augustss 	{ { USB_VENDOR_DLINK,		USB_PRODUCT_DLINK_DUBE100}, 0 },
    297   1.35  pgoyette 	{ { USB_VENDOR_DLINK,		USB_PRODUCT_DLINK_DUBE100B1 }, AX772 },
    298   1.74     skrll 	{ { USB_VENDOR_DLINK2,		USB_PRODUCT_DLINK2_DUBE100B1 }, AX772 },
    299   1.76     skrll 	{ { USB_VENDOR_DLINK,		USB_PRODUCT_DLINK_DUBE100C1 }, AX772B },
    300   1.35  pgoyette 	{ { USB_VENDOR_GOODWAY,		USB_PRODUCT_GOODWAY_GWUSB2E}, 0 },
    301   1.35  pgoyette 	{ { USB_VENDOR_IODATA,		USB_PRODUCT_IODATA_ETGUS2 }, AX178 },
    302   1.35  pgoyette 	{ { USB_VENDOR_JVC,		USB_PRODUCT_JVC_MP_PRX1}, 0 },
    303   1.76     skrll 	{ { USB_VENDOR_LENOVO,		USB_PRODUCT_LENOVO_ETHERNET }, AX772B },
    304   1.97   msaitoh 	{ { USB_VENDOR_LINKSYS,		USB_PRODUCT_LINKSYS_HG20F9}, AX772B },
    305    1.1  augustss 	{ { USB_VENDOR_LINKSYS2,	USB_PRODUCT_LINKSYS2_USB200M}, 0 },
    306   1.35  pgoyette 	{ { USB_VENDOR_LINKSYS4,	USB_PRODUCT_LINKSYS4_USB1000 }, AX178 },
    307   1.35  pgoyette 	{ { USB_VENDOR_LOGITEC,		USB_PRODUCT_LOGITEC_LAN_GTJU2}, AX178 },
    308   1.35  pgoyette 	{ { USB_VENDOR_MELCO,		USB_PRODUCT_MELCO_LUAU2GT}, AX178 },
    309    1.2  augustss 	{ { USB_VENDOR_MELCO,		USB_PRODUCT_MELCO_LUAU2KTX}, 0 },
    310   1.35  pgoyette 	{ { USB_VENDOR_MSI,		USB_PRODUCT_MSI_AX88772A}, AX772 },
    311    1.1  augustss 	{ { USB_VENDOR_NETGEAR,		USB_PRODUCT_NETGEAR_FA120}, 0 },
    312   1.35  pgoyette 	{ { USB_VENDOR_OQO,		USB_PRODUCT_OQO_ETHER01PLUS }, AX772 },
    313   1.35  pgoyette 	{ { USB_VENDOR_PLANEX3,		USB_PRODUCT_PLANEX3_GU1000T }, AX178 },
    314   1.76     skrll 	{ { USB_VENDOR_SITECOM,		USB_PRODUCT_SITECOM_LN029}, 0 },
    315   1.76     skrll 	{ { USB_VENDOR_SITECOMEU,	USB_PRODUCT_SITECOMEU_LN028 }, AX178 },
    316   1.76     skrll 	{ { USB_VENDOR_SITECOMEU,	USB_PRODUCT_SITECOMEU_LN031 }, AX178 },
    317   1.35  pgoyette 	{ { USB_VENDOR_SYSTEMTALKS,	USB_PRODUCT_SYSTEMTALKS_SGCX2UL}, 0 },
    318    1.1  augustss };
    319    1.9  christos #define axe_lookup(v, p) ((const struct axe_type *)usb_lookup(axe_devs, v, p))
    320    1.1  augustss 
    321   1.76     skrll static const struct ax88772b_mfb ax88772b_mfb_table[] = {
    322   1.76     skrll 	{ 0x8000, 0x8001, 2048 },
    323   1.76     skrll 	{ 0x8100, 0x8147, 4096 },
    324   1.76     skrll 	{ 0x8200, 0x81EB, 6144 },
    325   1.76     skrll 	{ 0x8300, 0x83D7, 8192 },
    326   1.76     skrll 	{ 0x8400, 0x851E, 16384 },
    327   1.76     skrll 	{ 0x8500, 0x8666, 20480 },
    328   1.76     skrll 	{ 0x8600, 0x87AE, 24576 },
    329   1.76     skrll 	{ 0x8700, 0x8A3D, 32768 }
    330   1.76     skrll };
    331   1.76     skrll 
    332   1.35  pgoyette int	axe_match(device_t, cfdata_t, void *);
    333   1.35  pgoyette void	axe_attach(device_t, device_t, void *);
    334   1.35  pgoyette int	axe_detach(device_t, int);
    335   1.35  pgoyette int	axe_activate(device_t, devact_t);
    336   1.35  pgoyette 
    337   1.35  pgoyette CFATTACH_DECL_NEW(axe, sizeof(struct axe_softc),
    338   1.35  pgoyette 	axe_match, axe_attach, axe_detach, axe_activate);
    339   1.35  pgoyette 
    340   1.35  pgoyette static int	axe_tx_list_init(struct axe_softc *);
    341   1.35  pgoyette static int	axe_rx_list_init(struct axe_softc *);
    342   1.35  pgoyette static int	axe_encap(struct axe_softc *, struct mbuf *, int);
    343   1.71     skrll static void	axe_rxeof(struct usbd_xfer *, void *, usbd_status);
    344   1.71     skrll static void	axe_txeof(struct usbd_xfer *, void *, usbd_status);
    345   1.35  pgoyette static void	axe_tick(void *);
    346   1.35  pgoyette static void	axe_tick_task(void *);
    347   1.35  pgoyette static void	axe_start(struct ifnet *);
    348  1.100       mrg static void	axe_start_locked(struct ifnet *);
    349   1.35  pgoyette static int	axe_ioctl(struct ifnet *, u_long, void *);
    350   1.35  pgoyette static int	axe_init(struct ifnet *);
    351  1.100       mrg static int	axe_init_locked(struct ifnet *);
    352   1.35  pgoyette static void	axe_stop(struct ifnet *, int);
    353  1.100       mrg static void	axe_stop_locked(struct ifnet *, int);
    354   1.35  pgoyette static void	axe_watchdog(struct ifnet *);
    355  1.100       mrg static int	axe_miibus_readreg(device_t, int, int, uint16_t *);
    356   1.95   msaitoh static int	axe_miibus_readreg_locked(device_t, int, int, uint16_t *);
    357  1.100       mrg static int	axe_miibus_writereg(device_t, int, int, uint16_t);
    358   1.95   msaitoh static int	axe_miibus_writereg_locked(device_t, int, int, uint16_t);
    359   1.56      matt static void	axe_miibus_statchg(struct ifnet *);
    360   1.35  pgoyette static int	axe_cmd(struct axe_softc *, int, int, int, void *);
    361   1.71     skrll static void	axe_reset(struct axe_softc *);
    362   1.35  pgoyette 
    363   1.35  pgoyette static void	axe_setmulti(struct axe_softc *);
    364  1.100       mrg static void	axe_setmulti_locked(struct axe_softc *);
    365   1.71     skrll static void	axe_lock_mii(struct axe_softc *);
    366   1.71     skrll static void	axe_unlock_mii(struct axe_softc *);
    367   1.35  pgoyette 
    368   1.35  pgoyette static void	axe_ax88178_init(struct axe_softc *);
    369   1.35  pgoyette static void	axe_ax88772_init(struct axe_softc *);
    370   1.82     ozaki static void	axe_ax88772a_init(struct axe_softc *);
    371   1.82     ozaki static void	axe_ax88772b_init(struct axe_softc *);
    372    1.1  augustss 
    373    1.1  augustss /* Get exclusive access to the MII registers */
    374   1.35  pgoyette static void
    375    1.1  augustss axe_lock_mii(struct axe_softc *sc)
    376    1.1  augustss {
    377   1.38   tsutsui 
    378  1.100       mrg 	mutex_enter(&sc->axe_lock);
    379  1.100       mrg 	sc->axe_refcnt++;
    380  1.100       mrg 	mutex_exit(&sc->axe_lock);
    381  1.100       mrg 
    382  1.100       mrg 	mutex_enter(&sc->axe_mii_lock);
    383  1.100       mrg }
    384  1.100       mrg 
    385  1.100       mrg static void
    386  1.100       mrg axe_lock_mii_sc_locked(struct axe_softc *sc)
    387  1.100       mrg {
    388  1.100       mrg 	KASSERT(mutex_owned(&sc->axe_lock));
    389  1.100       mrg 
    390    1.1  augustss 	sc->axe_refcnt++;
    391   1.21        ad 	mutex_enter(&sc->axe_mii_lock);
    392    1.1  augustss }
    393    1.1  augustss 
    394   1.35  pgoyette static void
    395    1.1  augustss axe_unlock_mii(struct axe_softc *sc)
    396    1.1  augustss {
    397   1.38   tsutsui 
    398   1.21        ad 	mutex_exit(&sc->axe_mii_lock);
    399  1.100       mrg 	mutex_enter(&sc->axe_lock);
    400    1.1  augustss 	if (--sc->axe_refcnt < 0)
    401  1.100       mrg 		cv_broadcast(&sc->axe_detachcv);
    402  1.100       mrg 	mutex_exit(&sc->axe_lock);
    403  1.100       mrg }
    404  1.100       mrg 
    405  1.100       mrg static void
    406  1.100       mrg axe_unlock_mii_sc_locked(struct axe_softc *sc)
    407  1.100       mrg {
    408  1.100       mrg 	KASSERT(mutex_owned(&sc->axe_lock));
    409  1.100       mrg 
    410  1.100       mrg 	mutex_exit(&sc->axe_mii_lock);
    411  1.100       mrg 	if (--sc->axe_refcnt < 0)
    412  1.100       mrg 		cv_broadcast(&sc->axe_detachcv);
    413    1.1  augustss }
    414    1.1  augustss 
    415   1.35  pgoyette static int
    416    1.1  augustss axe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf)
    417    1.1  augustss {
    418   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
    419   1.38   tsutsui 	usb_device_request_t req;
    420   1.38   tsutsui 	usbd_status err;
    421    1.1  augustss 
    422   1.21        ad 	KASSERT(mutex_owned(&sc->axe_mii_lock));
    423   1.21        ad 
    424    1.1  augustss 	if (sc->axe_dying)
    425   1.86  christos 		return -1;
    426    1.1  augustss 
    427   1.83  pgoyette 	DPRINTFN(20, "cmd %#jx index %#jx val %#jx", cmd, index, val, 0);
    428   1.76     skrll 
    429    1.1  augustss 	if (AXE_CMD_DIR(cmd))
    430    1.1  augustss 		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    431    1.1  augustss 	else
    432    1.1  augustss 		req.bmRequestType = UT_READ_VENDOR_DEVICE;
    433    1.1  augustss 	req.bRequest = AXE_CMD_CMD(cmd);
    434    1.1  augustss 	USETW(req.wValue, val);
    435    1.1  augustss 	USETW(req.wIndex, index);
    436    1.1  augustss 	USETW(req.wLength, AXE_CMD_LEN(cmd));
    437    1.1  augustss 
    438    1.1  augustss 	err = usbd_do_request(sc->axe_udev, &req, buf);
    439    1.1  augustss 
    440   1.35  pgoyette 	if (err) {
    441   1.83  pgoyette 		DPRINTF("cmd %jd err %jd", cmd, err, 0, 0);
    442   1.35  pgoyette 		return -1;
    443   1.35  pgoyette 	}
    444   1.35  pgoyette 	return 0;
    445    1.1  augustss }
    446    1.1  augustss 
    447   1.35  pgoyette static int
    448   1.95   msaitoh axe_miibus_readreg_locked(device_t dev, int phy, int reg, uint16_t *val)
    449    1.1  augustss {
    450   1.77     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
    451   1.28    dyoung 	struct axe_softc *sc = device_private(dev);
    452   1.38   tsutsui 	usbd_status err;
    453   1.95   msaitoh 	uint16_t data;
    454    1.1  augustss 
    455  1.100       mrg 	mutex_enter(&sc->axe_lock);
    456  1.100       mrg 	if (sc->axe_dying || sc->axe_phyno != phy) {
    457  1.100       mrg 		mutex_exit(&sc->axe_lock);
    458  1.100       mrg 		return -1;
    459  1.100       mrg 	}
    460  1.100       mrg 	mutex_exit(&sc->axe_lock);
    461  1.100       mrg 
    462   1.83  pgoyette 	DPRINTFN(30, "phy 0x%jx reg 0x%jx\n", phy, reg, 0, 0);
    463   1.76     skrll 
    464   1.66       roy 	axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
    465   1.76     skrll 
    466   1.95   msaitoh 	err = axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, &data);
    467   1.66       roy 	axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
    468  1.100       mrg 
    469   1.66       roy 	if (err) {
    470   1.66       roy 		aprint_error_dev(sc->axe_dev, "read PHY failed\n");
    471   1.95   msaitoh 		return err;
    472   1.66       roy 	}
    473   1.66       roy 
    474   1.95   msaitoh 	*val = le16toh(data);
    475   1.76     skrll 	if (AXE_IS_772(sc) && reg == MII_BMSR) {
    476   1.66       roy 		/*
    477   1.76     skrll 		 * BMSR of AX88772 indicates that it supports extended
    478   1.66       roy 		 * capability but the extended status register is
    479   1.76     skrll 		 * reserved for embedded ethernet PHY. So clear the
    480   1.66       roy 		 * extended capability bit of BMSR.
    481   1.66       roy 		 */
    482   1.95   msaitoh 		*val &= ~BMSR_EXTCAP;
    483    1.1  augustss 	}
    484    1.1  augustss 
    485   1.95   msaitoh 	DPRINTFN(30, "phy 0x%jx reg 0x%jx val %#jx", phy, reg, *val, 0);
    486   1.66       roy 
    487   1.95   msaitoh 	return 0;
    488   1.66       roy }
    489   1.66       roy 
    490   1.66       roy static int
    491   1.95   msaitoh axe_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val)
    492   1.66       roy {
    493   1.66       roy 	struct axe_softc *sc = device_private(dev);
    494   1.95   msaitoh 	int rv;
    495   1.66       roy 
    496  1.100       mrg 	mutex_enter(&sc->axe_lock);
    497  1.100       mrg 	if (sc->axe_dying || sc->axe_phyno != phy) {
    498  1.100       mrg 		mutex_exit(&sc->axe_lock);
    499   1.95   msaitoh 		return -1;
    500  1.100       mrg 	}
    501  1.100       mrg 	mutex_exit(&sc->axe_lock);
    502    1.1  augustss 
    503   1.66       roy 	axe_lock_mii(sc);
    504   1.95   msaitoh 	rv = axe_miibus_readreg_locked(dev, phy, reg, val);
    505   1.66       roy 	axe_unlock_mii(sc);
    506    1.1  augustss 
    507   1.95   msaitoh 	return rv;
    508    1.1  augustss }
    509    1.1  augustss 
    510   1.95   msaitoh static int
    511   1.95   msaitoh axe_miibus_writereg_locked(device_t dev, int phy, int reg, uint16_t aval)
    512    1.1  augustss {
    513   1.38   tsutsui 	struct axe_softc *sc = device_private(dev);
    514   1.38   tsutsui 	usbd_status err;
    515   1.38   tsutsui 	uint16_t val;
    516    1.1  augustss 
    517   1.66       roy 	val = htole16(aval);
    518    1.1  augustss 
    519    1.1  augustss 	axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
    520   1.86  christos 	err = axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, &val);
    521    1.1  augustss 	axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
    522    1.1  augustss 
    523    1.1  augustss 	if (err) {
    524   1.25      cube 		aprint_error_dev(sc->axe_dev, "write PHY failed\n");
    525   1.95   msaitoh 		return err;
    526    1.1  augustss 	}
    527   1.95   msaitoh 
    528   1.95   msaitoh 	return 0;
    529    1.1  augustss }
    530    1.1  augustss 
    531   1.95   msaitoh static int
    532   1.95   msaitoh axe_miibus_writereg(device_t dev, int phy, int reg, uint16_t aval)
    533   1.66       roy {
    534   1.66       roy 	struct axe_softc *sc = device_private(dev);
    535   1.95   msaitoh 	int rv;
    536   1.66       roy 
    537  1.100       mrg 	mutex_enter(&sc->axe_lock);
    538  1.100       mrg 	if (sc->axe_dying || sc->axe_phyno != phy) {
    539  1.100       mrg 		mutex_exit(&sc->axe_lock);
    540   1.95   msaitoh 		return -1;
    541  1.100       mrg 	}
    542  1.100       mrg 	mutex_exit(&sc->axe_lock);
    543   1.66       roy 
    544   1.66       roy 	axe_lock_mii(sc);
    545   1.95   msaitoh 	rv = axe_miibus_writereg_locked(dev, phy, reg, aval);
    546   1.66       roy 	axe_unlock_mii(sc);
    547   1.95   msaitoh 
    548   1.95   msaitoh 	return rv;
    549   1.66       roy }
    550   1.66       roy 
    551   1.66       roy static void
    552   1.56      matt axe_miibus_statchg(struct ifnet *ifp)
    553    1.1  augustss {
    554   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
    555   1.76     skrll 
    556  1.100       mrg 	struct axe_softc * const sc = ifp->if_softc;
    557   1.38   tsutsui 	struct mii_data *mii = &sc->axe_mii;
    558    1.5  augustss 	int val, err;
    559    1.5  augustss 
    560  1.100       mrg 	if (sc->axe_dying)
    561  1.100       mrg 		return;
    562  1.100       mrg 
    563   1.76     skrll 	val = 0;
    564   1.76     skrll 	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
    565   1.76     skrll 		val |= AXE_MEDIA_FULL_DUPLEX;
    566   1.76     skrll 		if (AXE_IS_178_FAMILY(sc)) {
    567   1.76     skrll 			if ((IFM_OPTIONS(mii->mii_media_active) &
    568   1.76     skrll 			    IFM_ETH_TXPAUSE) != 0)
    569   1.76     skrll 				val |= AXE_178_MEDIA_TXFLOW_CONTROL_EN;
    570   1.76     skrll 			if ((IFM_OPTIONS(mii->mii_media_active) &
    571   1.76     skrll 			    IFM_ETH_RXPAUSE) != 0)
    572   1.76     skrll 				val |= AXE_178_MEDIA_RXFLOW_CONTROL_EN;
    573   1.76     skrll 		}
    574   1.76     skrll 	}
    575   1.76     skrll 	if (AXE_IS_178_FAMILY(sc)) {
    576   1.76     skrll 		val |= AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC;
    577   1.66       roy 		if (sc->axe_flags & AX178)
    578   1.66       roy 			val |= AXE_178_MEDIA_ENCK;
    579   1.35  pgoyette 		switch (IFM_SUBTYPE(mii->mii_media_active)) {
    580   1.38   tsutsui 		case IFM_1000_T:
    581   1.35  pgoyette 			val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK;
    582   1.35  pgoyette 			break;
    583   1.35  pgoyette 		case IFM_100_TX:
    584   1.35  pgoyette 			val |= AXE_178_MEDIA_100TX;
    585   1.35  pgoyette 			break;
    586   1.35  pgoyette 		case IFM_10_T:
    587   1.35  pgoyette 			/* doesn't need to be handled */
    588   1.35  pgoyette 			break;
    589   1.35  pgoyette 		}
    590   1.35  pgoyette 	}
    591   1.35  pgoyette 
    592   1.83  pgoyette 	DPRINTF("val=0x%jx", val, 0, 0, 0);
    593   1.21        ad 	axe_lock_mii(sc);
    594    1.5  augustss 	err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL);
    595   1.21        ad 	axe_unlock_mii(sc);
    596    1.5  augustss 	if (err) {
    597   1.25      cube 		aprint_error_dev(sc->axe_dev, "media change failed\n");
    598    1.5  augustss 		return;
    599    1.5  augustss 	}
    600    1.1  augustss }
    601    1.1  augustss 
    602   1.35  pgoyette static void
    603  1.100       mrg axe_setmulti_locked(struct axe_softc *sc)
    604    1.1  augustss {
    605   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
    606   1.98   msaitoh 	struct ethercom *ec = &sc->axe_ec;
    607   1.38   tsutsui 	struct ifnet *ifp = &sc->sc_if;
    608   1.38   tsutsui 	struct ether_multi *enm;
    609   1.38   tsutsui 	struct ether_multistep step;
    610   1.38   tsutsui 	uint32_t h = 0;
    611   1.38   tsutsui 	uint16_t rxmode;
    612   1.38   tsutsui 	uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    613    1.1  augustss 
    614  1.100       mrg 	KASSERT(mutex_owned(&sc->axe_mii_lock));
    615  1.100       mrg 
    616    1.1  augustss 	if (sc->axe_dying)
    617    1.1  augustss 		return;
    618    1.1  augustss 
    619   1.86  christos 	if (axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, &rxmode)) {
    620   1.86  christos 		aprint_error_dev(sc->axe_dev, "can't read rxmode");
    621   1.86  christos 		return;
    622   1.86  christos 	}
    623   1.10      tron 	rxmode = le16toh(rxmode);
    624    1.1  augustss 
    625   1.76     skrll 	rxmode &=
    626   1.76     skrll 	    ~(AXE_RXCMD_ALLMULTI | AXE_RXCMD_PROMISC |
    627   1.76     skrll 	    AXE_RXCMD_BROADCAST | AXE_RXCMD_MULTICAST);
    628   1.76     skrll 
    629   1.76     skrll 	rxmode |=
    630   1.76     skrll 	    (ifp->if_flags & IFF_BROADCAST) ? AXE_RXCMD_BROADCAST : 0;
    631   1.76     skrll 
    632   1.76     skrll 	if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
    633   1.76     skrll 		if (ifp->if_flags & IFF_PROMISC)
    634   1.76     skrll 			rxmode |= AXE_RXCMD_PROMISC;
    635   1.35  pgoyette 		goto allmulti;
    636   1.35  pgoyette 	}
    637    1.1  augustss 
    638   1.35  pgoyette 	/* Now program new ones */
    639   1.98   msaitoh 	ETHER_LOCK(ec);
    640   1.98   msaitoh 	ETHER_FIRST_MULTI(step, ec, enm);
    641    1.1  augustss 	while (enm != NULL) {
    642    1.1  augustss 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
    643   1.98   msaitoh 		    ETHER_ADDR_LEN) != 0) {
    644   1.98   msaitoh 			ETHER_UNLOCK(ec);
    645    1.1  augustss 			goto allmulti;
    646   1.98   msaitoh 		}
    647    1.1  augustss 
    648    1.1  augustss 		h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
    649   1.35  pgoyette 		hashtbl[h >> 3] |= 1U << (h & 7);
    650    1.1  augustss 		ETHER_NEXT_MULTI(step, enm);
    651    1.1  augustss 	}
    652   1.98   msaitoh 	ETHER_UNLOCK(ec);
    653    1.1  augustss 	ifp->if_flags &= ~IFF_ALLMULTI;
    654   1.76     skrll 	rxmode |= AXE_RXCMD_MULTICAST;
    655   1.76     skrll 
    656   1.86  christos 	axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, hashtbl);
    657    1.1  augustss 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
    658    1.1  augustss 	return;
    659   1.35  pgoyette 
    660   1.35  pgoyette  allmulti:
    661   1.35  pgoyette 	ifp->if_flags |= IFF_ALLMULTI;
    662   1.35  pgoyette 	rxmode |= AXE_RXCMD_ALLMULTI;
    663   1.35  pgoyette 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
    664  1.100       mrg }
    665  1.100       mrg 
    666  1.100       mrg static void
    667  1.100       mrg axe_setmulti(struct axe_softc *sc)
    668  1.100       mrg {
    669  1.100       mrg 	axe_lock_mii(sc);
    670  1.100       mrg 	axe_setmulti_locked(sc);
    671   1.35  pgoyette 	axe_unlock_mii(sc);
    672    1.1  augustss }
    673    1.1  augustss 
    674   1.88  christos static void
    675   1.88  christos axe_ax_init(struct axe_softc *sc)
    676   1.88  christos {
    677   1.89  christos 	int cmd = AXE_178_CMD_READ_NODEID;
    678   1.89  christos 
    679   1.88  christos 	if (sc->axe_flags & AX178) {
    680   1.88  christos 		axe_ax88178_init(sc);
    681   1.88  christos 	} else if (sc->axe_flags & AX772) {
    682   1.88  christos 		axe_ax88772_init(sc);
    683   1.88  christos 	} else if (sc->axe_flags & AX772A) {
    684   1.88  christos 		axe_ax88772a_init(sc);
    685   1.88  christos 	} else if (sc->axe_flags & AX772B) {
    686   1.88  christos 		axe_ax88772b_init(sc);
    687   1.89  christos 		return;
    688   1.89  christos 	} else {
    689   1.89  christos 		cmd = AXE_172_CMD_READ_NODEID;
    690   1.89  christos 	}
    691   1.89  christos 
    692   1.89  christos 	if (axe_cmd(sc, cmd, 0, 0, sc->axe_enaddr)) {
    693   1.89  christos 		aprint_error_dev(sc->axe_dev,
    694   1.89  christos 		    "failed to read ethernet address\n");
    695   1.88  christos 	}
    696   1.88  christos }
    697   1.88  christos 
    698   1.76     skrll 
    699   1.35  pgoyette static void
    700    1.1  augustss axe_reset(struct axe_softc *sc)
    701    1.1  augustss {
    702   1.38   tsutsui 
    703    1.1  augustss 	if (sc->axe_dying)
    704    1.1  augustss 		return;
    705   1.76     skrll 
    706   1.76     skrll 	/*
    707   1.76     skrll 	 * softnet_lock can be taken when NET_MPAFE is not defined when calling
    708  1.100       mrg 	 * if_addr_init -> if_init.  This doesn't mix well with the
    709   1.76     skrll 	 * usbd_delay_ms calls in the init routines as things like nd6_slowtimo
    710   1.76     skrll 	 * can fire during the wait and attempt to take softnet_lock and then
    711   1.76     skrll 	 * block the softclk thread meaing the wait never ends.
    712   1.76     skrll 	 */
    713   1.76     skrll #ifndef NET_MPSAFE
    714    1.1  augustss 	/* XXX What to reset? */
    715    1.1  augustss 
    716    1.1  augustss 	/* Wait a little while for the chip to get its brains in order. */
    717    1.1  augustss 	DELAY(1000);
    718   1.76     skrll #else
    719   1.76     skrll 	axe_lock_mii(sc);
    720   1.76     skrll 
    721   1.88  christos 	axe_ax_init(sc);
    722   1.88  christos 
    723   1.76     skrll 	axe_unlock_mii(sc);
    724   1.76     skrll #endif
    725    1.1  augustss }
    726    1.1  augustss 
    727   1.66       roy static int
    728   1.66       roy axe_get_phyno(struct axe_softc *sc, int sel)
    729   1.66       roy {
    730   1.66       roy 	int phyno;
    731   1.66       roy 
    732   1.66       roy 	switch (AXE_PHY_TYPE(sc->axe_phyaddrs[sel])) {
    733   1.66       roy 	case PHY_TYPE_100_HOME:
    734   1.66       roy 		/* FALLTHROUGH */
    735   1.66       roy 	case PHY_TYPE_GIG:
    736   1.66       roy 		phyno = AXE_PHY_NO(sc->axe_phyaddrs[sel]);
    737   1.66       roy 		break;
    738   1.66       roy 	case PHY_TYPE_SPECIAL:
    739   1.66       roy 		/* FALLTHROUGH */
    740   1.66       roy 	case PHY_TYPE_RSVD:
    741   1.66       roy 		/* FALLTHROUGH */
    742   1.66       roy 	case PHY_TYPE_NON_SUP:
    743   1.66       roy 		/* FALLTHROUGH */
    744   1.66       roy 	default:
    745   1.66       roy 		phyno = -1;
    746   1.66       roy 		break;
    747   1.66       roy 	}
    748   1.66       roy 
    749   1.66       roy 	return phyno;
    750   1.66       roy }
    751   1.66       roy 
    752   1.66       roy #define	AXE_GPIO_WRITE(x, y)	do {				\
    753   1.66       roy 	axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, (x), NULL);		\
    754   1.66       roy 	usbd_delay_ms(sc->axe_udev, hztoms(y));			\
    755   1.66       roy } while (0)
    756   1.66       roy 
    757   1.35  pgoyette static void
    758   1.35  pgoyette axe_ax88178_init(struct axe_softc *sc)
    759   1.35  pgoyette {
    760   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
    761   1.66       roy 	int gpio0, ledmode, phymode;
    762   1.66       roy 	uint16_t eeprom, val;
    763   1.35  pgoyette 
    764   1.35  pgoyette 	axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL);
    765   1.35  pgoyette 	/* XXX magic */
    766   1.86  christos 	if (axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom) != 0)
    767   1.86  christos 		eeprom = 0xffff;
    768   1.35  pgoyette 	axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE, 0, 0, NULL);
    769   1.35  pgoyette 
    770   1.35  pgoyette 	eeprom = le16toh(eeprom);
    771   1.35  pgoyette 
    772   1.83  pgoyette 	DPRINTF("EEPROM is 0x%jx", eeprom, 0, 0, 0);
    773   1.35  pgoyette 
    774   1.35  pgoyette 	/* if EEPROM is invalid we have to use to GPIO0 */
    775   1.35  pgoyette 	if (eeprom == 0xffff) {
    776   1.66       roy 		phymode = AXE_PHY_MODE_MARVELL;
    777   1.35  pgoyette 		gpio0 = 1;
    778   1.66       roy 		ledmode = 0;
    779   1.35  pgoyette 	} else {
    780   1.66       roy 		phymode = eeprom & 0x7f;
    781   1.35  pgoyette 		gpio0 = (eeprom & 0x80) ? 0 : 1;
    782   1.66       roy 		ledmode = eeprom >> 8;
    783   1.35  pgoyette 	}
    784   1.35  pgoyette 
    785   1.83  pgoyette 	DPRINTF("use gpio0: %jd, phymode %jd", gpio0, phymode, 0, 0);
    786   1.35  pgoyette 
    787   1.66       roy 	/* Program GPIOs depending on PHY hardware. */
    788   1.66       roy 	switch (phymode) {
    789   1.66       roy 	case AXE_PHY_MODE_MARVELL:
    790   1.66       roy 		if (gpio0 == 1) {
    791   1.66       roy 			AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO0_EN,
    792   1.66       roy 			    hz / 32);
    793   1.66       roy 			AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2 | AXE_GPIO2_EN,
    794   1.66       roy 			    hz / 32);
    795   1.66       roy 			AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2_EN, hz / 4);
    796   1.66       roy 			AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2 | AXE_GPIO2_EN,
    797   1.66       roy 			    hz / 32);
    798   1.66       roy 		} else {
    799   1.66       roy 			AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO1 |
    800   1.66       roy 			    AXE_GPIO1_EN, hz / 3);
    801   1.66       roy 			if (ledmode == 1) {
    802   1.66       roy 				AXE_GPIO_WRITE(AXE_GPIO1_EN, hz / 3);
    803   1.66       roy 				AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN,
    804   1.66       roy 				    hz / 3);
    805   1.66       roy 			} else {
    806   1.66       roy 				AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN |
    807   1.66       roy 				    AXE_GPIO2 | AXE_GPIO2_EN, hz / 32);
    808   1.66       roy 				AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN |
    809   1.66       roy 				    AXE_GPIO2_EN, hz / 4);
    810   1.66       roy 				AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN |
    811   1.66       roy 				    AXE_GPIO2 | AXE_GPIO2_EN, hz / 32);
    812   1.66       roy 			}
    813   1.66       roy 		}
    814   1.66       roy 		break;
    815   1.66       roy 	case AXE_PHY_MODE_CICADA:
    816   1.66       roy 	case AXE_PHY_MODE_CICADA_V2:
    817   1.66       roy 	case AXE_PHY_MODE_CICADA_V2_ASIX:
    818   1.66       roy 		if (gpio0 == 1)
    819   1.66       roy 			AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO0 |
    820   1.66       roy 			    AXE_GPIO0_EN, hz / 32);
    821   1.66       roy 		else
    822   1.66       roy 			AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO1 |
    823   1.66       roy 			    AXE_GPIO1_EN, hz / 32);
    824   1.66       roy 		break;
    825   1.66       roy 	case AXE_PHY_MODE_AGERE:
    826   1.66       roy 		AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO1 |
    827   1.66       roy 		    AXE_GPIO1_EN, hz / 32);
    828   1.66       roy 		AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN | AXE_GPIO2 |
    829   1.66       roy 		    AXE_GPIO2_EN, hz / 32);
    830   1.66       roy 		AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN | AXE_GPIO2_EN, hz / 4);
    831   1.66       roy 		AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN | AXE_GPIO2 |
    832   1.66       roy 		    AXE_GPIO2_EN, hz / 32);
    833   1.66       roy 		break;
    834   1.66       roy 	case AXE_PHY_MODE_REALTEK_8211CL:
    835   1.66       roy 	case AXE_PHY_MODE_REALTEK_8211BN:
    836   1.66       roy 	case AXE_PHY_MODE_REALTEK_8251CL:
    837   1.66       roy 		val = gpio0 == 1 ? AXE_GPIO0 | AXE_GPIO0_EN :
    838   1.66       roy 		    AXE_GPIO1 | AXE_GPIO1_EN;
    839   1.66       roy 		AXE_GPIO_WRITE(val, hz / 32);
    840   1.66       roy 		AXE_GPIO_WRITE(val | AXE_GPIO2 | AXE_GPIO2_EN, hz / 32);
    841   1.66       roy 		AXE_GPIO_WRITE(val | AXE_GPIO2_EN, hz / 4);
    842   1.66       roy 		AXE_GPIO_WRITE(val | AXE_GPIO2 | AXE_GPIO2_EN, hz / 32);
    843   1.66       roy 		if (phymode == AXE_PHY_MODE_REALTEK_8211CL) {
    844   1.66       roy 			axe_miibus_writereg_locked(sc->axe_dev,
    845   1.66       roy 			    sc->axe_phyno, 0x1F, 0x0005);
    846   1.66       roy 			axe_miibus_writereg_locked(sc->axe_dev,
    847   1.66       roy 			    sc->axe_phyno, 0x0C, 0x0000);
    848   1.95   msaitoh 			axe_miibus_readreg_locked(sc->axe_dev,
    849   1.95   msaitoh 			    sc->axe_phyno, 0x0001, &val);
    850   1.66       roy 			axe_miibus_writereg_locked(sc->axe_dev,
    851   1.66       roy 			    sc->axe_phyno, 0x01, val | 0x0080);
    852   1.66       roy 			axe_miibus_writereg_locked(sc->axe_dev,
    853   1.66       roy 			    sc->axe_phyno, 0x1F, 0x0000);
    854   1.66       roy 		}
    855   1.66       roy 		break;
    856   1.66       roy 	default:
    857   1.66       roy 		/* Unknown PHY model or no need to program GPIOs. */
    858   1.66       roy 		break;
    859   1.35  pgoyette 	}
    860   1.35  pgoyette 
    861   1.35  pgoyette 	/* soft reset */
    862   1.35  pgoyette 	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL);
    863   1.35  pgoyette 	usbd_delay_ms(sc->axe_udev, 150);
    864   1.35  pgoyette 	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
    865   1.35  pgoyette 	    AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL);
    866   1.35  pgoyette 	usbd_delay_ms(sc->axe_udev, 150);
    867   1.76     skrll 	/* Enable MII/GMII/RGMII interface to work with external PHY. */
    868   1.35  pgoyette 	axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0, NULL);
    869   1.35  pgoyette 	usbd_delay_ms(sc->axe_udev, 10);
    870   1.35  pgoyette 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
    871   1.35  pgoyette }
    872   1.35  pgoyette 
    873   1.35  pgoyette static void
    874   1.35  pgoyette axe_ax88772_init(struct axe_softc *sc)
    875   1.35  pgoyette {
    876   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
    877   1.35  pgoyette 
    878   1.35  pgoyette 	axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL);
    879   1.35  pgoyette 	usbd_delay_ms(sc->axe_udev, 40);
    880   1.35  pgoyette 
    881   1.66       roy 	if (sc->axe_phyno == AXE_772_PHY_NO_EPHY) {
    882   1.35  pgoyette 		/* ask for the embedded PHY */
    883   1.76     skrll 		axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0,
    884   1.76     skrll 		    AXE_SW_PHY_SELECT_EMBEDDED, NULL);
    885   1.35  pgoyette 		usbd_delay_ms(sc->axe_udev, 10);
    886   1.35  pgoyette 
    887   1.35  pgoyette 		/* power down and reset state, pin reset state */
    888   1.35  pgoyette 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL);
    889   1.35  pgoyette 		usbd_delay_ms(sc->axe_udev, 60);
    890   1.35  pgoyette 
    891   1.35  pgoyette 		/* power down/reset state, pin operating state */
    892   1.35  pgoyette 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
    893   1.35  pgoyette 		    AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL);
    894   1.35  pgoyette 		usbd_delay_ms(sc->axe_udev, 150);
    895   1.35  pgoyette 
    896   1.35  pgoyette 		/* power up, reset */
    897   1.35  pgoyette 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_PRL, NULL);
    898   1.35  pgoyette 
    899   1.35  pgoyette 		/* power up, operating */
    900   1.35  pgoyette 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
    901   1.35  pgoyette 		    AXE_SW_RESET_IPRL | AXE_SW_RESET_PRL, NULL);
    902   1.35  pgoyette 	} else {
    903   1.35  pgoyette 		/* ask for external PHY */
    904   1.76     skrll 		axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, AXE_SW_PHY_SELECT_EXT,
    905   1.76     skrll 		    NULL);
    906   1.35  pgoyette 		usbd_delay_ms(sc->axe_udev, 10);
    907   1.35  pgoyette 
    908   1.35  pgoyette 		/* power down internal PHY */
    909   1.35  pgoyette 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
    910   1.35  pgoyette 		    AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL);
    911   1.35  pgoyette 	}
    912   1.35  pgoyette 
    913   1.35  pgoyette 	usbd_delay_ms(sc->axe_udev, 150);
    914   1.35  pgoyette 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
    915   1.35  pgoyette }
    916   1.35  pgoyette 
    917   1.76     skrll static void
    918   1.76     skrll axe_ax88772_phywake(struct axe_softc *sc)
    919   1.76     skrll {
    920   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
    921   1.76     skrll 
    922   1.76     skrll 	if (sc->axe_phyno == AXE_772_PHY_NO_EPHY) {
    923   1.76     skrll 		/* Manually select internal(embedded) PHY - MAC mode. */
    924   1.76     skrll 		axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0,
    925   1.86  christos 		    AXE_SW_PHY_SELECT_EMBEDDED, NULL);
    926   1.76     skrll 		usbd_delay_ms(sc->axe_udev, hztoms(hz / 32));
    927   1.76     skrll 	} else {
    928   1.76     skrll 		/*
    929   1.76     skrll 		 * Manually select external PHY - MAC mode.
    930   1.76     skrll 		 * Reverse MII/RMII is for AX88772A PHY mode.
    931   1.76     skrll 		 */
    932   1.76     skrll 		axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, AXE_SW_PHY_SELECT_SS_ENB |
    933   1.76     skrll 		    AXE_SW_PHY_SELECT_EXT | AXE_SW_PHY_SELECT_SS_MII, NULL);
    934   1.76     skrll 		usbd_delay_ms(sc->axe_udev, hztoms(hz / 32));
    935   1.76     skrll 	}
    936   1.76     skrll 
    937   1.76     skrll 	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPPD |
    938   1.76     skrll 	    AXE_SW_RESET_IPRL, NULL);
    939   1.76     skrll 
    940   1.76     skrll 	/* T1 = min 500ns everywhere */
    941   1.76     skrll 	usbd_delay_ms(sc->axe_udev, 150);
    942   1.76     skrll 
    943   1.76     skrll 	/* Take PHY out of power down. */
    944   1.76     skrll 	if (sc->axe_phyno == AXE_772_PHY_NO_EPHY) {
    945   1.76     skrll 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPRL, NULL);
    946   1.76     skrll 	} else {
    947   1.76     skrll 		axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_PRTE, NULL);
    948   1.76     skrll 	}
    949   1.76     skrll 
    950   1.76     skrll 	/* 772 T2 is 60ms. 772A T2 is 160ms, 772B T2 is 600ms */
    951   1.76     skrll 	usbd_delay_ms(sc->axe_udev, 600);
    952   1.76     skrll 
    953   1.76     skrll 	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL);
    954   1.76     skrll 
    955   1.76     skrll 	/* T3 = 500ns everywhere */
    956   1.76     skrll 	usbd_delay_ms(sc->axe_udev, hztoms(hz / 32));
    957   1.76     skrll 	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPRL, NULL);
    958   1.76     skrll 	usbd_delay_ms(sc->axe_udev, hztoms(hz / 32));
    959   1.76     skrll }
    960   1.76     skrll 
    961   1.76     skrll static void
    962   1.76     skrll axe_ax88772a_init(struct axe_softc *sc)
    963   1.76     skrll {
    964   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
    965   1.76     skrll 
    966   1.76     skrll 	/* Reload EEPROM. */
    967   1.76     skrll 	AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM, hz / 32);
    968   1.76     skrll 	axe_ax88772_phywake(sc);
    969   1.76     skrll 	/* Stop MAC. */
    970   1.76     skrll 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
    971   1.76     skrll }
    972   1.76     skrll 
    973   1.76     skrll static void
    974   1.76     skrll axe_ax88772b_init(struct axe_softc *sc)
    975   1.76     skrll {
    976   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
    977   1.76     skrll 	uint16_t eeprom;
    978   1.76     skrll 	int i;
    979   1.76     skrll 
    980   1.76     skrll 	/* Reload EEPROM. */
    981   1.76     skrll 	AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM , hz / 32);
    982   1.76     skrll 
    983   1.76     skrll 	/*
    984   1.76     skrll 	 * Save PHY power saving configuration(high byte) and
    985   1.76     skrll 	 * clear EEPROM checksum value(low byte).
    986   1.76     skrll 	 */
    987   1.86  christos 	if (axe_cmd(sc, AXE_CMD_SROM_READ, 0, AXE_EEPROM_772B_PHY_PWRCFG,
    988   1.86  christos 	    &eeprom)) {
    989   1.86  christos 		aprint_error_dev(sc->axe_dev, "failed to read eeprom\n");
    990   1.86  christos 		return;
    991   1.86  christos 	}
    992   1.86  christos 
    993   1.76     skrll 	sc->sc_pwrcfg = le16toh(eeprom) & 0xFF00;
    994   1.76     skrll 
    995   1.76     skrll 	/*
    996   1.76     skrll 	 * Auto-loaded default station address from internal ROM is
    997   1.76     skrll 	 * 00:00:00:00:00:00 such that an explicit access to EEPROM
    998   1.76     skrll 	 * is required to get real station address.
    999   1.76     skrll 	 */
   1000   1.76     skrll 	uint8_t *eaddr = sc->axe_enaddr;
   1001   1.76     skrll 	for (i = 0; i < ETHER_ADDR_LEN / 2; i++) {
   1002   1.86  christos 		if (axe_cmd(sc, AXE_CMD_SROM_READ, 0,
   1003   1.86  christos 		    AXE_EEPROM_772B_NODE_ID + i, &eeprom)) {
   1004   1.86  christos 			aprint_error_dev(sc->axe_dev,
   1005   1.86  christos 			    "failed to read eeprom\n");
   1006   1.86  christos 		    eeprom = 0;
   1007   1.86  christos 		}
   1008   1.76     skrll 		eeprom = le16toh(eeprom);
   1009   1.76     skrll 		*eaddr++ = (uint8_t)(eeprom & 0xFF);
   1010   1.76     skrll 		*eaddr++ = (uint8_t)((eeprom >> 8) & 0xFF);
   1011   1.76     skrll 	}
   1012   1.76     skrll 	/* Wakeup PHY. */
   1013   1.76     skrll 	axe_ax88772_phywake(sc);
   1014   1.76     skrll 	/* Stop MAC. */
   1015   1.76     skrll 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
   1016   1.76     skrll }
   1017   1.76     skrll 
   1018   1.76     skrll #undef	AXE_GPIO_WRITE
   1019   1.76     skrll 
   1020    1.1  augustss /*
   1021    1.1  augustss  * Probe for a AX88172 chip.
   1022    1.1  augustss  */
   1023   1.27    dyoung int
   1024   1.27    dyoung axe_match(device_t parent, cfdata_t match, void *aux)
   1025    1.1  augustss {
   1026   1.27    dyoung 	struct usb_attach_arg *uaa = aux;
   1027    1.1  augustss 
   1028   1.71     skrll 	return axe_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ?
   1029   1.38   tsutsui 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
   1030    1.1  augustss }
   1031    1.1  augustss 
   1032    1.1  augustss /*
   1033    1.1  augustss  * Attach the interface. Allocate softc structures, do ifmedia
   1034    1.1  augustss  * setup and ethernet/BPF attach.
   1035    1.1  augustss  */
   1036   1.27    dyoung void
   1037   1.27    dyoung axe_attach(device_t parent, device_t self, void *aux)
   1038    1.1  augustss {
   1039   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1040   1.27    dyoung 	struct axe_softc *sc = device_private(self);
   1041   1.27    dyoung 	struct usb_attach_arg *uaa = aux;
   1042   1.71     skrll 	struct usbd_device *dev = uaa->uaa_device;
   1043    1.1  augustss 	usbd_status err;
   1044    1.1  augustss 	usb_interface_descriptor_t *id;
   1045    1.1  augustss 	usb_endpoint_descriptor_t *ed;
   1046    1.1  augustss 	struct mii_data	*mii;
   1047    1.8  augustss 	char *devinfop;
   1048   1.25      cube 	const char *devname = device_xname(self);
   1049    1.1  augustss 	struct ifnet *ifp;
   1050  1.100       mrg 	int i;
   1051    1.1  augustss 
   1052   1.28    dyoung 	aprint_naive("\n");
   1053   1.28    dyoung 	aprint_normal("\n");
   1054   1.29    plunky 
   1055   1.35  pgoyette 	sc->axe_dev = self;
   1056   1.35  pgoyette 	sc->axe_udev = dev;
   1057   1.35  pgoyette 
   1058   1.29    plunky 	devinfop = usbd_devinfo_alloc(dev, 0);
   1059   1.29    plunky 	aprint_normal_dev(self, "%s\n", devinfop);
   1060   1.29    plunky 	usbd_devinfo_free(devinfop);
   1061    1.1  augustss 
   1062    1.1  augustss 	err = usbd_set_config_no(dev, AXE_CONFIG_NO, 1);
   1063    1.1  augustss 	if (err) {
   1064   1.61     skrll 		aprint_error_dev(self, "failed to set configuration"
   1065   1.61     skrll 		    ", err=%s\n", usbd_errstr(err));
   1066   1.28    dyoung 		return;
   1067    1.1  augustss 	}
   1068    1.1  augustss 
   1069   1.71     skrll 	sc->axe_flags = axe_lookup(uaa->uaa_vendor, uaa->uaa_product)->axe_flags;
   1070   1.35  pgoyette 
   1071  1.100       mrg 	usb_init_task(&sc->axe_tick_task, axe_tick_task, sc, USB_TASKQ_MPSAFE);
   1072    1.1  augustss 
   1073    1.1  augustss 	err = usbd_device2interface_handle(dev, AXE_IFACE_IDX, &sc->axe_iface);
   1074    1.1  augustss 	if (err) {
   1075   1.25      cube 		aprint_error_dev(self, "getting interface handle failed\n");
   1076   1.28    dyoung 		return;
   1077    1.1  augustss 	}
   1078    1.1  augustss 
   1079   1.71     skrll 	sc->axe_product = uaa->uaa_product;
   1080   1.71     skrll 	sc->axe_vendor = uaa->uaa_vendor;
   1081    1.1  augustss 
   1082    1.1  augustss 	id = usbd_get_interface_descriptor(sc->axe_iface);
   1083    1.1  augustss 
   1084   1.35  pgoyette 	/* decide on what our bufsize will be */
   1085   1.76     skrll 	if (AXE_IS_178_FAMILY(sc))
   1086   1.71     skrll 		sc->axe_bufsz = (sc->axe_udev->ud_speed == USB_SPEED_HIGH) ?
   1087   1.35  pgoyette 		    AXE_178_MAX_BUFSZ : AXE_178_MIN_BUFSZ;
   1088   1.35  pgoyette 	else
   1089   1.35  pgoyette 		sc->axe_bufsz = AXE_172_BUFSZ;
   1090   1.35  pgoyette 
   1091   1.76     skrll 	sc->axe_ed[AXE_ENDPT_RX] = -1;
   1092   1.76     skrll 	sc->axe_ed[AXE_ENDPT_TX] = -1;
   1093   1.76     skrll 	sc->axe_ed[AXE_ENDPT_INTR] = -1;
   1094   1.76     skrll 
   1095    1.1  augustss 	/* Find endpoints. */
   1096    1.1  augustss 	for (i = 0; i < id->bNumEndpoints; i++) {
   1097    1.1  augustss 		ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i);
   1098   1.38   tsutsui 		if (ed == NULL) {
   1099   1.25      cube 			aprint_error_dev(self, "couldn't get ep %d\n", i);
   1100   1.28    dyoung 			return;
   1101    1.1  augustss 		}
   1102   1.76     skrll 		const uint8_t xt = UE_GET_XFERTYPE(ed->bmAttributes);
   1103   1.76     skrll 		const uint8_t dir = UE_GET_DIR(ed->bEndpointAddress);
   1104   1.76     skrll 
   1105   1.76     skrll 		if (dir == UE_DIR_IN && xt == UE_BULK &&
   1106   1.76     skrll 		    sc->axe_ed[AXE_ENDPT_RX] == -1) {
   1107    1.1  augustss 			sc->axe_ed[AXE_ENDPT_RX] = ed->bEndpointAddress;
   1108   1.76     skrll 		} else if (dir == UE_DIR_OUT && xt == UE_BULK &&
   1109   1.76     skrll 		    sc->axe_ed[AXE_ENDPT_TX] == -1) {
   1110    1.1  augustss 			sc->axe_ed[AXE_ENDPT_TX] = ed->bEndpointAddress;
   1111   1.76     skrll 		} else if (dir == UE_DIR_IN && xt == UE_INTERRUPT) {
   1112    1.1  augustss 			sc->axe_ed[AXE_ENDPT_INTR] = ed->bEndpointAddress;
   1113    1.1  augustss 		}
   1114    1.1  augustss 	}
   1115    1.1  augustss 
   1116  1.100       mrg 	/* Set these up now for axe_cmd().  */
   1117  1.100       mrg 	mutex_init(&sc->axe_mii_lock, MUTEX_DEFAULT, IPL_NONE);
   1118  1.100       mrg 	mutex_init(&sc->axe_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
   1119  1.100       mrg 	mutex_init(&sc->axe_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
   1120  1.100       mrg 	mutex_init(&sc->axe_lock, MUTEX_DEFAULT, IPL_NONE);
   1121  1.100       mrg 	cv_init(&sc->axe_detachcv, "axedet");
   1122    1.1  augustss 
   1123   1.35  pgoyette 	/* We need the PHYID for init dance in some cases */
   1124   1.35  pgoyette 	axe_lock_mii(sc);
   1125   1.86  christos 	if (axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, &sc->axe_phyaddrs)) {
   1126   1.86  christos 		aprint_error_dev(self, "failed to read phyaddrs\n");
   1127  1.100       mrg 
   1128  1.100       mrg 		cv_destroy(&sc->axe_detachcv);
   1129  1.100       mrg 		mutex_destroy(&sc->axe_lock);
   1130  1.100       mrg 		mutex_destroy(&sc->axe_rxlock);
   1131  1.100       mrg 		mutex_destroy(&sc->axe_txlock);
   1132  1.100       mrg 		mutex_destroy(&sc->axe_mii_lock);
   1133  1.100       mrg 
   1134   1.86  christos 		return;
   1135   1.86  christos 	}
   1136   1.35  pgoyette 
   1137   1.83  pgoyette 	DPRINTF(" phyaddrs[0]: %jx phyaddrs[1]: %jx",
   1138   1.76     skrll 	    sc->axe_phyaddrs[0], sc->axe_phyaddrs[1], 0, 0);
   1139   1.66       roy 	sc->axe_phyno = axe_get_phyno(sc, AXE_PHY_SEL_PRI);
   1140   1.66       roy 	if (sc->axe_phyno == -1)
   1141   1.66       roy 		sc->axe_phyno = axe_get_phyno(sc, AXE_PHY_SEL_SEC);
   1142   1.66       roy 	if (sc->axe_phyno == -1) {
   1143   1.76     skrll 		DPRINTF(" no valid PHY address found, assuming PHY address 0",
   1144   1.76     skrll 		    0, 0, 0, 0);
   1145   1.66       roy 		sc->axe_phyno = 0;
   1146   1.66       roy 	}
   1147   1.35  pgoyette 
   1148   1.76     skrll 	/* Initialize controller and get station address. */
   1149   1.76     skrll 
   1150   1.88  christos 	axe_ax_init(sc);
   1151   1.86  christos 
   1152    1.1  augustss 	/*
   1153   1.76     skrll 	 * Fetch IPG values.
   1154    1.1  augustss 	 */
   1155   1.76     skrll 	if (sc->axe_flags & (AX772A | AX772B)) {
   1156   1.76     skrll 		/* Set IPG values. */
   1157   1.76     skrll 		sc->axe_ipgs[0] = AXE_IPG0_DEFAULT;
   1158   1.76     skrll 		sc->axe_ipgs[1] = AXE_IPG1_DEFAULT;
   1159   1.76     skrll 		sc->axe_ipgs[2] = AXE_IPG2_DEFAULT;
   1160   1.86  christos 	} else {
   1161   1.86  christos 		if (axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->axe_ipgs)) {
   1162   1.86  christos 			aprint_error_dev(self, "failed to read ipg\n");
   1163  1.100       mrg 
   1164  1.100       mrg 			cv_destroy(&sc->axe_detachcv);
   1165  1.100       mrg 			mutex_destroy(&sc->axe_lock);
   1166  1.100       mrg 			mutex_destroy(&sc->axe_rxlock);
   1167  1.100       mrg 			mutex_destroy(&sc->axe_txlock);
   1168  1.100       mrg 			mutex_destroy(&sc->axe_mii_lock);
   1169  1.100       mrg 
   1170   1.86  christos 			return;
   1171   1.86  christos 		}
   1172   1.86  christos 	}
   1173    1.1  augustss 
   1174   1.21        ad 	axe_unlock_mii(sc);
   1175    1.1  augustss 
   1176    1.1  augustss 	/*
   1177    1.1  augustss 	 * An ASIX chip was detected. Inform the world.
   1178    1.1  augustss 	 */
   1179   1.76     skrll 	aprint_normal_dev(self, "Ethernet address %s\n",
   1180   1.76     skrll 	    ether_sprintf(sc->axe_enaddr));
   1181    1.1  augustss 
   1182    1.1  augustss 	/* Initialize interface info.*/
   1183   1.35  pgoyette 	ifp = &sc->sc_if;
   1184    1.1  augustss 	ifp->if_softc = sc;
   1185   1.80      maya 	strlcpy(ifp->if_xname, devname, IFNAMSIZ);
   1186    1.1  augustss 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
   1187  1.100       mrg 	ifp->if_extflags = IFEF_MPSAFE;
   1188    1.1  augustss 	ifp->if_ioctl = axe_ioctl;
   1189    1.1  augustss 	ifp->if_start = axe_start;
   1190   1.35  pgoyette 	ifp->if_init = axe_init;
   1191   1.35  pgoyette 	ifp->if_stop = axe_stop;
   1192    1.1  augustss 	ifp->if_watchdog = axe_watchdog;
   1193    1.1  augustss 
   1194   1.35  pgoyette 	IFQ_SET_READY(&ifp->if_snd);
   1195    1.1  augustss 
   1196   1.76     skrll 	if (AXE_IS_178_FAMILY(sc))
   1197   1.76     skrll 		sc->axe_ec.ec_capabilities = ETHERCAP_VLAN_MTU;
   1198   1.76     skrll 	if (sc->axe_flags & AX772B) {
   1199   1.76     skrll 		ifp->if_capabilities =
   1200   1.76     skrll 		    IFCAP_CSUM_IPv4_Rx |
   1201   1.76     skrll 		    IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx |
   1202   1.76     skrll 		    IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx;
   1203   1.76     skrll 		/*
   1204   1.76     skrll 		 * Checksum offloading of AX88772B also works with VLAN
   1205   1.76     skrll 		 * tagged frames but there is no way to take advantage
   1206   1.76     skrll 		 * of the feature because vlan(4) assumes
   1207   1.76     skrll 		 * IFCAP_VLAN_HWTAGGING is prerequisite condition to
   1208   1.76     skrll 		 * support checksum offloading with VLAN. VLAN hardware
   1209   1.76     skrll 		 * tagging support of AX88772B is very limited so it's
   1210   1.76     skrll 		 * not possible to announce IFCAP_VLAN_HWTAGGING.
   1211   1.76     skrll 		 */
   1212   1.76     skrll 	}
   1213   1.76     skrll 	u_int adv_pause;
   1214   1.76     skrll 	if (sc->axe_flags & (AX772A | AX772B | AX178))
   1215   1.76     skrll 		adv_pause = MIIF_DOPAUSE;
   1216   1.76     skrll 	else
   1217   1.76     skrll 		adv_pause = 0;
   1218   1.76     skrll 	adv_pause = 0;
   1219    1.1  augustss 
   1220    1.1  augustss 	/* Initialize MII/media info. */
   1221    1.1  augustss 	mii = &sc->axe_mii;
   1222    1.1  augustss 	mii->mii_ifp = ifp;
   1223    1.1  augustss 	mii->mii_readreg = axe_miibus_readreg;
   1224    1.1  augustss 	mii->mii_writereg = axe_miibus_writereg;
   1225    1.1  augustss 	mii->mii_statchg = axe_miibus_statchg;
   1226    1.1  augustss 	mii->mii_flags = MIIF_AUTOTSLEEP;
   1227    1.1  augustss 
   1228   1.22    dyoung 	sc->axe_ec.ec_mii = mii;
   1229   1.76     skrll 	ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus);
   1230   1.35  pgoyette 
   1231   1.35  pgoyette 	mii_attach(sc->axe_dev, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
   1232   1.76     skrll 	    adv_pause);
   1233    1.1  augustss 
   1234   1.22    dyoung 	if (LIST_EMPTY(&mii->mii_phys)) {
   1235    1.1  augustss 		ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
   1236    1.1  augustss 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
   1237    1.1  augustss 	} else
   1238    1.1  augustss 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
   1239    1.1  augustss 
   1240    1.1  augustss 	/* Attach the interface. */
   1241    1.1  augustss 	if_attach(ifp);
   1242   1.76     skrll 	ether_ifattach(ifp, sc->axe_enaddr);
   1243   1.28    dyoung 	rnd_attach_source(&sc->rnd_source, device_xname(sc->axe_dev),
   1244   1.67       tls 	    RND_TYPE_NET, RND_FLAG_DEFAULT);
   1245    1.1  augustss 
   1246  1.100       mrg 	callout_init(&sc->axe_stat_ch, CALLOUT_MPSAFE);
   1247   1.35  pgoyette 	callout_setfunc(&sc->axe_stat_ch, axe_tick, sc);
   1248    1.1  augustss 
   1249   1.45   tsutsui 	sc->axe_attached = true;
   1250    1.1  augustss 
   1251   1.28    dyoung 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->axe_udev, sc->axe_dev);
   1252   1.68    nonaka 
   1253   1.68    nonaka 	if (!pmf_device_register(self, NULL, NULL))
   1254   1.68    nonaka 		aprint_error_dev(self, "couldn't establish power handler\n");
   1255    1.1  augustss }
   1256    1.1  augustss 
   1257   1.27    dyoung int
   1258   1.27    dyoung axe_detach(device_t self, int flags)
   1259    1.1  augustss {
   1260   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1261   1.38   tsutsui 	struct axe_softc *sc = device_private(self);
   1262   1.38   tsutsui 	struct ifnet *ifp = &sc->sc_if;
   1263    1.1  augustss 
   1264  1.100       mrg 	mutex_enter(&sc->axe_lock);
   1265  1.100       mrg 	sc->axe_dying = true;
   1266  1.100       mrg 	mutex_exit(&sc->axe_lock);
   1267  1.100       mrg 
   1268    1.1  augustss 	/* Detached before attached finished, so just bail out. */
   1269    1.1  augustss 	if (!sc->axe_attached)
   1270   1.35  pgoyette 		return 0;
   1271    1.1  augustss 
   1272   1.68    nonaka 	pmf_device_deregister(self);
   1273   1.68    nonaka 
   1274   1.91  riastrad 	callout_halt(&sc->axe_stat_ch, NULL);
   1275   1.92  riastrad 	usb_rem_task_wait(sc->axe_udev, &sc->axe_tick_task, USB_TASKQ_DRIVER,
   1276   1.92  riastrad 	    NULL);
   1277    1.1  augustss 
   1278  1.100       mrg 	if (ifp->if_flags & IFF_RUNNING) {
   1279  1.100       mrg 		IFNET_LOCK(ifp);
   1280  1.100       mrg 		axe_stop(ifp, 1);
   1281  1.100       mrg 		IFNET_UNLOCK(ifp);
   1282  1.100       mrg 	}
   1283    1.1  augustss 
   1284  1.100       mrg 	mutex_enter(&sc->axe_lock);
   1285  1.100       mrg 	sc->axe_refcnt--;
   1286  1.100       mrg 	while (sc->axe_refcnt > 0) {
   1287  1.100       mrg 		/* Wait for processes to go away */
   1288  1.100       mrg 		cv_wait(&sc->axe_detachcv, &sc->axe_lock);
   1289  1.100       mrg 	}
   1290    1.1  augustss 
   1291  1.100       mrg #ifdef DIAGNOSTIC
   1292  1.100       mrg 	if (sc->axe_ep[AXE_ENDPT_TX] != NULL ||
   1293  1.100       mrg 	    sc->axe_ep[AXE_ENDPT_RX] != NULL ||
   1294  1.100       mrg 	    sc->axe_ep[AXE_ENDPT_INTR] != NULL)
   1295  1.100       mrg 		aprint_debug_dev(self, "detach has active endpoints\n");
   1296  1.100       mrg #endif
   1297   1.76     skrll 
   1298  1.100       mrg 	mutex_exit(&sc->axe_lock);
   1299   1.76     skrll 
   1300   1.36   tsutsui 	callout_destroy(&sc->axe_stat_ch);
   1301    1.1  augustss 	rnd_detach_source(&sc->rnd_source);
   1302    1.1  augustss 	mii_detach(&sc->axe_mii, MII_PHY_ANY, MII_OFFSET_ANY);
   1303    1.1  augustss 	ifmedia_delete_instance(&sc->axe_mii.mii_media, IFM_INST_ANY);
   1304    1.1  augustss 	ether_ifdetach(ifp);
   1305    1.1  augustss 	if_detach(ifp);
   1306    1.1  augustss 
   1307   1.45   tsutsui 	sc->axe_attached = false;
   1308    1.1  augustss 
   1309  1.100       mrg 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->axe_udev, sc->axe_dev);
   1310    1.1  augustss 
   1311  1.100       mrg 	cv_destroy(&sc->axe_detachcv);
   1312  1.100       mrg 	mutex_destroy(&sc->axe_lock);
   1313  1.100       mrg 	mutex_destroy(&sc->axe_rxlock);
   1314  1.100       mrg 	mutex_destroy(&sc->axe_txlock);
   1315  1.100       mrg 	mutex_destroy(&sc->axe_mii_lock);
   1316    1.1  augustss 
   1317   1.35  pgoyette 	return 0;
   1318    1.1  augustss }
   1319    1.1  augustss 
   1320    1.1  augustss int
   1321   1.35  pgoyette axe_activate(device_t self, devact_t act)
   1322    1.1  augustss {
   1323   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1324   1.25      cube 	struct axe_softc *sc = device_private(self);
   1325    1.1  augustss 
   1326    1.1  augustss 	switch (act) {
   1327    1.1  augustss 	case DVACT_DEACTIVATE:
   1328    1.1  augustss 		if_deactivate(&sc->axe_ec.ec_if);
   1329  1.100       mrg 
   1330  1.100       mrg 		mutex_enter(&sc->axe_lock);
   1331   1.45   tsutsui 		sc->axe_dying = true;
   1332  1.100       mrg 		mutex_exit(&sc->axe_lock);
   1333  1.100       mrg 
   1334  1.100       mrg 		mutex_enter(&sc->axe_rxlock);
   1335  1.100       mrg 		mutex_enter(&sc->axe_txlock);
   1336  1.100       mrg 		sc->axe_stopping = true;
   1337  1.100       mrg 		mutex_exit(&sc->axe_txlock);
   1338  1.100       mrg 		mutex_exit(&sc->axe_rxlock);
   1339  1.100       mrg 
   1340   1.30    dyoung 		return 0;
   1341   1.30    dyoung 	default:
   1342   1.30    dyoung 		return EOPNOTSUPP;
   1343    1.1  augustss 	}
   1344    1.1  augustss }
   1345    1.1  augustss 
   1346   1.35  pgoyette static int
   1347    1.1  augustss axe_rx_list_init(struct axe_softc *sc)
   1348    1.1  augustss {
   1349   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1350   1.76     skrll 
   1351    1.1  augustss 	struct axe_cdata *cd;
   1352    1.1  augustss 	struct axe_chain *c;
   1353    1.1  augustss 	int i;
   1354    1.1  augustss 
   1355    1.1  augustss 	cd = &sc->axe_cdata;
   1356    1.1  augustss 	for (i = 0; i < AXE_RX_LIST_CNT; i++) {
   1357    1.1  augustss 		c = &cd->axe_rx_chain[i];
   1358    1.1  augustss 		c->axe_sc = sc;
   1359    1.1  augustss 		if (c->axe_xfer == NULL) {
   1360   1.71     skrll 			int err = usbd_create_xfer(sc->axe_ep[AXE_ENDPT_RX],
   1361   1.84     skrll 			    sc->axe_bufsz, 0, 0, &c->axe_xfer);
   1362   1.71     skrll 			if (err)
   1363   1.71     skrll 				return err;
   1364   1.71     skrll 			c->axe_buf = usbd_get_buffer(c->axe_xfer);
   1365    1.1  augustss 		}
   1366    1.1  augustss 	}
   1367    1.1  augustss 
   1368   1.35  pgoyette 	return 0;
   1369    1.1  augustss }
   1370    1.1  augustss 
   1371   1.35  pgoyette static int
   1372    1.1  augustss axe_tx_list_init(struct axe_softc *sc)
   1373    1.1  augustss {
   1374   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1375    1.1  augustss 	struct axe_cdata *cd;
   1376    1.1  augustss 	struct axe_chain *c;
   1377    1.1  augustss 	int i;
   1378    1.1  augustss 
   1379    1.1  augustss 	cd = &sc->axe_cdata;
   1380    1.1  augustss 	for (i = 0; i < AXE_TX_LIST_CNT; i++) {
   1381    1.1  augustss 		c = &cd->axe_tx_chain[i];
   1382    1.1  augustss 		c->axe_sc = sc;
   1383    1.1  augustss 		if (c->axe_xfer == NULL) {
   1384   1.71     skrll 			int err = usbd_create_xfer(sc->axe_ep[AXE_ENDPT_TX],
   1385   1.71     skrll 			    sc->axe_bufsz, USBD_FORCE_SHORT_XFER, 0,
   1386   1.71     skrll 			    &c->axe_xfer);
   1387   1.71     skrll 			if (err)
   1388   1.71     skrll 				return err;
   1389   1.71     skrll 			c->axe_buf = usbd_get_buffer(c->axe_xfer);
   1390    1.1  augustss 		}
   1391    1.1  augustss 	}
   1392    1.1  augustss 
   1393  1.100       mrg 	cd->axe_tx_cnt = 0;
   1394  1.100       mrg 
   1395   1.35  pgoyette 	return 0;
   1396    1.1  augustss }
   1397    1.1  augustss 
   1398    1.1  augustss /*
   1399    1.1  augustss  * A frame has been uploaded: pass the resulting mbuf chain up to
   1400    1.1  augustss  * the higher level protocols.
   1401    1.1  augustss  */
   1402   1.35  pgoyette static void
   1403   1.71     skrll axe_rxeof(struct usbd_xfer *xfer, void * priv, usbd_status status)
   1404    1.1  augustss {
   1405   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1406  1.100       mrg 	struct axe_chain *c = (struct axe_chain *)priv;
   1407  1.100       mrg 	struct axe_softc * const sc = c->axe_sc;
   1408  1.100       mrg 	struct ifnet *ifp = &sc->sc_if;
   1409  1.100       mrg 	uint8_t *buf = c->axe_buf;
   1410   1.38   tsutsui 	uint32_t total_len;
   1411   1.38   tsutsui 	struct mbuf *m;
   1412    1.1  augustss 
   1413  1.100       mrg 	mutex_enter(&sc->axe_rxlock);
   1414    1.1  augustss 
   1415  1.100       mrg 	if (sc->axe_dying || sc->axe_stopping ||
   1416  1.100       mrg 	    status == USBD_INVAL || status == USBD_NOT_STARTED ||
   1417  1.100       mrg 	    status == USBD_CANCELLED || !(ifp->if_flags & IFF_RUNNING)) {
   1418  1.100       mrg 		mutex_exit(&sc->axe_rxlock);
   1419    1.1  augustss 		return;
   1420  1.100       mrg 	}
   1421    1.1  augustss 
   1422    1.1  augustss 	if (status != USBD_NORMAL_COMPLETION) {
   1423   1.76     skrll 		if (usbd_ratecheck(&sc->axe_rx_notice)) {
   1424   1.35  pgoyette 			aprint_error_dev(sc->axe_dev, "usb errors on rx: %s\n",
   1425   1.35  pgoyette 			    usbd_errstr(status));
   1426   1.76     skrll 		}
   1427    1.1  augustss 		if (status == USBD_STALLED)
   1428   1.12  augustss 			usbd_clear_endpoint_stall_async(sc->axe_ep[AXE_ENDPT_RX]);
   1429    1.1  augustss 		goto done;
   1430    1.1  augustss 	}
   1431    1.1  augustss 
   1432    1.1  augustss 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
   1433    1.1  augustss 
   1434   1.35  pgoyette 	do {
   1435   1.76     skrll 		u_int pktlen = 0;
   1436   1.76     skrll 		u_int rxlen = 0;
   1437   1.76     skrll 		int flags = 0;
   1438   1.76     skrll 		if ((sc->axe_flags & AXSTD_FRAME) != 0) {
   1439   1.76     skrll 			struct axe_sframe_hdr hdr;
   1440   1.76     skrll 
   1441   1.35  pgoyette 			if (total_len < sizeof(hdr)) {
   1442   1.35  pgoyette 				ifp->if_ierrors++;
   1443   1.35  pgoyette 				goto done;
   1444   1.35  pgoyette 			}
   1445   1.35  pgoyette 
   1446   1.94       rin #if !defined(__NO_STRICT_ALIGNMENT) && __GNUC_PREREQ__(6, 1)
   1447   1.94       rin 			/*
   1448   1.94       rin 			 * XXX hdr is 2-byte aligned in buf, not 4-byte.
   1449   1.94       rin 			 * For some architectures, __builtin_memcpy() of
   1450   1.94       rin 			 * GCC 6 attempts to copy sizeof(hdr) = 4 bytes
   1451   1.94       rin 			 * at onece, which results in alignment error.
   1452   1.94       rin 			 */
   1453   1.94       rin 			hdr.len = *(uint16_t *)buf;
   1454   1.94       rin 			hdr.ilen = *(uint16_t *)(buf + sizeof(uint16_t));
   1455   1.94       rin #else
   1456   1.35  pgoyette 			memcpy(&hdr, buf, sizeof(hdr));
   1457   1.94       rin #endif
   1458   1.76     skrll 
   1459   1.83  pgoyette 			DPRINTFN(20, "total_len %#jx len %jx ilen %#jx",
   1460   1.76     skrll 			    total_len,
   1461   1.76     skrll 			    (le16toh(hdr.len) & AXE_RH1M_RXLEN_MASK),
   1462   1.76     skrll 			    (le16toh(hdr.ilen) & AXE_RH1M_RXLEN_MASK), 0);
   1463   1.76     skrll 
   1464   1.35  pgoyette 			total_len -= sizeof(hdr);
   1465   1.42   tsutsui 			buf += sizeof(hdr);
   1466   1.35  pgoyette 
   1467   1.58  christos 			if (((le16toh(hdr.len) & AXE_RH1M_RXLEN_MASK) ^
   1468   1.62  christos 			    (le16toh(hdr.ilen) & AXE_RH1M_RXLEN_MASK)) !=
   1469   1.62  christos 			    AXE_RH1M_RXLEN_MASK) {
   1470   1.35  pgoyette 				ifp->if_ierrors++;
   1471   1.35  pgoyette 				goto done;
   1472   1.35  pgoyette 			}
   1473   1.42   tsutsui 
   1474   1.63  christos 			rxlen = le16toh(hdr.len) & AXE_RH1M_RXLEN_MASK;
   1475   1.42   tsutsui 			if (total_len < rxlen) {
   1476   1.42   tsutsui 				pktlen = total_len;
   1477   1.42   tsutsui 				total_len = 0;
   1478   1.42   tsutsui 			} else {
   1479   1.43   tsutsui 				pktlen = rxlen;
   1480   1.43   tsutsui 				rxlen = roundup2(rxlen, 2);
   1481   1.42   tsutsui 				total_len -= rxlen;
   1482   1.35  pgoyette 			}
   1483   1.35  pgoyette 
   1484   1.76     skrll 		} else if ((sc->axe_flags & AXCSUM_FRAME) != 0) {
   1485   1.76     skrll 			struct axe_csum_hdr csum_hdr;
   1486   1.76     skrll 
   1487   1.97   msaitoh 			if (total_len <	 sizeof(csum_hdr)) {
   1488   1.76     skrll 				ifp->if_ierrors++;
   1489   1.76     skrll 				goto done;
   1490   1.76     skrll 			}
   1491   1.76     skrll 
   1492   1.76     skrll 			memcpy(&csum_hdr, buf, sizeof(csum_hdr));
   1493   1.76     skrll 
   1494   1.76     skrll 			csum_hdr.len = le16toh(csum_hdr.len);
   1495   1.76     skrll 			csum_hdr.ilen = le16toh(csum_hdr.ilen);
   1496   1.76     skrll 			csum_hdr.cstatus = le16toh(csum_hdr.cstatus);
   1497   1.76     skrll 
   1498   1.83  pgoyette 			DPRINTFN(20, "total_len %#jx len %#jx ilen %#jx"
   1499   1.83  pgoyette 			    " cstatus %#jx", total_len,
   1500   1.76     skrll 			    csum_hdr.len, csum_hdr.ilen, csum_hdr.cstatus);
   1501   1.76     skrll 
   1502   1.76     skrll 			if ((AXE_CSUM_RXBYTES(csum_hdr.len) ^
   1503   1.76     skrll 			    AXE_CSUM_RXBYTES(csum_hdr.ilen)) !=
   1504   1.76     skrll 			    sc->sc_lenmask) {
   1505   1.76     skrll 				/* we lost sync */
   1506   1.76     skrll 				ifp->if_ierrors++;
   1507   1.83  pgoyette 				DPRINTFN(20, "len %#jx ilen %#jx lenmask %#jx "
   1508   1.83  pgoyette 				    "err",
   1509   1.76     skrll 				    AXE_CSUM_RXBYTES(csum_hdr.len),
   1510   1.76     skrll 				    AXE_CSUM_RXBYTES(csum_hdr.ilen),
   1511   1.76     skrll 				    sc->sc_lenmask, 0);
   1512   1.76     skrll 				goto done;
   1513   1.76     skrll 			}
   1514   1.76     skrll 			/*
   1515   1.76     skrll 			 * Get total transferred frame length including
   1516   1.76     skrll 			 * checksum header.  The length should be multiple
   1517   1.76     skrll 			 * of 4.
   1518   1.76     skrll 			 */
   1519   1.76     skrll 			pktlen = AXE_CSUM_RXBYTES(csum_hdr.len);
   1520   1.78     skrll 			u_int len = sizeof(csum_hdr) + pktlen;
   1521   1.76     skrll 			len = (len + 3) & ~3;
   1522   1.76     skrll 			if (total_len < len) {
   1523   1.83  pgoyette 				DPRINTFN(20, "total_len %#jx < len %#jx",
   1524   1.76     skrll 				    total_len, len, 0, 0);
   1525   1.76     skrll 				/* invalid length */
   1526   1.76     skrll 				ifp->if_ierrors++;
   1527   1.76     skrll 				goto done;
   1528   1.76     skrll 			}
   1529   1.76     skrll 			buf += sizeof(csum_hdr);
   1530   1.76     skrll 
   1531   1.76     skrll 			const uint16_t cstatus = csum_hdr.cstatus;
   1532   1.76     skrll 
   1533   1.76     skrll 			if (cstatus & AXE_CSUM_HDR_L3_TYPE_IPV4) {
   1534   1.76     skrll 				if (cstatus & AXE_CSUM_HDR_L4_CSUM_ERR)
   1535   1.76     skrll 					flags |= M_CSUM_TCP_UDP_BAD;
   1536   1.76     skrll 				if (cstatus & AXE_CSUM_HDR_L3_CSUM_ERR)
   1537   1.76     skrll 					flags |= M_CSUM_IPv4_BAD;
   1538   1.76     skrll 
   1539   1.76     skrll 				const uint16_t l4type =
   1540   1.76     skrll 				    cstatus & AXE_CSUM_HDR_L4_TYPE_MASK;
   1541   1.76     skrll 
   1542   1.76     skrll 				if (l4type == AXE_CSUM_HDR_L4_TYPE_TCP)
   1543   1.76     skrll 					flags |= M_CSUM_TCPv4;
   1544   1.76     skrll 				if (l4type == AXE_CSUM_HDR_L4_TYPE_UDP)
   1545   1.76     skrll 					flags |= M_CSUM_UDPv4;
   1546   1.76     skrll 			}
   1547   1.76     skrll 			if (total_len < len) {
   1548   1.76     skrll 				pktlen = total_len;
   1549   1.76     skrll 				total_len = 0;
   1550   1.76     skrll 			} else {
   1551   1.76     skrll 				total_len -= len;
   1552   1.76     skrll 				rxlen = len - sizeof(csum_hdr);
   1553   1.76     skrll 			}
   1554   1.83  pgoyette 			DPRINTFN(20, "total_len %#jx len %#jx pktlen %#jx"
   1555   1.83  pgoyette 			    " rxlen %#jx", total_len, len, pktlen, rxlen);
   1556   1.35  pgoyette 		} else { /* AX172 */
   1557   1.42   tsutsui 			pktlen = rxlen = total_len;
   1558   1.35  pgoyette 			total_len = 0;
   1559   1.35  pgoyette 		}
   1560   1.35  pgoyette 
   1561   1.44   tsutsui 		MGETHDR(m, M_DONTWAIT, MT_DATA);
   1562   1.44   tsutsui 		if (m == NULL) {
   1563   1.35  pgoyette 			ifp->if_ierrors++;
   1564   1.35  pgoyette 			goto done;
   1565   1.35  pgoyette 		}
   1566    1.1  augustss 
   1567   1.44   tsutsui 		if (pktlen > MHLEN - ETHER_ALIGN) {
   1568   1.44   tsutsui 			MCLGET(m, M_DONTWAIT);
   1569   1.44   tsutsui 			if ((m->m_flags & M_EXT) == 0) {
   1570   1.44   tsutsui 				m_freem(m);
   1571   1.44   tsutsui 				ifp->if_ierrors++;
   1572   1.44   tsutsui 				goto done;
   1573   1.44   tsutsui 			}
   1574   1.44   tsutsui 		}
   1575   1.44   tsutsui 		m->m_data += ETHER_ALIGN;
   1576   1.44   tsutsui 
   1577   1.72     ozaki 		m_set_rcvif(m, ifp);
   1578   1.35  pgoyette 		m->m_pkthdr.len = m->m_len = pktlen;
   1579   1.76     skrll 		m->m_pkthdr.csum_flags = flags;
   1580    1.1  augustss 
   1581   1.45   tsutsui 		memcpy(mtod(m, uint8_t *), buf, pktlen);
   1582   1.42   tsutsui 		buf += rxlen;
   1583    1.1  augustss 
   1584   1.83  pgoyette 		DPRINTFN(10, "deliver %jd (%#jx)", m->m_len, m->m_len, 0, 0);
   1585   1.76     skrll 
   1586  1.100       mrg 		mutex_exit(&sc->axe_rxlock);
   1587    1.1  augustss 
   1588   1.70     ozaki 		if_percpuq_enqueue((ifp)->if_percpuq, (m));
   1589    1.1  augustss 
   1590  1.100       mrg 		mutex_enter(&sc->axe_rxlock);
   1591  1.100       mrg 		if (sc->axe_dying || sc->axe_stopping) {
   1592  1.100       mrg 			mutex_exit(&sc->axe_rxlock);
   1593  1.100       mrg 			return;
   1594  1.100       mrg 		}
   1595    1.1  augustss 
   1596   1.35  pgoyette 	} while (total_len > 0);
   1597    1.1  augustss 
   1598    1.1  augustss  done:
   1599    1.1  augustss 
   1600  1.100       mrg 	if (sc->axe_dying || sc->axe_stopping) {
   1601  1.100       mrg 		mutex_exit(&sc->axe_rxlock);
   1602  1.100       mrg 		return;
   1603  1.100       mrg 	}
   1604  1.100       mrg 
   1605  1.100       mrg 	mutex_exit(&sc->axe_rxlock);
   1606  1.100       mrg 
   1607    1.1  augustss 	/* Setup new transfer. */
   1608   1.71     skrll 	usbd_setup_xfer(xfer, c, c->axe_buf, sc->axe_bufsz,
   1609   1.71     skrll 	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, axe_rxeof);
   1610    1.1  augustss 	usbd_transfer(xfer);
   1611    1.1  augustss 
   1612   1.76     skrll 	DPRINTFN(10, "start rx", 0, 0, 0, 0);
   1613    1.1  augustss }
   1614    1.1  augustss 
   1615    1.1  augustss /*
   1616    1.1  augustss  * A frame was downloaded to the chip. It's safe for us to clean up
   1617    1.1  augustss  * the list buffers.
   1618    1.1  augustss  */
   1619    1.1  augustss 
   1620   1.35  pgoyette static void
   1621   1.71     skrll axe_txeof(struct usbd_xfer *xfer, void * priv, usbd_status status)
   1622    1.1  augustss {
   1623   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1624   1.76     skrll 	struct axe_chain *c = priv;
   1625   1.76     skrll 	struct axe_softc *sc = c->axe_sc;
   1626  1.100       mrg 	struct axe_cdata *cd = &sc->axe_cdata;
   1627   1.76     skrll 	struct ifnet *ifp = &sc->sc_if;
   1628    1.1  augustss 
   1629  1.100       mrg 	mutex_enter(&sc->axe_txlock);
   1630  1.100       mrg 	if (sc->axe_stopping || sc->axe_dying) {
   1631  1.100       mrg 		mutex_exit(&sc->axe_txlock);
   1632  1.100       mrg 		return;
   1633  1.100       mrg 	}
   1634  1.100       mrg 
   1635  1.100       mrg 	KASSERT(cd->axe_tx_cnt == 1);
   1636  1.100       mrg 	cd->axe_tx_cnt--;
   1637    1.1  augustss 
   1638  1.100       mrg 	sc->axe_timer = 0;
   1639    1.1  augustss 
   1640  1.100       mrg 	switch (status) {
   1641  1.100       mrg 	case USBD_NOT_STARTED:
   1642  1.100       mrg 	case USBD_CANCELLED:
   1643  1.100       mrg 		break;
   1644    1.1  augustss 
   1645  1.100       mrg 	case USBD_NORMAL_COMPLETION:
   1646  1.100       mrg 		ifp->if_opackets++;
   1647  1.100       mrg 		if (!IFQ_IS_EMPTY(&ifp->if_snd))
   1648  1.100       mrg 			axe_start_locked(ifp);
   1649  1.100       mrg 		break;
   1650  1.100       mrg 
   1651  1.100       mrg 	default:
   1652   1.66       roy 
   1653    1.1  augustss 		ifp->if_oerrors++;
   1654  1.100       mrg 		if (usbd_ratecheck(&sc->axe_tx_notice))
   1655  1.100       mrg 			aprint_error_dev(sc->axe_dev, "usb error on tx: %s\n",
   1656  1.100       mrg 			    usbd_errstr(status));
   1657    1.1  augustss 		if (status == USBD_STALLED)
   1658   1.12  augustss 			usbd_clear_endpoint_stall_async(sc->axe_ep[AXE_ENDPT_TX]);
   1659  1.100       mrg 		break;
   1660    1.1  augustss 	}
   1661    1.1  augustss 
   1662  1.100       mrg 	mutex_exit(&sc->axe_txlock);
   1663    1.1  augustss }
   1664    1.1  augustss 
   1665   1.35  pgoyette static void
   1666    1.1  augustss axe_tick(void *xsc)
   1667    1.1  augustss {
   1668   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1669    1.1  augustss 	struct axe_softc *sc = xsc;
   1670    1.1  augustss 
   1671    1.1  augustss 	if (sc == NULL)
   1672    1.1  augustss 		return;
   1673    1.1  augustss 
   1674  1.100       mrg 	mutex_enter(&sc->axe_lock);
   1675  1.100       mrg 	if (!sc->axe_stopping && !sc->axe_dying) {
   1676  1.100       mrg 		/* Perform periodic stuff in process context */
   1677  1.100       mrg 		usb_add_task(sc->axe_udev, &sc->axe_tick_task, USB_TASKQ_DRIVER);
   1678  1.100       mrg 	}
   1679  1.100       mrg 	mutex_exit(&sc->axe_lock);
   1680    1.1  augustss 
   1681    1.1  augustss }
   1682    1.1  augustss 
   1683   1.35  pgoyette static void
   1684    1.1  augustss axe_tick_task(void *xsc)
   1685    1.1  augustss {
   1686   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1687   1.76     skrll 	struct axe_softc *sc = xsc;
   1688   1.38   tsutsui 	struct ifnet *ifp;
   1689   1.38   tsutsui 	struct mii_data *mii;
   1690    1.1  augustss 
   1691    1.1  augustss 	if (sc == NULL)
   1692    1.1  augustss 		return;
   1693    1.1  augustss 
   1694  1.100       mrg 	mutex_enter(&sc->axe_lock);
   1695  1.100       mrg 	if (sc->axe_stopping || sc->axe_dying) {
   1696  1.100       mrg 		mutex_exit(&sc->axe_lock);
   1697    1.1  augustss 		return;
   1698  1.100       mrg 	}
   1699    1.1  augustss 
   1700   1.35  pgoyette 	ifp = &sc->sc_if;
   1701   1.35  pgoyette 	mii = &sc->axe_mii;
   1702   1.35  pgoyette 
   1703  1.100       mrg 	if (mii == NULL) {
   1704  1.100       mrg 		mutex_exit(&sc->axe_lock);
   1705    1.1  augustss 		return;
   1706  1.100       mrg 	}
   1707  1.100       mrg 
   1708  1.100       mrg 	sc->axe_refcnt++;
   1709  1.100       mrg 	mutex_exit(&sc->axe_lock);
   1710    1.1  augustss 
   1711  1.100       mrg 	if (sc->axe_timer != 0 && --sc->axe_timer == 0)
   1712  1.100       mrg 		axe_watchdog(ifp);
   1713    1.1  augustss 
   1714    1.1  augustss 	mii_tick(mii);
   1715  1.100       mrg 
   1716   1.38   tsutsui 	if (sc->axe_link == 0 &&
   1717   1.38   tsutsui 	    (mii->mii_media_status & IFM_ACTIVE) != 0 &&
   1718   1.35  pgoyette 	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
   1719   1.76     skrll 		DPRINTF("got link", 0, 0, 0, 0);
   1720   1.35  pgoyette 		sc->axe_link++;
   1721   1.36   tsutsui 		if (!IFQ_IS_EMPTY(&ifp->if_snd))
   1722   1.35  pgoyette 			axe_start(ifp);
   1723   1.35  pgoyette 	}
   1724    1.1  augustss 
   1725    1.1  augustss 
   1726  1.100       mrg 	mutex_enter(&sc->axe_lock);
   1727  1.100       mrg 	if (--sc->axe_refcnt < 0)
   1728  1.100       mrg 		cv_broadcast(&sc->axe_detachcv);
   1729  1.100       mrg 	if (!sc->axe_stopping && !sc->axe_dying)
   1730  1.100       mrg 		callout_schedule(&sc->axe_stat_ch, hz);
   1731  1.100       mrg 	mutex_exit(&sc->axe_lock);
   1732    1.1  augustss }
   1733    1.1  augustss 
   1734   1.35  pgoyette static int
   1735    1.1  augustss axe_encap(struct axe_softc *sc, struct mbuf *m, int idx)
   1736    1.1  augustss {
   1737   1.38   tsutsui 	struct ifnet *ifp = &sc->sc_if;
   1738   1.38   tsutsui 	struct axe_chain *c;
   1739   1.38   tsutsui 	usbd_status err;
   1740   1.38   tsutsui 	int length, boundary;
   1741    1.1  augustss 
   1742  1.100       mrg 	KASSERT(mutex_owned(&sc->axe_txlock));
   1743  1.100       mrg 
   1744    1.1  augustss 	c = &sc->axe_cdata.axe_tx_chain[idx];
   1745    1.1  augustss 
   1746    1.1  augustss 	/*
   1747    1.1  augustss 	 * Copy the mbuf data into a contiguous buffer, leaving two
   1748    1.1  augustss 	 * bytes at the beginning to hold the frame length.
   1749    1.1  augustss 	 */
   1750   1.76     skrll 	if (AXE_IS_178_FAMILY(sc)) {
   1751   1.97   msaitoh 		struct axe_sframe_hdr hdr;
   1752   1.76     skrll 
   1753   1.71     skrll 		boundary = (sc->axe_udev->ud_speed == USB_SPEED_HIGH) ? 512 : 64;
   1754   1.35  pgoyette 
   1755   1.35  pgoyette 		hdr.len = htole16(m->m_pkthdr.len);
   1756   1.35  pgoyette 		hdr.ilen = ~hdr.len;
   1757   1.35  pgoyette 
   1758   1.35  pgoyette 		memcpy(c->axe_buf, &hdr, sizeof(hdr));
   1759   1.35  pgoyette 		length = sizeof(hdr);
   1760   1.35  pgoyette 
   1761   1.35  pgoyette 		m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf + length);
   1762   1.35  pgoyette 		length += m->m_pkthdr.len;
   1763   1.35  pgoyette 
   1764   1.35  pgoyette 		if ((length % boundary) == 0) {
   1765   1.35  pgoyette 			hdr.len = 0x0000;
   1766   1.35  pgoyette 			hdr.ilen = 0xffff;
   1767   1.35  pgoyette 			memcpy(c->axe_buf + length, &hdr, sizeof(hdr));
   1768   1.35  pgoyette 			length += sizeof(hdr);
   1769   1.35  pgoyette 		}
   1770   1.35  pgoyette 	} else {
   1771   1.35  pgoyette 		m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf);
   1772   1.35  pgoyette 		length = m->m_pkthdr.len;
   1773   1.35  pgoyette 	}
   1774    1.1  augustss 
   1775   1.71     skrll 	usbd_setup_xfer(c->axe_xfer, c, c->axe_buf, length,
   1776   1.71     skrll 	    USBD_FORCE_SHORT_XFER, 10000, axe_txeof);
   1777    1.1  augustss 
   1778    1.1  augustss 	/* Transmit */
   1779    1.1  augustss 	err = usbd_transfer(c->axe_xfer);
   1780    1.1  augustss 	if (err != USBD_IN_PROGRESS) {
   1781  1.100       mrg 		/* XXXSMP IFNET_LOCK */
   1782   1.35  pgoyette 		axe_stop(ifp, 0);
   1783   1.35  pgoyette 		return EIO;
   1784    1.1  augustss 	}
   1785    1.1  augustss 
   1786    1.1  augustss 	sc->axe_cdata.axe_tx_cnt++;
   1787    1.1  augustss 
   1788   1.35  pgoyette 	return 0;
   1789    1.1  augustss }
   1790    1.1  augustss 
   1791   1.76     skrll 
   1792   1.76     skrll static void
   1793   1.76     skrll axe_csum_cfg(struct axe_softc *sc)
   1794   1.76     skrll {
   1795   1.76     skrll 	struct ifnet *ifp = &sc->sc_if;
   1796   1.76     skrll 	uint16_t csum1, csum2;
   1797   1.76     skrll 
   1798   1.76     skrll 	if ((sc->axe_flags & AX772B) != 0) {
   1799   1.76     skrll 		csum1 = 0;
   1800   1.76     skrll 		csum2 = 0;
   1801   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_IPv4_Tx) != 0)
   1802   1.76     skrll 			csum1 |= AXE_TXCSUM_IP;
   1803   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx) != 0)
   1804   1.76     skrll 			csum1 |= AXE_TXCSUM_TCP;
   1805   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx) != 0)
   1806   1.76     skrll 			csum1 |= AXE_TXCSUM_UDP;
   1807   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_TCPv6_Tx) != 0)
   1808   1.76     skrll 			csum1 |= AXE_TXCSUM_TCPV6;
   1809   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_UDPv6_Tx) != 0)
   1810   1.76     skrll 			csum1 |= AXE_TXCSUM_UDPV6;
   1811   1.76     skrll 		axe_cmd(sc, AXE_772B_CMD_WRITE_TXCSUM, csum2, csum1, NULL);
   1812   1.76     skrll 		csum1 = 0;
   1813   1.76     skrll 		csum2 = 0;
   1814   1.76     skrll 
   1815   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_IPv4_Rx) != 0)
   1816   1.76     skrll 			csum1 |= AXE_RXCSUM_IP;
   1817   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) != 0)
   1818   1.76     skrll 			csum1 |= AXE_RXCSUM_TCP;
   1819   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) != 0)
   1820   1.76     skrll 			csum1 |= AXE_RXCSUM_UDP;
   1821   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_TCPv6_Rx) != 0)
   1822   1.76     skrll 			csum1 |= AXE_RXCSUM_TCPV6;
   1823   1.76     skrll 		if ((ifp->if_capenable & IFCAP_CSUM_UDPv6_Rx) != 0)
   1824   1.76     skrll 			csum1 |= AXE_RXCSUM_UDPV6;
   1825   1.76     skrll 		axe_cmd(sc, AXE_772B_CMD_WRITE_RXCSUM, csum2, csum1, NULL);
   1826   1.76     skrll 	}
   1827   1.76     skrll }
   1828   1.76     skrll 
   1829   1.35  pgoyette static void
   1830  1.100       mrg axe_start_locked(struct ifnet *ifp)
   1831    1.1  augustss {
   1832  1.100       mrg 	struct axe_softc *sc = ifp->if_softc;
   1833   1.46   tsutsui 	struct mbuf *m;
   1834  1.100       mrg 	struct axe_cdata *cd = &sc->axe_cdata;
   1835    1.1  augustss 
   1836  1.100       mrg 	KASSERT(mutex_owned(&sc->axe_txlock));
   1837  1.100       mrg 
   1838  1.100       mrg 	if (cd->axe_tx_cnt != 0)
   1839  1.100       mrg 		return;
   1840    1.1  augustss 
   1841  1.100       mrg 	if (sc->axe_link == 0 || (ifp->if_flags & IFF_RUNNING) == 0)
   1842    1.1  augustss 		return;
   1843    1.1  augustss 
   1844   1.46   tsutsui 	IFQ_POLL(&ifp->if_snd, m);
   1845   1.46   tsutsui 	if (m == NULL) {
   1846    1.1  augustss 		return;
   1847    1.1  augustss 	}
   1848    1.1  augustss 
   1849   1.46   tsutsui 	if (axe_encap(sc, m, 0)) {
   1850    1.1  augustss 		return;
   1851    1.1  augustss 	}
   1852   1.46   tsutsui 	IFQ_DEQUEUE(&ifp->if_snd, m);
   1853    1.1  augustss 
   1854    1.1  augustss 	/*
   1855    1.1  augustss 	 * If there's a BPF listener, bounce a copy of this frame
   1856    1.1  augustss 	 * to him.
   1857    1.1  augustss 	 */
   1858   1.90   msaitoh 	bpf_mtap(ifp, m, BPF_D_OUT);
   1859   1.46   tsutsui 	m_freem(m);
   1860    1.1  augustss 
   1861    1.1  augustss 	/*
   1862    1.1  augustss 	 * Set a timeout in case the chip goes out to lunch.
   1863    1.1  augustss 	 */
   1864  1.100       mrg 	sc->axe_timer = 5;
   1865    1.1  augustss 
   1866    1.1  augustss 	return;
   1867    1.1  augustss }
   1868    1.1  augustss 
   1869  1.100       mrg static void
   1870  1.100       mrg axe_start(struct ifnet *ifp)
   1871  1.100       mrg {
   1872  1.100       mrg 	struct axe_softc * const sc = ifp->if_softc;
   1873  1.100       mrg 
   1874  1.100       mrg 	mutex_enter(&sc->axe_txlock);
   1875  1.100       mrg 	if (!sc->axe_stopping)
   1876  1.100       mrg 		axe_start_locked(ifp);
   1877  1.100       mrg 	mutex_exit(&sc->axe_txlock);
   1878  1.100       mrg }
   1879  1.100       mrg 
   1880   1.35  pgoyette static int
   1881  1.100       mrg axe_init_locked(struct ifnet *ifp)
   1882    1.1  augustss {
   1883   1.76     skrll 	AXEHIST_FUNC(); AXEHIST_CALLED();
   1884   1.38   tsutsui 	struct axe_softc *sc = ifp->if_softc;
   1885   1.38   tsutsui 	struct axe_chain *c;
   1886   1.38   tsutsui 	usbd_status err;
   1887   1.38   tsutsui 	int rxmode;
   1888  1.100       mrg 	int i;
   1889   1.35  pgoyette 
   1890  1.100       mrg 	KASSERT(mutex_owned(&sc->axe_lock));
   1891  1.100       mrg 
   1892  1.100       mrg 	if (sc->axe_dying)
   1893  1.100       mrg 		return EIO;
   1894    1.1  augustss 
   1895  1.100       mrg 	/* Cancel pending I/O */
   1896  1.100       mrg 	axe_stop_locked(ifp, 0);
   1897    1.1  augustss 
   1898  1.100       mrg 	/* Reset the ethernet interface. */
   1899    1.1  augustss 	axe_reset(sc);
   1900    1.1  augustss 
   1901  1.100       mrg 	axe_lock_mii_sc_locked(sc);
   1902   1.35  pgoyette 
   1903   1.76     skrll #if 0
   1904   1.76     skrll 	ret = asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 |
   1905   1.76     skrll 			      AX_GPIO_GPO2EN, 5, in_pm);
   1906   1.76     skrll #endif
   1907   1.76     skrll 	/* Set MAC address and transmitter IPG values. */
   1908   1.76     skrll 	if (AXE_IS_178_FAMILY(sc)) {
   1909   1.76     skrll 		axe_cmd(sc, AXE_178_CMD_WRITE_NODEID, 0, 0, sc->axe_enaddr);
   1910   1.35  pgoyette 		axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->axe_ipgs[2],
   1911   1.35  pgoyette 		    (sc->axe_ipgs[1] << 8) | (sc->axe_ipgs[0]), NULL);
   1912   1.76     skrll 	} else {
   1913   1.76     skrll 		axe_cmd(sc, AXE_172_CMD_WRITE_NODEID, 0, 0, sc->axe_enaddr);
   1914   1.35  pgoyette 		axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
   1915   1.35  pgoyette 		axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
   1916   1.35  pgoyette 		axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
   1917   1.35  pgoyette 	}
   1918   1.76     skrll 	if (AXE_IS_178_FAMILY(sc)) {
   1919   1.76     skrll 		sc->axe_flags &= ~(AXSTD_FRAME | AXCSUM_FRAME);
   1920   1.76     skrll 		if ((sc->axe_flags & AX772B) != 0 &&
   1921   1.76     skrll 		    (ifp->if_capenable & AX_RXCSUM) != 0) {
   1922   1.76     skrll 			sc->sc_lenmask = AXE_CSUM_HDR_LEN_MASK;
   1923   1.76     skrll 			sc->axe_flags |= AXCSUM_FRAME;
   1924   1.76     skrll 		} else {
   1925   1.76     skrll 			sc->sc_lenmask = AXE_HDR_LEN_MASK;
   1926   1.76     skrll 			sc->axe_flags |= AXSTD_FRAME;
   1927   1.76     skrll 		}
   1928   1.76     skrll 	}
   1929   1.76     skrll 
   1930   1.76     skrll 	/* Configure TX/RX checksum offloading. */
   1931   1.76     skrll 	axe_csum_cfg(sc);
   1932    1.1  augustss 
   1933   1.76     skrll 	if (sc->axe_flags & AX772B) {
   1934   1.76     skrll 		/* AX88772B uses different maximum frame burst configuration. */
   1935   1.76     skrll 		axe_cmd(sc, AXE_772B_CMD_RXCTL_WRITE_CFG,
   1936   1.76     skrll 		    ax88772b_mfb_table[AX88772B_MFB_16K].threshold,
   1937   1.76     skrll 		    ax88772b_mfb_table[AX88772B_MFB_16K].byte_cnt, NULL);
   1938   1.76     skrll 	}
   1939    1.1  augustss 	/* Enable receiver, set RX mode */
   1940   1.76     skrll 	rxmode = (AXE_RXCMD_MULTICAST | AXE_RXCMD_ENABLE);
   1941   1.76     skrll 	if (AXE_IS_178_FAMILY(sc)) {
   1942   1.76     skrll 		if (sc->axe_flags & AX772B) {
   1943   1.76     skrll 			/*
   1944   1.76     skrll 			 * Select RX header format type 1.  Aligning IP
   1945   1.76     skrll 			 * header on 4 byte boundary is not needed when
   1946   1.76     skrll 			 * checksum offloading feature is not used
   1947   1.76     skrll 			 * because we always copy the received frame in
   1948   1.76     skrll 			 * RX handler.  When RX checksum offloading is
   1949   1.76     skrll 			 * active, aligning IP header is required to
   1950   1.76     skrll 			 * reflect actual frame length including RX
   1951   1.76     skrll 			 * header size.
   1952   1.76     skrll 			 */
   1953   1.76     skrll 			rxmode |= AXE_772B_RXCMD_HDR_TYPE_1;
   1954   1.76     skrll 			if (sc->axe_flags & AXCSUM_FRAME)
   1955   1.76     skrll 				rxmode |= AXE_772B_RXCMD_IPHDR_ALIGN;
   1956   1.76     skrll 		} else {
   1957   1.76     skrll 			/*
   1958   1.76     skrll 			 * Default Rx buffer size is too small to get
   1959   1.76     skrll 			 * maximum performance.
   1960   1.76     skrll 			 */
   1961   1.76     skrll #if 0
   1962   1.76     skrll 			if (sc->axe_udev->ud_speed == USB_SPEED_HIGH) {
   1963   1.76     skrll 				/* Largest possible USB buffer size for AX88178 */
   1964  1.100       mrg 			}
   1965   1.76     skrll #endif
   1966   1.76     skrll 			rxmode |= AXE_178_RXCMD_MFB_16384;
   1967   1.35  pgoyette 		}
   1968   1.76     skrll 	} else {
   1969   1.35  pgoyette 		rxmode |= AXE_172_RXCMD_UNICAST;
   1970   1.76     skrll 	}
   1971   1.76     skrll 
   1972    1.1  augustss 
   1973    1.1  augustss 	/* If we want promiscuous mode, set the allframes bit. */
   1974    1.1  augustss 	if (ifp->if_flags & IFF_PROMISC)
   1975    1.1  augustss 		rxmode |= AXE_RXCMD_PROMISC;
   1976    1.1  augustss 
   1977    1.1  augustss 	if (ifp->if_flags & IFF_BROADCAST)
   1978    1.1  augustss 		rxmode |= AXE_RXCMD_BROADCAST;
   1979    1.1  augustss 
   1980   1.83  pgoyette 	DPRINTF("rxmode 0x%#jx", rxmode, 0, 0, 0);
   1981   1.76     skrll 
   1982    1.1  augustss 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
   1983    1.1  augustss 
   1984    1.1  augustss 	/* Load the multicast filter. */
   1985  1.100       mrg 	axe_setmulti_locked(sc);
   1986  1.100       mrg 
   1987  1.100       mrg 	axe_unlock_mii_sc_locked(sc);
   1988    1.1  augustss 
   1989    1.1  augustss 	/* Open RX and TX pipes. */
   1990    1.1  augustss 	err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_RX],
   1991  1.100       mrg 	    USBD_EXCLUSIVE_USE | USBD_MPSAFE, &sc->axe_ep[AXE_ENDPT_RX]);
   1992    1.1  augustss 	if (err) {
   1993   1.35  pgoyette 		aprint_error_dev(sc->axe_dev, "open rx pipe failed: %s\n",
   1994   1.35  pgoyette 		    usbd_errstr(err));
   1995   1.35  pgoyette 		return EIO;
   1996    1.1  augustss 	}
   1997    1.1  augustss 
   1998    1.1  augustss 	err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX],
   1999  1.100       mrg 	    USBD_EXCLUSIVE_USE | USBD_MPSAFE, &sc->axe_ep[AXE_ENDPT_TX]);
   2000    1.1  augustss 	if (err) {
   2001   1.35  pgoyette 		aprint_error_dev(sc->axe_dev, "open tx pipe failed: %s\n",
   2002   1.35  pgoyette 		    usbd_errstr(err));
   2003   1.35  pgoyette 		return EIO;
   2004    1.1  augustss 	}
   2005    1.1  augustss 
   2006   1.71     skrll 	/* Init RX ring. */
   2007   1.71     skrll 	if (axe_rx_list_init(sc) != 0) {
   2008   1.71     skrll 		aprint_error_dev(sc->axe_dev, "rx list init failed\n");
   2009   1.71     skrll 		return ENOBUFS;
   2010   1.71     skrll 	}
   2011   1.71     skrll 
   2012   1.71     skrll 	/* Init TX ring. */
   2013   1.71     skrll 	if (axe_tx_list_init(sc) != 0) {
   2014   1.71     skrll 		aprint_error_dev(sc->axe_dev, "tx list init failed\n");
   2015   1.71     skrll 		return ENOBUFS;
   2016   1.71     skrll 	}
   2017   1.71     skrll 
   2018  1.100       mrg 	mutex_enter(&sc->axe_rxlock);
   2019  1.100       mrg 	mutex_enter(&sc->axe_txlock);
   2020  1.100       mrg 	sc->axe_stopping = false;
   2021  1.100       mrg 
   2022    1.1  augustss 	/* Start up the receive pipe. */
   2023    1.1  augustss 	for (i = 0; i < AXE_RX_LIST_CNT; i++) {
   2024    1.1  augustss 		c = &sc->axe_cdata.axe_rx_chain[i];
   2025   1.71     skrll 		usbd_setup_xfer(c->axe_xfer, c, c->axe_buf, sc->axe_bufsz,
   2026   1.71     skrll 		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, axe_rxeof);
   2027    1.1  augustss 		usbd_transfer(c->axe_xfer);
   2028    1.1  augustss 	}
   2029    1.1  augustss 
   2030  1.100       mrg 	mutex_exit(&sc->axe_txlock);
   2031  1.100       mrg 	mutex_exit(&sc->axe_rxlock);
   2032  1.100       mrg 
   2033  1.100       mrg 	/* Indicate we are up and running. */
   2034  1.100       mrg 	KASSERT(IFNET_LOCKED(ifp));
   2035    1.1  augustss 	ifp->if_flags |= IFF_RUNNING;
   2036    1.1  augustss 
   2037   1.35  pgoyette 	callout_schedule(&sc->axe_stat_ch, hz);
   2038   1.35  pgoyette 	return 0;
   2039    1.1  augustss }
   2040    1.1  augustss 
   2041   1.35  pgoyette static int
   2042  1.100       mrg axe_init(struct ifnet *ifp)
   2043  1.100       mrg {
   2044  1.100       mrg 	struct axe_softc * const sc = ifp->if_softc;
   2045  1.100       mrg 
   2046  1.100       mrg 	mutex_enter(&sc->axe_lock);
   2047  1.100       mrg 	int ret = axe_init_locked(ifp);
   2048  1.100       mrg 	mutex_exit(&sc->axe_lock);
   2049  1.100       mrg 
   2050  1.100       mrg 	return ret;
   2051  1.100       mrg }
   2052  1.100       mrg 
   2053  1.100       mrg static int
   2054   1.18  christos axe_ioctl(struct ifnet *ifp, u_long cmd, void *data)
   2055    1.1  augustss {
   2056   1.38   tsutsui 	struct axe_softc *sc = ifp->if_softc;
   2057   1.38   tsutsui 	int error = 0;
   2058    1.1  augustss 
   2059   1.96   msaitoh 	switch (cmd) {
   2060   1.35  pgoyette 	case SIOCSIFFLAGS:
   2061   1.38   tsutsui 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
   2062   1.38   tsutsui 			break;
   2063   1.35  pgoyette 
   2064   1.35  pgoyette 		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
   2065   1.35  pgoyette 		case IFF_RUNNING:
   2066   1.35  pgoyette 			axe_stop(ifp, 1);
   2067   1.35  pgoyette 			break;
   2068   1.35  pgoyette 		case IFF_UP:
   2069   1.35  pgoyette 			axe_init(ifp);
   2070   1.35  pgoyette 			break;
   2071   1.35  pgoyette 		case IFF_UP | IFF_RUNNING:
   2072   1.35  pgoyette 			if ((ifp->if_flags ^ sc->axe_if_flags) == IFF_PROMISC)
   2073   1.35  pgoyette 				axe_setmulti(sc);
   2074   1.35  pgoyette 			else
   2075   1.35  pgoyette 				axe_init(ifp);
   2076    1.1  augustss 			break;
   2077    1.1  augustss 		}
   2078  1.100       mrg 		mutex_enter(&sc->axe_rxlock);
   2079  1.100       mrg 		mutex_enter(&sc->axe_txlock);
   2080   1.35  pgoyette 		sc->axe_if_flags = ifp->if_flags;
   2081  1.100       mrg 		mutex_exit(&sc->axe_txlock);
   2082  1.100       mrg 		mutex_exit(&sc->axe_rxlock);
   2083    1.1  augustss 		break;
   2084    1.1  augustss 
   2085   1.35  pgoyette 	default:
   2086   1.35  pgoyette 		if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
   2087   1.26    dyoung 			break;
   2088    1.1  augustss 
   2089    1.1  augustss 		error = 0;
   2090   1.35  pgoyette 
   2091   1.35  pgoyette 		if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI)
   2092   1.35  pgoyette 			axe_setmulti(sc);
   2093   1.35  pgoyette 
   2094    1.1  augustss 	}
   2095    1.1  augustss 
   2096   1.35  pgoyette 	return error;
   2097    1.1  augustss }
   2098    1.1  augustss 
   2099   1.35  pgoyette static void
   2100    1.1  augustss axe_watchdog(struct ifnet *ifp)
   2101    1.1  augustss {
   2102  1.100       mrg 	struct axe_softc * const sc = ifp->if_softc;
   2103   1.38   tsutsui 	struct axe_chain *c;
   2104   1.38   tsutsui 	usbd_status stat;
   2105    1.1  augustss 
   2106    1.1  augustss 	ifp->if_oerrors++;
   2107   1.35  pgoyette 	aprint_error_dev(sc->axe_dev, "watchdog timeout\n");
   2108    1.1  augustss 
   2109    1.1  augustss 	c = &sc->axe_cdata.axe_tx_chain[0];
   2110    1.1  augustss 	usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &stat);
   2111    1.1  augustss 	axe_txeof(c->axe_xfer, c, stat);
   2112    1.1  augustss 
   2113   1.35  pgoyette 	if (!IFQ_IS_EMPTY(&ifp->if_snd))
   2114    1.1  augustss 		axe_start(ifp);
   2115    1.1  augustss }
   2116    1.1  augustss 
   2117    1.1  augustss /*
   2118    1.1  augustss  * Stop the adapter and free any mbufs allocated to the
   2119    1.1  augustss  * RX and TX lists.
   2120    1.1  augustss  */
   2121   1.35  pgoyette static void
   2122  1.100       mrg axe_stop_locked(struct ifnet *ifp, int disable)
   2123    1.1  augustss {
   2124  1.100       mrg 	struct axe_softc * const sc = ifp->if_softc;
   2125   1.38   tsutsui 	usbd_status err;
   2126   1.38   tsutsui 	int i;
   2127    1.1  augustss 
   2128  1.100       mrg 	KASSERT(mutex_owned(&sc->axe_lock));
   2129  1.100       mrg 
   2130  1.100       mrg 	mutex_enter(&sc->axe_rxlock);
   2131  1.100       mrg 	mutex_enter(&sc->axe_txlock);
   2132  1.100       mrg 	sc->axe_stopping = true;
   2133  1.100       mrg 	mutex_exit(&sc->axe_txlock);
   2134  1.100       mrg 	mutex_exit(&sc->axe_rxlock);
   2135  1.100       mrg 
   2136  1.100       mrg 	/*
   2137  1.100       mrg 	 * XXXSMP Would like to
   2138  1.100       mrg 	 *	KASSERT(IFNET_LOCKED(ifp))
   2139  1.100       mrg 	 * here but the locking order is:
   2140  1.100       mrg 	 *	ifnet -> sc lock -> rxlock -> txlock
   2141  1.100       mrg 	 * and sc lock is already held.
   2142  1.100       mrg 	 */
   2143  1.100       mrg 	ifp->if_flags &= ~IFF_RUNNING;
   2144  1.100       mrg 	sc->axe_timer = 0;
   2145    1.1  augustss 
   2146   1.47    dyoung 	callout_stop(&sc->axe_stat_ch);
   2147  1.100       mrg 	sc->axe_link = 0;
   2148    1.1  augustss 
   2149    1.1  augustss 	/* Stop transfers. */
   2150    1.1  augustss 	if (sc->axe_ep[AXE_ENDPT_RX] != NULL) {
   2151    1.1  augustss 		err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]);
   2152    1.1  augustss 		if (err) {
   2153   1.35  pgoyette 			aprint_error_dev(sc->axe_dev,
   2154   1.35  pgoyette 			    "abort rx pipe failed: %s\n", usbd_errstr(err));
   2155    1.1  augustss 		}
   2156    1.1  augustss 	}
   2157    1.1  augustss 
   2158    1.1  augustss 	if (sc->axe_ep[AXE_ENDPT_TX] != NULL) {
   2159    1.1  augustss 		err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]);
   2160    1.1  augustss 		if (err) {
   2161   1.35  pgoyette 			aprint_error_dev(sc->axe_dev,
   2162   1.35  pgoyette 			    "abort tx pipe failed: %s\n", usbd_errstr(err));
   2163    1.1  augustss 		}
   2164    1.1  augustss 	}
   2165    1.1  augustss 
   2166    1.1  augustss 	if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) {
   2167    1.1  augustss 		err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
   2168    1.1  augustss 		if (err) {
   2169   1.35  pgoyette 			aprint_error_dev(sc->axe_dev,
   2170   1.35  pgoyette 			    "abort intr pipe failed: %s\n", usbd_errstr(err));
   2171    1.1  augustss 		}
   2172    1.1  augustss 	}
   2173    1.1  augustss 
   2174   1.76     skrll 	axe_reset(sc);
   2175   1.76     skrll 
   2176    1.1  augustss 	/* Free RX resources. */
   2177    1.1  augustss 	for (i = 0; i < AXE_RX_LIST_CNT; i++) {
   2178    1.1  augustss 		if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) {
   2179   1.71     skrll 			usbd_destroy_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer);
   2180    1.1  augustss 			sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL;
   2181    1.1  augustss 		}
   2182    1.1  augustss 	}
   2183    1.1  augustss 
   2184    1.1  augustss 	/* Free TX resources. */
   2185    1.1  augustss 	for (i = 0; i < AXE_TX_LIST_CNT; i++) {
   2186    1.1  augustss 		if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) {
   2187   1.71     skrll 			usbd_destroy_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer);
   2188    1.1  augustss 			sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL;
   2189    1.1  augustss 		}
   2190    1.1  augustss 	}
   2191    1.1  augustss 
   2192   1.71     skrll 	/* Close pipes. */
   2193   1.71     skrll 	if (sc->axe_ep[AXE_ENDPT_RX] != NULL) {
   2194   1.71     skrll 		err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX]);
   2195   1.71     skrll 		if (err) {
   2196   1.71     skrll 			aprint_error_dev(sc->axe_dev,
   2197   1.71     skrll 			    "close rx pipe failed: %s\n", usbd_errstr(err));
   2198   1.71     skrll 		}
   2199   1.71     skrll 		sc->axe_ep[AXE_ENDPT_RX] = NULL;
   2200   1.71     skrll 	}
   2201   1.71     skrll 
   2202   1.71     skrll 	if (sc->axe_ep[AXE_ENDPT_TX] != NULL) {
   2203   1.71     skrll 		err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX]);
   2204   1.71     skrll 		if (err) {
   2205   1.71     skrll 			aprint_error_dev(sc->axe_dev,
   2206   1.71     skrll 			    "close tx pipe failed: %s\n", usbd_errstr(err));
   2207   1.71     skrll 		}
   2208   1.71     skrll 		sc->axe_ep[AXE_ENDPT_TX] = NULL;
   2209   1.71     skrll 	}
   2210   1.71     skrll 
   2211   1.71     skrll 	if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) {
   2212   1.71     skrll 		err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
   2213   1.71     skrll 		if (err) {
   2214   1.71     skrll 			aprint_error_dev(sc->axe_dev,
   2215   1.71     skrll 			    "close intr pipe failed: %s\n", usbd_errstr(err));
   2216   1.71     skrll 		}
   2217   1.71     skrll 		sc->axe_ep[AXE_ENDPT_INTR] = NULL;
   2218   1.71     skrll 	}
   2219  1.100       mrg }
   2220   1.71     skrll 
   2221  1.100       mrg static void
   2222  1.100       mrg axe_stop(struct ifnet *ifp, int disable)
   2223  1.100       mrg {
   2224  1.100       mrg 	struct axe_softc * const sc = ifp->if_softc;
   2225  1.100       mrg 
   2226  1.100       mrg 	mutex_enter(&sc->axe_lock);
   2227  1.100       mrg 	axe_stop_locked(ifp, disable);
   2228  1.100       mrg 	mutex_exit(&sc->axe_lock);
   2229    1.1  augustss }
   2230   1.48  pgoyette 
   2231   1.93  christos MODULE(MODULE_CLASS_DRIVER, if_axe, NULL);
   2232   1.48  pgoyette 
   2233   1.48  pgoyette #ifdef _MODULE
   2234   1.48  pgoyette #include "ioconf.c"
   2235   1.48  pgoyette #endif
   2236   1.48  pgoyette 
   2237   1.48  pgoyette static int
   2238   1.48  pgoyette if_axe_modcmd(modcmd_t cmd, void *aux)
   2239   1.48  pgoyette {
   2240   1.48  pgoyette 	int error = 0;
   2241   1.48  pgoyette 
   2242   1.48  pgoyette 	switch (cmd) {
   2243   1.48  pgoyette 	case MODULE_CMD_INIT:
   2244   1.48  pgoyette #ifdef _MODULE
   2245   1.49  pgoyette 		error = config_init_component(cfdriver_ioconf_axe,
   2246   1.49  pgoyette 		    cfattach_ioconf_axe, cfdata_ioconf_axe);
   2247   1.48  pgoyette #endif
   2248   1.48  pgoyette 		return error;
   2249   1.48  pgoyette 	case MODULE_CMD_FINI:
   2250   1.48  pgoyette #ifdef _MODULE
   2251   1.49  pgoyette 		error = config_fini_component(cfdriver_ioconf_axe,
   2252   1.49  pgoyette 		    cfattach_ioconf_axe, cfdata_ioconf_axe);
   2253   1.48  pgoyette #endif
   2254   1.48  pgoyette 		return error;
   2255   1.48  pgoyette 	default:
   2256   1.48  pgoyette 		return ENOTTY;
   2257   1.48  pgoyette 	}
   2258   1.48  pgoyette }
   2259