Home | History | Annotate | Line # | Download | only in usb
if_udav.c revision 1.61
      1 /*	$NetBSD: if_udav.c,v 1.61 2019/08/07 19:21:48 skrll Exp $	*/
      2 /*	$nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $	*/
      3 
      4 /*
      5  * Copyright (c) 2003
      6  *     Shingo WATANABE <nabe (at) nabechan.org>.  All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. Neither the name of the author nor the names of any co-contributors
     17  *    may be used to endorse or promote products derived from this software
     18  *    without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     30  * SUCH DAMAGE.
     31  *
     32  */
     33 
     34 /*
     35  * DM9601(DAVICOM USB to Ethernet MAC Controller with Integrated 10/100 PHY)
     36  * The spec can be found at the following url.
     37  *   http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-F01-062202s.pdf
     38  */
     39 
     40 /*
     41  * TODO:
     42  *	Interrupt Endpoint support
     43  *	External PHYs
     44  *	powerhook() support?
     45  */
     46 
     47 #include <sys/cdefs.h>
     48 __KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.61 2019/08/07 19:21:48 skrll Exp $");
     49 
     50 #ifdef _KERNEL_OPT
     51 #include "opt_usb.h"
     52 #endif
     53 
     54 #include <sys/param.h>
     55 #include <sys/systm.h>
     56 #include <sys/module.h>
     57 #include <sys/kernel.h>
     58 
     59 #include <dev/usb/usbnet.h>
     60 #include <dev/usb/if_udavreg.h>
     61 
     62 struct udav_softc {
     63 	struct usbnet		sc_un;
     64 	uint16_t		sc_flags;
     65 };
     66 
     67 /* Function declarations */
     68 int	udav_match(device_t, cfdata_t, void *);
     69 void	udav_attach(device_t, device_t, void *);
     70 
     71 CFATTACH_DECL_NEW(udav, sizeof(struct udav_softc), udav_match, udav_attach,
     72     usbnet_detach, usbnet_activate);
     73 
     74 static void udav_chip_init(struct usbnet *);
     75 
     76 static unsigned udav_tx_prepare(struct usbnet *, struct mbuf *,
     77 			        struct usbnet_chain *);
     78 static void udav_rxeof_loop(struct usbnet *, struct usbd_xfer *,
     79 			    struct usbnet_chain *, uint32_t);
     80 static void udav_stop_cb(struct ifnet *, int);
     81 static int udav_ioctl_cb(struct ifnet *, u_long, void *);
     82 static usbd_status udav_mii_read_reg(struct usbnet *, int, int, uint16_t *);
     83 static usbd_status udav_mii_write_reg(struct usbnet *, int, int, uint16_t);
     84 static void udav_mii_statchg(struct ifnet *);
     85 static int udav_init(struct ifnet *);
     86 static void udav_setiff(struct usbnet *);
     87 static void udav_setiff_locked(struct usbnet *);
     88 static void udav_reset(struct usbnet *);
     89 
     90 static int udav_csr_read(struct udav_softc *, int, void *, int);
     91 static int udav_csr_write(struct udav_softc *, int, void *, int);
     92 static int udav_csr_read1(struct udav_softc *, int);
     93 static int udav_csr_write1(struct udav_softc *, int, unsigned char);
     94 
     95 #if 0
     96 static int udav_mem_read(struct udav_softc *, int, void *, int);
     97 static int udav_mem_write(struct udav_softc *, int, void *, int);
     98 static int udav_mem_write1(struct udav_softc *, int, unsigned char);
     99 #endif
    100 
    101 /* Macros */
    102 #ifdef UDAV_DEBUG
    103 #define DPRINTF(x)	if (udavdebug) printf x
    104 #define DPRINTFN(n, x)	if (udavdebug >= (n)) printf x
    105 int udavdebug = 10;
    106 #else
    107 #define DPRINTF(x)
    108 #define DPRINTFN(n, x)
    109 #endif
    110 
    111 #define	UDAV_SETBIT(sc, reg, x)	\
    112 	udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x))
    113 
    114 #define	UDAV_CLRBIT(sc, reg, x)	\
    115 	udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x))
    116 
    117 static const struct udav_type {
    118 	struct usb_devno udav_dev;
    119 	uint16_t udav_flags;
    120 #define UDAV_EXT_PHY	0x0001
    121 #define UDAV_NO_PHY	0x0002
    122 } udav_devs [] = {
    123 	/* Corega USB-TXC */
    124 	{{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC }, 0},
    125 	/* ShanTou ST268 USB NIC */
    126 	{{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ST268_USB_NIC }, 0},
    127 	/* ShanTou ADM8515 */
    128 	{{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ADM8515 }, 0},
    129 	/* SUNRISING SR9600 */
    130 	{{ USB_VENDOR_SUNRISING, USB_PRODUCT_SUNRISING_SR9600 }, 0 },
    131 	/* SUNRISING QF9700 */
    132 	{{ USB_VENDOR_SUNRISING, USB_PRODUCT_SUNRISING_QF9700 }, UDAV_NO_PHY },
    133 	/* QUAN DM9601 */
    134 	{{USB_VENDOR_QUAN, USB_PRODUCT_QUAN_DM9601 }, 0},
    135 #if 0
    136 	/* DAVICOM DM9601 Generic? */
    137 	/*  XXX: The following ids was obtained from the data sheet. */
    138 	{{ 0x0a46, 0x9601 }, 0},
    139 #endif
    140 };
    141 #define udav_lookup(v, p) ((const struct udav_type *)usb_lookup(udav_devs, v, p))
    142 
    143 
    144 /* Probe */
    145 int
    146 udav_match(device_t parent, cfdata_t match, void *aux)
    147 {
    148 	struct usb_attach_arg *uaa = aux;
    149 
    150 	return udav_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ?
    151 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
    152 }
    153 
    154 /* Attach */
    155 void
    156 udav_attach(device_t parent, device_t self, void *aux)
    157 {
    158 	struct udav_softc *sc = device_private(self);
    159 	struct usbnet * const un = &sc->sc_un;
    160 	struct usb_attach_arg *uaa = aux;
    161 	struct usbd_device *dev = uaa->uaa_device;
    162 	struct usbd_interface *iface;
    163 	usbd_status err;
    164 	usb_interface_descriptor_t *id;
    165 	usb_endpoint_descriptor_t *ed;
    166 	char *devinfop;
    167 	int i;
    168 
    169 	/* Switch to usbnet for device_private() */
    170 	self->dv_private = un;
    171 
    172 	aprint_naive("\n");
    173 	aprint_normal("\n");
    174 	devinfop = usbd_devinfo_alloc(dev, 0);
    175 	aprint_normal_dev(self, "%s\n", devinfop);
    176 	usbd_devinfo_free(devinfop);
    177 
    178 	un->un_dev = self;
    179 	un->un_udev = dev;
    180 	un->un_sc = sc;
    181 	un->un_stop_cb = udav_stop_cb;
    182 	un->un_ioctl_cb = udav_ioctl_cb;
    183 	un->un_read_reg_cb = udav_mii_read_reg;
    184 	un->un_write_reg_cb = udav_mii_write_reg;
    185 	un->un_statchg_cb = udav_mii_statchg;
    186 	un->un_tx_prepare_cb = udav_tx_prepare;
    187 	un->un_rx_loop_cb = udav_rxeof_loop;
    188 	un->un_init_cb = udav_init;
    189 	un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
    190 	un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER;
    191 
    192 	/* Move the device into the configured state. */
    193 	err = usbd_set_config_no(dev, UDAV_CONFIG_NO, 1); /* idx 0 */
    194 	if (err) {
    195 		aprint_error_dev(self, "failed to set configuration"
    196 		    ", err=%s\n", usbd_errstr(err));
    197 		return;
    198 	}
    199 
    200 	/* get control interface */
    201 	err = usbd_device2interface_handle(dev, UDAV_IFACE_INDEX, &iface);
    202 	if (err) {
    203 		aprint_error_dev(self, "failed to get interface, err=%s\n",
    204 		       usbd_errstr(err));
    205 		return;
    206 	}
    207 
    208 	un->un_iface = iface;
    209 	sc->sc_flags = udav_lookup(uaa->uaa_vendor,
    210 	    uaa->uaa_product)->udav_flags;
    211 
    212 	/* get interface descriptor */
    213 	id = usbd_get_interface_descriptor(un->un_iface);
    214 
    215 	/* find endpoints */
    216 	un->un_ed[USBNET_ENDPT_RX] = un->un_ed[USBNET_ENDPT_TX] =
    217 	    un->un_ed[USBNET_ENDPT_INTR] = -1;
    218 	for (i = 0; i < id->bNumEndpoints; i++) {
    219 		ed = usbd_interface2endpoint_descriptor(un->un_iface, i);
    220 		if (ed == NULL) {
    221 			aprint_error_dev(self, "couldn't get endpoint %d\n", i);
    222 			return;
    223 		}
    224 		if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
    225 		    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
    226 			un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
    227 		else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
    228 			 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
    229 			un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
    230 		else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT &&
    231 			 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
    232 			un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress;
    233 	}
    234 
    235 	if (un->un_ed[USBNET_ENDPT_RX] == -1 ||
    236 	    un->un_ed[USBNET_ENDPT_TX] == -1 ||
    237 	    un->un_ed[USBNET_ENDPT_INTR] == -1) {
    238 		aprint_error_dev(self, "missing endpoint\n");
    239 		return;
    240 	}
    241 
    242 	/* Not supported yet. */
    243 	un->un_ed[USBNET_ENDPT_INTR] = 0;
    244 
    245 	un->un_cdata.uncd_rx_bufsz = un->un_cdata.uncd_tx_bufsz = UDAV_BUFSZ;
    246 
    247 // 	/* reset the adapter */
    248 // 	udav_reset(un);
    249 
    250 	usbnet_attach(un, "udavdet", UDAV_RX_LIST_CNT, UDAV_TX_LIST_CNT);
    251 
    252 	/* Get Ethernet Address */
    253 	usbnet_lock_mii(un);
    254 	err = udav_csr_read(sc, UDAV_PAR, un->un_eaddr, ETHER_ADDR_LEN);
    255 	usbnet_unlock_mii(un);
    256 	if (err) {
    257 		aprint_error_dev(self, "read MAC address failed\n");
    258 		return;
    259 	}
    260 
    261 	bool have_mii = !ISSET(sc->sc_flags, UDAV_NO_PHY);
    262 	if (!have_mii)
    263 		un->un_link = 1;
    264 
    265 	/* initialize interface information */
    266 	usbnet_attach_ifp(un, have_mii,
    267 	    IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 0, 0);
    268 
    269 	return;
    270 }
    271 
    272 #if 0
    273 /* read memory */
    274 static int
    275 udav_mem_read(struct udav_softc *sc, int offset, void *buf, int len)
    276 {
    277 	usb_device_request_t req;
    278 	usbd_status err;
    279 
    280 	if (sc == NULL)
    281 		return 0;
    282 
    283 	DPRINTFN(0x200,
    284 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    285 
    286 	if (un->un_dying)
    287 		return 0;
    288 
    289 	offset &= 0xffff;
    290 	len &= 0xff;
    291 
    292 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    293 	req.bRequest = UDAV_REQ_MEM_READ;
    294 	USETW(req.wValue, 0x0000);
    295 	USETW(req.wIndex, offset);
    296 	USETW(req.wLength, len);
    297 
    298 	err = usbd_do_request(un->un_udev, &req, buf);
    299 	if (err) {
    300 		DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
    301 			 device_xname(un->un_dev), __func__, offset, err));
    302 	}
    303 
    304 	return err;
    305 }
    306 
    307 /* write memory */
    308 static int
    309 udav_mem_write(struct udav_softc *sc, int offset, void *buf, int len)
    310 {
    311 	usb_device_request_t req;
    312 	usbd_status err;
    313 
    314 	if (sc == NULL)
    315 		return 0;
    316 
    317 	DPRINTFN(0x200,
    318 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    319 
    320 	if (un->un_dying)
    321 		return 0;
    322 
    323 	offset &= 0xffff;
    324 	len &= 0xff;
    325 
    326 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    327 	req.bRequest = UDAV_REQ_MEM_WRITE;
    328 	USETW(req.wValue, 0x0000);
    329 	USETW(req.wIndex, offset);
    330 	USETW(req.wLength, len);
    331 
    332 	err = usbd_do_request(un->un_udev, &req, buf);
    333 	if (err) {
    334 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
    335 			 device_xname(un->un_dev), __func__, offset, err));
    336 	}
    337 
    338 	return err;
    339 }
    340 
    341 /* write memory */
    342 static int
    343 udav_mem_write1(struct udav_softc *sc, int offset, unsigned char ch)
    344 {
    345 	usb_device_request_t req;
    346 	usbd_status err;
    347 
    348 	if (sc == NULL)
    349 		return 0;
    350 
    351 	DPRINTFN(0x200,
    352 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    353 
    354 	if (un->un_dying)
    355 		return 0;
    356 
    357 	offset &= 0xffff;
    358 
    359 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    360 	req.bRequest = UDAV_REQ_MEM_WRITE1;
    361 	USETW(req.wValue, ch);
    362 	USETW(req.wIndex, offset);
    363 	USETW(req.wLength, 0x0000);
    364 
    365 	err = usbd_do_request(un->un_udev, &req, NULL);
    366 	if (err) {
    367 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
    368 			 device_xname(un->un_dev), __func__, offset, err));
    369 	}
    370 
    371 	return err;
    372 }
    373 #endif
    374 
    375 /* read register(s) */
    376 static int
    377 udav_csr_read(struct udav_softc *sc, int offset, void *buf, int len)
    378 {
    379 	struct usbnet * const un = &sc->sc_un;
    380 	usb_device_request_t req;
    381 	usbd_status err;
    382 
    383 	usbnet_isowned_mii(un);
    384 	KASSERT(!un->un_dying);
    385 
    386 	DPRINTFN(0x200,
    387 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    388 
    389 	offset &= 0xff;
    390 	len &= 0xff;
    391 
    392 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    393 	req.bRequest = UDAV_REQ_REG_READ;
    394 	USETW(req.wValue, 0x0000);
    395 	USETW(req.wIndex, offset);
    396 	USETW(req.wLength, len);
    397 
    398 	err = usbd_do_request(un->un_udev, &req, buf);
    399 	if (err) {
    400 		DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
    401 			 device_xname(un->un_dev), __func__, offset, err));
    402 	}
    403 
    404 	return err;
    405 }
    406 
    407 /* write register(s) */
    408 static int
    409 udav_csr_write(struct udav_softc *sc, int offset, void *buf, int len)
    410 {
    411 	struct usbnet * const un = &sc->sc_un;
    412 	usb_device_request_t req;
    413 	usbd_status err;
    414 
    415 	usbnet_isowned_mii(un);
    416 	KASSERT(!un->un_dying);
    417 
    418 	DPRINTFN(0x200,
    419 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    420 
    421 	offset &= 0xff;
    422 	len &= 0xff;
    423 
    424 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    425 	req.bRequest = UDAV_REQ_REG_WRITE;
    426 	USETW(req.wValue, 0x0000);
    427 	USETW(req.wIndex, offset);
    428 	USETW(req.wLength, len);
    429 
    430 	err = usbd_do_request(un->un_udev, &req, buf);
    431 	if (err) {
    432 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
    433 			 device_xname(un->un_dev), __func__, offset, err));
    434 	}
    435 
    436 	return err;
    437 }
    438 
    439 static int
    440 udav_csr_read1(struct udav_softc *sc, int offset)
    441 {
    442 	struct usbnet * const un = &sc->sc_un;
    443 	uint8_t val = 0;
    444 
    445 	usbnet_isowned_mii(un);
    446 
    447 	DPRINTFN(0x200,
    448 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    449 
    450 	if (un->un_dying)
    451 		return 0;
    452 
    453 	return udav_csr_read(sc, offset, &val, 1) ? 0 : val;
    454 }
    455 
    456 /* write a register */
    457 static int
    458 udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch)
    459 {
    460 	struct usbnet * const un = &sc->sc_un;
    461 	usb_device_request_t req;
    462 	usbd_status err;
    463 
    464 	usbnet_isowned_mii(un);
    465 	KASSERT(!un->un_dying);
    466 
    467 	DPRINTFN(0x200,
    468 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    469 
    470 	offset &= 0xff;
    471 
    472 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    473 	req.bRequest = UDAV_REQ_REG_WRITE1;
    474 	USETW(req.wValue, ch);
    475 	USETW(req.wIndex, offset);
    476 	USETW(req.wLength, 0x0000);
    477 
    478 	err = usbd_do_request(un->un_udev, &req, NULL);
    479 	if (err) {
    480 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
    481 			 device_xname(un->un_dev), __func__, offset, err));
    482 	}
    483 
    484 	return err;
    485 }
    486 
    487 static int
    488 udav_init_locked(struct ifnet *ifp)
    489 {
    490 	struct usbnet * const un = ifp->if_softc;
    491 	struct mii_data * const mii = usbnet_mii(un);
    492 	struct udav_softc *sc = usbnet_softc(un);
    493 	uint8_t eaddr[ETHER_ADDR_LEN];
    494 	int rc;
    495 
    496 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    497 
    498 	usbnet_isowned(un);
    499 
    500 	if (un->un_dying)
    501 		return EIO;
    502 
    503 	/* Cancel pending I/O and free all TX/RX buffers */
    504 	if (ifp->if_flags & IFF_RUNNING)
    505 		usbnet_stop(un, ifp, 1);
    506 
    507 	usbnet_lock_mii_un_locked(un);
    508 
    509 	memcpy(eaddr, CLLADDR(ifp->if_sadl), sizeof(eaddr));
    510 	udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN);
    511 
    512 	/* Initialize network control register */
    513 	/*  Disable loopback  */
    514 	UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1);
    515 
    516 	/* Initialize RX control register */
    517 	UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC);
    518 
    519 	/* If we want promiscuous mode, accept all physical frames. */
    520 	if (ifp->if_flags & IFF_PROMISC)
    521 		UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC);
    522 	else
    523 		UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC);
    524 
    525 	/* Load the multicast filter */
    526 	udav_setiff_locked(un);
    527 
    528 	/* Enable RX */
    529 	UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN);
    530 
    531 	/* clear POWER_DOWN state of internal PHY */
    532 	UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0);
    533 	UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0);
    534 
    535 	usbnet_unlock_mii_un_locked(un);
    536 
    537 	rc = 0;
    538 	if (mii) {
    539 		if ((rc = mii_mediachg(mii)) == ENXIO)
    540 			rc = 0;
    541 	}
    542 
    543 	if (rc != 0)
    544 		return rc;
    545 
    546 	return usbnet_init_rx_tx(un, 0, USBD_FORCE_SHORT_XFER);
    547 }
    548 
    549 static int
    550 udav_init(struct ifnet *ifp)
    551 {
    552 	struct usbnet * const un = ifp->if_softc;
    553 
    554 	usbnet_lock(un);
    555 	int ret = udav_init_locked(ifp);
    556 	usbnet_unlock(un);
    557 
    558 	return ret;
    559 }
    560 
    561 static void
    562 udav_reset(struct usbnet *un)
    563 {
    564     	usbnet_isowned(un);
    565 
    566 	if (un->un_dying)
    567 		return;
    568 
    569 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    570 
    571 	udav_chip_init(un);
    572 }
    573 
    574 static void
    575 udav_chip_init(struct usbnet *un)
    576 {
    577     	struct udav_softc * const sc = usbnet_softc(un);
    578 
    579 	usbnet_lock_mii_un_locked(un);
    580 
    581 	/* Select PHY */
    582 #if 1
    583 	/*
    584 	 * XXX: force select internal phy.
    585 	 *	external phy routines are not tested.
    586 	 */
    587 	UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
    588 #else
    589 	if (sc->sc_flags & UDAV_EXT_PHY) {
    590 		UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
    591 	} else {
    592 		UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
    593 	}
    594 #endif
    595 
    596 	UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST);
    597 
    598 	for (int i = 0; i < UDAV_TX_TIMEOUT; i++) {
    599 		if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST))
    600 			break;
    601 		delay(10);	/* XXX */
    602 	}
    603 	delay(10000);		/* XXX */
    604 
    605 	usbnet_unlock_mii_un_locked(un);
    606 }
    607 
    608 #define UDAV_BITS	6
    609 
    610 #define UDAV_CALCHASH(addr) \
    611 	(ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1))
    612 
    613 static void
    614 udav_setiff_locked(struct usbnet *un)
    615 {
    616 	struct udav_softc *sc = usbnet_softc(un);
    617 	struct ethercom *ec = usbnet_ec(un);
    618 	struct ifnet * const ifp = usbnet_ifp(un);
    619 	struct ether_multi *enm;
    620 	struct ether_multistep step;
    621 	uint8_t hashes[8];
    622 	int h = 0;
    623 
    624 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    625 
    626 	usbnet_isowned_mii(un);
    627 
    628 	if (un->un_dying)
    629 		return;
    630 
    631 	if (ISSET(sc->sc_flags, UDAV_NO_PHY)) {
    632 		UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
    633 		UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_PRMSC);
    634 		return;
    635 	}
    636 
    637 	if (ifp->if_flags & IFF_PROMISC) {
    638 		UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC);
    639 		return;
    640 	} else if (ifp->if_flags & IFF_ALLMULTI) {
    641 allmulti:
    642 		ifp->if_flags |= IFF_ALLMULTI;
    643 		UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
    644 		UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_PRMSC);
    645 		return;
    646 	}
    647 
    648 	/* first, zot all the existing hash bits */
    649 	memset(hashes, 0x00, sizeof(hashes));
    650 	hashes[7] |= 0x80;	/* broadcast address */
    651 	udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
    652 
    653 	/* now program new ones */
    654 	ETHER_LOCK(ec);
    655 	ETHER_FIRST_MULTI(step, ec, enm);
    656 	while (enm != NULL) {
    657 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
    658 		    ETHER_ADDR_LEN) != 0) {
    659 			ETHER_UNLOCK(ec);
    660 			goto allmulti;
    661 		}
    662 
    663 		h = UDAV_CALCHASH(enm->enm_addrlo);
    664 		hashes[h>>3] |= 1 << (h & 0x7);
    665 		ETHER_NEXT_MULTI(step, enm);
    666 	}
    667 	ETHER_UNLOCK(ec);
    668 
    669 	/* disable all multicast */
    670 	ifp->if_flags &= ~IFF_ALLMULTI;
    671 	UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
    672 
    673 	/* write hash value to the register */
    674 	udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
    675 }
    676 
    677 static void
    678 udav_setiff(struct usbnet *un)
    679 {
    680 	usbnet_lock_mii(un);
    681 	udav_setiff_locked(un);
    682 	usbnet_unlock_mii(un);
    683 }
    684 
    685 
    686 static unsigned
    687 udav_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
    688 {
    689 	int total_len;
    690 	uint8_t *buf = c->unc_buf;
    691 
    692 	usbnet_isowned_tx(un);
    693 
    694 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    695 
    696 	if (m->m_pkthdr.len > UDAV_BUFSZ - 2)
    697 		return 0;
    698 
    699 	/* Copy the mbuf data into a contiguous buffer */
    700 	m_copydata(m, 0, m->m_pkthdr.len, buf + 2);
    701 	total_len = m->m_pkthdr.len;
    702 	if (total_len < UDAV_MIN_FRAME_LEN) {
    703 		memset(buf + 2 + total_len, 0,
    704 		    UDAV_MIN_FRAME_LEN - total_len);
    705 		total_len = UDAV_MIN_FRAME_LEN;
    706 	}
    707 
    708 	/* Frame length is specified in the first 2bytes of the buffer */
    709 	buf[0] = (uint8_t)total_len;
    710 	buf[1] = (uint8_t)(total_len >> 8);
    711 	total_len += 2;
    712 
    713 	DPRINTF(("%s: %s: send %d bytes\n", device_xname(un->un_dev),
    714 	    __func__, total_len));
    715 
    716 	return total_len;
    717 }
    718 
    719 static void
    720 udav_rxeof_loop(struct usbnet *un, struct usbd_xfer *xfer,
    721 	        struct usbnet_chain *c, uint32_t total_len)
    722 {
    723 	struct ifnet *ifp = usbnet_ifp(un);
    724 	uint8_t *buf = c->unc_buf;
    725 	uint16_t pkt_len;
    726 	uint8_t pktstat;
    727 
    728 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    729 
    730 	/* first byte in received data */
    731 	pktstat = *buf;
    732 	total_len -= sizeof(pktstat);
    733 	buf += sizeof(pktstat);
    734 
    735 	DPRINTF(("%s: RX Status: 0x%02x\n", device_xname(un->un_dev), pktstat));
    736 
    737 	pkt_len = UGETW(buf);
    738  	total_len -= sizeof(pkt_len);
    739 	buf += sizeof(pkt_len);
    740 
    741 	DPRINTF(("%s: RX Length: 0x%02x\n", device_xname(un->un_dev), pkt_len));
    742 
    743 	if (pktstat & UDAV_RSR_LCS) {
    744 		ifp->if_collisions++;
    745 		return;
    746 	}
    747 
    748 	if (pkt_len < sizeof(struct ether_header) ||
    749 	    pkt_len > total_len ||
    750 	    (pktstat & UDAV_RSR_ERR)) {
    751 		ifp->if_ierrors++;
    752 		return;
    753 	}
    754 
    755 	pkt_len -= ETHER_CRC_LEN;
    756 
    757 	DPRINTF(("%s: Rx deliver: 0x%02x\n", device_xname(un->un_dev), pkt_len));
    758 
    759 	usbnet_enqueue(un, buf, pkt_len, 0, 0, 0);
    760 }
    761 
    762 static int
    763 udav_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data)
    764 {
    765 	struct usbnet * const un = ifp->if_softc;
    766 
    767 	switch (cmd) {
    768 	case SIOCADDMULTI:
    769 	case SIOCDELMULTI:
    770 		udav_setiff(un);
    771 		break;
    772 	default:
    773 		break;
    774 	}
    775 
    776 
    777 	return 0;
    778 }
    779 
    780 /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
    781 static void
    782 udav_stop_cb(struct ifnet *ifp, int disable)
    783 {
    784 	struct usbnet * const un = ifp->if_softc;
    785 
    786 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    787 
    788 	udav_reset(un);
    789 }
    790 
    791 static usbd_status
    792 udav_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val)
    793 {
    794 	struct udav_softc *sc = usbnet_softc(un);
    795 	uint8_t data[2];
    796 
    797 	usbnet_isowned_mii(un);
    798 
    799 	DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n",
    800 		 device_xname(un->un_dev), __func__, phy, reg));
    801 
    802 	if (un->un_dying) {
    803 #ifdef DIAGNOSTIC
    804 		printf("%s: %s: dying\n", device_xname(un->un_dev),
    805 		       __func__);
    806 #endif
    807 		return USBD_INVAL;
    808 	}
    809 
    810 	/* XXX: one PHY only for the internal PHY */
    811 	if (phy != 0) {
    812 		DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
    813 			 device_xname(un->un_dev), __func__, phy));
    814 		return USBD_INVAL;
    815 	}
    816 
    817 	/* select internal PHY and set PHY register address */
    818 	udav_csr_write1(sc, UDAV_EPAR,
    819 			UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
    820 
    821 	/* select PHY operation and start read command */
    822 	udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRR);
    823 
    824 	/* XXX: should be wait? */
    825 
    826 	/* end read command */
    827 	UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRR);
    828 
    829 	/* retrieve the result from data registers */
    830 	udav_csr_read(sc, UDAV_EPDRL, data, 2);
    831 
    832 	*val = data[0] | (data[1] << 8);
    833 
    834 	DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04hx\n",
    835 		device_xname(un->un_dev), __func__, phy, reg, *val));
    836 
    837 	return USBD_NORMAL_COMPLETION;
    838 }
    839 
    840 static usbd_status
    841 udav_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val)
    842 {
    843 	struct udav_softc *sc = usbnet_softc(un);
    844 	uint8_t data[2];
    845 
    846 	usbnet_isowned_mii(un);
    847 
    848 	DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x val=0x%04hx\n",
    849 		 device_xname(un->un_dev), __func__, phy, reg, val));
    850 
    851 	if (un->un_dying) {
    852 #ifdef DIAGNOSTIC
    853 		printf("%s: %s: dying\n", device_xname(un->un_dev),
    854 		       __func__);
    855 #endif
    856 		return -1;
    857 	}
    858 
    859 	/* XXX: one PHY only for the internal PHY */
    860 	if (phy != 0) {
    861 		DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
    862 			 device_xname(un->un_dev), __func__, phy));
    863 		return -1;
    864 	}
    865 
    866 	/* select internal PHY and set PHY register address */
    867 	udav_csr_write1(sc, UDAV_EPAR,
    868 			UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
    869 
    870 	/* put the value to the data registers */
    871 	data[0] = val & 0xff;
    872 	data[1] = (val >> 8) & 0xff;
    873 	udav_csr_write(sc, UDAV_EPDRL, data, 2);
    874 
    875 	/* select PHY operation and start write command */
    876 	udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRW);
    877 
    878 	/* XXX: should be wait? */
    879 
    880 	/* end write command */
    881 	UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW);
    882 
    883 	return USBD_NORMAL_COMPLETION;
    884 }
    885 
    886 static void
    887 udav_mii_statchg(struct ifnet *ifp)
    888 {
    889 	struct usbnet * const un = ifp->if_softc;
    890 	struct mii_data * const mii = usbnet_mii(un);
    891 
    892 	DPRINTF(("%s: %s: enter\n", ifp->if_xname, __func__));
    893 
    894 	if (un->un_dying)
    895 		return;
    896 
    897 	un->un_link = false;
    898 	if (mii->mii_media_status & IFM_ACTIVE &&
    899 	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
    900 		DPRINTF(("%s: %s: got link\n",
    901 			 device_xname(un->un_dev), __func__));
    902 		un->un_link = true;
    903 	}
    904 }
    905 
    906 MODULE(MODULE_CLASS_DRIVER, if_udav, "usbnet");
    907 
    908 #ifdef _MODULE
    909 #include "ioconf.c"
    910 #endif
    911 
    912 static int
    913 if_udav_modcmd(modcmd_t cmd, void *aux)
    914 {
    915 	int error = 0;
    916 
    917 	switch (cmd) {
    918 	case MODULE_CMD_INIT:
    919 #ifdef _MODULE
    920 		error = config_init_component(cfdriver_ioconf_udav,
    921 		    cfattach_ioconf_udav, cfdata_ioconf_udav);
    922 #endif
    923 		return error;
    924 	case MODULE_CMD_FINI:
    925 #ifdef _MODULE
    926 		error = config_fini_component(cfdriver_ioconf_udav,
    927 		    cfattach_ioconf_udav, cfdata_ioconf_udav);
    928 #endif
    929 		return error;
    930 	default:
    931 		return ENOTTY;
    932 	}
    933 }
    934