Deleted Added
full compact
if_axe.c (226479) if_axe.c (226743)
1/*-
2 * Copyright (c) 1997, 1998, 1999, 2000-2003
3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1997, 1998, 1999, 2000-2003
3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_axe.c 226479 2011-10-17 19:51:38Z yongari $");
34__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_axe.c 226743 2011-10-25 18:36:18Z yongari $");
35
36/*
37 * ASIX Electronics AX88172/AX88178/AX88778 USB 2.0 ethernet driver.
38 * Used in the LinkSys USB200M and various other adapters.
39 *
40 * Manuals available from:
41 * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF
42 * Note: you need the manual for the AX88170 chip (USB 1.x ethernet

--- 28 unchanged lines hidden (view full) ---

71 * Ax88178 and Ax88772 support backported from the OpenBSD driver.
72 * 2007/02/12, J.R. Oldroyd, fbsd@opal.com
73 *
74 * Manual here:
75 * http://www.asix.com.tw/FrootAttach/datasheet/AX88178_datasheet_Rev10.pdf
76 * http://www.asix.com.tw/FrootAttach/datasheet/AX88772_datasheet_Rev10.pdf
77 */
78
35
36/*
37 * ASIX Electronics AX88172/AX88178/AX88778 USB 2.0 ethernet driver.
38 * Used in the LinkSys USB200M and various other adapters.
39 *
40 * Manuals available from:
41 * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF
42 * Note: you need the manual for the AX88170 chip (USB 1.x ethernet

--- 28 unchanged lines hidden (view full) ---

71 * Ax88178 and Ax88772 support backported from the OpenBSD driver.
72 * 2007/02/12, J.R. Oldroyd, fbsd@opal.com
73 *
74 * Manual here:
75 * http://www.asix.com.tw/FrootAttach/datasheet/AX88178_datasheet_Rev10.pdf
76 * http://www.asix.com.tw/FrootAttach/datasheet/AX88772_datasheet_Rev10.pdf
77 */
78
79#include <sys/stdint.h>
80#include <sys/stddef.h>
81#include <sys/param.h>
79#include <sys/param.h>
82#include <sys/queue.h>
83#include <sys/types.h>
84#include <sys/systm.h>
80#include <sys/systm.h>
85#include <sys/kernel.h>
86#include <sys/bus.h>
81#include <sys/bus.h>
87#include <sys/module.h>
82#include <sys/condvar.h>
83#include <sys/endian.h>
84#include <sys/kernel.h>
88#include <sys/lock.h>
85#include <sys/lock.h>
86#include <sys/malloc.h>
87#include <sys/mbuf.h>
88#include <sys/module.h>
89#include <sys/mutex.h>
89#include <sys/mutex.h>
90#include <sys/condvar.h>
90#include <sys/socket.h>
91#include <sys/sockio.h>
91#include <sys/sysctl.h>
92#include <sys/sx.h>
92#include <sys/sysctl.h>
93#include <sys/sx.h>
93#include <sys/unistd.h>
94#include <sys/callout.h>
95#include <sys/malloc.h>
96#include <sys/priv.h>
97
94
95#include <net/if.h>
96#include <net/ethernet.h>
97#include <net/if_types.h>
98#include <net/if_media.h>
99#include <net/if_vlan_var.h>
100
101#include <dev/mii/mii.h>
102#include <dev/mii/miivar.h>
103
98#include <dev/usb/usb.h>
99#include <dev/usb/usbdi.h>
100#include <dev/usb/usbdi_util.h>
101#include "usbdevs.h"
102
103#define USB_DEBUG_VAR axe_debug
104#include <dev/usb/usb_debug.h>
105#include <dev/usb/usb_process.h>

--- 11 unchanged lines hidden (view full) ---

117 * use the largest your system can handle without USB stalling.
118 *
119 * NB: 88772 parts appear to generate lots of input errors with
120 * a 2K rx buffer and 8K is only slightly faster than 4K on an
121 * EHCI port on a T42 so change at your own risk.
122 */
123#define AXE_178_MAX_FRAME_BURST 1
124
104#include <dev/usb/usb.h>
105#include <dev/usb/usbdi.h>
106#include <dev/usb/usbdi_util.h>
107#include "usbdevs.h"
108
109#define USB_DEBUG_VAR axe_debug
110#include <dev/usb/usb_debug.h>
111#include <dev/usb/usb_process.h>

--- 11 unchanged lines hidden (view full) ---

123 * use the largest your system can handle without USB stalling.
124 *
125 * NB: 88772 parts appear to generate lots of input errors with
126 * a 2K rx buffer and 8K is only slightly faster than 4K on an
127 * EHCI port on a T42 so change at your own risk.
128 */
129#define AXE_178_MAX_FRAME_BURST 1
130
131#define AXE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP)
132
125#ifdef USB_DEBUG
126static int axe_debug = 0;
127
128SYSCTL_NODE(_hw_usb, OID_AUTO, axe, CTLFLAG_RW, 0, "USB axe");
129SYSCTL_INT(_hw_usb_axe, OID_AUTO, debug, CTLFLAG_RW, &axe_debug, 0,
130 "Debug level");
131#endif
132

--- 48 unchanged lines hidden (view full) ---

181static uether_fn_t axe_attach_post;
182static uether_fn_t axe_init;
183static uether_fn_t axe_stop;
184static uether_fn_t axe_start;
185static uether_fn_t axe_tick;
186static uether_fn_t axe_setmulti;
187static uether_fn_t axe_setpromisc;
188
133#ifdef USB_DEBUG
134static int axe_debug = 0;
135
136SYSCTL_NODE(_hw_usb, OID_AUTO, axe, CTLFLAG_RW, 0, "USB axe");
137SYSCTL_INT(_hw_usb_axe, OID_AUTO, debug, CTLFLAG_RW, &axe_debug, 0,
138 "Debug level");
139#endif
140

--- 48 unchanged lines hidden (view full) ---

189static uether_fn_t axe_attach_post;
190static uether_fn_t axe_init;
191static uether_fn_t axe_stop;
192static uether_fn_t axe_start;
193static uether_fn_t axe_tick;
194static uether_fn_t axe_setmulti;
195static uether_fn_t axe_setpromisc;
196
197static int axe_attach_post_sub(struct usb_ether *);
189static int axe_ifmedia_upd(struct ifnet *);
190static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
191static int axe_cmd(struct axe_softc *, int, int, int, void *);
192static void axe_ax88178_init(struct axe_softc *);
193static void axe_ax88772_init(struct axe_softc *);
194static void axe_ax88772_phywake(struct axe_softc *);
195static void axe_ax88772a_init(struct axe_softc *);
196static void axe_ax88772b_init(struct axe_softc *);
197static int axe_get_phyno(struct axe_softc *, int);
198static int axe_ifmedia_upd(struct ifnet *);
199static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
200static int axe_cmd(struct axe_softc *, int, int, int, void *);
201static void axe_ax88178_init(struct axe_softc *);
202static void axe_ax88772_init(struct axe_softc *);
203static void axe_ax88772_phywake(struct axe_softc *);
204static void axe_ax88772a_init(struct axe_softc *);
205static void axe_ax88772b_init(struct axe_softc *);
206static int axe_get_phyno(struct axe_softc *, int);
207static int axe_ioctl(struct ifnet *, u_long, caddr_t);
208static int axe_rx_frame(struct usb_ether *, struct usb_page_cache *, int);
209static int axe_rxeof(struct usb_ether *, struct usb_page_cache *,
210 unsigned int offset, unsigned int, struct axe_csum_hdr *);
211static void axe_csum_cfg(struct usb_ether *);
198
199static const struct usb_config axe_config[AXE_N_TRANSFER] = {
200
201 [AXE_BULK_DT_WR] = {
202 .type = UE_BULK,
203 .endpoint = UE_ADDR_ANY,
204 .direction = UE_DIR_OUT,
205 .frames = 16,

--- 55 unchanged lines hidden (view full) ---

261MODULE_DEPEND(axe, uether, 1, 1, 1);
262MODULE_DEPEND(axe, usb, 1, 1, 1);
263MODULE_DEPEND(axe, ether, 1, 1, 1);
264MODULE_DEPEND(axe, miibus, 1, 1, 1);
265MODULE_VERSION(axe, 1);
266
267static const struct usb_ether_methods axe_ue_methods = {
268 .ue_attach_post = axe_attach_post,
212
213static const struct usb_config axe_config[AXE_N_TRANSFER] = {
214
215 [AXE_BULK_DT_WR] = {
216 .type = UE_BULK,
217 .endpoint = UE_ADDR_ANY,
218 .direction = UE_DIR_OUT,
219 .frames = 16,

--- 55 unchanged lines hidden (view full) ---

275MODULE_DEPEND(axe, uether, 1, 1, 1);
276MODULE_DEPEND(axe, usb, 1, 1, 1);
277MODULE_DEPEND(axe, ether, 1, 1, 1);
278MODULE_DEPEND(axe, miibus, 1, 1, 1);
279MODULE_VERSION(axe, 1);
280
281static const struct usb_ether_methods axe_ue_methods = {
282 .ue_attach_post = axe_attach_post,
283 .ue_attach_post_sub = axe_attach_post_sub,
269 .ue_start = axe_start,
270 .ue_init = axe_init,
271 .ue_stop = axe_stop,
272 .ue_tick = axe_tick,
273 .ue_setmulti = axe_setmulti,
274 .ue_setpromisc = axe_setpromisc,
275 .ue_mii_upd = axe_ifmedia_upd,
276 .ue_mii_sts = axe_ifmedia_sts,

--- 22 unchanged lines hidden (view full) ---

299
300static int
301axe_miibus_readreg(device_t dev, int phy, int reg)
302{
303 struct axe_softc *sc = device_get_softc(dev);
304 uint16_t val;
305 int locked;
306
284 .ue_start = axe_start,
285 .ue_init = axe_init,
286 .ue_stop = axe_stop,
287 .ue_tick = axe_tick,
288 .ue_setmulti = axe_setmulti,
289 .ue_setpromisc = axe_setpromisc,
290 .ue_mii_upd = axe_ifmedia_upd,
291 .ue_mii_sts = axe_ifmedia_sts,

--- 22 unchanged lines hidden (view full) ---

314
315static int
316axe_miibus_readreg(device_t dev, int phy, int reg)
317{
318 struct axe_softc *sc = device_get_softc(dev);
319 uint16_t val;
320 int locked;
321
307 if (sc->sc_phyno != phy)
308 return (0);
309
310 locked = mtx_owned(&sc->sc_mtx);
311 if (!locked)
312 AXE_LOCK(sc);
313
314 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
315 axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, &val);
316 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
317

--- 15 unchanged lines hidden (view full) ---

333
334static int
335axe_miibus_writereg(device_t dev, int phy, int reg, int val)
336{
337 struct axe_softc *sc = device_get_softc(dev);
338 int locked;
339
340 val = htole32(val);
322 locked = mtx_owned(&sc->sc_mtx);
323 if (!locked)
324 AXE_LOCK(sc);
325
326 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
327 axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, &val);
328 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
329

--- 15 unchanged lines hidden (view full) ---

345
346static int
347axe_miibus_writereg(device_t dev, int phy, int reg, int val)
348{
349 struct axe_softc *sc = device_get_softc(dev);
350 int locked;
351
352 val = htole32(val);
341
342 if (sc->sc_phyno != phy)
343 return (0);
344
345 locked = mtx_owned(&sc->sc_mtx);
346 if (!locked)
347 AXE_LOCK(sc);
348
349 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
350 axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, &val);
351 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
352

--- 14 unchanged lines hidden (view full) ---

367 locked = mtx_owned(&sc->sc_mtx);
368 if (!locked)
369 AXE_LOCK(sc);
370
371 ifp = uether_getifp(&sc->sc_ue);
372 if (mii == NULL || ifp == NULL ||
373 (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
374 goto done;
353 locked = mtx_owned(&sc->sc_mtx);
354 if (!locked)
355 AXE_LOCK(sc);
356
357 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
358 axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, &val);
359 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
360

--- 14 unchanged lines hidden (view full) ---

375 locked = mtx_owned(&sc->sc_mtx);
376 if (!locked)
377 AXE_LOCK(sc);
378
379 ifp = uether_getifp(&sc->sc_ue);
380 if (mii == NULL || ifp == NULL ||
381 (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
382 goto done;
375
383
376 sc->sc_flags &= ~AXE_FLAG_LINK;
377 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
378 (IFM_ACTIVE | IFM_AVALID)) {
379 switch (IFM_SUBTYPE(mii->mii_media_active)) {
380 case IFM_10_T:
381 case IFM_100_TX:
382 sc->sc_flags |= AXE_FLAG_LINK;
383 break;
384 case IFM_1000_T:
385 if ((sc->sc_flags & AXE_FLAG_178) == 0)
386 break;
387 sc->sc_flags |= AXE_FLAG_LINK;
388 break;
389 default:
390 break;
391 }
392 }
384 sc->sc_flags &= ~AXE_FLAG_LINK;
385 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
386 (IFM_ACTIVE | IFM_AVALID)) {
387 switch (IFM_SUBTYPE(mii->mii_media_active)) {
388 case IFM_10_T:
389 case IFM_100_TX:
390 sc->sc_flags |= AXE_FLAG_LINK;
391 break;
392 case IFM_1000_T:
393 if ((sc->sc_flags & AXE_FLAG_178) == 0)
394 break;
395 sc->sc_flags |= AXE_FLAG_LINK;
396 break;
397 default:
398 break;
399 }
400 }
393
401
394 /* Lost link, do nothing. */
395 if ((sc->sc_flags & AXE_FLAG_LINK) == 0)
396 goto done;
402 /* Lost link, do nothing. */
403 if ((sc->sc_flags & AXE_FLAG_LINK) == 0)
404 goto done;
397
405
398 val = 0;
406 val = 0;
399 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
407 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
400 val |= AXE_MEDIA_FULL_DUPLEX;
408 val |= AXE_MEDIA_FULL_DUPLEX;
409 if (AXE_IS_178_FAMILY(sc)) {
410 if ((IFM_OPTIONS(mii->mii_media_active) &
411 IFM_ETH_TXPAUSE) != 0)
412 val |= AXE_178_MEDIA_TXFLOW_CONTROL_EN;
413 if ((IFM_OPTIONS(mii->mii_media_active) &
414 IFM_ETH_RXPAUSE) != 0)
415 val |= AXE_178_MEDIA_RXFLOW_CONTROL_EN;
416 }
417 }
401 if (AXE_IS_178_FAMILY(sc)) {
402 val |= AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC;
403 if ((sc->sc_flags & AXE_FLAG_178) != 0)
404 val |= AXE_178_MEDIA_ENCK;
405 switch (IFM_SUBTYPE(mii->mii_media_active)) {
406 case IFM_1000_T:
407 val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK;
408 break;

--- 431 unchanged lines hidden (view full) ---

840 /* Set IPG values. */
841 sc->sc_ipgs[0] = 0x15;
842 sc->sc_ipgs[1] = 0x16;
843 sc->sc_ipgs[2] = 0x1A;
844 } else
845 axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->sc_ipgs);
846}
847
418 if (AXE_IS_178_FAMILY(sc)) {
419 val |= AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC;
420 if ((sc->sc_flags & AXE_FLAG_178) != 0)
421 val |= AXE_178_MEDIA_ENCK;
422 switch (IFM_SUBTYPE(mii->mii_media_active)) {
423 case IFM_1000_T:
424 val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK;
425 break;

--- 431 unchanged lines hidden (view full) ---

857 /* Set IPG values. */
858 sc->sc_ipgs[0] = 0x15;
859 sc->sc_ipgs[1] = 0x16;
860 sc->sc_ipgs[2] = 0x1A;
861 } else
862 axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->sc_ipgs);
863}
864
865static int
866axe_attach_post_sub(struct usb_ether *ue)
867{
868 struct axe_softc *sc;
869 struct ifnet *ifp;
870 u_int adv_pause;
871 int error;
872
873 sc = uether_getsc(ue);
874 ifp = ue->ue_ifp;
875 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
876 ifp->if_start = uether_start;
877 ifp->if_ioctl = axe_ioctl;
878 ifp->if_init = uether_init;
879 IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
880 ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
881 IFQ_SET_READY(&ifp->if_snd);
882
883 if (AXE_IS_178_FAMILY(sc))
884 ifp->if_capabilities |= IFCAP_VLAN_MTU;
885 if (sc->sc_flags & AXE_FLAG_772B) {
886 ifp->if_capabilities |= IFCAP_TXCSUM | IFCAP_RXCSUM;
887 ifp->if_hwassist = AXE_CSUM_FEATURES;
888 /*
889 * Checksum offloading of AX88772B also works with VLAN
890 * tagged frames but there is no way to take advantage
891 * of the feature because vlan(4) assumes
892 * IFCAP_VLAN_HWTAGGING is prerequisite condition to
893 * support checksum offloading with VLAN. VLAN hardware
894 * tagging support of AX88772B is very limited so it's
895 * not possible to announce IFCAP_VLAN_HWTAGGING.
896 */
897 }
898 ifp->if_capenable = ifp->if_capabilities;
899 if (sc->sc_flags & (AXE_FLAG_772A | AXE_FLAG_772B | AXE_FLAG_178))
900 adv_pause = MIIF_DOPAUSE;
901 else
902 adv_pause = 0;
903 mtx_lock(&Giant);
904 error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
905 uether_ifmedia_upd, ue->ue_methods->ue_mii_sts,
906 BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, adv_pause);
907 mtx_unlock(&Giant);
908
909 return (error);
910}
911
848/*
849 * Probe for a AX88172 chip.
850 */
851static int
852axe_probe(device_t dev)
853{
854 struct usb_attach_arg *uaa = device_get_ivars(dev);
855

--- 69 unchanged lines hidden (view full) ---

925#error "Please update axe_bulk_read_callback()!"
926#endif
927
928static void
929axe_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
930{
931 struct axe_softc *sc = usbd_xfer_softc(xfer);
932 struct usb_ether *ue = &sc->sc_ue;
912/*
913 * Probe for a AX88172 chip.
914 */
915static int
916axe_probe(device_t dev)
917{
918 struct usb_attach_arg *uaa = device_get_ivars(dev);
919

--- 69 unchanged lines hidden (view full) ---

989#error "Please update axe_bulk_read_callback()!"
990#endif
991
992static void
993axe_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
994{
995 struct axe_softc *sc = usbd_xfer_softc(xfer);
996 struct usb_ether *ue = &sc->sc_ue;
933 struct ifnet *ifp = uether_getifp(ue);
934 struct axe_sframe_hdr hdr;
935 struct usb_page_cache *pc;
997 struct usb_page_cache *pc;
936 int err, pos, len;
937 int actlen;
938
939 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
940
941 switch (USB_GET_STATE(xfer)) {
942 case USB_ST_TRANSFERRED:
998 int actlen;
999
1000 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1001
1002 switch (USB_GET_STATE(xfer)) {
1003 case USB_ST_TRANSFERRED:
943 pos = 0;
944 len = 0;
945 err = 0;
946
947 pc = usbd_xfer_get_frame(xfer, 0);
1004 pc = usbd_xfer_get_frame(xfer, 0);
948 if (AXE_IS_178_FAMILY(sc)) {
949 while (pos < actlen) {
950 if ((pos + sizeof(hdr)) > actlen) {
951 /* too little data */
952 err = EINVAL;
953 break;
954 }
955 usbd_copy_out(pc, pos, &hdr, sizeof(hdr));
1005 axe_rx_frame(ue, pc, actlen);
956
1006
957 if ((hdr.len ^ hdr.ilen) != 0xFFFF) {
958 /* we lost sync */
959 err = EINVAL;
960 break;
961 }
962 pos += sizeof(hdr);
963
964 len = le16toh(hdr.len);
965 if ((pos + len) > actlen) {
966 /* invalid length */
967 err = EINVAL;
968 break;
969 }
970 uether_rxbuf(ue, pc, pos, len);
971
972 pos += len + (len % 2);
973 }
974 } else
975 uether_rxbuf(ue, pc, 0, actlen);
976
977 if (err != 0)
978 ifp->if_ierrors++;
979
980 /* FALLTHROUGH */
981 case USB_ST_SETUP:
982tr_setup:
983 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
984 usbd_transfer_submit(xfer);
985 uether_rxflush(ue);
986 return;
987

--- 5 unchanged lines hidden (view full) ---

993 usbd_xfer_set_stall(xfer);
994 goto tr_setup;
995 }
996 return;
997
998 }
999}
1000
1007 /* FALLTHROUGH */
1008 case USB_ST_SETUP:
1009tr_setup:
1010 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1011 usbd_transfer_submit(xfer);
1012 uether_rxflush(ue);
1013 return;
1014

--- 5 unchanged lines hidden (view full) ---

1020 usbd_xfer_set_stall(xfer);
1021 goto tr_setup;
1022 }
1023 return;
1024
1025 }
1026}
1027
1028static int
1029axe_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen)
1030{
1031 struct axe_softc *sc;
1032 struct axe_sframe_hdr hdr;
1033 struct axe_csum_hdr csum_hdr;
1034 int error, len, pos;
1035
1036 sc = uether_getsc(ue);
1037 pos = 0;
1038 len = 0;
1039 error = 0;
1040 if ((sc->sc_flags & AXE_FLAG_STD_FRAME) != 0) {
1041 while (pos < actlen) {
1042 if ((pos + sizeof(hdr)) > actlen) {
1043 /* too little data */
1044 error = EINVAL;
1045 break;
1046 }
1047 usbd_copy_out(pc, pos, &hdr, sizeof(hdr));
1048
1049 if ((hdr.len ^ hdr.ilen) != sc->sc_lenmask) {
1050 /* we lost sync */
1051 error = EINVAL;
1052 break;
1053 }
1054 pos += sizeof(hdr);
1055 len = le16toh(hdr.len);
1056 if (pos + len > actlen) {
1057 /* invalid length */
1058 error = EINVAL;
1059 break;
1060 }
1061 axe_rxeof(ue, pc, pos, len, NULL);
1062 pos += len + (len % 2);
1063 }
1064 } else if ((sc->sc_flags & AXE_FLAG_CSUM_FRAME) != 0) {
1065 while (pos < actlen) {
1066 if ((pos + sizeof(csum_hdr)) > actlen) {
1067 /* too little data */
1068 error = EINVAL;
1069 break;
1070 }
1071 usbd_copy_out(pc, pos, &csum_hdr, sizeof(csum_hdr));
1072
1073 csum_hdr.len = le16toh(csum_hdr.len);
1074 csum_hdr.ilen = le16toh(csum_hdr.ilen);
1075 csum_hdr.cstatus = le16toh(csum_hdr.cstatus);
1076 if ((AXE_CSUM_RXBYTES(csum_hdr.len) ^
1077 AXE_CSUM_RXBYTES(csum_hdr.ilen)) !=
1078 sc->sc_lenmask) {
1079 /* we lost sync */
1080 error = EINVAL;
1081 break;
1082 }
1083 /*
1084 * Get total transferred frame length including
1085 * checksum header. The length should be multiple
1086 * of 4.
1087 */
1088 len = sizeof(csum_hdr) + AXE_CSUM_RXBYTES(csum_hdr.len);
1089 len = (len + 3) & ~3;
1090 if (pos + len > actlen) {
1091 /* invalid length */
1092 error = EINVAL;
1093 break;
1094 }
1095 axe_rxeof(ue, pc, pos + sizeof(csum_hdr),
1096 AXE_CSUM_RXBYTES(csum_hdr.len), &csum_hdr);
1097 pos += len;
1098 }
1099 } else
1100 axe_rxeof(ue, pc, 0, actlen, NULL);
1101
1102 if (error != 0)
1103 ue->ue_ifp->if_ierrors++;
1104 return (error);
1105}
1106
1107static int
1108axe_rxeof(struct usb_ether *ue, struct usb_page_cache *pc, unsigned int offset,
1109 unsigned int len, struct axe_csum_hdr *csum_hdr)
1110{
1111 struct ifnet *ifp = ue->ue_ifp;
1112 struct mbuf *m;
1113
1114 if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN) {
1115 ifp->if_ierrors++;
1116 return (EINVAL);
1117 }
1118
1119 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1120 if (m == NULL) {
1121 ifp->if_iqdrops++;
1122 return (ENOMEM);
1123 }
1124 m->m_len = m->m_pkthdr.len = MCLBYTES;
1125 m_adj(m, ETHER_ALIGN);
1126
1127 usbd_copy_out(pc, offset, mtod(m, uint8_t *), len);
1128
1129 ifp->if_ipackets++;
1130 m->m_pkthdr.rcvif = ifp;
1131 m->m_pkthdr.len = m->m_len = len;
1132
1133 if (csum_hdr != NULL && csum_hdr->cstatus & AXE_CSUM_HDR_L3_TYPE_IPV4) {
1134 if ((csum_hdr->cstatus & (AXE_CSUM_HDR_L4_CSUM_ERR |
1135 AXE_CSUM_HDR_L3_CSUM_ERR)) == 0) {
1136 m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED |
1137 CSUM_IP_VALID;
1138 if ((csum_hdr->cstatus & AXE_CSUM_HDR_L4_TYPE_MASK) ==
1139 AXE_CSUM_HDR_L4_TYPE_TCP ||
1140 (csum_hdr->cstatus & AXE_CSUM_HDR_L4_TYPE_MASK) ==
1141 AXE_CSUM_HDR_L4_TYPE_UDP) {
1142 m->m_pkthdr.csum_flags |=
1143 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
1144 m->m_pkthdr.csum_data = 0xffff;
1145 }
1146 }
1147 }
1148
1149 _IF_ENQUEUE(&ue->ue_rxq, m);
1150 return (0);
1151}
1152
1001#if ((AXE_BULK_BUF_SIZE >= 0x10000) || (AXE_BULK_BUF_SIZE < (MCLBYTES+4)))
1002#error "Please update axe_bulk_write_callback()!"
1003#endif
1004
1005static void
1006axe_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
1007{
1008 struct axe_softc *sc = usbd_xfer_softc(xfer);

--- 26 unchanged lines hidden (view full) ---

1035 break;
1036 usbd_xfer_set_frame_offset(xfer, nframes * MCLBYTES,
1037 nframes);
1038 pos = 0;
1039 pc = usbd_xfer_get_frame(xfer, nframes);
1040 if (AXE_IS_178_FAMILY(sc)) {
1041 hdr.len = htole16(m->m_pkthdr.len);
1042 hdr.ilen = ~hdr.len;
1153#if ((AXE_BULK_BUF_SIZE >= 0x10000) || (AXE_BULK_BUF_SIZE < (MCLBYTES+4)))
1154#error "Please update axe_bulk_write_callback()!"
1155#endif
1156
1157static void
1158axe_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
1159{
1160 struct axe_softc *sc = usbd_xfer_softc(xfer);

--- 26 unchanged lines hidden (view full) ---

1187 break;
1188 usbd_xfer_set_frame_offset(xfer, nframes * MCLBYTES,
1189 nframes);
1190 pos = 0;
1191 pc = usbd_xfer_get_frame(xfer, nframes);
1192 if (AXE_IS_178_FAMILY(sc)) {
1193 hdr.len = htole16(m->m_pkthdr.len);
1194 hdr.ilen = ~hdr.len;
1195 /*
1196 * If upper stack computed checksum, driver
1197 * should tell controller not to insert
1198 * computed checksum for checksum offloading
1199 * enabled controller.
1200 */
1201 if (ifp->if_capabilities & IFCAP_TXCSUM) {
1202 if ((m->m_pkthdr.csum_flags &
1203 AXE_CSUM_FEATURES) != 0)
1204 hdr.len |= htole16(
1205 AXE_TX_CSUM_PSEUDO_HDR);
1206 else
1207 hdr.len |= htole16(
1208 AXE_TX_CSUM_DIS);
1209 }
1043 usbd_copy_in(pc, pos, &hdr, sizeof(hdr));
1044 pos += sizeof(hdr);
1045 usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len);
1046 pos += m->m_pkthdr.len;
1047 if ((pos % 512) == 0) {
1048 hdr.len = 0;
1049 hdr.ilen = 0xffff;
1050 usbd_copy_in(pc, pos, &hdr,

--- 75 unchanged lines hidden (view full) ---

1126 /*
1127 * start the USB transfers, if not already started:
1128 */
1129 usbd_transfer_start(sc->sc_xfer[AXE_BULK_DT_RD]);
1130 usbd_transfer_start(sc->sc_xfer[AXE_BULK_DT_WR]);
1131}
1132
1133static void
1210 usbd_copy_in(pc, pos, &hdr, sizeof(hdr));
1211 pos += sizeof(hdr);
1212 usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len);
1213 pos += m->m_pkthdr.len;
1214 if ((pos % 512) == 0) {
1215 hdr.len = 0;
1216 hdr.ilen = 0xffff;
1217 usbd_copy_in(pc, pos, &hdr,

--- 75 unchanged lines hidden (view full) ---

1293 /*
1294 * start the USB transfers, if not already started:
1295 */
1296 usbd_transfer_start(sc->sc_xfer[AXE_BULK_DT_RD]);
1297 usbd_transfer_start(sc->sc_xfer[AXE_BULK_DT_WR]);
1298}
1299
1300static void
1301axe_csum_cfg(struct usb_ether *ue)
1302{
1303 struct axe_softc *sc;
1304 struct ifnet *ifp;
1305 uint16_t csum1, csum2;
1306
1307 sc = uether_getsc(ue);
1308 AXE_LOCK_ASSERT(sc, MA_OWNED);
1309
1310 if ((sc->sc_flags & AXE_FLAG_772B) != 0) {
1311 ifp = uether_getifp(ue);
1312 csum1 = 0;
1313 csum2 = 0;
1314 if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
1315 csum1 |= AXE_TXCSUM_IP | AXE_TXCSUM_TCP |
1316 AXE_TXCSUM_UDP;
1317 axe_cmd(sc, AXE_772B_CMD_WRITE_TXCSUM, csum2, csum1, NULL);
1318 csum1 = 0;
1319 csum2 = 0;
1320 if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
1321 csum1 |= AXE_RXCSUM_IP | AXE_RXCSUM_IPVE |
1322 AXE_RXCSUM_TCP | AXE_RXCSUM_UDP | AXE_RXCSUM_ICMP |
1323 AXE_RXCSUM_IGMP;
1324 axe_cmd(sc, AXE_772B_CMD_WRITE_RXCSUM, csum2, csum1, NULL);
1325 }
1326}
1327
1328static void
1134axe_init(struct usb_ether *ue)
1135{
1136 struct axe_softc *sc = uether_getsc(ue);
1137 struct ifnet *ifp = uether_getifp(ue);
1138 uint16_t rxmode;
1139
1140 AXE_LOCK_ASSERT(sc, MA_OWNED);
1141
1142 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
1143 return;
1144
1145 /* Cancel pending I/O */
1146 axe_stop(ue);
1147
1148 axe_reset(sc);
1149
1329axe_init(struct usb_ether *ue)
1330{
1331 struct axe_softc *sc = uether_getsc(ue);
1332 struct ifnet *ifp = uether_getifp(ue);
1333 uint16_t rxmode;
1334
1335 AXE_LOCK_ASSERT(sc, MA_OWNED);
1336
1337 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
1338 return;
1339
1340 /* Cancel pending I/O */
1341 axe_stop(ue);
1342
1343 axe_reset(sc);
1344
1150 /* Set MAC address. */
1151 if (AXE_IS_178_FAMILY(sc))
1345 /* Set MAC address and transmitter IPG values. */
1346 if (AXE_IS_178_FAMILY(sc)) {
1152 axe_cmd(sc, AXE_178_CMD_WRITE_NODEID, 0, 0, IF_LLADDR(ifp));
1347 axe_cmd(sc, AXE_178_CMD_WRITE_NODEID, 0, 0, IF_LLADDR(ifp));
1153 else
1154 axe_cmd(sc, AXE_172_CMD_WRITE_NODEID, 0, 0, IF_LLADDR(ifp));
1155
1156 /* Set transmitter IPG values */
1157 if (AXE_IS_178_FAMILY(sc))
1158 axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->sc_ipgs[2],
1159 (sc->sc_ipgs[1] << 8) | (sc->sc_ipgs[0]), NULL);
1348 axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->sc_ipgs[2],
1349 (sc->sc_ipgs[1] << 8) | (sc->sc_ipgs[0]), NULL);
1160 else {
1350 } else {
1351 axe_cmd(sc, AXE_172_CMD_WRITE_NODEID, 0, 0, IF_LLADDR(ifp));
1161 axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->sc_ipgs[0], NULL);
1162 axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->sc_ipgs[1], NULL);
1163 axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->sc_ipgs[2], NULL);
1164 }
1165
1352 axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->sc_ipgs[0], NULL);
1353 axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->sc_ipgs[1], NULL);
1354 axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->sc_ipgs[2], NULL);
1355 }
1356
1166 /* AX88772B uses different maximum frame burst configuration. */
1167 if (sc->sc_flags & AXE_FLAG_772B)
1357 if (AXE_IS_178_FAMILY(sc)) {
1358 sc->sc_flags &= ~(AXE_FLAG_STD_FRAME | AXE_FLAG_CSUM_FRAME);
1359 if ((sc->sc_flags & AXE_FLAG_772B) != 0)
1360 sc->sc_lenmask = AXE_CSUM_HDR_LEN_MASK;
1361 else
1362 sc->sc_lenmask = AXE_HDR_LEN_MASK;
1363 if ((sc->sc_flags & AXE_FLAG_772B) != 0 &&
1364 (ifp->if_capenable & IFCAP_RXCSUM) != 0)
1365 sc->sc_flags |= AXE_FLAG_CSUM_FRAME;
1366 else
1367 sc->sc_flags |= AXE_FLAG_STD_FRAME;
1368 }
1369
1370 /* Configure TX/RX checksum offloading. */
1371 axe_csum_cfg(ue);
1372
1373 if (sc->sc_flags & AXE_FLAG_772B) {
1374 /* AX88772B uses different maximum frame burst configuration. */
1168 axe_cmd(sc, AXE_772B_CMD_RXCTL_WRITE_CFG,
1169 ax88772b_mfb_table[AX88772B_MFB_16K].threshold,
1170 ax88772b_mfb_table[AX88772B_MFB_16K].byte_cnt, NULL);
1375 axe_cmd(sc, AXE_772B_CMD_RXCTL_WRITE_CFG,
1376 ax88772b_mfb_table[AX88772B_MFB_16K].threshold,
1377 ax88772b_mfb_table[AX88772B_MFB_16K].byte_cnt, NULL);
1378 }
1171
1172 /* Enable receiver, set RX mode. */
1173 rxmode = (AXE_RXCMD_MULTICAST | AXE_RXCMD_ENABLE);
1174 if (AXE_IS_178_FAMILY(sc)) {
1175 if (sc->sc_flags & AXE_FLAG_772B) {
1176 /*
1177 * Select RX header format type 1. Aligning IP
1379
1380 /* Enable receiver, set RX mode. */
1381 rxmode = (AXE_RXCMD_MULTICAST | AXE_RXCMD_ENABLE);
1382 if (AXE_IS_178_FAMILY(sc)) {
1383 if (sc->sc_flags & AXE_FLAG_772B) {
1384 /*
1385 * Select RX header format type 1. Aligning IP
1178 * header on 4 byte boundary is not needed
1386 * header on 4 byte boundary is not needed when
1387 * checksum offloading feature is not used
1179 * because we always copy the received frame in
1388 * because we always copy the received frame in
1180 * RX handler.
1389 * RX handler. When RX checksum offloading is
1390 * active, aligning IP header is required to
1391 * reflect actual frame length including RX
1392 * header size.
1181 */
1182 rxmode |= AXE_772B_RXCMD_HDR_TYPE_1;
1393 */
1394 rxmode |= AXE_772B_RXCMD_HDR_TYPE_1;
1395 if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
1396 rxmode |= AXE_772B_RXCMD_IPHDR_ALIGN;
1183 } else {
1184 /*
1185 * Default Rx buffer size is too small to get
1186 * maximum performance.
1187 */
1188 rxmode |= AXE_178_RXCMD_MFB_16384;
1189 }
1190 } else {

--- 12 unchanged lines hidden (view full) ---

1203 /* Load the multicast filter. */
1204 axe_setmulti(ue);
1205
1206 usbd_xfer_set_stall(sc->sc_xfer[AXE_BULK_DT_WR]);
1207
1208 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1209 /* Switch to selected media. */
1210 axe_ifmedia_upd(ifp);
1397 } else {
1398 /*
1399 * Default Rx buffer size is too small to get
1400 * maximum performance.
1401 */
1402 rxmode |= AXE_178_RXCMD_MFB_16384;
1403 }
1404 } else {

--- 12 unchanged lines hidden (view full) ---

1417 /* Load the multicast filter. */
1418 axe_setmulti(ue);
1419
1420 usbd_xfer_set_stall(sc->sc_xfer[AXE_BULK_DT_WR]);
1421
1422 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1423 /* Switch to selected media. */
1424 axe_ifmedia_upd(ifp);
1211 axe_start(ue);
1212}
1213
1214static void
1215axe_setpromisc(struct usb_ether *ue)
1216{
1217 struct axe_softc *sc = uether_getsc(ue);
1218 struct ifnet *ifp = uether_getifp(ue);
1219 uint16_t rxmode;

--- 25 unchanged lines hidden (view full) ---

1245 sc->sc_flags &= ~AXE_FLAG_LINK;
1246
1247 /*
1248 * stop all the transfers, if not already stopped:
1249 */
1250 usbd_transfer_stop(sc->sc_xfer[AXE_BULK_DT_WR]);
1251 usbd_transfer_stop(sc->sc_xfer[AXE_BULK_DT_RD]);
1252}
1425}
1426
1427static void
1428axe_setpromisc(struct usb_ether *ue)
1429{
1430 struct axe_softc *sc = uether_getsc(ue);
1431 struct ifnet *ifp = uether_getifp(ue);
1432 uint16_t rxmode;

--- 25 unchanged lines hidden (view full) ---

1458 sc->sc_flags &= ~AXE_FLAG_LINK;
1459
1460 /*
1461 * stop all the transfers, if not already stopped:
1462 */
1463 usbd_transfer_stop(sc->sc_xfer[AXE_BULK_DT_WR]);
1464 usbd_transfer_stop(sc->sc_xfer[AXE_BULK_DT_RD]);
1465}
1466
1467static int
1468axe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1469{
1470 struct usb_ether *ue = ifp->if_softc;
1471 struct axe_softc *sc;
1472 struct ifreq *ifr;
1473 int error, mask, reinit;
1474
1475 sc = uether_getsc(ue);
1476 ifr = (struct ifreq *)data;
1477 error = 0;
1478 reinit = 0;
1479 if (cmd == SIOCSIFCAP) {
1480 AXE_LOCK(sc);
1481 mask = ifr->ifr_reqcap ^ ifp->if_capenable;
1482 if ((mask & IFCAP_TXCSUM) != 0 &&
1483 (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
1484 ifp->if_capenable ^= IFCAP_TXCSUM;
1485 if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
1486 ifp->if_hwassist |= AXE_CSUM_FEATURES;
1487 else
1488 ifp->if_hwassist &= ~AXE_CSUM_FEATURES;
1489 reinit++;
1490 }
1491 if ((mask & IFCAP_RXCSUM) != 0 &&
1492 (ifp->if_capabilities & IFCAP_RXCSUM) != 0) {
1493 ifp->if_capenable ^= IFCAP_RXCSUM;
1494 reinit++;
1495 }
1496 if (reinit > 0 && ifp->if_drv_flags & IFF_DRV_RUNNING)
1497 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1498 else
1499 reinit = 0;
1500 AXE_UNLOCK(sc);
1501 if (reinit > 0)
1502 uether_init(ue);
1503 } else
1504 error = uether_ioctl(ifp, cmd, data);
1505
1506 return (error);
1507}