1/*-
2 * SPDX-License-Identifier: (BSD-1-Clause AND BSD-4-Clause)
3 *
4 * Copyright (c) 2011 Rick van der Zwet <info@rickvanderzwet.nl>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*-
20 * Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net>
21 *
22 * Permission to use, copy, modify, and distribute this software for any
23 * purpose with or without fee is hereby granted, provided that the above
24 * copyright notice and this permission notice appear in all copies.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
27 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
29 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
30 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
31 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
32 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 */
34
35/*-
36 * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org>
37 *
38 * Permission to use, copy, modify, and distribute this software for any
39 * purpose with or without fee is hereby granted, provided that the above
40 * copyright notice and this permission notice appear in all copies.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
48 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49 */
50
51/*-
52 * Copyright (c) 1997, 1998, 1999, 2000-2003
53 *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
54 *
55 * Redistribution and use in source and binary forms, with or without
56 * modification, are permitted provided that the following conditions
57 * are met:
58 * 1. Redistributions of source code must retain the above copyright
59 *    notice, this list of conditions and the following disclaimer.
60 * 2. Redistributions in binary form must reproduce the above copyright
61 *    notice, this list of conditions and the following disclaimer in the
62 *    documentation and/or other materials provided with the distribution.
63 * 3. All advertising materials mentioning features or use of this software
64 *    must display the following acknowledgement:
65 *	This product includes software developed by Bill Paul.
66 * 4. Neither the name of the author nor the names of any co-contributors
67 *    may be used to endorse or promote products derived from this software
68 *    without specific prior written permission.
69 *
70 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
71 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
72 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
73 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
74 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
75 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
76 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
77 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
78 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
79 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
80 * THE POSSIBILITY OF SUCH DAMAGE.
81 */
82
83#include <sys/cdefs.h>
84__FBSDID("$FreeBSD$");
85
86/*
87 * Moschip MCS7730/MCS7830/MCS7832 USB to Ethernet controller
88 * The datasheet is available at the following URL:
89 * http://www.moschip.com/data/products/MCS7830/Data%20Sheet_7830.pdf
90 */
91
92/*
93 * The FreeBSD if_mos.c driver is based on various different sources:
94 * The vendor provided driver at the following URL:
95 * http://www.moschip.com/data/products/MCS7830/Driver_FreeBSD_7830.tar.gz
96 *
97 * Mixed together with the OpenBSD if_mos.c driver for validation and checking
98 * and the FreeBSD if_reu.c as reference for the USB Ethernet framework.
99 */
100
101#include <sys/stdint.h>
102#include <sys/stddef.h>
103#include <sys/param.h>
104#include <sys/queue.h>
105#include <sys/types.h>
106#include <sys/systm.h>
107#include <sys/socket.h>
108#include <sys/kernel.h>
109#include <sys/bus.h>
110#include <sys/module.h>
111#include <sys/lock.h>
112#include <sys/mutex.h>
113#include <sys/condvar.h>
114#include <sys/sysctl.h>
115#include <sys/sx.h>
116#include <sys/unistd.h>
117#include <sys/callout.h>
118#include <sys/malloc.h>
119#include <sys/priv.h>
120
121#include <net/if.h>
122#include <net/if_var.h>
123#include <net/if_media.h>
124
125#include <dev/mii/mii.h>
126#include <dev/mii/miivar.h>
127
128#include <dev/usb/usb.h>
129#include <dev/usb/usbdi.h>
130#include <dev/usb/usbdi_util.h>
131#include "usbdevs.h"
132
133#define	USB_DEBUG_VAR mos_debug
134#include <dev/usb/usb_debug.h>
135#include <dev/usb/usb_process.h>
136
137#include <dev/usb/net/usb_ethernet.h>
138
139#include "miibus_if.h"
140
141//#include <dev/usb/net/if_mosreg.h>
142#include "if_mosreg.h"
143
144#ifdef USB_DEBUG
145static int mos_debug = 0;
146
147static SYSCTL_NODE(_hw_usb, OID_AUTO, mos, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
148    "USB mos");
149SYSCTL_INT(_hw_usb_mos, OID_AUTO, debug, CTLFLAG_RWTUN, &mos_debug, 0,
150    "Debug level");
151#endif
152
153#define MOS_DPRINTFN(fmt,...) \
154  DPRINTF("mos: %s: " fmt "\n",__FUNCTION__,## __VA_ARGS__)
155
156#define	USB_PRODUCT_MOSCHIP_MCS7730	0x7730
157#define	USB_PRODUCT_SITECOMEU_LN030	0x0021
158
159/* Various supported device vendors/products. */
160static const STRUCT_USB_HOST_ID mos_devs[] = {
161	{USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7730, MCS7730)},
162	{USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7830, MCS7830)},
163	{USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7832, MCS7832)},
164	{USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN030, MCS7830)},
165};
166
167static int mos_probe(device_t dev);
168static int mos_attach(device_t dev);
169static void mos_attach_post(struct usb_ether *ue);
170static int mos_detach(device_t dev);
171
172static void mos_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error);
173static void mos_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error);
174static void mos_intr_callback(struct usb_xfer *xfer, usb_error_t error);
175static void mos_tick(struct usb_ether *);
176static void mos_start(struct usb_ether *);
177static void mos_init(struct usb_ether *);
178static void mos_chip_init(struct mos_softc *);
179static void mos_stop(struct usb_ether *);
180static int mos_miibus_readreg(device_t, int, int);
181static int mos_miibus_writereg(device_t, int, int, int);
182static void mos_miibus_statchg(device_t);
183static int mos_ifmedia_upd(struct ifnet *);
184static void mos_ifmedia_sts(struct ifnet *, struct ifmediareq *);
185static void mos_reset(struct mos_softc *sc);
186
187static int mos_reg_read_1(struct mos_softc *, int);
188static int mos_reg_read_2(struct mos_softc *, int);
189static int mos_reg_write_1(struct mos_softc *, int, int);
190static int mos_reg_write_2(struct mos_softc *, int, int);
191static int mos_readmac(struct mos_softc *, uint8_t *);
192static int mos_writemac(struct mos_softc *, uint8_t *);
193static int mos_write_mcast(struct mos_softc *, u_char *);
194
195static void mos_setmulti(struct usb_ether *);
196static void mos_setpromisc(struct usb_ether *);
197
198static const struct usb_config mos_config[MOS_ENDPT_MAX] = {
199	[MOS_ENDPT_TX] = {
200		.type = UE_BULK,
201		.endpoint = UE_ADDR_ANY,
202		.direction = UE_DIR_OUT,
203		.bufsize = (MCLBYTES + 2),
204		.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
205		.callback = mos_bulk_write_callback,
206		.timeout = 10000,
207	},
208
209	[MOS_ENDPT_RX] = {
210		.type = UE_BULK,
211		.endpoint = UE_ADDR_ANY,
212		.direction = UE_DIR_IN,
213		.bufsize = (MCLBYTES + 4 + ETHER_CRC_LEN),
214		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
215		.callback = mos_bulk_read_callback,
216	},
217
218	[MOS_ENDPT_INTR] = {
219		.type = UE_INTERRUPT,
220		.endpoint = UE_ADDR_ANY,
221		.direction = UE_DIR_IN,
222		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
223		.bufsize = 0,
224		.callback = mos_intr_callback,
225	},
226};
227
228static device_method_t mos_methods[] = {
229	/* Device interface */
230	DEVMETHOD(device_probe, mos_probe),
231	DEVMETHOD(device_attach, mos_attach),
232	DEVMETHOD(device_detach, mos_detach),
233
234	/* MII interface */
235	DEVMETHOD(miibus_readreg, mos_miibus_readreg),
236	DEVMETHOD(miibus_writereg, mos_miibus_writereg),
237	DEVMETHOD(miibus_statchg, mos_miibus_statchg),
238
239	DEVMETHOD_END
240};
241
242static driver_t mos_driver = {
243	.name = "mos",
244	.methods = mos_methods,
245	.size = sizeof(struct mos_softc)
246};
247
248static devclass_t mos_devclass;
249
250DRIVER_MODULE(mos, uhub, mos_driver, mos_devclass, NULL, 0);
251DRIVER_MODULE(miibus, mos, miibus_driver, miibus_devclass, 0, 0);
252MODULE_DEPEND(mos, uether, 1, 1, 1);
253MODULE_DEPEND(mos, usb, 1, 1, 1);
254MODULE_DEPEND(mos, ether, 1, 1, 1);
255MODULE_DEPEND(mos, miibus, 1, 1, 1);
256USB_PNP_HOST_INFO(mos_devs);
257
258static const struct usb_ether_methods mos_ue_methods = {
259	.ue_attach_post = mos_attach_post,
260	.ue_start = mos_start,
261	.ue_init = mos_init,
262	.ue_stop = mos_stop,
263	.ue_tick = mos_tick,
264	.ue_setmulti = mos_setmulti,
265	.ue_setpromisc = mos_setpromisc,
266	.ue_mii_upd = mos_ifmedia_upd,
267	.ue_mii_sts = mos_ifmedia_sts,
268};
269
270static int
271mos_reg_read_1(struct mos_softc *sc, int reg)
272{
273	struct usb_device_request req;
274	usb_error_t err;
275	uByte val = 0;
276
277	req.bmRequestType = UT_READ_VENDOR_DEVICE;
278	req.bRequest = MOS_UR_READREG;
279	USETW(req.wValue, 0);
280	USETW(req.wIndex, reg);
281	USETW(req.wLength, 1);
282
283	err = uether_do_request(&sc->sc_ue, &req, &val, 1000);
284
285	if (err) {
286		MOS_DPRINTFN("mos_reg_read_1 error, reg: %d\n", reg);
287		return (-1);
288	}
289	return (val);
290}
291
292static int
293mos_reg_read_2(struct mos_softc *sc, int reg)
294{
295	struct usb_device_request req;
296	usb_error_t err;
297	uWord val;
298
299	USETW(val, 0);
300
301	req.bmRequestType = UT_READ_VENDOR_DEVICE;
302	req.bRequest = MOS_UR_READREG;
303	USETW(req.wValue, 0);
304	USETW(req.wIndex, reg);
305	USETW(req.wLength, 2);
306
307	err = uether_do_request(&sc->sc_ue, &req, &val, 1000);
308
309	if (err) {
310		MOS_DPRINTFN("mos_reg_read_2 error, reg: %d", reg);
311		return (-1);
312	}
313	return (UGETW(val));
314}
315
316static int
317mos_reg_write_1(struct mos_softc *sc, int reg, int aval)
318{
319	struct usb_device_request req;
320	usb_error_t err;
321	uByte val;
322	val = aval;
323
324	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
325	req.bRequest = MOS_UR_WRITEREG;
326	USETW(req.wValue, 0);
327	USETW(req.wIndex, reg);
328	USETW(req.wLength, 1);
329
330	err = uether_do_request(&sc->sc_ue, &req, &val, 1000);
331
332	if (err) {
333		MOS_DPRINTFN("mos_reg_write_1 error, reg: %d", reg);
334		return (-1);
335	}
336	return (0);
337}
338
339static int
340mos_reg_write_2(struct mos_softc *sc, int reg, int aval)
341{
342	struct usb_device_request req;
343	usb_error_t err;
344	uWord val;
345
346	USETW(val, aval);
347
348	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
349	req.bRequest = MOS_UR_WRITEREG;
350	USETW(req.wValue, 0);
351	USETW(req.wIndex, reg);
352	USETW(req.wLength, 2);
353
354	err = uether_do_request(&sc->sc_ue, &req, &val, 1000);
355
356	if (err) {
357		MOS_DPRINTFN("mos_reg_write_2 error, reg: %d", reg);
358		return (-1);
359	}
360	return (0);
361}
362
363static int
364mos_readmac(struct mos_softc *sc, u_char *mac)
365{
366	struct usb_device_request req;
367	usb_error_t err;
368
369	req.bmRequestType = UT_READ_VENDOR_DEVICE;
370	req.bRequest = MOS_UR_READREG;
371	USETW(req.wValue, 0);
372	USETW(req.wIndex, MOS_MAC);
373	USETW(req.wLength, ETHER_ADDR_LEN);
374
375	err = uether_do_request(&sc->sc_ue, &req, mac, 1000);
376
377	if (err) {
378		return (-1);
379	}
380	return (0);
381}
382
383static int
384mos_writemac(struct mos_softc *sc, uint8_t *mac)
385{
386	struct usb_device_request req;
387	usb_error_t err;
388
389	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
390	req.bRequest = MOS_UR_WRITEREG;
391	USETW(req.wValue, 0);
392	USETW(req.wIndex, MOS_MAC);
393	USETW(req.wLength, ETHER_ADDR_LEN);
394
395	err = uether_do_request(&sc->sc_ue, &req, mac, 1000);
396
397	if (err) {
398		MOS_DPRINTFN("mos_writemac error");
399		return (-1);
400	}
401	return (0);
402}
403
404static int
405mos_write_mcast(struct mos_softc *sc, u_char *hashtbl)
406{
407	struct usb_device_request req;
408	usb_error_t err;
409
410	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
411	req.bRequest = MOS_UR_WRITEREG;
412	USETW(req.wValue, 0);
413	USETW(req.wIndex, MOS_MCAST_TABLE);
414	USETW(req.wLength, 8);
415
416	err = uether_do_request(&sc->sc_ue, &req, hashtbl, 1000);
417
418	if (err) {
419		MOS_DPRINTFN("mos_reg_mcast error");
420		return (-1);
421	}
422	return (0);
423}
424
425static int
426mos_miibus_readreg(device_t dev, int phy, int reg)
427{
428	struct mos_softc *sc = device_get_softc(dev);
429	uWord val;
430	int i, res, locked;
431
432	USETW(val, 0);
433
434	locked = mtx_owned(&sc->sc_mtx);
435	if (!locked)
436		MOS_LOCK(sc);
437
438	mos_reg_write_2(sc, MOS_PHY_DATA, 0);
439	mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) |
440	    MOS_PHYCTL_READ);
441	mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) |
442	    MOS_PHYSTS_PENDING);
443
444	for (i = 0; i < MOS_TIMEOUT; i++) {
445		if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY)
446			break;
447	}
448	if (i == MOS_TIMEOUT) {
449		MOS_DPRINTFN("MII read timeout");
450	}
451	res = mos_reg_read_2(sc, MOS_PHY_DATA);
452
453	if (!locked)
454		MOS_UNLOCK(sc);
455	return (res);
456}
457
458static int
459mos_miibus_writereg(device_t dev, int phy, int reg, int val)
460{
461	struct mos_softc *sc = device_get_softc(dev);
462	int i, locked;
463
464	locked = mtx_owned(&sc->sc_mtx);
465	if (!locked)
466		MOS_LOCK(sc);
467
468	mos_reg_write_2(sc, MOS_PHY_DATA, val);
469	mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) |
470	    MOS_PHYCTL_WRITE);
471	mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) |
472	    MOS_PHYSTS_PENDING);
473
474	for (i = 0; i < MOS_TIMEOUT; i++) {
475		if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY)
476			break;
477	}
478	if (i == MOS_TIMEOUT)
479		MOS_DPRINTFN("MII write timeout");
480
481	if (!locked)
482		MOS_UNLOCK(sc);
483	return 0;
484}
485
486static void
487mos_miibus_statchg(device_t dev)
488{
489	struct mos_softc *sc = device_get_softc(dev);
490	struct mii_data *mii = GET_MII(sc);
491	int val, err, locked;
492
493	locked = mtx_owned(&sc->sc_mtx);
494	if (!locked)
495		MOS_LOCK(sc);
496
497	/* disable RX, TX prior to changing FDX, SPEEDSEL */
498	val = mos_reg_read_1(sc, MOS_CTL);
499	val &= ~(MOS_CTL_TX_ENB | MOS_CTL_RX_ENB);
500	mos_reg_write_1(sc, MOS_CTL, val);
501
502	/* reset register which counts dropped frames */
503	mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0);
504
505	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
506		val |= MOS_CTL_FDX_ENB;
507	else
508		val &= ~(MOS_CTL_FDX_ENB);
509
510	switch (IFM_SUBTYPE(mii->mii_media_active)) {
511	case IFM_100_TX:
512		val |= MOS_CTL_SPEEDSEL;
513		break;
514	case IFM_10_T:
515		val &= ~(MOS_CTL_SPEEDSEL);
516		break;
517	}
518
519	/* re-enable TX, RX */
520	val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB);
521	err = mos_reg_write_1(sc, MOS_CTL, val);
522
523	if (err)
524		MOS_DPRINTFN("media change failed");
525
526	if (!locked)
527		MOS_UNLOCK(sc);
528}
529
530/*
531 * Set media options.
532 */
533static int
534mos_ifmedia_upd(struct ifnet *ifp)
535{
536	struct mos_softc *sc = ifp->if_softc;
537	struct mii_data *mii = GET_MII(sc);
538	struct mii_softc *miisc;
539	int error;
540
541	MOS_LOCK_ASSERT(sc, MA_OWNED);
542
543	sc->mos_link = 0;
544	LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
545		PHY_RESET(miisc);
546	error = mii_mediachg(mii);
547	return (error);
548}
549
550/*
551 * Report current media status.
552 */
553static void
554mos_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
555{
556	struct mos_softc *sc = ifp->if_softc;
557	struct mii_data *mii = GET_MII(sc);
558
559	MOS_LOCK(sc);
560	mii_pollstat(mii);
561
562	ifmr->ifm_active = mii->mii_media_active;
563	ifmr->ifm_status = mii->mii_media_status;
564	MOS_UNLOCK(sc);
565}
566
567static void
568mos_setpromisc(struct usb_ether *ue)
569{
570	struct mos_softc *sc = uether_getsc(ue);
571	struct ifnet *ifp = uether_getifp(ue);
572
573	uint8_t rxmode;
574
575	MOS_LOCK_ASSERT(sc, MA_OWNED);
576
577	rxmode = mos_reg_read_1(sc, MOS_CTL);
578
579	/* If we want promiscuous mode, set the allframes bit. */
580	if (ifp->if_flags & IFF_PROMISC) {
581		rxmode |= MOS_CTL_RX_PROMISC;
582	} else {
583		rxmode &= ~MOS_CTL_RX_PROMISC;
584	}
585
586	mos_reg_write_1(sc, MOS_CTL, rxmode);
587}
588
589static u_int
590mos_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
591{
592	uint8_t *hashtbl = arg;
593	uint32_t h;
594
595	h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
596	hashtbl[h / 8] |= 1 << (h % 8);
597
598	return (1);
599}
600
601static void
602mos_setmulti(struct usb_ether *ue)
603{
604	struct mos_softc *sc = uether_getsc(ue);
605	struct ifnet *ifp = uether_getifp(ue);
606	uint8_t rxmode;
607	uint8_t hashtbl[8] = {0, 0, 0, 0, 0, 0, 0, 0};
608	int allmulti = 0;
609
610	MOS_LOCK_ASSERT(sc, MA_OWNED);
611
612	rxmode = mos_reg_read_1(sc, MOS_CTL);
613
614	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC)
615		allmulti = 1;
616
617	/* get all new ones */
618	if_foreach_llmaddr(ifp, mos_hash_maddr, &hashtbl);
619
620	/* now program new ones */
621	if (allmulti == 1) {
622		rxmode |= MOS_CTL_ALLMULTI;
623		mos_reg_write_1(sc, MOS_CTL, rxmode);
624	} else {
625		rxmode &= ~MOS_CTL_ALLMULTI;
626		mos_write_mcast(sc, (void *)&hashtbl);
627		mos_reg_write_1(sc, MOS_CTL, rxmode);
628	}
629}
630
631static void
632mos_reset(struct mos_softc *sc)
633{
634	uint8_t ctl;
635
636	ctl = mos_reg_read_1(sc, MOS_CTL);
637	ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB |
638	    MOS_CTL_RX_ENB);
639	/* Disable RX, TX, promiscuous and allmulticast mode */
640	mos_reg_write_1(sc, MOS_CTL, ctl);
641
642	/* Reset frame drop counter register to zero */
643	mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0);
644
645	/* Wait a little while for the chip to get its brains in order. */
646	usb_pause_mtx(&sc->sc_mtx, hz / 128);
647	return;
648}
649
650static void
651mos_chip_init(struct mos_softc *sc)
652{
653	int i;
654
655	/*
656	 * Rev.C devices have a pause threshold register which needs to be set
657	 * at startup.
658	 */
659	if (mos_reg_read_1(sc, MOS_PAUSE_TRHD) != -1) {
660		for (i = 0; i < MOS_PAUSE_REWRITES; i++)
661			mos_reg_write_1(sc, MOS_PAUSE_TRHD, 0);
662	}
663	sc->mos_phyaddrs[0] = 1;
664	sc->mos_phyaddrs[1] = 0xFF;
665}
666
667/*
668 * Probe for a MCS7x30 chip.
669 */
670static int
671mos_probe(device_t dev)
672{
673	struct usb_attach_arg *uaa = device_get_ivars(dev);
674        int retval;
675
676	if (uaa->usb_mode != USB_MODE_HOST)
677		return (ENXIO);
678	if (uaa->info.bConfigIndex != MOS_CONFIG_IDX)
679		return (ENXIO);
680	if (uaa->info.bIfaceIndex != MOS_IFACE_IDX)
681		return (ENXIO);
682
683	retval = usbd_lookup_id_by_uaa(mos_devs, sizeof(mos_devs), uaa);
684	return (retval);
685}
686
687/*
688 * Attach the interface. Allocate softc structures, do ifmedia
689 * setup and ethernet/BPF attach.
690 */
691static int
692mos_attach(device_t dev)
693{
694	struct usb_attach_arg *uaa = device_get_ivars(dev);
695	struct mos_softc *sc = device_get_softc(dev);
696	struct usb_ether *ue = &sc->sc_ue;
697	uint8_t iface_index;
698	int error;
699
700	sc->mos_flags = USB_GET_DRIVER_INFO(uaa);
701
702	device_set_usb_desc(dev);
703	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
704
705	iface_index = MOS_IFACE_IDX;
706	error = usbd_transfer_setup(uaa->device, &iface_index,
707	    sc->sc_xfer, mos_config, MOS_ENDPT_MAX,
708	    sc, &sc->sc_mtx);
709
710	if (error) {
711		device_printf(dev, "allocating USB transfers failed\n");
712		goto detach;
713	}
714	ue->ue_sc = sc;
715	ue->ue_dev = dev;
716	ue->ue_udev = uaa->device;
717	ue->ue_mtx = &sc->sc_mtx;
718	ue->ue_methods = &mos_ue_methods;
719
720	if (sc->mos_flags & MCS7730) {
721		MOS_DPRINTFN("model: MCS7730");
722	} else if (sc->mos_flags & MCS7830) {
723		MOS_DPRINTFN("model: MCS7830");
724	} else if (sc->mos_flags & MCS7832) {
725		MOS_DPRINTFN("model: MCS7832");
726	}
727	error = uether_ifattach(ue);
728	if (error) {
729		device_printf(dev, "could not attach interface\n");
730		goto detach;
731	}
732	return (0);
733
734detach:
735	mos_detach(dev);
736	return (ENXIO);
737}
738
739static void
740mos_attach_post(struct usb_ether *ue)
741{
742	struct mos_softc *sc = uether_getsc(ue);
743        int err;
744
745	/* Read MAC address, inform the world. */
746	err = mos_readmac(sc, ue->ue_eaddr);
747
748	if (err)
749	  MOS_DPRINTFN("couldn't get MAC address");
750
751	MOS_DPRINTFN("address: %s", ether_sprintf(ue->ue_eaddr));
752
753	mos_chip_init(sc);
754}
755
756static int
757mos_detach(device_t dev)
758{
759	struct mos_softc *sc = device_get_softc(dev);
760	struct usb_ether *ue = &sc->sc_ue;
761
762	usbd_transfer_unsetup(sc->sc_xfer, MOS_ENDPT_MAX);
763	uether_ifdetach(ue);
764	mtx_destroy(&sc->sc_mtx);
765
766	return (0);
767}
768
769/*
770 * A frame has been uploaded: pass the resulting mbuf chain up to
771 * the higher level protocols.
772 */
773static void
774mos_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
775{
776	struct mos_softc *sc = usbd_xfer_softc(xfer);
777	struct usb_ether *ue = &sc->sc_ue;
778	struct ifnet *ifp = uether_getifp(ue);
779
780	uint8_t rxstat = 0;
781	uint32_t actlen;
782	uint16_t pktlen = 0;
783	struct usb_page_cache *pc;
784
785	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
786	pc = usbd_xfer_get_frame(xfer, 0);
787
788	switch (USB_GET_STATE(xfer)) {
789	case USB_ST_TRANSFERRED:
790		MOS_DPRINTFN("actlen : %d", actlen);
791		if (actlen <= 1) {
792			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
793			goto tr_setup;
794		}
795		/* evaluate status byte at the end */
796		usbd_copy_out(pc, actlen - sizeof(rxstat), &rxstat,
797		    sizeof(rxstat));
798
799		if (rxstat != MOS_RXSTS_VALID) {
800			MOS_DPRINTFN("erroneous frame received");
801			if (rxstat & MOS_RXSTS_SHORT_FRAME)
802				MOS_DPRINTFN("frame size less than 64 bytes");
803			if (rxstat & MOS_RXSTS_LARGE_FRAME) {
804				MOS_DPRINTFN("frame size larger than "
805				    "1532 bytes");
806			}
807			if (rxstat & MOS_RXSTS_CRC_ERROR)
808				MOS_DPRINTFN("CRC error");
809			if (rxstat & MOS_RXSTS_ALIGN_ERROR)
810				MOS_DPRINTFN("alignment error");
811			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
812			goto tr_setup;
813		}
814		/* Remember the last byte was used for the status fields */
815		pktlen = actlen - 1;
816		if (pktlen < sizeof(struct ether_header)) {
817			MOS_DPRINTFN("error: pktlen %d is smaller "
818			    "than ether_header %zd", pktlen,
819			    sizeof(struct ether_header));
820			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
821			goto tr_setup;
822		}
823		uether_rxbuf(ue, pc, 0, actlen);
824		/* FALLTHROUGH */
825	case USB_ST_SETUP:
826tr_setup:
827		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
828		usbd_transfer_submit(xfer);
829		uether_rxflush(ue);
830		return;
831	default:
832		MOS_DPRINTFN("bulk read error, %s", usbd_errstr(error));
833		if (error != USB_ERR_CANCELLED) {
834			usbd_xfer_set_stall(xfer);
835			goto tr_setup;
836		}
837		MOS_DPRINTFN("start rx %i", usbd_xfer_max_len(xfer));
838		return;
839	}
840}
841
842/*
843 * A frame was downloaded to the chip. It's safe for us to clean up
844 * the list buffers.
845 */
846static void
847mos_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
848{
849	struct mos_softc *sc = usbd_xfer_softc(xfer);
850	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
851	struct usb_page_cache *pc;
852	struct mbuf *m;
853
854	switch (USB_GET_STATE(xfer)) {
855	case USB_ST_TRANSFERRED:
856		MOS_DPRINTFN("transfer of complete");
857		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
858		/* FALLTHROUGH */
859	case USB_ST_SETUP:
860tr_setup:
861		/*
862		 * XXX: don't send anything if there is no link?
863		 */
864		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
865		if (m == NULL)
866			return;
867
868		pc = usbd_xfer_get_frame(xfer, 0);
869		usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len);
870
871		usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len);
872
873		/*
874		 * if there's a BPF listener, bounce a copy
875		 * of this frame to him:
876		 */
877		BPF_MTAP(ifp, m);
878
879		m_freem(m);
880
881		usbd_transfer_submit(xfer);
882
883		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
884		return;
885	default:
886		MOS_DPRINTFN("usb error on tx: %s\n", usbd_errstr(error));
887		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
888		if (error != USB_ERR_CANCELLED) {
889			usbd_xfer_set_stall(xfer);
890			goto tr_setup;
891		}
892		return;
893	}
894}
895
896static void
897mos_tick(struct usb_ether *ue)
898{
899	struct mos_softc *sc = uether_getsc(ue);
900	struct mii_data *mii = GET_MII(sc);
901
902	MOS_LOCK_ASSERT(sc, MA_OWNED);
903
904	mii_tick(mii);
905	if (!sc->mos_link && mii->mii_media_status & IFM_ACTIVE &&
906	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
907		MOS_DPRINTFN("got link");
908		sc->mos_link++;
909		mos_start(ue);
910	}
911}
912
913static void
914mos_start(struct usb_ether *ue)
915{
916	struct mos_softc *sc = uether_getsc(ue);
917
918	/*
919	 * start the USB transfers, if not already started:
920	 */
921	usbd_transfer_start(sc->sc_xfer[MOS_ENDPT_TX]);
922	usbd_transfer_start(sc->sc_xfer[MOS_ENDPT_RX]);
923	usbd_transfer_start(sc->sc_xfer[MOS_ENDPT_INTR]);
924}
925
926static void
927mos_init(struct usb_ether *ue)
928{
929	struct mos_softc *sc = uether_getsc(ue);
930	struct ifnet *ifp = uether_getifp(ue);
931	uint8_t rxmode;
932
933	MOS_LOCK_ASSERT(sc, MA_OWNED);
934
935	/* Cancel pending I/O and free all RX/TX buffers. */
936	mos_reset(sc);
937
938	/* Write MAC address */
939	mos_writemac(sc, IF_LLADDR(ifp));
940
941	/* Read and set transmitter IPG values */
942	sc->mos_ipgs[0] = mos_reg_read_1(sc, MOS_IPG0);
943	sc->mos_ipgs[1] = mos_reg_read_1(sc, MOS_IPG1);
944	mos_reg_write_1(sc, MOS_IPG0, sc->mos_ipgs[0]);
945	mos_reg_write_1(sc, MOS_IPG1, sc->mos_ipgs[1]);
946
947	/*
948	 * Enable receiver and transmitter, bridge controls speed/duplex
949	 * mode
950	 */
951	rxmode = mos_reg_read_1(sc, MOS_CTL);
952	rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB;
953	rxmode &= ~(MOS_CTL_SLEEP);
954
955	mos_setpromisc(ue);
956
957	/* XXX: broadcast mode? */
958	mos_reg_write_1(sc, MOS_CTL, rxmode);
959
960	/* Load the multicast filter. */
961	mos_setmulti(ue);
962
963	ifp->if_drv_flags |= IFF_DRV_RUNNING;
964	mos_start(ue);
965}
966
967static void
968mos_intr_callback(struct usb_xfer *xfer, usb_error_t error)
969{
970	struct mos_softc *sc = usbd_xfer_softc(xfer);
971	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
972	struct usb_page_cache *pc;
973	uint32_t pkt;
974	int actlen;
975
976	if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
977
978	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
979	MOS_DPRINTFN("actlen %i", actlen);
980
981	switch (USB_GET_STATE(xfer)) {
982	case USB_ST_TRANSFERRED:
983
984		pc = usbd_xfer_get_frame(xfer, 0);
985		usbd_copy_out(pc, 0, &pkt, sizeof(pkt));
986		/* FALLTHROUGH */
987	case USB_ST_SETUP:
988tr_setup:
989		return;
990	default:
991		if (error != USB_ERR_CANCELLED) {
992			usbd_xfer_set_stall(xfer);
993			goto tr_setup;
994		}
995		return;
996	}
997}
998
999/*
1000 * Stop the adapter and free any mbufs allocated to the
1001 * RX and TX lists.
1002 */
1003static void
1004mos_stop(struct usb_ether *ue)
1005{
1006	struct mos_softc *sc = uether_getsc(ue);
1007	struct ifnet *ifp = uether_getifp(ue);
1008
1009	mos_reset(sc);
1010
1011	MOS_LOCK_ASSERT(sc, MA_OWNED);
1012	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1013
1014	/* stop all the transfers, if not already stopped */
1015	usbd_transfer_stop(sc->sc_xfer[MOS_ENDPT_TX]);
1016	usbd_transfer_stop(sc->sc_xfer[MOS_ENDPT_RX]);
1017	usbd_transfer_stop(sc->sc_xfer[MOS_ENDPT_INTR]);
1018
1019	sc->mos_link = 0;
1020}
1021