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