1 /* $NetBSD: if_axe.c,v 1.29 2009/09/23 19:07:19 plunky Exp $ */
4 * Copyright (c) 1997, 1998, 1999, 2000-2003
5 * Bill Paul <wpaul@windriver.com>. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
36 * ASIX Electronics AX88172 USB 2.0 ethernet driver. Used in the
37 * LinkSys USB200M and various other adapters.
39 * Manuals available from:
40 * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF
41 * (also http://people.freebsd.org/~wpaul/ASIX/Ax88172.PDF)
42 * Note: you need the manual for the AX88170 chip (USB 1.x ethernet
43 * controller) to find the definitions for the RX control register.
44 * http://www.asix.com.tw/datasheet/mac/Ax88170.PDF
46 * Written by Bill Paul <wpaul@windriver.com>
52 * The AX88172 provides USB ethernet supports at 10 and 100Mbps.
53 * It uses an external PHY (reference designs use a RealTek chip),
54 * and has a 64-bit multicast hash filter. There is some information
55 * missing from the manual which one needs to know in order to make
58 * - You must set bit 7 in the RX control register, otherwise the
59 * chip won't receive any packets.
60 * - You must initialize all 3 IPG registers, or you won't be able
61 * to send any packets.
63 * Note that this device appears to only support loading the station
64 * address via autload from the EEPROM (i.e. there's no way to manaully
67 * (Adam Weinberger wanted me to name this driver if_gir.c.)
71 * Ported to OpenBSD 3/28/2004 by Greg Taleck <taleck@oz.net>
72 * with bits and pieces from the aue and url drivers.
75 #include <sys/cdefs.h>
76 __KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.29 2009/09/23 19:07:19 plunky Exp $");
78 #if defined(__NetBSD__)
85 #include <sys/param.h>
86 #include <sys/systm.h>
87 #include <sys/sockio.h>
88 #include <sys/mutex.h>
90 #include <sys/kernel.h>
91 #if defined(__OpenBSD__)
94 #include <sys/socket.h>
96 #include <sys/device.h>
102 #if defined(__NetBSD__)
103 #include <net/if_arp.h>
105 #include <net/if_dl.h>
106 #include <net/if_media.h>
108 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
114 #if defined(__NetBSD__)
115 #include <net/if_ether.h>
117 #include <netinet/in.h>
118 #include <netinet/if_inarp.h>
120 #endif /* defined(__NetBSD__) */
122 #if defined(__OpenBSD__)
124 #include <netinet/in.h>
125 #include <netinet/in_systm.h>
126 #include <netinet/in_var.h>
127 #include <netinet/ip.h>
128 #include <netinet/if_ether.h>
130 #endif /* defined(__OpenBSD__) */
133 #include <dev/mii/mii.h>
134 #include <dev/mii/miivar.h>
136 #include <dev/usb/usb.h>
137 #include <dev/usb/usbdi.h>
138 #include <dev/usb/usbdi_util.h>
139 #include <dev/usb/usbdevs.h>
141 #include <dev/usb/if_axereg.h>
144 #define DPRINTF(x) do { if (axedebug) logprintf x; } while (0)
145 #define DPRINTFN(n,x) do { if (axedebug >= (n)) logprintf x; } while (0)
149 #define DPRINTFN(n,x)
153 * Various supported device vendors/products.
155 Static
const struct axe_type axe_devs
[] = {
156 { { USB_VENDOR_ASIX
, USB_PRODUCT_ASIX_AX88172
}, 0 },
157 { { USB_VENDOR_COREGA
, USB_PRODUCT_COREGA_FETHER_USB2_TX
}, 0},
158 { { USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DUBE100
}, 0 },
159 { { USB_VENDOR_LINKSYS2
, USB_PRODUCT_LINKSYS2_USB200M
}, 0 },
160 { { USB_VENDOR_MELCO
, USB_PRODUCT_MELCO_LUAU2KTX
}, 0 },
161 { { USB_VENDOR_NETGEAR
, USB_PRODUCT_NETGEAR_FA120
}, 0 },
162 { { USB_VENDOR_SITECOM
, USB_PRODUCT_SITECOM_LN029
}, 0 },
163 { { USB_VENDOR_SYSTEMTALKS
, USB_PRODUCT_SYSTEMTALKS_SGCX2UL
}, 0 },
165 #define axe_lookup(v, p) ((const struct axe_type *)usb_lookup(axe_devs, v, p))
167 int axe_match(device_t
, cfdata_t
, void *);
168 void axe_attach(device_t
, device_t
, void *);
169 int axe_detach(device_t
, int);
170 int axe_activate(device_t
, enum devact
);
171 extern struct cfdriver axe_cd
;
172 CFATTACH_DECL_NEW(axe
, sizeof(struct axe_softc
), axe_match
, axe_attach
,
173 axe_detach
, axe_activate
);
175 Static
int axe_tx_list_init(struct axe_softc
*);
176 Static
int axe_rx_list_init(struct axe_softc
*);
177 Static
int axe_newbuf(struct axe_softc
*, struct axe_chain
*, struct mbuf
*);
178 Static
int axe_encap(struct axe_softc
*, struct mbuf
*, int);
179 Static
void axe_rxeof(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
180 Static
void axe_txeof(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
181 Static
void axe_tick(void *);
182 Static
void axe_tick_task(void *);
184 Static
void axe_rxstart(struct ifnet
*);
186 Static
void axe_start(struct ifnet
*);
187 Static
int axe_ioctl(struct ifnet
*, u_long
, void *);
188 Static
void axe_init(void *);
189 Static
void axe_stop(struct axe_softc
*);
190 Static
void axe_watchdog(struct ifnet
*);
191 Static
int axe_miibus_readreg(device_t
, int, int);
192 Static
void axe_miibus_writereg(device_t
, int, int, int);
193 Static
void axe_miibus_statchg(device_t
);
194 Static
int axe_cmd(struct axe_softc
*, int, int, int, void *);
195 Static
void axe_reset(struct axe_softc
*sc
);
197 Static
void axe_setmulti(struct axe_softc
*);
198 Static
void axe_lock_mii(struct axe_softc
*sc
);
199 Static
void axe_unlock_mii(struct axe_softc
*sc
);
201 /* Get exclusive access to the MII registers */
203 axe_lock_mii(struct axe_softc
*sc
)
206 mutex_enter(&sc
->axe_mii_lock
);
210 axe_unlock_mii(struct axe_softc
*sc
)
212 mutex_exit(&sc
->axe_mii_lock
);
213 if (--sc
->axe_refcnt
< 0)
214 usb_detach_wakeup((sc
->axe_dev
));
218 axe_cmd(struct axe_softc
*sc
, int cmd
, int index
, int val
, void *buf
)
220 usb_device_request_t req
;
223 KASSERT(mutex_owned(&sc
->axe_mii_lock
));
228 if (AXE_CMD_DIR(cmd
))
229 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
231 req
.bmRequestType
= UT_READ_VENDOR_DEVICE
;
232 req
.bRequest
= AXE_CMD_CMD(cmd
);
233 USETW(req
.wValue
, val
);
234 USETW(req
.wIndex
, index
);
235 USETW(req
.wLength
, AXE_CMD_LEN(cmd
));
237 err
= usbd_do_request(sc
->axe_udev
, &req
, buf
);
246 axe_miibus_readreg(device_t dev
, int phy
, int reg
)
248 struct axe_softc
*sc
= device_private(dev
);
253 DPRINTF(("axe: dying\n"));
259 * The chip tells us the MII address of any supported
260 * PHYs attached to the chip, so only read from those.
263 if (sc
->axe_phyaddrs
[0] != AXE_NOPHY
&& phy
!= sc
->axe_phyaddrs
[0])
266 if (sc
->axe_phyaddrs
[1] != AXE_NOPHY
&& phy
!= sc
->axe_phyaddrs
[1])
269 if (sc
->axe_phyaddrs
[0] != 0xFF && sc
->axe_phyaddrs
[0] != phy
)
275 axe_cmd(sc
, AXE_CMD_MII_OPMODE_SW
, 0, 0, NULL
);
276 err
= axe_cmd(sc
, AXE_CMD_MII_READ_REG
, reg
, phy
, (void *)&val
);
277 axe_cmd(sc
, AXE_CMD_MII_OPMODE_HW
, 0, 0, NULL
);
281 aprint_error_dev(sc
->axe_dev
, "read PHY failed\n");
286 sc
->axe_phyaddrs
[0] = phy
;
288 return (le16toh(val
));
292 axe_miibus_writereg(device_t dev
, int phy
, int reg
, int aval
)
294 struct axe_softc
*sc
= device_private(dev
);
303 axe_cmd(sc
, AXE_CMD_MII_OPMODE_SW
, 0, 0, NULL
);
304 err
= axe_cmd(sc
, AXE_CMD_MII_WRITE_REG
, reg
, phy
, (void *)&val
);
305 axe_cmd(sc
, AXE_CMD_MII_OPMODE_HW
, 0, 0, NULL
);
309 aprint_error_dev(sc
->axe_dev
, "write PHY failed\n");
315 axe_miibus_statchg(device_t dev
)
317 struct axe_softc
*sc
= device_private(dev
);
318 struct mii_data
*mii
= GET_MII(sc
);
321 if ((mii
->mii_media_active
& IFM_GMASK
) == IFM_FDX
)
322 val
= AXE_MEDIA_FULL_DUPLEX
;
325 DPRINTF(("axe_miibus_statchg: val=0x%x\n", val
));
327 err
= axe_cmd(sc
, AXE_CMD_WRITE_MEDIA
, 0, val
, NULL
);
330 aprint_error_dev(sc
->axe_dev
, "media change failed\n");
336 axe_setmulti(struct axe_softc
*sc
)
339 struct ether_multi
*enm
;
340 struct ether_multistep step
;
343 u_int8_t hashtbl
[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
351 axe_cmd(sc
, AXE_CMD_RXCTL_READ
, 0, 0, (void *)&rxmode
);
352 rxmode
= le16toh(rxmode
);
354 if (ifp
->if_flags
& IFF_ALLMULTI
|| ifp
->if_flags
& IFF_PROMISC
) {
356 rxmode
|= AXE_RXCMD_ALLMULTI
;
357 axe_cmd(sc
, AXE_CMD_RXCTL_WRITE
, 0, rxmode
, NULL
);
360 rxmode
&= ~AXE_RXCMD_ALLMULTI
;
362 /* now program new ones */
363 #if defined(__NetBSD__)
364 ETHER_FIRST_MULTI(step
, &sc
->axe_ec
, enm
);
366 ETHER_FIRST_MULTI(step
, &sc
->arpcom
, enm
);
368 while (enm
!= NULL
) {
369 if (memcmp(enm
->enm_addrlo
, enm
->enm_addrhi
,
370 ETHER_ADDR_LEN
) != 0)
373 h
= ether_crc32_be(enm
->enm_addrlo
, ETHER_ADDR_LEN
) >> 26;
374 hashtbl
[h
/ 8] |= 1 << (h
% 8);
375 ETHER_NEXT_MULTI(step
, enm
);
378 ifp
->if_flags
&= ~IFF_ALLMULTI
;
379 axe_cmd(sc
, AXE_CMD_WRITE_MCAST
, 0, 0, (void *)&hashtbl
);
380 axe_cmd(sc
, AXE_CMD_RXCTL_WRITE
, 0, rxmode
, NULL
);
386 axe_reset(struct axe_softc
*sc
)
390 /* XXX What to reset? */
392 /* Wait a little while for the chip to get its brains in order. */
398 * Probe for a AX88172 chip.
401 axe_match(device_t parent
, cfdata_t match
, void *aux
)
403 struct usb_attach_arg
*uaa
= aux
;
405 return (axe_lookup(uaa
->vendor
, uaa
->product
) != NULL
?
406 UMATCH_VENDOR_PRODUCT
: UMATCH_NONE
);
410 * Attach the interface. Allocate softc structures, do ifmedia
411 * setup and ethernet/BPF attach.
414 axe_attach(device_t parent
, device_t self
, void *aux
)
416 struct axe_softc
*sc
= device_private(self
);
417 struct usb_attach_arg
*uaa
= aux
;
418 usbd_device_handle dev
= uaa
->device
;
420 usb_interface_descriptor_t
*id
;
421 usb_endpoint_descriptor_t
*ed
;
422 struct mii_data
*mii
;
423 u_char eaddr
[ETHER_ADDR_LEN
];
425 const char *devname
= device_xname(self
);
434 devinfop
= usbd_devinfo_alloc(dev
, 0);
435 aprint_normal_dev(self
, "%s\n", devinfop
);
436 usbd_devinfo_free(devinfop
);
438 err
= usbd_set_config_no(dev
, AXE_CONFIG_NO
, 1);
440 aprint_error_dev(self
, "getting interface handle failed\n");
444 usb_init_task(&sc
->axe_tick_task
, axe_tick_task
, sc
);
445 mutex_init(&sc
->axe_mii_lock
, MUTEX_DEFAULT
, IPL_NONE
);
446 usb_init_task(&sc
->axe_stop_task
, (void (*)(void *))axe_stop
, sc
);
448 err
= usbd_device2interface_handle(dev
, AXE_IFACE_IDX
, &sc
->axe_iface
);
450 aprint_error_dev(self
, "getting interface handle failed\n");
455 sc
->axe_product
= uaa
->product
;
456 sc
->axe_vendor
= uaa
->vendor
;
458 id
= usbd_get_interface_descriptor(sc
->axe_iface
);
460 /* Find endpoints. */
461 for (i
= 0; i
< id
->bNumEndpoints
; i
++) {
462 ed
= usbd_interface2endpoint_descriptor(sc
->axe_iface
, i
);
464 aprint_error_dev(self
, "couldn't get ep %d\n", i
);
467 if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
468 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
469 sc
->axe_ed
[AXE_ENDPT_RX
] = ed
->bEndpointAddress
;
470 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_OUT
&&
471 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
472 sc
->axe_ed
[AXE_ENDPT_TX
] = ed
->bEndpointAddress
;
473 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
474 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_INTERRUPT
) {
475 sc
->axe_ed
[AXE_ENDPT_INTR
] = ed
->bEndpointAddress
;
482 * Get station address.
485 axe_cmd(sc
, AXE_CMD_READ_NODEID
, 0, 0, &eaddr
);
488 * Load IPG values and PHY indexes.
490 axe_cmd(sc
, AXE_CMD_READ_IPG012
, 0, 0, (void *)&sc
->axe_ipgs
);
491 axe_cmd(sc
, AXE_CMD_READ_PHYID
, 0, 0, (void *)&sc
->axe_phyaddrs
);
495 * Work around broken adapters that appear to lie about
496 * their PHY addresses.
498 sc
->axe_phyaddrs
[0] = sc
->axe_phyaddrs
[1] = 0xFF;
501 * An ASIX chip was detected. Inform the world.
503 aprint_normal_dev(self
, "Ethernet address %s\n",
504 ether_sprintf(eaddr
));
506 /* Initialize interface info.*/
509 strncpy(ifp
->if_xname
, devname
, IFNAMSIZ
);
510 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
511 ifp
->if_ioctl
= axe_ioctl
;
512 ifp
->if_start
= axe_start
;
514 ifp
->if_watchdog
= axe_watchdog
;
516 /* ifp->if_baudrate = 10000000; */
517 /* ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;*/
519 IFQ_SET_READY(&ifp
->if_snd
);
521 /* Initialize MII/media info. */
524 mii
->mii_readreg
= axe_miibus_readreg
;
525 mii
->mii_writereg
= axe_miibus_writereg
;
526 mii
->mii_statchg
= axe_miibus_statchg
;
527 mii
->mii_flags
= MIIF_AUTOTSLEEP
;
529 sc
->axe_ec
.ec_mii
= mii
;
530 ifmedia_init(&mii
->mii_media
, 0, ether_mediachange
, ether_mediastatus
);
531 mii_attach(self
, mii
, 0xffffffff, MII_PHY_ANY
, MII_OFFSET_ANY
, 0);
533 if (LIST_EMPTY(&mii
->mii_phys
)) {
534 ifmedia_add(&mii
->mii_media
, IFM_ETHER
| IFM_NONE
, 0, NULL
);
535 ifmedia_set(&mii
->mii_media
, IFM_ETHER
| IFM_NONE
);
537 ifmedia_set(&mii
->mii_media
, IFM_ETHER
| IFM_AUTO
);
539 /* Attach the interface. */
541 ether_ifattach(ifp
, eaddr
);
543 rnd_attach_source(&sc
->rnd_source
, device_xname(sc
->axe_dev
),
547 callout_init(&(sc
->axe_stat_ch
), 0);
549 sc
->axe_attached
= 1;
552 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH
, sc
->axe_udev
, sc
->axe_dev
);
558 axe_detach(device_t self
, int flags
)
560 struct axe_softc
*sc
= device_private(self
);
562 struct ifnet
*ifp
= GET_IFP(sc
);
564 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc
->axe_dev
), __func__
));
566 /* Detached before attached finished, so just bail out. */
567 if (!sc
->axe_attached
)
570 callout_stop(&(sc
->axe_stat_ch
));
576 if (sc
->axe_ep
[AXE_ENDPT_TX
] != NULL
)
577 usbd_abort_pipe(sc
->axe_ep
[AXE_ENDPT_TX
]);
578 if (sc
->axe_ep
[AXE_ENDPT_RX
] != NULL
)
579 usbd_abort_pipe(sc
->axe_ep
[AXE_ENDPT_RX
]);
580 if (sc
->axe_ep
[AXE_ENDPT_INTR
] != NULL
)
581 usbd_abort_pipe(sc
->axe_ep
[AXE_ENDPT_INTR
]);
584 * Remove any pending tasks. They cannot be executing because they run
585 * in the same thread as detach.
587 usb_rem_task(sc
->axe_udev
, &sc
->axe_tick_task
);
588 usb_rem_task(sc
->axe_udev
, &sc
->axe_stop_task
);
592 if (--sc
->axe_refcnt
>= 0) {
593 /* Wait for processes to go away */
594 usb_detach_wait((sc
->axe_dev
));
597 if (ifp
->if_flags
& IFF_RUNNING
)
600 #if defined(__NetBSD__)
602 rnd_detach_source(&sc
->rnd_source
);
604 #endif /* __NetBSD__ */
605 mii_detach(&sc
->axe_mii
, MII_PHY_ANY
, MII_OFFSET_ANY
);
606 ifmedia_delete_instance(&sc
->axe_mii
.mii_media
, IFM_INST_ANY
);
611 if (sc
->axe_ep
[AXE_ENDPT_TX
] != NULL
||
612 sc
->axe_ep
[AXE_ENDPT_RX
] != NULL
||
613 sc
->axe_ep
[AXE_ENDPT_INTR
] != NULL
)
614 aprint_debug_dev(self
, "detach has active endpoints\n");
617 sc
->axe_attached
= 0;
619 if (--sc
->axe_refcnt
>= 0) {
620 /* Wait for processes to go away. */
621 usb_detach_wait((sc
->axe_dev
));
625 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH
, sc
->axe_udev
, sc
->axe_dev
);
631 axe_activate(device_t self
, enum devact act
)
633 struct axe_softc
*sc
= device_private(self
);
635 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc
->axe_dev
), __func__
));
638 case DVACT_DEACTIVATE
:
639 if_deactivate(&sc
->axe_ec
.ec_if
);
648 * Initialize an RX descriptor and attach an MBUF cluster.
651 axe_newbuf(struct axe_softc
*sc
, struct axe_chain
*c
, struct mbuf
*m
)
653 struct mbuf
*m_new
= NULL
;
655 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc
->axe_dev
),__func__
));
658 MGETHDR(m_new
, M_DONTWAIT
, MT_DATA
);
660 aprint_error_dev(sc
->axe_dev
, "no memory for rx list "
661 "-- packet dropped!\n");
665 MCLGET(m_new
, M_DONTWAIT
);
666 if (!(m_new
->m_flags
& M_EXT
)) {
667 aprint_error_dev(sc
->axe_dev
, "no memory for rx list "
668 "-- packet dropped!\n");
672 m_new
->m_len
= m_new
->m_pkthdr
.len
= MCLBYTES
;
675 m_new
->m_len
= m_new
->m_pkthdr
.len
= MCLBYTES
;
676 m_new
->m_data
= m_new
->m_ext
.ext_buf
;
679 m_adj(m_new
, ETHER_ALIGN
);
686 axe_rx_list_init(struct axe_softc
*sc
)
688 struct axe_cdata
*cd
;
692 DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc
->axe_dev
), __func__
));
695 for (i
= 0; i
< AXE_RX_LIST_CNT
; i
++) {
696 c
= &cd
->axe_rx_chain
[i
];
699 if (axe_newbuf(sc
, c
, NULL
) == ENOBUFS
)
701 if (c
->axe_xfer
== NULL
) {
702 c
->axe_xfer
= usbd_alloc_xfer(sc
->axe_udev
);
703 if (c
->axe_xfer
== NULL
)
705 c
->axe_buf
= usbd_alloc_buffer(c
->axe_xfer
, AXE_BUFSZ
);
706 if (c
->axe_buf
== NULL
) {
707 usbd_free_xfer(c
->axe_xfer
);
717 axe_tx_list_init(struct axe_softc
*sc
)
719 struct axe_cdata
*cd
;
723 DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc
->axe_dev
), __func__
));
726 for (i
= 0; i
< AXE_TX_LIST_CNT
; i
++) {
727 c
= &cd
->axe_tx_chain
[i
];
731 if (c
->axe_xfer
== NULL
) {
732 c
->axe_xfer
= usbd_alloc_xfer(sc
->axe_udev
);
733 if (c
->axe_xfer
== NULL
)
735 c
->axe_buf
= usbd_alloc_buffer(c
->axe_xfer
, AXE_BUFSZ
);
736 if (c
->axe_buf
== NULL
) {
737 usbd_free_xfer(c
->axe_xfer
);
748 axe_rxstart(struct ifnet
*ifp
)
750 struct axe_softc
*sc
;
755 c
= &sc
->axe_cdata
.axe_rx_chain
[sc
->axe_cdata
.axe_rx_prod
];
757 if (axe_newbuf(sc
, c
, NULL
) == ENOBUFS
) {
763 /* Setup new transfer. */
764 usbd_setup_xfer(c
->axe_xfer
, sc
->axe_ep
[AXE_ENDPT_RX
],
765 c
, mtod(c
->axe_mbuf
, char *), AXE_BUFSZ
, USBD_SHORT_XFER_OK
,
766 USBD_NO_TIMEOUT
, axe_rxeof
);
767 usbd_transfer(c
->axe_xfer
);
775 * A frame has been uploaded: pass the resulting mbuf chain up to
776 * the higher level protocols.
779 axe_rxeof(usbd_xfer_handle xfer
, usbd_private_handle priv
, usbd_status status
)
781 struct axe_softc
*sc
;
792 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc
->axe_dev
),__func__
));
797 if (!(ifp
->if_flags
& IFF_RUNNING
))
800 if (status
!= USBD_NORMAL_COMPLETION
) {
801 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
)
803 if (usbd_ratecheck(&sc
->axe_rx_notice
)) {
804 printf("%s: usb errors on rx: %s\n",
805 device_xname(sc
->axe_dev
), usbd_errstr(status
));
807 if (status
== USBD_STALLED
)
808 usbd_clear_endpoint_stall_async(sc
->axe_ep
[AXE_ENDPT_RX
]);
812 usbd_get_xfer_status(xfer
, NULL
, NULL
, &total_len
, NULL
);
816 if (total_len
<= sizeof(struct ether_header
)) {
822 m
->m_pkthdr
.rcvif
= ifp
;
823 m
->m_pkthdr
.len
= m
->m_len
= total_len
;
826 memcpy(mtod(c
->axe_mbuf
, char *), c
->axe_buf
, total_len
);
828 /* No errors; receive the packet. */
829 total_len
-= ETHER_CRC_LEN
+ 4;
834 if (axe_newbuf(sc
, c
, NULL
) == ENOBUFS
) {
844 DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc
->axe_dev
),
845 __func__
, m
->m_len
));
846 (*(ifp
)->if_input
)((ifp
), (m
));
852 /* Setup new transfer. */
853 usbd_setup_xfer(xfer
, sc
->axe_ep
[AXE_ENDPT_RX
],
854 c
, c
->axe_buf
, AXE_BUFSZ
,
855 USBD_SHORT_XFER_OK
| USBD_NO_COPY
,
856 USBD_NO_TIMEOUT
, axe_rxeof
);
859 DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc
->axe_dev
),
865 * A frame was downloaded to the chip. It's safe for us to clean up
870 axe_txeof(usbd_xfer_handle xfer
, usbd_private_handle priv
,
873 struct axe_softc
*sc
;
887 if (status
!= USBD_NORMAL_COMPLETION
) {
888 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
) {
893 printf("%s: usb error on tx: %s\n", device_xname(sc
->axe_dev
),
894 usbd_errstr(status
));
895 if (status
== USBD_STALLED
)
896 usbd_clear_endpoint_stall_async(sc
->axe_ep
[AXE_ENDPT_TX
]);
902 ifp
->if_flags
&= ~IFF_OACTIVE
;
904 m_freem(c
->axe_mbuf
);
907 if (IFQ_IS_EMPTY(&ifp
->if_snd
) == 0)
918 struct axe_softc
*sc
= xsc
;
923 DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc
->axe_dev
),
929 /* Perform periodic stuff in process context */
930 usb_add_task(sc
->axe_udev
, &sc
->axe_tick_task
, USB_TASKQ_DRIVER
);
935 axe_tick_task(void *xsc
)
938 struct axe_softc
*sc
;
940 struct mii_data
*mii
;
959 callout_reset(&(sc
->axe_stat_ch
), (hz
), (axe_tick
), (sc
));
965 axe_encap(struct axe_softc
*sc
, struct mbuf
*m
, int idx
)
970 c
= &sc
->axe_cdata
.axe_tx_chain
[idx
];
973 * Copy the mbuf data into a contiguous buffer, leaving two
974 * bytes at the beginning to hold the frame length.
976 m_copydata(m
, 0, m
->m_pkthdr
.len
, c
->axe_buf
);
979 usbd_setup_xfer(c
->axe_xfer
, sc
->axe_ep
[AXE_ENDPT_TX
],
980 c
, c
->axe_buf
, m
->m_pkthdr
.len
, USBD_FORCE_SHORT_XFER
, 10000,
984 err
= usbd_transfer(c
->axe_xfer
);
985 if (err
!= USBD_IN_PROGRESS
) {
990 sc
->axe_cdata
.axe_tx_cnt
++;
996 axe_start(struct ifnet
*ifp
)
998 struct axe_softc
*sc
;
999 struct mbuf
*m_head
= NULL
;
1003 if ((ifp
->if_flags
& (IFF_OACTIVE
|IFF_RUNNING
)) != IFF_RUNNING
)
1006 IF_DEQUEUE(&ifp
->if_snd
, m_head
);
1007 if (m_head
== NULL
) {
1011 if (axe_encap(sc
, m_head
, 0)) {
1012 IF_PREPEND(&ifp
->if_snd
, m_head
);
1013 ifp
->if_flags
|= IFF_OACTIVE
;
1018 * If there's a BPF listener, bounce a copy of this frame
1023 BPF_MTAP(ifp
, m_head
);
1026 ifp
->if_flags
|= IFF_OACTIVE
;
1029 * Set a timeout in case the chip goes out to lunch.
1039 struct axe_softc
*sc
= xsc
;
1040 struct ifnet
*ifp
= GET_IFP(sc
);
1041 struct axe_chain
*c
;
1046 if (ifp
->if_flags
& IFF_RUNNING
)
1052 * Cancel pending I/O and free all RX/TX buffers.
1056 /* Enable RX logic. */
1059 if (axe_rx_list_init(sc
) == ENOBUFS
) {
1060 printf("%s: rx list init failed\n", device_xname(sc
->axe_dev
));
1066 if (axe_tx_list_init(sc
) == ENOBUFS
) {
1067 printf("%s: tx list init failed\n", device_xname(sc
->axe_dev
));
1072 /* Set transmitter IPG values */
1074 axe_cmd(sc
, AXE_CMD_WRITE_IPG0
, 0, sc
->axe_ipgs
[0], NULL
);
1075 axe_cmd(sc
, AXE_CMD_WRITE_IPG1
, 0, sc
->axe_ipgs
[1], NULL
);
1076 axe_cmd(sc
, AXE_CMD_WRITE_IPG2
, 0, sc
->axe_ipgs
[2], NULL
);
1078 /* Enable receiver, set RX mode */
1079 rxmode
= AXE_RXCMD_UNICAST
|AXE_RXCMD_MULTICAST
|AXE_RXCMD_ENABLE
;
1081 /* If we want promiscuous mode, set the allframes bit. */
1082 if (ifp
->if_flags
& IFF_PROMISC
)
1083 rxmode
|= AXE_RXCMD_PROMISC
;
1085 if (ifp
->if_flags
& IFF_BROADCAST
)
1086 rxmode
|= AXE_RXCMD_BROADCAST
;
1088 axe_cmd(sc
, AXE_CMD_RXCTL_WRITE
, 0, rxmode
, NULL
);
1091 /* Load the multicast filter. */
1094 /* Open RX and TX pipes. */
1095 err
= usbd_open_pipe(sc
->axe_iface
, sc
->axe_ed
[AXE_ENDPT_RX
],
1096 USBD_EXCLUSIVE_USE
, &sc
->axe_ep
[AXE_ENDPT_RX
]);
1098 printf("%s: open rx pipe failed: %s\n",
1099 device_xname(sc
->axe_dev
), usbd_errstr(err
));
1104 err
= usbd_open_pipe(sc
->axe_iface
, sc
->axe_ed
[AXE_ENDPT_TX
],
1105 USBD_EXCLUSIVE_USE
, &sc
->axe_ep
[AXE_ENDPT_TX
]);
1107 printf("%s: open tx pipe failed: %s\n",
1108 device_xname(sc
->axe_dev
), usbd_errstr(err
));
1113 /* Start up the receive pipe. */
1114 for (i
= 0; i
< AXE_RX_LIST_CNT
; i
++) {
1115 c
= &sc
->axe_cdata
.axe_rx_chain
[i
];
1116 usbd_setup_xfer(c
->axe_xfer
, sc
->axe_ep
[AXE_ENDPT_RX
],
1117 c
, mtod(c
->axe_mbuf
, char *), AXE_BUFSZ
,
1118 USBD_SHORT_XFER_OK
, USBD_NO_TIMEOUT
, axe_rxeof
);
1119 usbd_transfer(c
->axe_xfer
);
1122 ifp
->if_flags
|= IFF_RUNNING
;
1123 ifp
->if_flags
&= ~IFF_OACTIVE
;
1127 callout_init(&(sc
->axe_stat_ch
), 0);
1128 callout_reset(&(sc
->axe_stat_ch
), (hz
), (axe_tick
), (sc
));
1133 axe_ioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
1135 struct axe_softc
*sc
= ifp
->if_softc
;
1136 struct ifreq
*ifr
= (struct ifreq
*)data
;
1137 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
1142 case SIOCINITIFADDR
:
1143 ifp
->if_flags
|= IFF_UP
;
1146 switch (ifa
->ifa_addr
->sa_family
) {
1149 #if defined(__NetBSD__)
1150 arp_ifinit(ifp
, ifa
);
1152 arp_ifinit(&sc
->arpcom
, ifa
);
1160 if (ifr
->ifr_mtu
< ETHERMIN
|| ifr
->ifr_mtu
> ETHERMTU
)
1162 else if ((error
= ifioctl_common(ifp
, cmd
, data
)) == ENETRESET
)
1167 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
1169 if (ifp
->if_flags
& IFF_UP
) {
1170 if (ifp
->if_flags
& IFF_RUNNING
&&
1171 ifp
->if_flags
& IFF_PROMISC
&&
1172 !(sc
->axe_if_flags
& IFF_PROMISC
)) {
1175 axe_cmd(sc
, AXE_CMD_RXCTL_READ
,
1176 0, 0, (void *)&rxmode
);
1177 rxmode
= le16toh(rxmode
) | AXE_RXCMD_PROMISC
;
1178 axe_cmd(sc
, AXE_CMD_RXCTL_WRITE
,
1183 } else if (ifp
->if_flags
& IFF_RUNNING
&&
1184 !(ifp
->if_flags
& IFF_PROMISC
) &&
1185 sc
->axe_if_flags
& IFF_PROMISC
) {
1187 axe_cmd(sc
, AXE_CMD_RXCTL_READ
,
1188 0, 0, (void *)&rxmode
);
1189 rxmode
= le16toh(rxmode
) & ~AXE_RXCMD_PROMISC
;
1190 axe_cmd(sc
, AXE_CMD_RXCTL_WRITE
,
1194 } else if (!(ifp
->if_flags
& IFF_RUNNING
))
1197 if (ifp
->if_flags
& IFF_RUNNING
)
1200 sc
->axe_if_flags
= ifp
->if_flags
;
1207 error
= ether_ioctl(ifp
, cmd
, data
);
1208 if (error
== ENETRESET
) {
1210 * Multicast list has changed; set the hardware
1211 * filter accordingly.
1213 if (ifp
->if_flags
& IFF_RUNNING
)
1219 error
= ether_ioctl(ifp
, cmd
, data
);
1228 * You can't call axe_txeof since the USB transfer has not
1232 axe_watchdog(struct ifnet
*ifp
)
1234 struct axe_softc
*sc
;
1235 struct axe_chain
*c
;
1242 printf("%s: watchdog timeout\n", device_xname(sc
->axe_dev
));
1245 c
= &sc
->axe_cdata
.axe_tx_chain
[0];
1246 usbd_get_xfer_status(c
->axe_xfer
, NULL
, NULL
, NULL
, &stat
);
1247 axe_txeof(c
->axe_xfer
, c
, stat
);
1249 if (ifp
->if_snd
.ifq_head
!= NULL
)
1255 * Stop the adapter and free any mbufs allocated to the
1259 axe_stop(struct axe_softc
*sc
)
1270 callout_stop(&(sc
->axe_stat_ch
));
1272 /* Stop transfers. */
1273 if (sc
->axe_ep
[AXE_ENDPT_RX
] != NULL
) {
1274 err
= usbd_abort_pipe(sc
->axe_ep
[AXE_ENDPT_RX
]);
1276 printf("%s: abort rx pipe failed: %s\n",
1277 device_xname(sc
->axe_dev
), usbd_errstr(err
));
1279 err
= usbd_close_pipe(sc
->axe_ep
[AXE_ENDPT_RX
]);
1281 printf("%s: close rx pipe failed: %s\n",
1282 device_xname(sc
->axe_dev
), usbd_errstr(err
));
1284 sc
->axe_ep
[AXE_ENDPT_RX
] = NULL
;
1287 if (sc
->axe_ep
[AXE_ENDPT_TX
] != NULL
) {
1288 err
= usbd_abort_pipe(sc
->axe_ep
[AXE_ENDPT_TX
]);
1290 printf("%s: abort tx pipe failed: %s\n",
1291 device_xname(sc
->axe_dev
), usbd_errstr(err
));
1293 err
= usbd_close_pipe(sc
->axe_ep
[AXE_ENDPT_TX
]);
1295 printf("%s: close tx pipe failed: %s\n",
1296 device_xname(sc
->axe_dev
), usbd_errstr(err
));
1298 sc
->axe_ep
[AXE_ENDPT_TX
] = NULL
;
1301 if (sc
->axe_ep
[AXE_ENDPT_INTR
] != NULL
) {
1302 err
= usbd_abort_pipe(sc
->axe_ep
[AXE_ENDPT_INTR
]);
1304 printf("%s: abort intr pipe failed: %s\n",
1305 device_xname(sc
->axe_dev
), usbd_errstr(err
));
1307 err
= usbd_close_pipe(sc
->axe_ep
[AXE_ENDPT_INTR
]);
1309 printf("%s: close intr pipe failed: %s\n",
1310 device_xname(sc
->axe_dev
), usbd_errstr(err
));
1312 sc
->axe_ep
[AXE_ENDPT_INTR
] = NULL
;
1315 /* Free RX resources. */
1316 for (i
= 0; i
< AXE_RX_LIST_CNT
; i
++) {
1317 if (sc
->axe_cdata
.axe_rx_chain
[i
].axe_mbuf
!= NULL
) {
1318 m_freem(sc
->axe_cdata
.axe_rx_chain
[i
].axe_mbuf
);
1319 sc
->axe_cdata
.axe_rx_chain
[i
].axe_mbuf
= NULL
;
1321 if (sc
->axe_cdata
.axe_rx_chain
[i
].axe_xfer
!= NULL
) {
1322 usbd_free_xfer(sc
->axe_cdata
.axe_rx_chain
[i
].axe_xfer
);
1323 sc
->axe_cdata
.axe_rx_chain
[i
].axe_xfer
= NULL
;
1327 /* Free TX resources. */
1328 for (i
= 0; i
< AXE_TX_LIST_CNT
; i
++) {
1329 if (sc
->axe_cdata
.axe_tx_chain
[i
].axe_mbuf
!= NULL
) {
1330 m_freem(sc
->axe_cdata
.axe_tx_chain
[i
].axe_mbuf
);
1331 sc
->axe_cdata
.axe_tx_chain
[i
].axe_mbuf
= NULL
;
1333 if (sc
->axe_cdata
.axe_tx_chain
[i
].axe_xfer
!= NULL
) {
1334 usbd_free_xfer(sc
->axe_cdata
.axe_tx_chain
[i
].axe_xfer
);
1335 sc
->axe_cdata
.axe_tx_chain
[i
].axe_xfer
= NULL
;
1339 ifp
->if_flags
&= ~(IFF_RUNNING
| IFF_OACTIVE
);