Home | History | Annotate | Line # | Download | only in usb
if_udav.c revision 1.77
      1 /*	$NetBSD: if_udav.c,v 1.77 2020/03/15 23:04:51 thorpej 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.77 2020/03/15 23:04:51 thorpej Exp $");
     49 
     50 #ifdef _KERNEL_OPT
     51 #include "opt_usb.h"
     52 #endif
     53 
     54 #include <sys/param.h>
     55 
     56 #include <dev/usb/usbnet.h>
     57 #include <dev/usb/if_udavreg.h>
     58 
     59 /* Function declarations */
     60 static int	udav_match(device_t, cfdata_t, void *);
     61 static void	udav_attach(device_t, device_t, void *);
     62 
     63 CFATTACH_DECL_NEW(udav, sizeof(struct usbnet), udav_match, udav_attach,
     64     usbnet_detach, usbnet_activate);
     65 
     66 static void udav_chip_init(struct usbnet *);
     67 
     68 static unsigned udav_uno_tx_prepare(struct usbnet *, struct mbuf *,
     69 				    struct usbnet_chain *);
     70 static void udav_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t);
     71 static void udav_uno_stop(struct ifnet *, int);
     72 static int udav_uno_ioctl(struct ifnet *, u_long, void *);
     73 static int udav_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *);
     74 static int udav_uno_mii_write_reg(struct usbnet *, int, int, uint16_t);
     75 static void udav_uno_mii_statchg(struct ifnet *);
     76 static int udav_uno_init(struct ifnet *);
     77 static void udav_setiff_locked(struct usbnet *);
     78 static void udav_reset(struct usbnet *);
     79 
     80 static int udav_csr_read(struct usbnet *, int, void *, int);
     81 static int udav_csr_write(struct usbnet *, int, void *, int);
     82 static int udav_csr_read1(struct usbnet *, int);
     83 static int udav_csr_write1(struct usbnet *, int, unsigned char);
     84 
     85 #if 0
     86 static int udav_mem_read(struct usbnet *, int, void *, int);
     87 static int udav_mem_write(struct usbnet *, int, void *, int);
     88 static int udav_mem_write1(struct usbnet *, int, unsigned char);
     89 #endif
     90 
     91 /* Macros */
     92 #ifdef UDAV_DEBUG
     93 #define DPRINTF(x)	if (udavdebug) printf x
     94 #define DPRINTFN(n, x)	if (udavdebug >= (n)) printf x
     95 int udavdebug = 0;
     96 #else
     97 #define DPRINTF(x)
     98 #define DPRINTFN(n, x)
     99 #endif
    100 
    101 #define	UDAV_SETBIT(un, reg, x)	\
    102 	udav_csr_write1(un, reg, udav_csr_read1(un, reg) | (x))
    103 
    104 #define	UDAV_CLRBIT(un, reg, x)	\
    105 	udav_csr_write1(un, reg, udav_csr_read1(un, reg) & ~(x))
    106 
    107 static const struct udav_type {
    108 	struct usb_devno udav_dev;
    109 	uint16_t udav_flags;
    110 #define UDAV_EXT_PHY	0x0001
    111 #define UDAV_NO_PHY	0x0002
    112 } udav_devs [] = {
    113 	/* Corega USB-TXC */
    114 	{{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC }, 0},
    115 	/* ShanTou ST268 USB NIC */
    116 	{{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ST268_USB_NIC }, 0},
    117 	/* ShanTou ADM8515 */
    118 	{{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ADM8515 }, 0},
    119 	/* SUNRISING SR9600 */
    120 	{{ USB_VENDOR_SUNRISING, USB_PRODUCT_SUNRISING_SR9600 }, 0 },
    121 	/* SUNRISING QF9700 */
    122 	{{ USB_VENDOR_SUNRISING, USB_PRODUCT_SUNRISING_QF9700 }, UDAV_NO_PHY },
    123 	/* QUAN DM9601 */
    124 	{{USB_VENDOR_QUAN, USB_PRODUCT_QUAN_DM9601 }, 0},
    125 #if 0
    126 	/* DAVICOM DM9601 Generic? */
    127 	/*  XXX: The following ids was obtained from the data sheet. */
    128 	{{ 0x0a46, 0x9601 }, 0},
    129 #endif
    130 };
    131 #define udav_lookup(v, p) ((const struct udav_type *)usb_lookup(udav_devs, v, p))
    132 
    133 static const struct usbnet_ops udav_ops = {
    134 	.uno_stop = udav_uno_stop,
    135 	.uno_ioctl = udav_uno_ioctl,
    136 	.uno_read_reg = udav_uno_mii_read_reg,
    137 	.uno_write_reg = udav_uno_mii_write_reg,
    138 	.uno_statchg = udav_uno_mii_statchg,
    139 	.uno_tx_prepare = udav_uno_tx_prepare,
    140 	.uno_rx_loop = udav_uno_rx_loop,
    141 	.uno_init = udav_uno_init,
    142 };
    143 
    144 /* Probe */
    145 static 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 static void
    156 udav_attach(device_t parent, device_t self, void *aux)
    157 {
    158 	USBNET_MII_DECL_DEFAULT(unm);
    159 	struct usbnet_mii *unmp;
    160 	struct usbnet * const un = device_private(self);
    161 	struct usb_attach_arg *uaa = aux;
    162 	struct usbd_device *dev = uaa->uaa_device;
    163 	struct usbd_interface *iface;
    164 	usbd_status err;
    165 	usb_interface_descriptor_t *id;
    166 	usb_endpoint_descriptor_t *ed;
    167 	char *devinfop;
    168 	int i;
    169 
    170 	aprint_naive("\n");
    171 	aprint_normal("\n");
    172 	devinfop = usbd_devinfo_alloc(dev, 0);
    173 	aprint_normal_dev(self, "%s\n", devinfop);
    174 	usbd_devinfo_free(devinfop);
    175 
    176 	un->un_dev = self;
    177 	un->un_udev = dev;
    178 	un->un_sc = un;
    179 	un->un_ops = &udav_ops;
    180 	un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
    181 	un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER;
    182 	un->un_rx_list_cnt = UDAV_RX_LIST_CNT;
    183 	un->un_tx_list_cnt = UDAV_TX_LIST_CNT;
    184 	un->un_rx_bufsz = UDAV_BUFSZ;
    185 	un->un_tx_bufsz = UDAV_BUFSZ;
    186 
    187 	/* Move the device into the configured state. */
    188 	err = usbd_set_config_no(dev, UDAV_CONFIG_NO, 1); /* idx 0 */
    189 	if (err) {
    190 		aprint_error_dev(self, "failed to set configuration"
    191 		    ", err=%s\n", usbd_errstr(err));
    192 		return;
    193 	}
    194 
    195 	/* get control interface */
    196 	err = usbd_device2interface_handle(dev, UDAV_IFACE_INDEX, &iface);
    197 	if (err) {
    198 		aprint_error_dev(self, "failed to get interface, err=%s\n",
    199 		       usbd_errstr(err));
    200 		return;
    201 	}
    202 
    203 	un->un_iface = iface;
    204 	un->un_flags = udav_lookup(uaa->uaa_vendor,
    205 	    uaa->uaa_product)->udav_flags;
    206 
    207 	/* get interface descriptor */
    208 	id = usbd_get_interface_descriptor(un->un_iface);
    209 
    210 	/* find endpoints */
    211 	un->un_ed[USBNET_ENDPT_RX] = un->un_ed[USBNET_ENDPT_TX] =
    212 	    un->un_ed[USBNET_ENDPT_INTR] = -1;
    213 	for (i = 0; i < id->bNumEndpoints; i++) {
    214 		ed = usbd_interface2endpoint_descriptor(un->un_iface, i);
    215 		if (ed == NULL) {
    216 			aprint_error_dev(self, "couldn't get endpoint %d\n", i);
    217 			return;
    218 		}
    219 		if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
    220 		    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
    221 			un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
    222 		else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
    223 			 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
    224 			un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
    225 		else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT &&
    226 			 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
    227 			un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress;
    228 	}
    229 
    230 	if (un->un_ed[USBNET_ENDPT_RX] == 0 ||
    231 	    un->un_ed[USBNET_ENDPT_TX] == 0 ||
    232 	    un->un_ed[USBNET_ENDPT_INTR] == 0) {
    233 		aprint_error_dev(self, "missing endpoint\n");
    234 		return;
    235 	}
    236 
    237 	/* Not supported yet. */
    238 	un->un_ed[USBNET_ENDPT_INTR] = 0;
    239 
    240 	usbnet_lock_core(un);
    241 	usbnet_busy(un);
    242 
    243 // 	/* reset the adapter */
    244 // 	udav_reset(un);
    245 
    246 	usbnet_attach(un, "udavdet");
    247 
    248 	/* Get Ethernet Address */
    249 	err = udav_csr_read(un, UDAV_PAR, un->un_eaddr, ETHER_ADDR_LEN);
    250 	usbnet_unbusy(un);
    251 	usbnet_unlock_core(un);
    252 	if (err) {
    253 		aprint_error_dev(self, "read MAC address failed\n");
    254 		return;
    255 	}
    256 
    257 	if (ISSET(un->un_flags, UDAV_NO_PHY))
    258 		unmp = NULL;
    259 	else
    260 		unmp = &unm;
    261 
    262 	/* initialize interface information */
    263 	usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST,
    264 	    0, unmp);
    265 
    266 	return;
    267 }
    268 
    269 #if 0
    270 /* read memory */
    271 static int
    272 udav_mem_read(struct usbnet *un, int offset, void *buf, int len)
    273 {
    274 	usb_device_request_t req;
    275 	usbd_status err;
    276 
    277 	DPRINTFN(0x200,
    278 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    279 
    280 	if (usbnet_isdying(un))
    281 		return 0;
    282 
    283 	offset &= 0xffff;
    284 	len &= 0xff;
    285 
    286 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    287 	req.bRequest = UDAV_REQ_MEM_READ;
    288 	USETW(req.wValue, 0x0000);
    289 	USETW(req.wIndex, offset);
    290 	USETW(req.wLength, len);
    291 
    292 	err = usbd_do_request(un->un_udev, &req, buf);
    293 	if (err) {
    294 		DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
    295 			 device_xname(un->un_dev), __func__, offset, err));
    296 	}
    297 
    298 	return err;
    299 }
    300 
    301 /* write memory */
    302 static int
    303 udav_mem_write(struct usbnet *un, int offset, void *buf, int len)
    304 {
    305 	usb_device_request_t req;
    306 	usbd_status err;
    307 
    308 	DPRINTFN(0x200,
    309 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    310 
    311 	if (usbnet_isdying(un))
    312 		return 0;
    313 
    314 	offset &= 0xffff;
    315 	len &= 0xff;
    316 
    317 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    318 	req.bRequest = UDAV_REQ_MEM_WRITE;
    319 	USETW(req.wValue, 0x0000);
    320 	USETW(req.wIndex, offset);
    321 	USETW(req.wLength, len);
    322 
    323 	err = usbd_do_request(un->un_udev, &req, buf);
    324 	if (err) {
    325 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
    326 			 device_xname(un->un_dev), __func__, offset, err));
    327 	}
    328 
    329 	return err;
    330 }
    331 
    332 /* write memory */
    333 static int
    334 udav_mem_write1(struct usbnet *un, int offset, unsigned char ch)
    335 {
    336 	usb_device_request_t req;
    337 	usbd_status err;
    338 
    339 	DPRINTFN(0x200,
    340 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    341 
    342 	if (usbnet_isdying(un))
    343 		return 0;
    344 
    345 	offset &= 0xffff;
    346 
    347 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    348 	req.bRequest = UDAV_REQ_MEM_WRITE1;
    349 	USETW(req.wValue, ch);
    350 	USETW(req.wIndex, offset);
    351 	USETW(req.wLength, 0x0000);
    352 
    353 	err = usbd_do_request(un->un_udev, &req, NULL);
    354 	if (err) {
    355 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
    356 			 device_xname(un->un_dev), __func__, offset, err));
    357 	}
    358 
    359 	return err;
    360 }
    361 #endif
    362 
    363 /* read register(s) */
    364 static int
    365 udav_csr_read(struct usbnet *un, int offset, void *buf, int len)
    366 {
    367 	usb_device_request_t req;
    368 	usbd_status err;
    369 
    370 	usbnet_isowned_core(un);
    371 	KASSERT(!usbnet_isdying(un));
    372 
    373 	DPRINTFN(0x200,
    374 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    375 
    376 	offset &= 0xff;
    377 	len &= 0xff;
    378 
    379 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    380 	req.bRequest = UDAV_REQ_REG_READ;
    381 	USETW(req.wValue, 0x0000);
    382 	USETW(req.wIndex, offset);
    383 	USETW(req.wLength, len);
    384 
    385 	err = usbd_do_request(un->un_udev, &req, buf);
    386 	if (err) {
    387 		DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
    388 			 device_xname(un->un_dev), __func__, offset, err));
    389 	}
    390 
    391 	return err;
    392 }
    393 
    394 /* write register(s) */
    395 static int
    396 udav_csr_write(struct usbnet *un, int offset, void *buf, int len)
    397 {
    398 	usb_device_request_t req;
    399 	usbd_status err;
    400 
    401 	usbnet_isowned_core(un);
    402 	KASSERT(!usbnet_isdying(un));
    403 
    404 	DPRINTFN(0x200,
    405 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    406 
    407 	offset &= 0xff;
    408 	len &= 0xff;
    409 
    410 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    411 	req.bRequest = UDAV_REQ_REG_WRITE;
    412 	USETW(req.wValue, 0x0000);
    413 	USETW(req.wIndex, offset);
    414 	USETW(req.wLength, len);
    415 
    416 	err = usbd_do_request(un->un_udev, &req, buf);
    417 	if (err) {
    418 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
    419 			 device_xname(un->un_dev), __func__, offset, err));
    420 	}
    421 
    422 	return err;
    423 }
    424 
    425 static int
    426 udav_csr_read1(struct usbnet *un, int offset)
    427 {
    428 	uint8_t val = 0;
    429 
    430 	usbnet_isowned_core(un);
    431 
    432 	DPRINTFN(0x200,
    433 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    434 
    435 	if (usbnet_isdying(un))
    436 		return 0;
    437 
    438 	return udav_csr_read(un, offset, &val, 1) ? 0 : val;
    439 }
    440 
    441 /* write a register */
    442 static int
    443 udav_csr_write1(struct usbnet *un, int offset, unsigned char ch)
    444 {
    445 	usb_device_request_t req;
    446 	usbd_status err;
    447 
    448 	usbnet_isowned_core(un);
    449 	KASSERT(!usbnet_isdying(un));
    450 
    451 	DPRINTFN(0x200,
    452 		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    453 
    454 	offset &= 0xff;
    455 
    456 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    457 	req.bRequest = UDAV_REQ_REG_WRITE1;
    458 	USETW(req.wValue, ch);
    459 	USETW(req.wIndex, offset);
    460 	USETW(req.wLength, 0x0000);
    461 
    462 	err = usbd_do_request(un->un_udev, &req, NULL);
    463 	if (err) {
    464 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
    465 			 device_xname(un->un_dev), __func__, offset, err));
    466 	}
    467 
    468 	return err;
    469 }
    470 
    471 static int
    472 udav_uno_init(struct ifnet *ifp)
    473 {
    474 	struct usbnet * const un = ifp->if_softc;
    475 	struct mii_data * const mii = usbnet_mii(un);
    476 	uint8_t eaddr[ETHER_ADDR_LEN];
    477 	int rc = 0;
    478 
    479 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    480 
    481 	usbnet_lock_core(un);
    482 
    483 	if (usbnet_isdying(un)) {
    484 		usbnet_unlock_core(un);
    485 		return EIO;
    486 	}
    487 
    488 	/* Cancel pending I/O and free all TX/RX buffers */
    489 	if (ifp->if_flags & IFF_RUNNING)
    490 		usbnet_stop(un, ifp, 1);
    491 
    492 	usbnet_busy(un);
    493 
    494 	memcpy(eaddr, CLLADDR(ifp->if_sadl), sizeof(eaddr));
    495 	udav_csr_write(un, UDAV_PAR, eaddr, ETHER_ADDR_LEN);
    496 
    497 	/* Initialize network control register */
    498 	/*  Disable loopback  */
    499 	UDAV_CLRBIT(un, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1);
    500 
    501 	/* Initialize RX control register */
    502 	UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC);
    503 
    504 	/* If we want promiscuous mode, accept all physical frames. */
    505 	if (ifp->if_flags & IFF_PROMISC)
    506 		UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC);
    507 	else
    508 		UDAV_CLRBIT(un, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC);
    509 
    510 	/* Load the multicast filter */
    511 	udav_setiff_locked(un);
    512 
    513 	/* Enable RX */
    514 	UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_RXEN);
    515 
    516 	/* clear POWER_DOWN state of internal PHY */
    517 	UDAV_SETBIT(un, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0);
    518 	UDAV_CLRBIT(un, UDAV_GPR, UDAV_GPR_GEPIO0);
    519 
    520 	if (mii && (rc = mii_mediachg(mii)) == ENXIO)
    521 		rc = 0;
    522 
    523 	if (rc != 0) {
    524 		usbnet_unbusy(un);
    525 		usbnet_unlock_core(un);
    526 		return rc;
    527 	}
    528 
    529 	if (usbnet_isdying(un))
    530 		rc = EIO;
    531 	else
    532 		rc = usbnet_init_rx_tx(un);
    533 
    534 	usbnet_unbusy(un);
    535 	usbnet_unlock_core(un);
    536 
    537 	return rc;
    538 }
    539 
    540 static void
    541 udav_reset(struct usbnet *un)
    542 {
    543     	usbnet_isowned_core(un);
    544 
    545 	if (usbnet_isdying(un))
    546 		return;
    547 
    548 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    549 
    550 	udav_chip_init(un);
    551 }
    552 
    553 static void
    554 udav_chip_init(struct usbnet *un)
    555 {
    556 	usbnet_isowned_core(un);
    557 
    558 	/* Select PHY */
    559 #if 1
    560 	/*
    561 	 * XXX: force select internal phy.
    562 	 *	external phy routines are not tested.
    563 	 */
    564 	UDAV_CLRBIT(un, UDAV_NCR, UDAV_NCR_EXT_PHY);
    565 #else
    566 	if (un->un_flags & UDAV_EXT_PHY) {
    567 		UDAV_SETBIT(un, UDAV_NCR, UDAV_NCR_EXT_PHY);
    568 	} else {
    569 		UDAV_CLRBIT(un, UDAV_NCR, UDAV_NCR_EXT_PHY);
    570 	}
    571 #endif
    572 
    573 	UDAV_SETBIT(un, UDAV_NCR, UDAV_NCR_RST);
    574 
    575 	for (int i = 0; i < UDAV_TX_TIMEOUT; i++) {
    576 		if (!(udav_csr_read1(un, UDAV_NCR) & UDAV_NCR_RST))
    577 			break;
    578 		delay(10);	/* XXX */
    579 	}
    580 	delay(10000);		/* XXX */
    581 }
    582 
    583 #define UDAV_BITS	6
    584 
    585 #define UDAV_CALCHASH(addr) \
    586 	(ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1))
    587 
    588 static void
    589 udav_setiff_locked(struct usbnet *un)
    590 {
    591 	struct ethercom *ec = usbnet_ec(un);
    592 	struct ifnet * const ifp = usbnet_ifp(un);
    593 	struct ether_multi *enm;
    594 	struct ether_multistep step;
    595 	uint8_t hashes[8];
    596 	int h = 0;
    597 
    598 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    599 
    600 	usbnet_isowned_core(un);
    601 
    602 	if (usbnet_isdying(un))
    603 		return;
    604 
    605 	if (ISSET(un->un_flags, UDAV_NO_PHY)) {
    606 		UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_ALL);
    607 		UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_PRMSC);
    608 		return;
    609 	}
    610 
    611 	if (ifp->if_flags & IFF_PROMISC) {
    612 		UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC);
    613 		return;
    614 	} else if (ifp->if_flags & IFF_ALLMULTI) {
    615 allmulti:
    616 		ifp->if_flags |= IFF_ALLMULTI;
    617 		UDAV_SETBIT(un, UDAV_RCR, UDAV_RCR_ALL);
    618 		UDAV_CLRBIT(un, UDAV_RCR, UDAV_RCR_PRMSC);
    619 		return;
    620 	}
    621 
    622 	/* first, zot all the existing hash bits */
    623 	memset(hashes, 0x00, sizeof(hashes));
    624 	hashes[7] |= 0x80;	/* broadcast address */
    625 	udav_csr_write(un, UDAV_MAR, hashes, sizeof(hashes));
    626 
    627 	/* now program new ones */
    628 	ETHER_LOCK(ec);
    629 	ETHER_FIRST_MULTI(step, ec, enm);
    630 	while (enm != NULL) {
    631 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
    632 		    ETHER_ADDR_LEN) != 0) {
    633 			ETHER_UNLOCK(ec);
    634 			goto allmulti;
    635 		}
    636 
    637 		h = UDAV_CALCHASH(enm->enm_addrlo);
    638 		hashes[h>>3] |= 1 << (h & 0x7);
    639 		ETHER_NEXT_MULTI(step, enm);
    640 	}
    641 	ETHER_UNLOCK(ec);
    642 
    643 	/* disable all multicast */
    644 	ifp->if_flags &= ~IFF_ALLMULTI;
    645 	UDAV_CLRBIT(un, UDAV_RCR, UDAV_RCR_ALL);
    646 
    647 	/* write hash value to the register */
    648 	udav_csr_write(un, UDAV_MAR, hashes, sizeof(hashes));
    649 }
    650 
    651 static unsigned
    652 udav_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
    653 {
    654 	int total_len;
    655 	uint8_t *buf = c->unc_buf;
    656 
    657 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    658 
    659 	if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz - 2)
    660 		return 0;
    661 
    662 	/* Copy the mbuf data into a contiguous buffer */
    663 	m_copydata(m, 0, m->m_pkthdr.len, buf + 2);
    664 	total_len = m->m_pkthdr.len;
    665 	if (total_len < UDAV_MIN_FRAME_LEN) {
    666 		memset(buf + 2 + total_len, 0,
    667 		    UDAV_MIN_FRAME_LEN - total_len);
    668 		total_len = UDAV_MIN_FRAME_LEN;
    669 	}
    670 
    671 	/* Frame length is specified in the first 2bytes of the buffer */
    672 	buf[0] = (uint8_t)total_len;
    673 	buf[1] = (uint8_t)(total_len >> 8);
    674 	total_len += 2;
    675 
    676 	DPRINTF(("%s: %s: send %d bytes\n", device_xname(un->un_dev),
    677 	    __func__, total_len));
    678 
    679 	return total_len;
    680 }
    681 
    682 static void
    683 udav_uno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len)
    684 {
    685 	struct ifnet *ifp = usbnet_ifp(un);
    686 	uint8_t *buf = c->unc_buf;
    687 	uint16_t pkt_len;
    688 	uint8_t pktstat;
    689 
    690 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    691 
    692 	/* first byte in received data */
    693 	pktstat = *buf;
    694 	total_len -= sizeof(pktstat);
    695 	buf += sizeof(pktstat);
    696 
    697 	DPRINTF(("%s: RX Status: 0x%02x\n", device_xname(un->un_dev), pktstat));
    698 
    699 	pkt_len = UGETW(buf);
    700  	total_len -= sizeof(pkt_len);
    701 	buf += sizeof(pkt_len);
    702 
    703 	DPRINTF(("%s: RX Length: 0x%02x\n", device_xname(un->un_dev), pkt_len));
    704 
    705 	if (pktstat & UDAV_RSR_LCS) {
    706 		if_statinc(ifp, if_collisions);
    707 		return;
    708 	}
    709 
    710 	if (pkt_len < sizeof(struct ether_header) ||
    711 	    pkt_len > total_len ||
    712 	    (pktstat & UDAV_RSR_ERR)) {
    713 		if_statinc(ifp, if_ierrors);
    714 		return;
    715 	}
    716 
    717 	pkt_len -= ETHER_CRC_LEN;
    718 
    719 	DPRINTF(("%s: Rx deliver: 0x%02x\n", device_xname(un->un_dev), pkt_len));
    720 
    721 	usbnet_enqueue(un, buf, pkt_len, 0, 0, 0);
    722 }
    723 
    724 static int
    725 udav_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data)
    726 {
    727 	struct usbnet * const un = ifp->if_softc;
    728 
    729 	usbnet_lock_core(un);
    730 	usbnet_busy(un);
    731 
    732 	switch (cmd) {
    733 	case SIOCADDMULTI:
    734 	case SIOCDELMULTI:
    735 		udav_setiff_locked(un);
    736 		break;
    737 	default:
    738 		break;
    739 	}
    740 
    741 	usbnet_unbusy(un);
    742 	usbnet_unlock_core(un);
    743 
    744 	return 0;
    745 }
    746 
    747 /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
    748 static void
    749 udav_uno_stop(struct ifnet *ifp, int disable)
    750 {
    751 	struct usbnet * const un = ifp->if_softc;
    752 
    753 	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    754 
    755 	udav_reset(un);
    756 }
    757 
    758 static int
    759 udav_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val)
    760 {
    761 	uint8_t data[2];
    762 
    763 	DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n",
    764 		 device_xname(un->un_dev), __func__, phy, reg));
    765 
    766 	if (usbnet_isdying(un)) {
    767 #ifdef DIAGNOSTIC
    768 		printf("%s: %s: dying\n", device_xname(un->un_dev),
    769 		       __func__);
    770 #endif
    771 		return EINVAL;
    772 	}
    773 
    774 	/* XXX: one PHY only for the internal PHY */
    775 	if (phy != 0) {
    776 		DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
    777 			 device_xname(un->un_dev), __func__, phy));
    778 		return EINVAL;
    779 	}
    780 
    781 	/* select internal PHY and set PHY register address */
    782 	udav_csr_write1(un, UDAV_EPAR,
    783 			UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
    784 
    785 	/* select PHY operation and start read command */
    786 	udav_csr_write1(un, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRR);
    787 
    788 	/* XXX: should be wait? */
    789 
    790 	/* end read command */
    791 	UDAV_CLRBIT(un, UDAV_EPCR, UDAV_EPCR_ERPRR);
    792 
    793 	/* retrieve the result from data registers */
    794 	udav_csr_read(un, UDAV_EPDRL, data, 2);
    795 
    796 	*val = data[0] | (data[1] << 8);
    797 
    798 	DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04hx\n",
    799 		device_xname(un->un_dev), __func__, phy, reg, *val));
    800 
    801 	return 0;
    802 }
    803 
    804 static int
    805 udav_uno_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val)
    806 {
    807 	uint8_t data[2];
    808 
    809 	DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x val=0x%04hx\n",
    810 		 device_xname(un->un_dev), __func__, phy, reg, val));
    811 
    812 	if (usbnet_isdying(un)) {
    813 #ifdef DIAGNOSTIC
    814 		printf("%s: %s: dying\n", device_xname(un->un_dev),
    815 		       __func__);
    816 #endif
    817 		return EIO;
    818 	}
    819 
    820 	/* XXX: one PHY only for the internal PHY */
    821 	if (phy != 0) {
    822 		DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
    823 			 device_xname(un->un_dev), __func__, phy));
    824 		return EIO;
    825 	}
    826 
    827 	/* select internal PHY and set PHY register address */
    828 	udav_csr_write1(un, UDAV_EPAR,
    829 			UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
    830 
    831 	/* put the value to the data registers */
    832 	data[0] = val & 0xff;
    833 	data[1] = (val >> 8) & 0xff;
    834 	udav_csr_write(un, UDAV_EPDRL, data, 2);
    835 
    836 	/* select PHY operation and start write command */
    837 	udav_csr_write1(un, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRW);
    838 
    839 	/* XXX: should be wait? */
    840 
    841 	/* end write command */
    842 	UDAV_CLRBIT(un, UDAV_EPCR, UDAV_EPCR_ERPRW);
    843 
    844 	return 0;
    845 }
    846 
    847 static void
    848 udav_uno_mii_statchg(struct ifnet *ifp)
    849 {
    850 	struct usbnet * const un = ifp->if_softc;
    851 	struct mii_data * const mii = usbnet_mii(un);
    852 
    853 	DPRINTF(("%s: %s: enter\n", ifp->if_xname, __func__));
    854 
    855 	if (usbnet_isdying(un))
    856 		return;
    857 
    858 	if ((mii->mii_media_status & IFM_ACTIVE) &&
    859 	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
    860 		DPRINTF(("%s: %s: got link\n",
    861 			 device_xname(un->un_dev), __func__));
    862 		usbnet_set_link(un, true);
    863 	}
    864 }
    865 
    866 #ifdef _MODULE
    867 #include "ioconf.c"
    868 #endif
    869 
    870 USBNET_MODULE(udav)
    871