2 * Copyright (c) 2011 Rick van der Zwet <info@rickvanderzwet.nl>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net>
20 * Permission to use, copy, modify, and distribute this software for any
21 * purpose with or without fee is hereby granted, provided that the above
22 * copyright notice and this permission notice appear in all copies.
24 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
25 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
27 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
28 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
29 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
30 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34 * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org>
36 * Permission to use, copy, modify, and distribute this software for any
37 * purpose with or without fee is hereby granted, provided that the above
38 * copyright notice and this permission notice appear in all copies.
40 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
41 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
42 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
43 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
44 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
45 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
46 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
50 * Copyright (c) 1997, 1998, 1999, 2000-2003
51 * Bill Paul <wpaul@windriver.com>. All rights reserved.
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
56 * 1. Redistributions of source code must retain the above copyright
57 * notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 * notice, this list of conditions and the following disclaimer in the
60 * documentation and/or other materials provided with the distribution.
61 * 3. All advertising materials mentioning features or use of this software
62 * must display the following acknowledgement:
63 * This product includes software developed by Bill Paul.
64 * 4. Neither the name of the author nor the names of any co-contributors
65 * may be used to endorse or promote products derived from this software
66 * without specific prior written permission.
68 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
69 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
70 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
71 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
72 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
73 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
74 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
75 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
76 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
77 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
78 * THE POSSIBILITY OF SUCH DAMAGE.
80 * $FreeBSD: head/sys/dev/usb/net/if_mos.c 271832 2014-09-18 21:09:22Z glebius $
84 * Moschip MCS7730/MCS7830/MCS7832 USB to Ethernet controller
85 * The datasheet is available at the following URL:
86 * http://www.moschip.com/data/products/MCS7830/Data%20Sheet_7830.pdf
90 * The FreeBSD if_mos.c driver is based on various different sources:
91 * The vendor provided driver at the following URL:
92 * http://www.moschip.com/data/products/MCS7830/Driver_FreeBSD_7830.tar.gz
94 * Mixed together with the OpenBSD if_mos.c driver for validation and checking
95 * and the FreeBSD if_reu.c as reference for the USB Ethernet framework.
98 #include <sys/stdint.h>
99 #include <sys/param.h>
100 #include <sys/queue.h>
101 #include <sys/types.h>
102 #include <sys/systm.h>
103 #include <sys/socket.h>
104 #include <sys/kernel.h>
106 #include <sys/module.h>
107 #include <sys/lock.h>
108 #include <sys/condvar.h>
109 #include <sys/sysctl.h>
110 #include <sys/unistd.h>
111 #include <sys/callout.h>
112 #include <sys/malloc.h>
113 #include <sys/priv.h>
116 #include <net/if_var.h>
117 #include <net/ifq_var.h>
119 #include <bus/u4b/usb.h>
120 #include <bus/u4b/usbdi.h>
121 #include <bus/u4b/usbdi_util.h>
124 #define USB_DEBUG_VAR mos_debug
125 #include <bus/u4b/usb_debug.h>
126 #include <bus/u4b/usb_process.h>
128 #include <bus/u4b/net/usb_ethernet.h>
130 //#include <bus/u4b/net/if_mosreg.h>
131 #include "if_mosreg.h"
134 static int mos_debug
= 0;
136 static SYSCTL_NODE(_hw_usb
, OID_AUTO
, mos
, CTLFLAG_RW
, 0, "USB mos");
137 SYSCTL_INT(_hw_usb_mos
, OID_AUTO
, debug
, CTLFLAG_RW
, &mos_debug
, 0,
141 #define MOS_DPRINTFN(fmt,...) \
142 DPRINTF("mos: %s: " fmt "\n",__func__,## __VA_ARGS__)
144 #define USB_PRODUCT_MOSCHIP_MCS7730 0x7730
145 #define USB_PRODUCT_SITECOMEU_LN030 0x0021
149 /* Various supported device vendors/products. */
150 static const STRUCT_USB_HOST_ID mos_devs
[] = {
151 {USB_VPI(USB_VENDOR_MOSCHIP
, USB_PRODUCT_MOSCHIP_MCS7730
, MCS7730
)},
152 {USB_VPI(USB_VENDOR_MOSCHIP
, USB_PRODUCT_MOSCHIP_MCS7830
, MCS7830
)},
153 {USB_VPI(USB_VENDOR_MOSCHIP
, USB_PRODUCT_MOSCHIP_MCS7832
, MCS7832
)},
154 {USB_VPI(USB_VENDOR_SITECOMEU
, USB_PRODUCT_SITECOMEU_LN030
, MCS7830
)},
157 static int mos_probe(device_t dev
);
158 static int mos_attach(device_t dev
);
159 static void mos_attach_post(struct usb_ether
*ue
);
160 static int mos_detach(device_t dev
);
162 static void mos_bulk_read_callback(struct usb_xfer
*xfer
, usb_error_t error
);
163 static void mos_bulk_write_callback(struct usb_xfer
*xfer
, usb_error_t error
);
164 static void mos_intr_callback(struct usb_xfer
*xfer
, usb_error_t error
);
165 static void mos_tick(struct usb_ether
*);
166 static void mos_start(struct usb_ether
*);
167 static void mos_init(struct usb_ether
*);
168 static void mos_chip_init(struct mos_softc
*);
169 static void mos_stop(struct usb_ether
*);
170 static int mos_miibus_readreg(device_t
, int, int);
171 static int mos_miibus_writereg(device_t
, int, int, int);
172 static void mos_miibus_statchg(device_t
);
173 static int mos_ifmedia_upd(struct ifnet
*);
174 static void mos_ifmedia_sts(struct ifnet
*, struct ifmediareq
*);
175 static void mos_reset(struct mos_softc
*sc
);
177 static int mos_reg_read_1(struct mos_softc
*, int);
178 static int mos_reg_read_2(struct mos_softc
*, int);
179 static int mos_reg_write_1(struct mos_softc
*, int, int);
180 static int mos_reg_write_2(struct mos_softc
*, int, int);
181 static int mos_readmac(struct mos_softc
*, uint8_t *);
182 static int mos_writemac(struct mos_softc
*, uint8_t *);
183 static int mos_write_mcast(struct mos_softc
*, u_char
*);
185 static void mos_setmulti(struct usb_ether
*);
186 static void mos_setpromisc(struct usb_ether
*);
188 static const struct usb_config mos_config
[MOS_ENDPT_MAX
] = {
192 .endpoint
= UE_ADDR_ANY
,
193 .direction
= UE_DIR_OUT
,
194 .bufsize
= (MCLBYTES
+ 2),
195 .flags
= {.pipe_bof
= 1,.force_short_xfer
= 1,},
196 .callback
= mos_bulk_write_callback
,
202 .endpoint
= UE_ADDR_ANY
,
203 .direction
= UE_DIR_IN
,
204 .bufsize
= (MCLBYTES
+ 4 + ETHER_CRC_LEN
),
205 .flags
= {.pipe_bof
= 1,.short_xfer_ok
= 1,},
206 .callback
= mos_bulk_read_callback
,
210 .type
= UE_INTERRUPT
,
211 .endpoint
= UE_ADDR_ANY
,
212 .direction
= UE_DIR_IN
,
213 .flags
= {.pipe_bof
= 1,.short_xfer_ok
= 1,},
215 .callback
= mos_intr_callback
,
219 static device_method_t mos_methods
[] = {
220 /* Device interface */
221 DEVMETHOD(device_probe
, mos_probe
),
222 DEVMETHOD(device_attach
, mos_attach
),
223 DEVMETHOD(device_detach
, mos_detach
),
226 DEVMETHOD(miibus_readreg
, mos_miibus_readreg
),
227 DEVMETHOD(miibus_writereg
, mos_miibus_writereg
),
228 DEVMETHOD(miibus_statchg
, mos_miibus_statchg
),
233 static driver_t mos_driver
= {
235 .methods
= mos_methods
,
236 .size
= sizeof(struct mos_softc
)
239 static devclass_t mos_devclass
;
241 DRIVER_MODULE(mos
, uhub
, mos_driver
, mos_devclass
, NULL
, NULL
);
242 DRIVER_MODULE(miibus
, mos
, miibus_driver
, miibus_devclass
, NULL
, NULL
);
243 MODULE_DEPEND(mos
, uether
, 1, 1, 1);
244 MODULE_DEPEND(mos
, usb
, 1, 1, 1);
245 MODULE_DEPEND(mos
, ether
, 1, 1, 1);
246 MODULE_DEPEND(mos
, miibus
, 1, 1, 1);
248 static const struct usb_ether_methods mos_ue_methods
= {
249 .ue_attach_post
= mos_attach_post
,
250 .ue_start
= mos_start
,
254 .ue_setmulti
= mos_setmulti
,
255 .ue_setpromisc
= mos_setpromisc
,
256 .ue_mii_upd
= mos_ifmedia_upd
,
257 .ue_mii_sts
= mos_ifmedia_sts
,
262 mos_reg_read_1(struct mos_softc
*sc
, int reg
)
264 struct usb_device_request req
;
268 req
.bmRequestType
= UT_READ_VENDOR_DEVICE
;
269 req
.bRequest
= MOS_UR_READREG
;
270 USETW(req
.wValue
, 0);
271 USETW(req
.wIndex
, reg
);
272 USETW(req
.wLength
, 1);
274 err
= uether_do_request(&sc
->sc_ue
, &req
, &val
, 1000);
277 MOS_DPRINTFN("mos_reg_read_1 error, reg: %d\n", reg
);
284 mos_reg_read_2(struct mos_softc
*sc
, int reg
)
286 struct usb_device_request req
;
292 req
.bmRequestType
= UT_READ_VENDOR_DEVICE
;
293 req
.bRequest
= MOS_UR_READREG
;
294 USETW(req
.wValue
, 0);
295 USETW(req
.wIndex
, reg
);
296 USETW(req
.wLength
, 2);
298 err
= uether_do_request(&sc
->sc_ue
, &req
, &val
, 1000);
301 MOS_DPRINTFN("mos_reg_read_2 error, reg: %d", reg
);
308 mos_reg_write_1(struct mos_softc
*sc
, int reg
, int aval
)
310 struct usb_device_request req
;
315 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
316 req
.bRequest
= MOS_UR_WRITEREG
;
317 USETW(req
.wValue
, 0);
318 USETW(req
.wIndex
, reg
);
319 USETW(req
.wLength
, 1);
321 err
= uether_do_request(&sc
->sc_ue
, &req
, &val
, 1000);
324 MOS_DPRINTFN("mos_reg_write_1 error, reg: %d", reg
);
331 mos_reg_write_2(struct mos_softc
*sc
, int reg
, int aval
)
333 struct usb_device_request req
;
339 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
340 req
.bRequest
= MOS_UR_WRITEREG
;
341 USETW(req
.wValue
, 0);
342 USETW(req
.wIndex
, reg
);
343 USETW(req
.wLength
, 2);
345 err
= uether_do_request(&sc
->sc_ue
, &req
, &val
, 1000);
348 MOS_DPRINTFN("mos_reg_write_2 error, reg: %d", reg
);
355 mos_readmac(struct mos_softc
*sc
, u_char
*mac
)
357 struct usb_device_request req
;
360 req
.bmRequestType
= UT_READ_VENDOR_DEVICE
;
361 req
.bRequest
= MOS_UR_READREG
;
362 USETW(req
.wValue
, 0);
363 USETW(req
.wIndex
, MOS_MAC
);
364 USETW(req
.wLength
, ETHER_ADDR_LEN
);
366 err
= uether_do_request(&sc
->sc_ue
, &req
, mac
, 1000);
375 mos_writemac(struct mos_softc
*sc
, uint8_t *mac
)
377 struct usb_device_request req
;
380 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
381 req
.bRequest
= MOS_UR_WRITEREG
;
382 USETW(req
.wValue
, 0);
383 USETW(req
.wIndex
, MOS_MAC
);
384 USETW(req
.wLength
, ETHER_ADDR_LEN
);
386 err
= uether_do_request(&sc
->sc_ue
, &req
, mac
, 1000);
389 MOS_DPRINTFN("mos_writemac error");
396 mos_write_mcast(struct mos_softc
*sc
, u_char
*hashtbl
)
398 struct usb_device_request req
;
401 req
.bmRequestType
= UT_WRITE_VENDOR_DEVICE
;
402 req
.bRequest
= MOS_UR_WRITEREG
;
403 USETW(req
.wValue
, 0);
404 USETW(req
.wIndex
, MOS_MCAST_TABLE
);
405 USETW(req
.wLength
, 8);
407 err
= uether_do_request(&sc
->sc_ue
, &req
, hashtbl
, 1000);
410 MOS_DPRINTFN("mos_reg_mcast error");
417 mos_miibus_readreg(device_t dev
, int phy
, int reg
)
419 struct mos_softc
*sc
= device_get_softc(dev
);
425 locked
= lockowned(&sc
->sc_lock
);
429 mos_reg_write_2(sc
, MOS_PHY_DATA
, 0);
430 mos_reg_write_1(sc
, MOS_PHY_CTL
, (phy
& MOS_PHYCTL_PHYADDR
) |
432 mos_reg_write_1(sc
, MOS_PHY_STS
, (reg
& MOS_PHYSTS_PHYREG
) |
435 for (i
= 0; i
< MOS_TIMEOUT
; i
++) {
436 if (mos_reg_read_1(sc
, MOS_PHY_STS
) & MOS_PHYSTS_READY
)
439 if (i
== MOS_TIMEOUT
) {
440 MOS_DPRINTFN("MII read timeout");
442 res
= mos_reg_read_2(sc
, MOS_PHY_DATA
);
450 mos_miibus_writereg(device_t dev
, int phy
, int reg
, int val
)
452 struct mos_softc
*sc
= device_get_softc(dev
);
455 locked
= lockowned(&sc
->sc_lock
);
459 mos_reg_write_2(sc
, MOS_PHY_DATA
, val
);
460 mos_reg_write_1(sc
, MOS_PHY_CTL
, (phy
& MOS_PHYCTL_PHYADDR
) |
462 mos_reg_write_1(sc
, MOS_PHY_STS
, (reg
& MOS_PHYSTS_PHYREG
) |
465 for (i
= 0; i
< MOS_TIMEOUT
; i
++) {
466 if (mos_reg_read_1(sc
, MOS_PHY_STS
) & MOS_PHYSTS_READY
)
469 if (i
== MOS_TIMEOUT
)
470 MOS_DPRINTFN("MII write timeout");
478 mos_miibus_statchg(device_t dev
)
480 struct mos_softc
*sc
= device_get_softc(dev
);
481 struct mii_data
*mii
= GET_MII(sc
);
482 int val
, err
, locked
;
484 locked
= lockowned(&sc
->sc_lock
);
488 /* disable RX, TX prior to changing FDX, SPEEDSEL */
489 val
= mos_reg_read_1(sc
, MOS_CTL
);
490 val
&= ~(MOS_CTL_TX_ENB
| MOS_CTL_RX_ENB
);
491 mos_reg_write_1(sc
, MOS_CTL
, val
);
493 /* reset register which counts dropped frames */
494 mos_reg_write_1(sc
, MOS_FRAME_DROP_CNT
, 0);
496 if ((mii
->mii_media_active
& IFM_GMASK
) == IFM_FDX
)
497 val
|= MOS_CTL_FDX_ENB
;
499 val
&= ~(MOS_CTL_FDX_ENB
);
501 switch (IFM_SUBTYPE(mii
->mii_media_active
)) {
503 val
|= MOS_CTL_SPEEDSEL
;
506 val
&= ~(MOS_CTL_SPEEDSEL
);
510 /* re-enable TX, RX */
511 val
|= (MOS_CTL_TX_ENB
| MOS_CTL_RX_ENB
);
512 err
= mos_reg_write_1(sc
, MOS_CTL
, val
);
515 MOS_DPRINTFN("media change failed");
525 mos_ifmedia_upd(struct ifnet
*ifp
)
527 struct mos_softc
*sc
= ifp
->if_softc
;
528 struct mii_data
*mii
= GET_MII(sc
);
529 struct mii_softc
*miisc
;
535 if (mii
->mii_instance
) {
536 LIST_FOREACH(miisc
, &mii
->mii_phys
, mii_list
)
537 mii_phy_reset(miisc
);
539 error
= mii_mediachg(mii
);
544 * Report current media status.
547 mos_ifmedia_sts(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)
549 struct mos_softc
*sc
= ifp
->if_softc
;
550 struct mii_data
*mii
= GET_MII(sc
);
555 ifmr
->ifm_active
= mii
->mii_media_active
;
556 ifmr
->ifm_status
= mii
->mii_media_status
;
561 mos_setpromisc(struct usb_ether
*ue
)
563 struct mos_softc
*sc
= uether_getsc(ue
);
564 struct ifnet
*ifp
= uether_getifp(ue
);
570 rxmode
= mos_reg_read_1(sc
, MOS_CTL
);
572 /* If we want promiscuous mode, set the allframes bit. */
573 if (ifp
->if_flags
& IFF_PROMISC
) {
574 rxmode
|= MOS_CTL_RX_PROMISC
;
576 rxmode
&= ~MOS_CTL_RX_PROMISC
;
579 mos_reg_write_1(sc
, MOS_CTL
, rxmode
);
585 mos_setmulti(struct usb_ether
*ue
)
587 struct mos_softc
*sc
= uether_getsc(ue
);
588 struct ifnet
*ifp
= uether_getifp(ue
);
589 struct ifmultiaddr
*ifma
;
593 uint8_t hashtbl
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
598 rxmode
= mos_reg_read_1(sc
, MOS_CTL
);
600 if (ifp
->if_flags
& IFF_ALLMULTI
|| ifp
->if_flags
& IFF_PROMISC
)
603 /* get all new ones */
604 TAILQ_FOREACH(ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
605 if (ifma
->ifma_addr
->sa_family
!= AF_LINK
) {
609 h
= ether_crc32_be(LLADDR((struct sockaddr_dl
*)
610 ifma
->ifma_addr
), ETHER_ADDR_LEN
) >> 26;
611 hashtbl
[h
/ 8] |= 1 << (h
% 8);
614 /* now program new ones */
616 rxmode
|= MOS_CTL_ALLMULTI
;
617 mos_reg_write_1(sc
, MOS_CTL
, rxmode
);
619 rxmode
&= ~MOS_CTL_ALLMULTI
;
620 mos_write_mcast(sc
, (void *)&hashtbl
);
621 mos_reg_write_1(sc
, MOS_CTL
, rxmode
);
626 mos_reset(struct mos_softc
*sc
)
630 ctl
= mos_reg_read_1(sc
, MOS_CTL
);
631 ctl
&= ~(MOS_CTL_RX_PROMISC
| MOS_CTL_ALLMULTI
| MOS_CTL_TX_ENB
|
633 /* Disable RX, TX, promiscuous and allmulticast mode */
634 mos_reg_write_1(sc
, MOS_CTL
, ctl
);
636 /* Reset frame drop counter register to zero */
637 mos_reg_write_1(sc
, MOS_FRAME_DROP_CNT
, 0);
639 /* Wait a little while for the chip to get its brains in order. */
640 usb_pause_mtx(&sc
->sc_lock
, hz
/ 128);
645 mos_chip_init(struct mos_softc
*sc
)
650 * Rev.C devices have a pause threshold register which needs to be set
653 if (mos_reg_read_1(sc
, MOS_PAUSE_TRHD
) != -1) {
654 for (i
= 0; i
< MOS_PAUSE_REWRITES
; i
++)
655 mos_reg_write_1(sc
, MOS_PAUSE_TRHD
, 0);
657 sc
->mos_phyaddrs
[0] = 1;
658 sc
->mos_phyaddrs
[1] = 0xFF;
662 * Probe for a MCS7x30 chip.
665 mos_probe(device_t dev
)
667 struct usb_attach_arg
*uaa
= device_get_ivars(dev
);
670 if (uaa
->usb_mode
!= USB_MODE_HOST
)
672 if (uaa
->info
.bConfigIndex
!= MOS_CONFIG_IDX
)
674 if (uaa
->info
.bIfaceIndex
!= MOS_IFACE_IDX
)
677 retval
= usbd_lookup_id_by_uaa(mos_devs
, sizeof(mos_devs
), uaa
);
682 * Attach the interface. Allocate softc structures, do ifmedia
683 * setup and ethernet/BPF attach.
686 mos_attach(device_t dev
)
688 struct usb_attach_arg
*uaa
= device_get_ivars(dev
);
689 struct mos_softc
*sc
= device_get_softc(dev
);
690 struct usb_ether
*ue
= &sc
->sc_ue
;
694 sc
->mos_flags
= USB_GET_DRIVER_INFO(uaa
);
696 device_set_usb_desc(dev
);
697 lockinit(&sc
->sc_lock
, device_get_nameunit(dev
), 0, LK_CANRECURSE
);
699 iface_index
= MOS_IFACE_IDX
;
700 error
= usbd_transfer_setup(uaa
->device
, &iface_index
,
701 sc
->sc_xfer
, mos_config
, MOS_ENDPT_MAX
,
705 device_printf(dev
, "allocating USB transfers failed\n");
710 ue
->ue_udev
= uaa
->device
;
711 ue
->ue_lock
= &sc
->sc_lock
;
712 ue
->ue_methods
= &mos_ue_methods
;
715 if (sc
->mos_flags
& MCS7730
) {
716 MOS_DPRINTFN("model: MCS7730");
717 } else if (sc
->mos_flags
& MCS7830
) {
718 MOS_DPRINTFN("model: MCS7830");
719 } else if (sc
->mos_flags
& MCS7832
) {
720 MOS_DPRINTFN("model: MCS7832");
722 error
= uether_ifattach(ue
);
724 device_printf(dev
, "could not attach interface\n");
737 mos_attach_post(struct usb_ether
*ue
)
739 struct mos_softc
*sc
= uether_getsc(ue
);
742 char ethstr
[ETHER_ADDRSTRLEN
+ 1];
745 /* Read MAC address, inform the world. */
746 err
= mos_readmac(sc
, ue
->ue_eaddr
);
749 MOS_DPRINTFN("couldn't get MAC address");
751 MOS_DPRINTFN("address: %s", kether_ntoa(ue
->ue_eaddr
, ethstr
));
757 mos_detach(device_t dev
)
759 struct mos_softc
*sc
= device_get_softc(dev
);
760 struct usb_ether
*ue
= &sc
->sc_ue
;
762 usbd_transfer_unsetup(sc
->sc_xfer
, MOS_ENDPT_MAX
);
764 lockuninit(&sc
->sc_lock
);
773 * A frame has been uploaded: pass the resulting mbuf chain up to
774 * the higher level protocols.
777 mos_bulk_read_callback(struct usb_xfer
*xfer
, usb_error_t error
)
779 struct mos_softc
*sc
= usbd_xfer_softc(xfer
);
780 struct usb_ether
*ue
= &sc
->sc_ue
;
781 struct ifnet
*ifp
= uether_getifp(ue
);
786 struct usb_page_cache
*pc
;
788 usbd_xfer_status(xfer
, &actlen
, NULL
, NULL
, NULL
);
789 pc
= usbd_xfer_get_frame(xfer
, 0);
791 switch (USB_GET_STATE(xfer
)) {
792 case USB_ST_TRANSFERRED
:
793 MOS_DPRINTFN("actlen : %d", actlen
);
795 IFNET_STAT_INC(ifp
, ierrors
, 1);
798 /* evaluate status byte at the end */
799 usbd_copy_out(pc
, actlen
- sizeof(rxstat
), &rxstat
,
802 if (rxstat
!= MOS_RXSTS_VALID
) {
803 MOS_DPRINTFN("erroneous frame received");
804 if (rxstat
& MOS_RXSTS_SHORT_FRAME
)
805 MOS_DPRINTFN("frame size less than 64 bytes");
806 if (rxstat
& MOS_RXSTS_LARGE_FRAME
) {
807 MOS_DPRINTFN("frame size larger than "
810 if (rxstat
& MOS_RXSTS_CRC_ERROR
)
811 MOS_DPRINTFN("CRC error");
812 if (rxstat
& MOS_RXSTS_ALIGN_ERROR
)
813 MOS_DPRINTFN("alignment error");
814 IFNET_STAT_INC(ifp
, ierrors
, 1);
817 /* Remember the last byte was used for the status fields */
819 if (pktlen
< sizeof(struct ether_header
)) {
820 MOS_DPRINTFN("error: pktlen %d is smaller "
821 "than ether_header %zd", pktlen
,
822 sizeof(struct ether_header
));
823 IFNET_STAT_INC(ifp
, ierrors
, 1);
826 uether_rxbuf(ue
, pc
, 0, actlen
);
830 usbd_xfer_set_frame_len(xfer
, 0, usbd_xfer_max_len(xfer
));
831 usbd_transfer_submit(xfer
);
835 MOS_DPRINTFN("bulk read error, %s", usbd_errstr(error
));
836 if (error
!= USB_ERR_CANCELLED
) {
837 usbd_xfer_set_stall(xfer
);
840 MOS_DPRINTFN("start rx %i", usbd_xfer_max_len(xfer
));
846 * A frame was downloaded to the chip. It's safe for us to clean up
850 mos_bulk_write_callback(struct usb_xfer
*xfer
, usb_error_t error
)
852 struct mos_softc
*sc
= usbd_xfer_softc(xfer
);
853 struct ifnet
*ifp
= uether_getifp(&sc
->sc_ue
);
854 struct usb_page_cache
*pc
;
859 switch (USB_GET_STATE(xfer
)) {
860 case USB_ST_TRANSFERRED
:
861 MOS_DPRINTFN("transfer of complete");
862 IFNET_STAT_INC(ifp
, opackets
, 1);
867 * XXX: don't send anything if there is no link?
869 m
= ifq_dequeue(&ifp
->if_snd
);
873 pc
= usbd_xfer_get_frame(xfer
, 0);
874 usbd_m_copy_in(pc
, 0, m
, 0, m
->m_pkthdr
.len
);
876 usbd_xfer_set_frame_len(xfer
, 0, m
->m_pkthdr
.len
);
880 * if there's a BPF listener, bounce a copy
881 * of this frame to him:
887 usbd_transfer_submit(xfer
);
889 IFNET_STAT_INC(ifp
, opackets
, 1);
892 MOS_DPRINTFN("usb error on tx: %s\n", usbd_errstr(error
));
893 IFNET_STAT_INC(ifp
, oerrors
, 1);
894 if (error
!= USB_ERR_CANCELLED
) {
895 usbd_xfer_set_stall(xfer
);
903 mos_tick(struct usb_ether
*ue
)
905 struct mos_softc
*sc
= uether_getsc(ue
);
906 struct mii_data
*mii
= GET_MII(sc
);
911 if (!sc
->mos_link
&& mii
->mii_media_status
& IFM_ACTIVE
&&
912 IFM_SUBTYPE(mii
->mii_media_active
) != IFM_NONE
) {
913 MOS_DPRINTFN("got link");
921 mos_start(struct usb_ether
*ue
)
923 struct mos_softc
*sc
= uether_getsc(ue
);
926 * start the USB transfers, if not already started:
928 usbd_transfer_start(sc
->sc_xfer
[MOS_ENDPT_TX
]);
929 usbd_transfer_start(sc
->sc_xfer
[MOS_ENDPT_RX
]);
930 usbd_transfer_start(sc
->sc_xfer
[MOS_ENDPT_INTR
]);
934 mos_init(struct usb_ether
*ue
)
936 struct mos_softc
*sc
= uether_getsc(ue
);
937 struct ifnet
*ifp
= uether_getifp(ue
);
942 /* Cancel pending I/O and free all RX/TX buffers. */
945 /* Write MAC address */
946 mos_writemac(sc
, IF_LLADDR(ifp
));
948 /* Read and set transmitter IPG values */
949 sc
->mos_ipgs
[0] = mos_reg_read_1(sc
, MOS_IPG0
);
950 sc
->mos_ipgs
[1] = mos_reg_read_1(sc
, MOS_IPG1
);
951 mos_reg_write_1(sc
, MOS_IPG0
, sc
->mos_ipgs
[0]);
952 mos_reg_write_1(sc
, MOS_IPG1
, sc
->mos_ipgs
[1]);
955 * Enable receiver and transmitter, bridge controls speed/duplex
958 rxmode
= mos_reg_read_1(sc
, MOS_CTL
);
959 rxmode
|= MOS_CTL_RX_ENB
| MOS_CTL_TX_ENB
| MOS_CTL_BS_ENB
;
960 rxmode
&= ~(MOS_CTL_SLEEP
);
964 /* XXX: broadcast mode? */
965 mos_reg_write_1(sc
, MOS_CTL
, rxmode
);
967 /* Load the multicast filter. */
970 ifp
->if_flags
|= IFF_RUNNING
;
976 mos_intr_callback(struct usb_xfer
*xfer
, usb_error_t error
)
978 struct mos_softc
*sc
= usbd_xfer_softc(xfer
);
979 struct ifnet
*ifp
= uether_getifp(&sc
->sc_ue
);
980 struct usb_page_cache
*pc
;
984 IFNET_STAT_INC(ifp
, oerrors
, 1);
986 usbd_xfer_status(xfer
, &actlen
, NULL
, NULL
, NULL
);
987 MOS_DPRINTFN("actlen %i", actlen
);
989 switch (USB_GET_STATE(xfer
)) {
990 case USB_ST_TRANSFERRED
:
992 pc
= usbd_xfer_get_frame(xfer
, 0);
993 usbd_copy_out(pc
, 0, &pkt
, sizeof(pkt
));
999 if (error
!= USB_ERR_CANCELLED
) {
1000 usbd_xfer_set_stall(xfer
);
1009 * Stop the adapter and free any mbufs allocated to the
1013 mos_stop(struct usb_ether
*ue
)
1015 struct mos_softc
*sc
= uether_getsc(ue
);
1016 struct ifnet
*ifp
= uether_getifp(ue
);
1020 MOS_LOCK_ASSERT(sc
);
1021 ifp
->if_flags
&= ~IFF_RUNNING
;
1023 /* stop all the transfers, if not already stopped */
1024 usbd_transfer_stop(sc
->sc_xfer
[MOS_ENDPT_TX
]);
1025 usbd_transfer_stop(sc
->sc_xfer
[MOS_ENDPT_RX
]);
1026 usbd_transfer_stop(sc
->sc_xfer
[MOS_ENDPT_INTR
]);