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