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