Annotation of sys/dev/usb/if_udav.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_udav.c,v 1.34 2007/06/14 10:11:15 mbalmer Exp $ */
2: /* $NetBSD: if_udav.c,v 1.3 2004/04/23 17:25:25 itojun Exp $ */
3: /* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */
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-P01-930914.pdf
38: */
39:
40: /*
41: * TODO:
42: * Interrupt Endpoint support
43: * External PHYs
44: * powerhook() support?
45: */
46:
47: #include <sys/cdefs.h>
48:
49: #include "bpfilter.h"
50:
51: #include <sys/param.h>
52: #include <sys/systm.h>
53: #include <sys/rwlock.h>
54: #include <sys/mbuf.h>
55: #include <sys/kernel.h>
56: #include <sys/proc.h>
57: #include <sys/socket.h>
58:
59: #include <sys/device.h>
60:
61: #include <net/if.h>
62: #include <net/if_arp.h>
63: #include <net/if_dl.h>
64: #include <net/if_media.h>
65:
66: #if NBPFILTER > 0
67: #include <net/bpf.h>
68: #endif
69:
70: #ifdef INET
71: #include <netinet/in.h>
72: #include <netinet/in_systm.h>
73: #include <netinet/in_var.h>
74: #include <netinet/ip.h>
75: #include <netinet/if_ether.h>
76: #endif
77:
78: #include <dev/mii/mii.h>
79: #include <dev/mii/miivar.h>
80:
81: #include <dev/usb/usb.h>
82: #include <dev/usb/usbdi.h>
83: #include <dev/usb/usbdi_util.h>
84: #include <dev/usb/usbdevs.h>
85:
86: #include <dev/usb/if_udavreg.h>
87:
88:
89: /* Function declarations */
90: int udav_match(struct device *, void *, void *);
91: void udav_attach(struct device *, struct device *, void *);
92: int udav_detach(struct device *, int);
93: int udav_activate(struct device *, enum devact);
94:
95: struct cfdriver udav_cd = {
96: NULL, "udav", DV_IFNET
97: };
98:
99: const struct cfattach udav_ca = {
100: sizeof(struct udav_softc),
101: udav_match,
102: udav_attach,
103: udav_detach,
104: udav_activate,
105: };
106:
107: int udav_openpipes(struct udav_softc *);
108: int udav_rx_list_init(struct udav_softc *);
109: int udav_tx_list_init(struct udav_softc *);
110: int udav_newbuf(struct udav_softc *, struct udav_chain *, struct mbuf *);
111: void udav_start(struct ifnet *);
112: int udav_send(struct udav_softc *, struct mbuf *, int);
113: void udav_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
114: void udav_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
115: void udav_tick(void *);
116: void udav_tick_task(void *);
117: int udav_ioctl(struct ifnet *, u_long, caddr_t);
118: void udav_stop_task(struct udav_softc *);
119: void udav_stop(struct ifnet *, int);
120: void udav_watchdog(struct ifnet *);
121: int udav_ifmedia_change(struct ifnet *);
122: void udav_ifmedia_status(struct ifnet *, struct ifmediareq *);
123: void udav_lock_mii(struct udav_softc *);
124: void udav_unlock_mii(struct udav_softc *);
125: int udav_miibus_readreg(struct device *, int, int);
126: void udav_miibus_writereg(struct device *, int, int, int);
127: void udav_miibus_statchg(struct device *);
128: int udav_init(struct ifnet *);
129: void udav_setmulti(struct udav_softc *);
130: void udav_reset(struct udav_softc *);
131:
132: int udav_csr_read(struct udav_softc *, int, void *, int);
133: int udav_csr_write(struct udav_softc *, int, void *, int);
134: int udav_csr_read1(struct udav_softc *, int);
135: int udav_csr_write1(struct udav_softc *, int, unsigned char);
136:
137: #if 0
138: int udav_mem_read(struct udav_softc *, int, void *, int);
139: int udav_mem_write(struct udav_softc *, int, void *, int);
140: int udav_mem_write1(struct udav_softc *, int, unsigned char);
141: #endif
142:
143: /* Macros */
144: #ifdef UDAV_DEBUG
145: #define DPRINTF(x) do { if (udavdebug) printf x; } while(0)
146: #define DPRINTFN(n,x) do { if (udavdebug >= (n)) printf x; } while(0)
147: int udavdebug = 0;
148: #else
149: #define DPRINTF(x)
150: #define DPRINTFN(n,x)
151: #endif
152:
153: #define UDAV_SETBIT(sc, reg, x) \
154: udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x))
155:
156: #define UDAV_CLRBIT(sc, reg, x) \
157: udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x))
158:
159: static const struct udav_type {
160: struct usb_devno udav_dev;
161: u_int16_t udav_flags;
162: #define UDAV_EXT_PHY 0x0001
163: } udav_devs [] = {
164: {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC }, 0 },
165: {{ USB_VENDOR_DAVICOM, USB_PRODUCT_DAVICOM_DM9601 }, 0 },
166: {{ USB_VENDOR_DAVICOM, USB_PRODUCT_DAVICOM_WK668 }, 0 },
167: {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_DM9601 }, 0 },
168: {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ST268 }, 0 }
169: };
170: #define udav_lookup(v, p) ((struct udav_type *)usb_lookup(udav_devs, v, p))
171:
172:
173: /* Probe */
174: int
175: udav_match(struct device *parent, void *match, void *aux)
176: {
177: struct usb_attach_arg *uaa = aux;
178:
179: if (uaa->iface != NULL)
180: return (UMATCH_NONE);
181:
182: return (udav_lookup(uaa->vendor, uaa->product) != NULL ?
183: UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
184: }
185:
186: /* Attach */
187: void
188: udav_attach(struct device *parent, struct device *self, void *aux)
189: {
190: struct udav_softc *sc = (struct udav_softc *)self;
191: struct usb_attach_arg *uaa = aux;
192: usbd_device_handle dev = uaa->device;
193: usbd_interface_handle iface;
194: usbd_status err;
195: usb_interface_descriptor_t *id;
196: usb_endpoint_descriptor_t *ed;
197: char *devinfop;
198: char *devname = sc->sc_dev.dv_xname;
199: struct ifnet *ifp;
200: struct mii_data *mii;
201: u_char eaddr[ETHER_ADDR_LEN];
202: int i, s;
203:
204: devinfop = usbd_devinfo_alloc(dev, 0);
205: printf("\n%s: %s", devname, devinfop);
206: usbd_devinfo_free(devinfop);
207:
208: /* Move the device into the configured state. */
209: err = usbd_set_config_no(dev, UDAV_CONFIG_NO, 1);
210: if (err) {
211: printf(", setting config no failed\n");
212: goto bad;
213: }
214:
215: usb_init_task(&sc->sc_tick_task, udav_tick_task, sc);
216: rw_init(&sc->sc_mii_lock, "udavmii");
217: usb_init_task(&sc->sc_stop_task, (void (*)(void *)) udav_stop_task, sc);
218:
219: /* get control interface */
220: err = usbd_device2interface_handle(dev, UDAV_IFACE_INDEX, &iface);
221: if (err) {
222: printf(", failed to get interface, err=%s\n", usbd_errstr(err));
223: goto bad;
224: }
225:
226: sc->sc_udev = dev;
227: sc->sc_ctl_iface = iface;
228: sc->sc_flags = udav_lookup(uaa->vendor, uaa->product)->udav_flags;
229:
230: /* get interface descriptor */
231: id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
232:
233: /* find endpoints */
234: sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1;
235: for (i = 0; i < id->bNumEndpoints; i++) {
236: ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
237: if (ed == NULL) {
238: printf(", couldn't get endpoint %d\n", i);
239: goto bad;
240: }
241: if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
242: UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
243: sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */
244: else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
245: UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
246: sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */
247: else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT &&
248: UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
249: sc->sc_intrin_no = ed->bEndpointAddress; /* Status */
250: }
251:
252: if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 ||
253: sc->sc_intrin_no == -1) {
254: printf(", missing endpoint\n");
255: goto bad;
256: }
257:
258: s = splnet();
259:
260: /* reset the adapter */
261: udav_reset(sc);
262:
263: /* Get Ethernet Address */
264: err = udav_csr_read(sc, UDAV_PAR, (void *)eaddr, ETHER_ADDR_LEN);
265: if (err) {
266: printf(", read MAC address failed\n");
267: splx(s);
268: goto bad;
269: }
270:
271: /* Print Ethernet Address */
272: printf(" address %s\n", ether_sprintf(eaddr));
273:
274: bcopy(eaddr, (char *)&sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
275:
276: /* initialize interface information */
277: ifp = GET_IFP(sc);
278: ifp->if_softc = sc;
279: strlcpy(ifp->if_xname, devname, IFNAMSIZ);
280: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
281: ifp->if_start = udav_start;
282: ifp->if_ioctl = udav_ioctl;
283: ifp->if_watchdog = udav_watchdog;
284:
285: IFQ_SET_READY(&ifp->if_snd);
286:
287: /*
288: * Do ifmedia setup.
289: */
290: mii = &sc->sc_mii;
291: mii->mii_ifp = ifp;
292: mii->mii_readreg = udav_miibus_readreg;
293: mii->mii_writereg = udav_miibus_writereg;
294: mii->mii_statchg = udav_miibus_statchg;
295: mii->mii_flags = MIIF_AUTOTSLEEP;
296: ifmedia_init(&mii->mii_media, 0,
297: udav_ifmedia_change, udav_ifmedia_status);
298: mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
299: if (LIST_FIRST(&mii->mii_phys) == NULL) {
300: ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
301: ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
302: } else
303: ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
304:
305: /* attach the interface */
306: if_attach(ifp);
307: ether_ifattach(ifp);
308:
309: timeout_set(&sc->sc_stat_ch, NULL, NULL);
310: sc->sc_attached = 1;
311: splx(s);
312:
313: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, &sc->sc_dev);
314:
315: return;
316:
317: bad:
318: sc->sc_dying = 1;
319: }
320:
321: /* detach */
322: int
323: udav_detach(struct device *self, int flags)
324: {
325: struct udav_softc *sc = (struct udav_softc *)self;
326: struct ifnet *ifp = GET_IFP(sc);
327: int s;
328:
329: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
330:
331: /* Detached before attached finished */
332: if (!sc->sc_attached)
333: return (0);
334:
335: timeout_del(&sc->sc_stat_ch);
336:
337: /* Remove any pending tasks */
338: usb_rem_task(sc->sc_udev, &sc->sc_tick_task);
339: usb_rem_task(sc->sc_udev, &sc->sc_stop_task);
340:
341: s = splusb();
342:
343: if (--sc->sc_refcnt >= 0) {
344: /* Wait for processes to go away */
345: usb_detach_wait(&sc->sc_dev);
346: }
347: if (ifp->if_flags & IFF_RUNNING)
348: udav_stop(GET_IFP(sc), 1);
349:
350: mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
351: ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
352: ether_ifdetach(ifp);
353: if_detach(ifp);
354:
355: #ifdef DIAGNOSTIC
356: if (sc->sc_pipe_tx != NULL)
357: printf("%s: detach has active tx endpoint.\n",
358: sc->sc_dev.dv_xname);
359: if (sc->sc_pipe_rx != NULL)
360: printf("%s: detach has active rx endpoint.\n",
361: sc->sc_dev.dv_xname);
362: if (sc->sc_pipe_intr != NULL)
363: printf("%s: detach has active intr endpoint.\n",
364: sc->sc_dev.dv_xname);
365: #endif
366: sc->sc_attached = 0;
367:
368: splx(s);
369:
370: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
371: &sc->sc_dev);
372:
373: return (0);
374: }
375:
376: #if 0
377: /* read memory */
378: int
379: udav_mem_read(struct udav_softc *sc, int offset, void *buf, int len)
380: {
381: usb_device_request_t req;
382: usbd_status err;
383:
384: if (sc == NULL)
385: return (0);
386:
387: DPRINTFN(0x200,
388: ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
389:
390: if (sc->sc_dying)
391: return (0);
392:
393: offset &= 0xffff;
394: len &= 0xff;
395:
396: req.bmRequestType = UT_READ_VENDOR_DEVICE;
397: req.bRequest = UDAV_REQ_MEM_READ;
398: USETW(req.wValue, 0x0000);
399: USETW(req.wIndex, offset);
400: USETW(req.wLength, len);
401:
402: sc->sc_refcnt++;
403: err = usbd_do_request(sc->sc_udev, &req, buf);
404: if (--sc->sc_refcnt < 0)
405: usb_detach_wakeup(&sc->sc_dev);
406: if (err) {
407: DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
408: sc->sc_dev.dv_xname, __func__, offset, err));
409: }
410:
411: return (err);
412: }
413:
414: /* write memory */
415: int
416: udav_mem_write(struct udav_softc *sc, int offset, void *buf, int len)
417: {
418: usb_device_request_t req;
419: usbd_status err;
420:
421: if (sc == NULL)
422: return (0);
423:
424: DPRINTFN(0x200,
425: ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
426:
427: if (sc->sc_dying)
428: return (0);
429:
430: offset &= 0xffff;
431: len &= 0xff;
432:
433: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
434: req.bRequest = UDAV_REQ_MEM_WRITE;
435: USETW(req.wValue, 0x0000);
436: USETW(req.wIndex, offset);
437: USETW(req.wLength, len);
438:
439: sc->sc_refcnt++;
440: err = usbd_do_request(sc->sc_udev, &req, buf);
441: if (--sc->sc_refcnt < 0)
442: usb_detach_wakeup(&sc->sc_dev);
443: if (err) {
444: DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
445: sc->sc_dev.dv_xname, __func__, offset, err));
446: }
447:
448: return (err);
449: }
450:
451: /* write memory */
452: int
453: udav_mem_write1(struct udav_softc *sc, int offset, unsigned char ch)
454: {
455: usb_device_request_t req;
456: usbd_status err;
457:
458: if (sc == NULL)
459: return (0);
460:
461: DPRINTFN(0x200,
462: ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
463:
464: if (sc->sc_dying)
465: return (0);
466:
467: offset &= 0xffff;
468:
469: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
470: req.bRequest = UDAV_REQ_MEM_WRITE1;
471: USETW(req.wValue, ch);
472: USETW(req.wIndex, offset);
473: USETW(req.wLength, 0x0000);
474:
475: sc->sc_refcnt++;
476: err = usbd_do_request(sc->sc_udev, &req, NULL);
477: if (--sc->sc_refcnt < 0)
478: usb_detach_wakeup(&sc->sc_dev);
479: if (err) {
480: DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
481: sc->sc_dev.dv_xname, __func__, offset, err));
482: }
483:
484: return (err);
485: }
486: #endif
487:
488: /* read register(s) */
489: int
490: udav_csr_read(struct udav_softc *sc, int offset, void *buf, int len)
491: {
492: usb_device_request_t req;
493: usbd_status err;
494:
495: if (sc == NULL)
496: return (0);
497:
498: DPRINTFN(0x200,
499: ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
500:
501: if (sc->sc_dying)
502: return (0);
503:
504: offset &= 0xff;
505: len &= 0xff;
506:
507: req.bmRequestType = UT_READ_VENDOR_DEVICE;
508: req.bRequest = UDAV_REQ_REG_READ;
509: USETW(req.wValue, 0x0000);
510: USETW(req.wIndex, offset);
511: USETW(req.wLength, len);
512:
513: sc->sc_refcnt++;
514: err = usbd_do_request(sc->sc_udev, &req, buf);
515: if (--sc->sc_refcnt < 0)
516: usb_detach_wakeup(&sc->sc_dev);
517: if (err) {
518: DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
519: sc->sc_dev.dv_xname, __func__, offset, err));
520: }
521:
522: return (err);
523: }
524:
525: /* write register(s) */
526: int
527: udav_csr_write(struct udav_softc *sc, int offset, void *buf, int len)
528: {
529: usb_device_request_t req;
530: usbd_status err;
531:
532: if (sc == NULL)
533: return (0);
534:
535: DPRINTFN(0x200,
536: ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
537:
538: if (sc->sc_dying)
539: return (0);
540:
541: offset &= 0xff;
542: len &= 0xff;
543:
544: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
545: req.bRequest = UDAV_REQ_REG_WRITE;
546: USETW(req.wValue, 0x0000);
547: USETW(req.wIndex, offset);
548: USETW(req.wLength, len);
549:
550: sc->sc_refcnt++;
551: err = usbd_do_request(sc->sc_udev, &req, buf);
552: if (--sc->sc_refcnt < 0)
553: usb_detach_wakeup(&sc->sc_dev);
554: if (err) {
555: DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
556: sc->sc_dev.dv_xname, __func__, offset, err));
557: }
558:
559: return (err);
560: }
561:
562: int
563: udav_csr_read1(struct udav_softc *sc, int offset)
564: {
565: u_int8_t val = 0;
566:
567: if (sc == NULL)
568: return (0);
569:
570: DPRINTFN(0x200,
571: ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
572:
573: if (sc->sc_dying)
574: return (0);
575:
576: return (udav_csr_read(sc, offset, &val, 1) ? 0 : val);
577: }
578:
579: /* write a register */
580: int
581: udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch)
582: {
583: usb_device_request_t req;
584: usbd_status err;
585:
586: if (sc == NULL)
587: return (0);
588:
589: DPRINTFN(0x200,
590: ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
591:
592: if (sc->sc_dying)
593: return (0);
594:
595: offset &= 0xff;
596:
597: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
598: req.bRequest = UDAV_REQ_REG_WRITE1;
599: USETW(req.wValue, ch);
600: USETW(req.wIndex, offset);
601: USETW(req.wLength, 0x0000);
602:
603: sc->sc_refcnt++;
604: err = usbd_do_request(sc->sc_udev, &req, NULL);
605: if (--sc->sc_refcnt < 0)
606: usb_detach_wakeup(&sc->sc_dev);
607: if (err) {
608: DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
609: sc->sc_dev.dv_xname, __func__, offset, err));
610: }
611:
612: return (err);
613: }
614:
615: int
616: udav_init(struct ifnet *ifp)
617: {
618: struct udav_softc *sc = ifp->if_softc;
619: struct mii_data *mii = GET_MII(sc);
620: u_char *eaddr;
621: int s;
622:
623: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
624:
625: if (sc->sc_dying)
626: return (EIO);
627:
628: s = splnet();
629:
630: /* Cancel pending I/O and free all TX/RX buffers */
631: udav_stop(ifp, 1);
632:
633: eaddr = sc->sc_ac.ac_enaddr;
634: udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN);
635:
636: /* Initialize network control register */
637: /* Disable loopback */
638: UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1);
639:
640: /* Initialize RX control register */
641: UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC);
642:
643: /* If we want promiscuous mode, accept all physical frames. */
644: if (ifp->if_flags & IFF_PROMISC)
645: UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
646: else
647: UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
648:
649: /* Initialize transmit ring */
650: if (udav_tx_list_init(sc) == ENOBUFS) {
651: printf("%s: tx list init failed\n", sc->sc_dev.dv_xname);
652: splx(s);
653: return (EIO);
654: }
655:
656: /* Initialize receive ring */
657: if (udav_rx_list_init(sc) == ENOBUFS) {
658: printf("%s: rx list init failed\n", sc->sc_dev.dv_xname);
659: splx(s);
660: return (EIO);
661: }
662:
663: /* Load the multicast filter */
664: udav_setmulti(sc);
665:
666: /* Enable RX */
667: UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN);
668:
669: /* clear POWER_DOWN state of internal PHY */
670: UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0);
671: UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0);
672:
673: mii_mediachg(mii);
674:
675: if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) {
676: if (udav_openpipes(sc)) {
677: splx(s);
678: return (EIO);
679: }
680: }
681:
682: ifp->if_flags |= IFF_RUNNING;
683: ifp->if_flags &= ~IFF_OACTIVE;
684:
685: splx(s);
686:
687: timeout_del(&sc->sc_stat_ch);
688: timeout_set(&sc->sc_stat_ch, udav_tick, sc);
689: timeout_add(&sc->sc_stat_ch, hz);
690:
691: return (0);
692: }
693:
694: void
695: udav_reset(struct udav_softc *sc)
696: {
697: int i;
698:
699: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
700:
701: if (sc->sc_dying)
702: return;
703:
704: /* Select PHY */
705: #if 1
706: /*
707: * XXX: force select internal phy.
708: * external phy routines are not tested.
709: */
710: UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
711: #else
712: if (sc->sc_flags & UDAV_EXT_PHY) {
713: UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
714: } else {
715: UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
716: }
717: #endif
718:
719: UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST);
720:
721: for (i = 0; i < UDAV_TX_TIMEOUT; i++) {
722: if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST))
723: break;
724: delay(10); /* XXX */
725: }
726: delay(10000); /* XXX */
727: }
728:
729: int
730: udav_activate(struct device *self, enum devact act)
731: {
732: struct udav_softc *sc = (struct udav_softc *)self;
733:
734: DPRINTF(("%s: %s: enter, act=%d\n", sc->sc_dev.dv_xname,
735: __func__, act));
736: switch (act) {
737: case DVACT_ACTIVATE:
738: break;
739:
740: case DVACT_DEACTIVATE:
741: sc->sc_dying = 1;
742: break;
743: }
744: return (0);
745: }
746:
747: #define UDAV_BITS 6
748:
749: #define UDAV_CALCHASH(addr) \
750: (ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1))
751:
752: void
753: udav_setmulti(struct udav_softc *sc)
754: {
755: struct ifnet *ifp;
756: struct ether_multi *enm;
757: struct ether_multistep step;
758: u_int8_t hashes[8];
759: int h = 0;
760:
761: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
762:
763: if (sc->sc_dying)
764: return;
765:
766: ifp = GET_IFP(sc);
767:
768: if (ifp->if_flags & IFF_PROMISC) {
769: UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
770: return;
771: } else if (ifp->if_flags & IFF_ALLMULTI) {
772: allmulti:
773: ifp->if_flags |= IFF_ALLMULTI;
774: UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
775: UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_PRMSC);
776: return;
777: }
778:
779: /* first, zot all the existing hash bits */
780: memset(hashes, 0x00, sizeof(hashes));
781: hashes[7] |= 0x80; /* broadcast address */
782: udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
783:
784: /* now program new ones */
785: ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
786: while (enm != NULL) {
787: if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
788: ETHER_ADDR_LEN) != 0)
789: goto allmulti;
790:
791: h = UDAV_CALCHASH(enm->enm_addrlo);
792: hashes[h>>3] |= 1 << (h & 0x7);
793: ETHER_NEXT_MULTI(step, enm);
794: }
795:
796: /* disable all multicast */
797: ifp->if_flags &= ~IFF_ALLMULTI;
798: UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
799:
800: /* write hash value to the register */
801: udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
802: }
803:
804: int
805: udav_openpipes(struct udav_softc *sc)
806: {
807: struct udav_chain *c;
808: usbd_status err;
809: int i;
810: int error = 0;
811:
812: if (sc->sc_dying)
813: return (EIO);
814:
815: sc->sc_refcnt++;
816:
817: /* Open RX pipe */
818: err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no,
819: USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx);
820: if (err) {
821: printf("%s: open rx pipe failed: %s\n",
822: sc->sc_dev.dv_xname, usbd_errstr(err));
823: error = EIO;
824: goto done;
825: }
826:
827: /* Open TX pipe */
828: err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
829: USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx);
830: if (err) {
831: printf("%s: open tx pipe failed: %s\n",
832: sc->sc_dev.dv_xname, usbd_errstr(err));
833: error = EIO;
834: goto done;
835: }
836:
837: #if 0
838: /* XXX: interrupt endpoint is not yet supported */
839: /* Open Interrupt pipe */
840: err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no,
841: USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc,
842: &sc->sc_cdata.udav_ibuf, UDAV_INTR_PKGLEN,
843: udav_intr, UDAV_INTR_INTERVAL);
844: if (err) {
845: printf("%s: open intr pipe failed: %s\n",
846: sc->sc_dev.dv_xname, usbd_errstr(err));
847: error = EIO;
848: goto done;
849: }
850: #endif
851:
852:
853: /* Start up the receive pipe. */
854: for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
855: c = &sc->sc_cdata.udav_rx_chain[i];
856: usbd_setup_xfer(c->udav_xfer, sc->sc_pipe_rx,
857: c, c->udav_buf, UDAV_BUFSZ,
858: USBD_SHORT_XFER_OK | USBD_NO_COPY,
859: USBD_NO_TIMEOUT, udav_rxeof);
860: (void)usbd_transfer(c->udav_xfer);
861: DPRINTF(("%s: %s: start read\n", sc->sc_dev.dv_xname,
862: __func__));
863: }
864:
865: done:
866: if (--sc->sc_refcnt < 0)
867: usb_detach_wakeup(&sc->sc_dev);
868:
869: return (error);
870: }
871:
872: int
873: udav_newbuf(struct udav_softc *sc, struct udav_chain *c, struct mbuf *m)
874: {
875: struct mbuf *m_new = NULL;
876:
877: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
878:
879: if (m == NULL) {
880: MGETHDR(m_new, M_DONTWAIT, MT_DATA);
881: if (m_new == NULL) {
882: printf("%s: no memory for rx list "
883: "-- packet dropped!\n", sc->sc_dev.dv_xname);
884: return (ENOBUFS);
885: }
886: MCLGET(m_new, M_DONTWAIT);
887: if (!(m_new->m_flags & M_EXT)) {
888: printf("%s: no memory for rx list "
889: "-- packet dropped!\n", sc->sc_dev.dv_xname);
890: m_freem(m_new);
891: return (ENOBUFS);
892: }
893: m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
894: } else {
895: m_new = m;
896: m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
897: m_new->m_data = m_new->m_ext.ext_buf;
898: }
899:
900: m_adj(m_new, ETHER_ALIGN);
901: c->udav_mbuf = m_new;
902:
903: return (0);
904: }
905:
906:
907: int
908: udav_rx_list_init(struct udav_softc *sc)
909: {
910: struct udav_cdata *cd;
911: struct udav_chain *c;
912: int i;
913:
914: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
915:
916: cd = &sc->sc_cdata;
917: for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
918: c = &cd->udav_rx_chain[i];
919: c->udav_sc = sc;
920: c->udav_idx = i;
921: if (udav_newbuf(sc, c, NULL) == ENOBUFS)
922: return (ENOBUFS);
923: if (c->udav_xfer == NULL) {
924: c->udav_xfer = usbd_alloc_xfer(sc->sc_udev);
925: if (c->udav_xfer == NULL)
926: return (ENOBUFS);
927: c->udav_buf = usbd_alloc_buffer(c->udav_xfer, UDAV_BUFSZ);
928: if (c->udav_buf == NULL) {
929: usbd_free_xfer(c->udav_xfer);
930: return (ENOBUFS);
931: }
932: }
933: }
934:
935: return (0);
936: }
937:
938: int
939: udav_tx_list_init(struct udav_softc *sc)
940: {
941: struct udav_cdata *cd;
942: struct udav_chain *c;
943: int i;
944:
945: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
946:
947: cd = &sc->sc_cdata;
948: for (i = 0; i < UDAV_TX_LIST_CNT; i++) {
949: c = &cd->udav_tx_chain[i];
950: c->udav_sc = sc;
951: c->udav_idx = i;
952: c->udav_mbuf = NULL;
953: if (c->udav_xfer == NULL) {
954: c->udav_xfer = usbd_alloc_xfer(sc->sc_udev);
955: if (c->udav_xfer == NULL)
956: return (ENOBUFS);
957: c->udav_buf = usbd_alloc_buffer(c->udav_xfer, UDAV_BUFSZ);
958: if (c->udav_buf == NULL) {
959: usbd_free_xfer(c->udav_xfer);
960: return (ENOBUFS);
961: }
962: }
963: }
964:
965: return (0);
966: }
967:
968: void
969: udav_start(struct ifnet *ifp)
970: {
971: struct udav_softc *sc = ifp->if_softc;
972: struct mbuf *m_head = NULL;
973:
974: DPRINTF(("%s: %s: enter, link=%d\n", sc->sc_dev.dv_xname,
975: __func__, sc->sc_link));
976:
977: if (sc->sc_dying)
978: return;
979:
980: if (!sc->sc_link)
981: return;
982:
983: if (ifp->if_flags & IFF_OACTIVE)
984: return;
985:
986: IFQ_POLL(&ifp->if_snd, m_head);
987: if (m_head == NULL)
988: return;
989:
990: if (udav_send(sc, m_head, 0)) {
991: ifp->if_flags |= IFF_OACTIVE;
992: return;
993: }
994:
995: IFQ_DEQUEUE(&ifp->if_snd, m_head);
996:
997: #if NBPFILTER > 0
998: if (ifp->if_bpf)
999: bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
1000: #endif
1001:
1002: ifp->if_flags |= IFF_OACTIVE;
1003:
1004: /* Set a timeout in case the chip goes out to lunch. */
1005: ifp->if_timer = 5;
1006: }
1007:
1008: int
1009: udav_send(struct udav_softc *sc, struct mbuf *m, int idx)
1010: {
1011: int total_len;
1012: struct udav_chain *c;
1013: usbd_status err;
1014:
1015: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
1016:
1017: c = &sc->sc_cdata.udav_tx_chain[idx];
1018:
1019: /* Copy the mbuf data into a contiguous buffer */
1020: /* first 2 bytes are packet length */
1021: m_copydata(m, 0, m->m_pkthdr.len, c->udav_buf + 2);
1022: c->udav_mbuf = m;
1023: total_len = m->m_pkthdr.len;
1024: if (total_len < UDAV_MIN_FRAME_LEN) {
1025: memset(c->udav_buf + 2 + total_len, 0,
1026: UDAV_MIN_FRAME_LEN - total_len);
1027: total_len = UDAV_MIN_FRAME_LEN;
1028: }
1029:
1030: /* Frame length is specified in the first 2bytes of the buffer */
1031: c->udav_buf[0] = (u_int8_t)total_len;
1032: c->udav_buf[1] = (u_int8_t)(total_len >> 8);
1033: total_len += 2;
1034:
1035: usbd_setup_xfer(c->udav_xfer, sc->sc_pipe_tx, c, c->udav_buf, total_len,
1036: USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
1037: UDAV_TX_TIMEOUT, udav_txeof);
1038:
1039: /* Transmit */
1040: sc->sc_refcnt++;
1041: err = usbd_transfer(c->udav_xfer);
1042: if (--sc->sc_refcnt < 0)
1043: usb_detach_wakeup(&sc->sc_dev);
1044: if (err != USBD_IN_PROGRESS) {
1045: printf("%s: udav_send error=%s\n", sc->sc_dev.dv_xname,
1046: usbd_errstr(err));
1047: /* Stop the interface */
1048: usb_add_task(sc->sc_udev, &sc->sc_stop_task);
1049: return (EIO);
1050: }
1051:
1052: DPRINTF(("%s: %s: send %d bytes\n", sc->sc_dev.dv_xname,
1053: __func__, total_len));
1054:
1055: sc->sc_cdata.udav_tx_cnt++;
1056:
1057: return (0);
1058: }
1059:
1060: void
1061: udav_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1062: {
1063: struct udav_chain *c = priv;
1064: struct udav_softc *sc = c->udav_sc;
1065: struct ifnet *ifp = GET_IFP(sc);
1066: int s;
1067:
1068: if (sc->sc_dying)
1069: return;
1070:
1071: s = splnet();
1072:
1073: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1074:
1075: ifp->if_timer = 0;
1076: ifp->if_flags &= ~IFF_OACTIVE;
1077:
1078: if (status != USBD_NORMAL_COMPLETION) {
1079: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1080: splx(s);
1081: return;
1082: }
1083: ifp->if_oerrors++;
1084: printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname,
1085: usbd_errstr(status));
1086: if (status == USBD_STALLED) {
1087: sc->sc_refcnt++;
1088: usbd_clear_endpoint_stall_async(sc->sc_pipe_tx);
1089: if (--sc->sc_refcnt < 0)
1090: usb_detach_wakeup(&sc->sc_dev);
1091: }
1092: splx(s);
1093: return;
1094: }
1095:
1096: ifp->if_opackets++;
1097:
1098: m_freem(c->udav_mbuf);
1099: c->udav_mbuf = NULL;
1100:
1101: if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1102: udav_start(ifp);
1103:
1104: splx(s);
1105: }
1106:
1107: void
1108: udav_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1109: {
1110: struct udav_chain *c = priv;
1111: struct udav_softc *sc = c->udav_sc;
1112: struct ifnet *ifp = GET_IFP(sc);
1113: struct udav_rx_hdr *h;
1114: struct mbuf *m;
1115: u_int32_t total_len;
1116: int s;
1117:
1118: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
1119:
1120: if (sc->sc_dying)
1121: return;
1122:
1123: if (status != USBD_NORMAL_COMPLETION) {
1124: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1125: return;
1126: sc->sc_rx_errs++;
1127: if (usbd_ratecheck(&sc->sc_rx_notice)) {
1128: printf("%s: %u usb errors on rx: %s\n",
1129: sc->sc_dev.dv_xname, sc->sc_rx_errs,
1130: usbd_errstr(status));
1131: sc->sc_rx_errs = 0;
1132: }
1133: if (status == USBD_STALLED) {
1134: sc->sc_refcnt++;
1135: usbd_clear_endpoint_stall_async(sc->sc_pipe_rx);
1136: if (--sc->sc_refcnt < 0)
1137: usb_detach_wakeup(&sc->sc_dev);
1138: }
1139: goto done;
1140: }
1141:
1142: usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
1143:
1144: h = (struct udav_rx_hdr *)c->udav_buf;
1145: total_len = UGETW(h->length) - ETHER_CRC_LEN;
1146:
1147: DPRINTF(("%s: RX Status: 0x%02x\n", h->pktstat));
1148:
1149: if (h->pktstat & UDAV_RSR_LCS) {
1150: ifp->if_collisions++;
1151: goto done;
1152: }
1153:
1154: if (total_len < sizeof(struct ether_header) ||
1155: h->pktstat & UDAV_RSR_ERR) {
1156: ifp->if_ierrors++;
1157: goto done;
1158: }
1159:
1160: /* copy data to mbuf */
1161: m = c->udav_mbuf;
1162: memcpy(mtod(m, char *), c->udav_buf + UDAV_RX_HDRLEN, total_len);
1163:
1164: ifp->if_ipackets++;
1165:
1166: m->m_pkthdr.len = m->m_len = total_len;
1167: m->m_pkthdr.rcvif = ifp;
1168:
1169: s = splnet();
1170:
1171: if (udav_newbuf(sc, c, NULL) == ENOBUFS) {
1172: ifp->if_ierrors++;
1173: goto done1;
1174: }
1175:
1176: #if NBPFILTER > 0
1177: if (ifp->if_bpf)
1178: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1179: #endif
1180:
1181: DPRINTF(("%s: %s: deliver %d\n", sc->sc_dev.dv_xname,
1182: __func__, m->m_len));
1183: ether_input_mbuf(ifp, m);
1184:
1185: done1:
1186: splx(s);
1187:
1188: done:
1189: /* Setup new transfer */
1190: usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->udav_buf, UDAV_BUFSZ,
1191: USBD_SHORT_XFER_OK | USBD_NO_COPY,
1192: USBD_NO_TIMEOUT, udav_rxeof);
1193: sc->sc_refcnt++;
1194: usbd_transfer(xfer);
1195: if (--sc->sc_refcnt < 0)
1196: usb_detach_wakeup(&sc->sc_dev);
1197:
1198: DPRINTF(("%s: %s: start rx\n", sc->sc_dev.dv_xname, __func__));
1199: }
1200:
1201: #if 0
1202: void udav_intr()
1203: {
1204: }
1205: #endif
1206:
1207: int
1208: udav_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1209: {
1210: struct udav_softc *sc = ifp->if_softc;
1211: struct ifaddr *ifa = (struct ifaddr *)data;
1212: struct ifreq *ifr = (struct ifreq *)data;
1213: struct mii_data *mii;
1214: int s, error = 0;
1215:
1216: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1217:
1218: if (sc->sc_dying)
1219: return (EIO);
1220:
1221: s = splnet();
1222:
1223: switch (cmd) {
1224: case SIOCGIFMEDIA:
1225: case SIOCSIFMEDIA:
1226: mii = GET_MII(sc);
1227: error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
1228: break;
1229: case SIOCSIFADDR:
1230: ifp->if_flags |= IFF_UP;
1231: udav_init(ifp);
1232:
1233: switch (ifa->ifa_addr->sa_family) {
1234: #ifdef INET
1235: case AF_INET:
1236: arp_ifinit(&sc->sc_ac, ifa);
1237: break;
1238: #endif /* INET */
1239: }
1240: break;
1241:
1242: case SIOCSIFMTU:
1243: if (ifr->ifr_mtu > ETHERMTU)
1244: error = EINVAL;
1245: else
1246: ifp->if_mtu = ifr->ifr_mtu;
1247: break;
1248: case SIOCSIFFLAGS:
1249: if (ifp->if_flags & IFF_UP) {
1250: if (ifp->if_flags & IFF_RUNNING &&
1251: ifp->if_flags & IFF_PROMISC) {
1252: UDAV_SETBIT(sc, UDAV_RCR,
1253: UDAV_RCR_ALL|UDAV_RCR_PRMSC);
1254: } else if (ifp->if_flags & IFF_RUNNING &&
1255: !(ifp->if_flags & IFF_PROMISC)) {
1256: UDAV_CLRBIT(sc, UDAV_RCR,
1257: UDAV_RCR_PRMSC);
1258: } else if (!(ifp->if_flags & IFF_RUNNING))
1259: udav_init(ifp);
1260: } else {
1261: if (ifp->if_flags & IFF_RUNNING)
1262: udav_stop(ifp, 1);
1263: }
1264: error = 0;
1265: break;
1266: case SIOCADDMULTI:
1267: case SIOCDELMULTI:
1268: error = (cmd == SIOCADDMULTI) ?
1269: ether_addmulti(ifr, &sc->sc_ac) :
1270: ether_delmulti(ifr, &sc->sc_ac);
1271:
1272: if (error == ENETRESET) {
1273: if (ifp->if_flags & IFF_RUNNING)
1274: udav_setmulti(sc);
1275: error = 0;
1276: }
1277: break;
1278: default:
1279: error = EINVAL;
1280: break;
1281: }
1282:
1283: splx(s);
1284:
1285: return (error);
1286: }
1287:
1288: void
1289: udav_watchdog(struct ifnet *ifp)
1290: {
1291: struct udav_softc *sc = ifp->if_softc;
1292: struct udav_chain *c;
1293: usbd_status stat;
1294: int s;
1295:
1296: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1297:
1298: ifp->if_oerrors++;
1299: printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
1300:
1301: s = splusb();
1302: c = &sc->sc_cdata.udav_tx_chain[0];
1303: usbd_get_xfer_status(c->udav_xfer, NULL, NULL, NULL, &stat);
1304: udav_txeof(c->udav_xfer, c, stat);
1305:
1306: if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1307: udav_start(ifp);
1308: splx(s);
1309: }
1310:
1311: void
1312: udav_stop_task(struct udav_softc *sc)
1313: {
1314: udav_stop(GET_IFP(sc), 1);
1315: }
1316:
1317: /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
1318: void
1319: udav_stop(struct ifnet *ifp, int disable)
1320: {
1321: struct udav_softc *sc = ifp->if_softc;
1322: usbd_status err;
1323: int i;
1324:
1325: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1326:
1327: ifp->if_timer = 0;
1328: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1329:
1330: udav_reset(sc);
1331:
1332: timeout_del(&sc->sc_stat_ch);
1333:
1334: /* Stop transfers */
1335: /* RX endpoint */
1336: if (sc->sc_pipe_rx != NULL) {
1337: err = usbd_abort_pipe(sc->sc_pipe_rx);
1338: if (err)
1339: printf("%s: abort rx pipe failed: %s\n",
1340: sc->sc_dev.dv_xname, usbd_errstr(err));
1341: err = usbd_close_pipe(sc->sc_pipe_rx);
1342: if (err)
1343: printf("%s: close rx pipe failed: %s\n",
1344: sc->sc_dev.dv_xname, usbd_errstr(err));
1345: sc->sc_pipe_rx = NULL;
1346: }
1347:
1348: /* TX endpoint */
1349: if (sc->sc_pipe_tx != NULL) {
1350: err = usbd_abort_pipe(sc->sc_pipe_tx);
1351: if (err)
1352: printf("%s: abort tx pipe failed: %s\n",
1353: sc->sc_dev.dv_xname, usbd_errstr(err));
1354: err = usbd_close_pipe(sc->sc_pipe_tx);
1355: if (err)
1356: printf("%s: close tx pipe failed: %s\n",
1357: sc->sc_dev.dv_xname, usbd_errstr(err));
1358: sc->sc_pipe_tx = NULL;
1359: }
1360:
1361: #if 0
1362: /* XXX: Interrupt endpoint is not yet supported!! */
1363: /* Interrupt endpoint */
1364: if (sc->sc_pipe_intr != NULL) {
1365: err = usbd_abort_pipe(sc->sc_pipe_intr);
1366: if (err)
1367: printf("%s: abort intr pipe failed: %s\n",
1368: sc->sc_dev.dv_xname, usbd_errstr(err));
1369: err = usbd_close_pipe(sc->sc_pipe_intr);
1370: if (err)
1371: printf("%s: close intr pipe failed: %s\n",
1372: sc->sc_dev.dv_xname, usbd_errstr(err));
1373: sc->sc_pipe_intr = NULL;
1374: }
1375: #endif
1376:
1377: /* Free RX resources. */
1378: for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
1379: if (sc->sc_cdata.udav_rx_chain[i].udav_mbuf != NULL) {
1380: m_freem(sc->sc_cdata.udav_rx_chain[i].udav_mbuf);
1381: sc->sc_cdata.udav_rx_chain[i].udav_mbuf = NULL;
1382: }
1383: if (sc->sc_cdata.udav_rx_chain[i].udav_xfer != NULL) {
1384: usbd_free_xfer(sc->sc_cdata.udav_rx_chain[i].udav_xfer);
1385: sc->sc_cdata.udav_rx_chain[i].udav_xfer = NULL;
1386: }
1387: }
1388:
1389: /* Free TX resources. */
1390: for (i = 0; i < UDAV_TX_LIST_CNT; i++) {
1391: if (sc->sc_cdata.udav_tx_chain[i].udav_mbuf != NULL) {
1392: m_freem(sc->sc_cdata.udav_tx_chain[i].udav_mbuf);
1393: sc->sc_cdata.udav_tx_chain[i].udav_mbuf = NULL;
1394: }
1395: if (sc->sc_cdata.udav_tx_chain[i].udav_xfer != NULL) {
1396: usbd_free_xfer(sc->sc_cdata.udav_tx_chain[i].udav_xfer);
1397: sc->sc_cdata.udav_tx_chain[i].udav_xfer = NULL;
1398: }
1399: }
1400:
1401: sc->sc_link = 0;
1402: }
1403:
1404: /* Set media options */
1405: int
1406: udav_ifmedia_change(struct ifnet *ifp)
1407: {
1408: struct udav_softc *sc = ifp->if_softc;
1409: struct mii_data *mii = GET_MII(sc);
1410:
1411: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1412:
1413: if (sc->sc_dying)
1414: return (0);
1415:
1416: sc->sc_link = 0;
1417: if (mii->mii_instance) {
1418: struct mii_softc *miisc;
1419: for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
1420: miisc = LIST_NEXT(miisc, mii_list))
1421: mii_phy_reset(miisc);
1422: }
1423:
1424: return (mii_mediachg(mii));
1425: }
1426:
1427: /* Report current media status. */
1428: void
1429: udav_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
1430: {
1431: struct udav_softc *sc = ifp->if_softc;
1432: struct mii_data *mii = GET_MII(sc);
1433:
1434: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1435:
1436: if (sc->sc_dying)
1437: return;
1438:
1439: if ((ifp->if_flags & IFF_RUNNING) == 0) {
1440: ifmr->ifm_active = IFM_ETHER | IFM_NONE;
1441: ifmr->ifm_status = 0;
1442: return;
1443: }
1444:
1445: mii_pollstat(mii);
1446: ifmr->ifm_active = mii->mii_media_active;
1447: ifmr->ifm_status = mii->mii_media_status;
1448: }
1449:
1450: void
1451: udav_tick(void *xsc)
1452: {
1453: struct udav_softc *sc = xsc;
1454:
1455: if (sc == NULL)
1456: return;
1457:
1458: DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
1459: __func__));
1460:
1461: if (sc->sc_dying)
1462: return;
1463:
1464: /* Perform periodic stuff in process context */
1465: usb_add_task(sc->sc_udev, &sc->sc_tick_task);
1466: }
1467:
1468: void
1469: udav_tick_task(void *xsc)
1470: {
1471: struct udav_softc *sc = xsc;
1472: struct ifnet *ifp;
1473: struct mii_data *mii;
1474: int s;
1475:
1476: if (sc == NULL)
1477: return;
1478:
1479: DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
1480: __func__));
1481:
1482: if (sc->sc_dying)
1483: return;
1484:
1485: ifp = GET_IFP(sc);
1486: mii = GET_MII(sc);
1487:
1488: if (mii == NULL)
1489: return;
1490:
1491: s = splnet();
1492:
1493: mii_tick(mii);
1494: if (!sc->sc_link && mii->mii_media_status & IFM_ACTIVE &&
1495: IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
1496: DPRINTF(("%s: %s: got link\n",
1497: sc->sc_dev.dv_xname, __func__));
1498: sc->sc_link++;
1499: if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1500: udav_start(ifp);
1501: }
1502:
1503: timeout_del(&sc->sc_stat_ch);
1504: timeout_set(&sc->sc_stat_ch, udav_tick, sc);
1505: timeout_add(&sc->sc_stat_ch, hz);
1506:
1507: splx(s);
1508: }
1509:
1510: /* Get exclusive access to the MII registers */
1511: void
1512: udav_lock_mii(struct udav_softc *sc)
1513: {
1514: DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
1515: __func__));
1516:
1517: sc->sc_refcnt++;
1518: rw_enter_write(&sc->sc_mii_lock);
1519: }
1520:
1521: void
1522: udav_unlock_mii(struct udav_softc *sc)
1523: {
1524: DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
1525: __func__));
1526:
1527: rw_exit_write(&sc->sc_mii_lock);
1528: if (--sc->sc_refcnt < 0)
1529: usb_detach_wakeup(&sc->sc_dev);
1530: }
1531:
1532: int
1533: udav_miibus_readreg(struct device *dev, int phy, int reg)
1534: {
1535: struct udav_softc *sc;
1536: u_int8_t val[2];
1537: u_int16_t data16;
1538:
1539: if (dev == NULL)
1540: return (0);
1541:
1542: sc = (void *)dev;
1543:
1544: DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n",
1545: sc->sc_dev.dv_xname, __func__, phy, reg));
1546:
1547: if (sc->sc_dying) {
1548: #ifdef DIAGNOSTIC
1549: printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
1550: __func__);
1551: #endif
1552: return (0);
1553: }
1554:
1555: /* XXX: one PHY only for the internal PHY */
1556: if (phy != 0) {
1557: DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
1558: sc->sc_dev.dv_xname, __func__, phy));
1559: return (0);
1560: }
1561:
1562: udav_lock_mii(sc);
1563:
1564: /* select internal PHY and set PHY register address */
1565: udav_csr_write1(sc, UDAV_EPAR,
1566: UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
1567:
1568: /* select PHY operation and start read command */
1569: udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRR);
1570:
1571: /* XXX: should be wait? */
1572:
1573: /* end read command */
1574: UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRR);
1575:
1576: /* retrieve the result from data registers */
1577: udav_csr_read(sc, UDAV_EPDRL, val, 2);
1578:
1579: udav_unlock_mii(sc);
1580:
1581: data16 = val[0] | (val[1] << 8);
1582:
1583: DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n",
1584: sc->sc_dev.dv_xname, __func__, phy, reg, data16));
1585:
1586: return (data16);
1587: }
1588:
1589: void
1590: udav_miibus_writereg(struct device *dev, int phy, int reg, int data)
1591: {
1592: struct udav_softc *sc;
1593: u_int8_t val[2];
1594:
1595: if (dev == NULL)
1596: return;
1597:
1598: sc = (void *)dev;
1599:
1600: DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n",
1601: sc->sc_dev.dv_xname, __func__, phy, reg, data));
1602:
1603: if (sc->sc_dying) {
1604: #ifdef DIAGNOSTIC
1605: printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
1606: __func__);
1607: #endif
1608: return;
1609: }
1610:
1611: /* XXX: one PHY only for the internal PHY */
1612: if (phy != 0) {
1613: DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
1614: sc->sc_dev.dv_xname, __func__, phy));
1615: return;
1616: }
1617:
1618: udav_lock_mii(sc);
1619:
1620: /* select internal PHY and set PHY register address */
1621: udav_csr_write1(sc, UDAV_EPAR,
1622: UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
1623:
1624: /* put the value to the data registers */
1625: val[0] = data & 0xff;
1626: val[1] = (data >> 8) & 0xff;
1627: udav_csr_write(sc, UDAV_EPDRL, val, 2);
1628:
1629: /* select PHY operation and start write command */
1630: udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRW);
1631:
1632: /* XXX: should be wait? */
1633:
1634: /* end write command */
1635: UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW);
1636:
1637: udav_unlock_mii(sc);
1638:
1639: return;
1640: }
1641:
1642: void
1643: udav_miibus_statchg(struct device *dev)
1644: {
1645: #ifdef UDAV_DEBUG
1646: struct udav_softc *sc;
1647:
1648: if (dev == NULL)
1649: return;
1650:
1651: sc = (void *)dev;
1652: DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1653: #endif
1654: /* Nothing to do */
1655: }
CVSweb