Sat Aug 25 20:12:22 2018 UTC ()
Add mue(4), driver for Microchip LAN75xx/LAN78xx known as internal NIC of
Raspberry Pi 3 B+, from OpenBSD.

Tested on Raspberry Pi 3 B+ (LAN7800) and Z-TEK ZE582 (LAN7500).

* BUGS/TODO

- If the media type is set to something other than 1000baseT-FDX, data
  transmission becomes quite unstable. Also, ukphy(4) recognize 1000baseT as
  a supported media type, but it is not in fact.

- Catch up with changes made to usmsc(4) in nick-nhusb branch, i.e.,
  make the driver MP-safe.

- Support RX/VLAN/TX chekcsum offloading.


(rin)
diff -r1.1611 -r1.1612 src/distrib/sets/lists/man/mi
diff -r1.116 -r1.117 src/distrib/sets/lists/modules/mi
diff -r1.664 -r1.665 src/share/man/man4/Makefile
diff -r0 -r1.1 src/share/man/man4/mue.4
diff -r1.151 -r1.152 src/sys/dev/usb/files.usb
diff -r0 -r1.1 src/sys/dev/usb/if_mue.c
diff -r0 -r1.1 src/sys/dev/usb/if_muereg.h
diff -r0 -r1.1 src/sys/dev/usb/if_muevar.h
diff -r1.32 -r1.33 src/sys/dev/usb/usbdevices.config
diff -r1.207 -r1.208 src/sys/modules/Makefile
diff -r0 -r1.1 src/sys/modules/if_mue/Makefile
diff -r0 -r1.1 src/sys/modules/if_mue/if_mue.ioconf

cvs diff -r1.1611 -r1.1612 src/distrib/sets/lists/man/mi (expand / switch to unified diff)

--- src/distrib/sets/lists/man/mi 2018/08/25 11:10:52 1.1611
+++ src/distrib/sets/lists/man/mi 2018/08/25 20:12:21 1.1612
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: mi,v 1.1611 2018/08/25 11:10:52 martin Exp $ 1# $NetBSD: mi,v 1.1612 2018/08/25 20:12:21 rin Exp $
2# 2#
3# Note: don't delete entries from here - mark them as "obsolete" instead. 3# Note: don't delete entries from here - mark them as "obsolete" instead.
4# 4#
5./etc/mtree/set.man man-sys-root 5./etc/mtree/set.man man-sys-root
6./usr/share/info/am-utils.info man-amd-info info 6./usr/share/info/am-utils.info man-amd-info info
7./usr/share/info/as.info man-computil-info binutils,info 7./usr/share/info/as.info man-computil-info binutils,info
8./usr/share/info/awk.info man-util-info info 8./usr/share/info/awk.info man-util-info info
9./usr/share/info/bfd.info man-computil-info binutils,info 9./usr/share/info/bfd.info man-computil-info binutils,info
10./usr/share/info/binutils.info man-computil-info binutils,info 10./usr/share/info/binutils.info man-computil-info binutils,info
11./usr/share/info/bzip2.info man-obsolete obsolete 11./usr/share/info/bzip2.info man-obsolete obsolete
12./usr/share/info/cpp.info man-util-info gcccmds,info 12./usr/share/info/cpp.info man-util-info gcccmds,info
13./usr/share/info/cvs.info man-cvs-info cvs,info 13./usr/share/info/cvs.info man-cvs-info cvs,info
14./usr/share/info/cvsclient.info man-cvs-info cvs,info 14./usr/share/info/cvsclient.info man-cvs-info cvs,info
@@ -1445,26 +1445,27 @@ @@ -1445,26 +1445,27 @@
1445./usr/share/man/cat4/module.0 man-obsolete obsolete 1445./usr/share/man/cat4/module.0 man-obsolete obsolete
1446./usr/share/man/cat4/mpii.0 man-sys-catman .cat 1446./usr/share/man/cat4/mpii.0 man-sys-catman .cat
1447./usr/share/man/cat4/mpl115a.0 man-sys-catman .cat 1447./usr/share/man/cat4/mpl115a.0 man-sys-catman .cat
1448./usr/share/man/cat4/mpls.0 man-sys-catman .cat 1448./usr/share/man/cat4/mpls.0 man-sys-catman .cat
1449./usr/share/man/cat4/mpt.0 man-sys-catman .cat 1449./usr/share/man/cat4/mpt.0 man-sys-catman .cat
1450./usr/share/man/cat4/mpu.0 man-sys-catman .cat 1450./usr/share/man/cat4/mpu.0 man-sys-catman .cat
1451./usr/share/man/cat4/mr.0 man-obsolete obsolete 1451./usr/share/man/cat4/mr.0 man-obsolete obsolete
1452./usr/share/man/cat4/msk.0 man-sys-catman .cat 1452./usr/share/man/cat4/msk.0 man-sys-catman .cat
1453./usr/share/man/cat4/mskc.0 man-sys-catman .cat 1453./usr/share/man/cat4/mskc.0 man-sys-catman .cat
1454./usr/share/man/cat4/msm6242b.0 man-sys-catman .cat 1454./usr/share/man/cat4/msm6242b.0 man-sys-catman .cat
1455./usr/share/man/cat4/mt2131.0 man-sys-catman .cat 1455./usr/share/man/cat4/mt2131.0 man-sys-catman .cat
1456./usr/share/man/cat4/mtd.0 man-sys-catman .cat 1456./usr/share/man/cat4/mtd.0 man-sys-catman .cat
1457./usr/share/man/cat4/mtio.0 man-sys-catman .cat 1457./usr/share/man/cat4/mtio.0 man-sys-catman .cat
 1458./usr/share/man/cat4/mue.0 man-sys-catman .cat
1458./usr/share/man/cat4/multicast.0 man-sys-catman .cat 1459./usr/share/man/cat4/multicast.0 man-sys-catman .cat
1459./usr/share/man/cat4/music.0 man-sys-catman .cat 1460./usr/share/man/cat4/music.0 man-sys-catman .cat
1460./usr/share/man/cat4/mvme68k/autoconf.0 man-sys-catman .cat 1461./usr/share/man/cat4/mvme68k/autoconf.0 man-sys-catman .cat
1461./usr/share/man/cat4/mvme68k/clmpcc.0 man-sys-catman .cat 1462./usr/share/man/cat4/mvme68k/clmpcc.0 man-sys-catman .cat
1462./usr/share/man/cat4/mvme68k/clock.0 man-sys-catman .cat 1463./usr/share/man/cat4/mvme68k/clock.0 man-sys-catman .cat
1463./usr/share/man/cat4/mvme68k/ie.0 man-sys-catman .cat 1464./usr/share/man/cat4/mvme68k/ie.0 man-sys-catman .cat
1464./usr/share/man/cat4/mvme68k/intro.0 man-sys-catman .cat 1465./usr/share/man/cat4/mvme68k/intro.0 man-sys-catman .cat
1465./usr/share/man/cat4/mvme68k/kmem.0 man-sys-catman .cat 1466./usr/share/man/cat4/mvme68k/kmem.0 man-sys-catman .cat
1466./usr/share/man/cat4/mvme68k/le.0 man-obsolete obsolete 1467./usr/share/man/cat4/mvme68k/le.0 man-obsolete obsolete
1467./usr/share/man/cat4/mvme68k/lpa.0 man-sys-catman .cat 1468./usr/share/man/cat4/mvme68k/lpa.0 man-sys-catman .cat
1468./usr/share/man/cat4/mvme68k/lpt.0 man-sys-catman .cat 1469./usr/share/man/cat4/mvme68k/lpt.0 man-sys-catman .cat
1469./usr/share/man/cat4/mvme68k/mainbus.0 man-sys-catman .cat 1470./usr/share/man/cat4/mvme68k/mainbus.0 man-sys-catman .cat
1470./usr/share/man/cat4/mvme68k/mem.0 man-sys-catman .cat 1471./usr/share/man/cat4/mvme68k/mem.0 man-sys-catman .cat
@@ -4556,26 +4557,27 @@ @@ -4556,26 +4557,27 @@
4556./usr/share/man/html4/module.html man-obsolete obsolete 4557./usr/share/man/html4/module.html man-obsolete obsolete
4557./usr/share/man/html4/mpii.html man-sys-htmlman html 4558./usr/share/man/html4/mpii.html man-sys-htmlman html
4558./usr/share/man/html4/mpl115a.html man-sys-htmlman html 4559./usr/share/man/html4/mpl115a.html man-sys-htmlman html
4559./usr/share/man/html4/mpls.html man-sys-htmlman html 4560./usr/share/man/html4/mpls.html man-sys-htmlman html
4560./usr/share/man/html4/mpt.html man-sys-htmlman html 4561./usr/share/man/html4/mpt.html man-sys-htmlman html
4561./usr/share/man/html4/mpu.html man-sys-htmlman html 4562./usr/share/man/html4/mpu.html man-sys-htmlman html
4562./usr/share/man/html4/mr.html man-obsolete obsolete 4563./usr/share/man/html4/mr.html man-obsolete obsolete
4563./usr/share/man/html4/msk.html man-sys-htmlman html 4564./usr/share/man/html4/msk.html man-sys-htmlman html
4564./usr/share/man/html4/mskc.html man-sys-htmlman html 4565./usr/share/man/html4/mskc.html man-sys-htmlman html
4565./usr/share/man/html4/msm6242b.html man-sys-htmlman html 4566./usr/share/man/html4/msm6242b.html man-sys-htmlman html
4566./usr/share/man/html4/mt2131.html man-sys-htmlman html 4567./usr/share/man/html4/mt2131.html man-sys-htmlman html
4567./usr/share/man/html4/mtd.html man-sys-htmlman html 4568./usr/share/man/html4/mtd.html man-sys-htmlman html
4568./usr/share/man/html4/mtio.html man-sys-htmlman html 4569./usr/share/man/html4/mtio.html man-sys-htmlman html
 4570./usr/share/man/html4/mue.html man-sys-htmlman html
4569./usr/share/man/html4/multicast.html man-sys-htmlman html 4571./usr/share/man/html4/multicast.html man-sys-htmlman html
4570./usr/share/man/html4/music.html man-sys-htmlman html 4572./usr/share/man/html4/music.html man-sys-htmlman html
4571./usr/share/man/html4/mvme68k/autoconf.html man-sys-htmlman html 4573./usr/share/man/html4/mvme68k/autoconf.html man-sys-htmlman html
4572./usr/share/man/html4/mvme68k/clmpcc.html man-sys-htmlman html 4574./usr/share/man/html4/mvme68k/clmpcc.html man-sys-htmlman html
4573./usr/share/man/html4/mvme68k/clock.html man-sys-htmlman html 4575./usr/share/man/html4/mvme68k/clock.html man-sys-htmlman html
4574./usr/share/man/html4/mvme68k/ie.html man-sys-htmlman html 4576./usr/share/man/html4/mvme68k/ie.html man-sys-htmlman html
4575./usr/share/man/html4/mvme68k/intro.html man-sys-htmlman html 4577./usr/share/man/html4/mvme68k/intro.html man-sys-htmlman html
4576./usr/share/man/html4/mvme68k/kmem.html man-sys-htmlman html 4578./usr/share/man/html4/mvme68k/kmem.html man-sys-htmlman html
4577./usr/share/man/html4/mvme68k/lpa.html man-sys-htmlman html 4579./usr/share/man/html4/mvme68k/lpa.html man-sys-htmlman html
4578./usr/share/man/html4/mvme68k/lpt.html man-sys-htmlman html 4580./usr/share/man/html4/mvme68k/lpt.html man-sys-htmlman html
4579./usr/share/man/html4/mvme68k/mainbus.html man-sys-htmlman html 4581./usr/share/man/html4/mvme68k/mainbus.html man-sys-htmlman html
4580./usr/share/man/html4/mvme68k/mem.html man-sys-htmlman html 4582./usr/share/man/html4/mvme68k/mem.html man-sys-htmlman html
4581./usr/share/man/html4/mvme68k/memc.html man-sys-htmlman html 4583./usr/share/man/html4/mvme68k/memc.html man-sys-htmlman html
@@ -7517,26 +7519,27 @@ @@ -7517,26 +7519,27 @@
7517./usr/share/man/man4/module.4 man-obsolete obsolete 7519./usr/share/man/man4/module.4 man-obsolete obsolete
7518./usr/share/man/man4/mpii.4 man-sys-man .man 7520./usr/share/man/man4/mpii.4 man-sys-man .man
7519./usr/share/man/man4/mpl115a.4 man-sys-man .man 7521./usr/share/man/man4/mpl115a.4 man-sys-man .man
7520./usr/share/man/man4/mpls.4 man-sys-man .man 7522./usr/share/man/man4/mpls.4 man-sys-man .man
7521./usr/share/man/man4/mpt.4 man-sys-man .man 7523./usr/share/man/man4/mpt.4 man-sys-man .man
7522./usr/share/man/man4/mpu.4 man-sys-man .man 7524./usr/share/man/man4/mpu.4 man-sys-man .man
7523./usr/share/man/man4/mr.4 man-obsolete obsolete 7525./usr/share/man/man4/mr.4 man-obsolete obsolete
7524./usr/share/man/man4/msk.4 man-sys-man .man 7526./usr/share/man/man4/msk.4 man-sys-man .man
7525./usr/share/man/man4/mskc.4 man-sys-man .man 7527./usr/share/man/man4/mskc.4 man-sys-man .man
7526./usr/share/man/man4/msm6242b.4 man-sys-man .man 7528./usr/share/man/man4/msm6242b.4 man-sys-man .man
7527./usr/share/man/man4/mt2131.4 man-sys-man .man 7529./usr/share/man/man4/mt2131.4 man-sys-man .man
7528./usr/share/man/man4/mtd.4 man-sys-man .man 7530./usr/share/man/man4/mtd.4 man-sys-man .man
7529./usr/share/man/man4/mtio.4 man-sys-man .man 7531./usr/share/man/man4/mtio.4 man-sys-man .man
 7532./usr/share/man/man4/mue.4 man-sys-man .man
7530./usr/share/man/man4/multicast.4 man-sys-man .man 7533./usr/share/man/man4/multicast.4 man-sys-man .man
7531./usr/share/man/man4/music.4 man-sys-man .man 7534./usr/share/man/man4/music.4 man-sys-man .man
7532./usr/share/man/man4/mvme68k/autoconf.4 man-sys-man .man 7535./usr/share/man/man4/mvme68k/autoconf.4 man-sys-man .man
7533./usr/share/man/man4/mvme68k/clmpcc.4 man-sys-man .man 7536./usr/share/man/man4/mvme68k/clmpcc.4 man-sys-man .man
7534./usr/share/man/man4/mvme68k/clock.4 man-sys-man .man 7537./usr/share/man/man4/mvme68k/clock.4 man-sys-man .man
7535./usr/share/man/man4/mvme68k/ie.4 man-sys-man .man 7538./usr/share/man/man4/mvme68k/ie.4 man-sys-man .man
7536./usr/share/man/man4/mvme68k/intro.4 man-sys-man .man 7539./usr/share/man/man4/mvme68k/intro.4 man-sys-man .man
7537./usr/share/man/man4/mvme68k/kmem.4 man-sys-man .man 7540./usr/share/man/man4/mvme68k/kmem.4 man-sys-man .man
7538./usr/share/man/man4/mvme68k/le.4 man-obsolete obsolete 7541./usr/share/man/man4/mvme68k/le.4 man-obsolete obsolete
7539./usr/share/man/man4/mvme68k/lpa.4 man-sys-man .man 7542./usr/share/man/man4/mvme68k/lpa.4 man-sys-man .man
7540./usr/share/man/man4/mvme68k/lpt.4 man-sys-man .man 7543./usr/share/man/man4/mvme68k/lpt.4 man-sys-man .man
7541./usr/share/man/man4/mvme68k/mainbus.4 man-sys-man .man 7544./usr/share/man/man4/mvme68k/mainbus.4 man-sys-man .man
7542./usr/share/man/man4/mvme68k/mem.4 man-sys-man .man 7545./usr/share/man/man4/mvme68k/mem.4 man-sys-man .man

cvs diff -r1.116 -r1.117 src/distrib/sets/lists/modules/mi (expand / switch to unified diff)

--- src/distrib/sets/lists/modules/mi 2018/05/20 14:08:33 1.116
+++ src/distrib/sets/lists/modules/mi 2018/08/25 20:12:21 1.117
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: mi,v 1.116 2018/05/20 14:08:33 thorpej Exp $ 1# $NetBSD: mi,v 1.117 2018/08/25 20:12:21 rin Exp $
2# 2#
3# Note: don't delete entries from here - mark them as "obsolete" instead. 3# Note: don't delete entries from here - mark them as "obsolete" instead.
4# 4#
5# IMPORTANT: When you add a module here, you have to add it twice to 5# IMPORTANT: When you add a module here, you have to add it twice to
6# md.evbppc as well. evbppc does not use mi, because 6# md.evbppc as well. evbppc does not use mi, because
7# powerpc-4xx and powerpc-booke modules are incompatible. 7# powerpc-4xx and powerpc-booke modules are incompatible.
8# Additionally, you may have to add it once more in md.amd64 8# Additionally, you may have to add it once more in md.amd64
9# (for xen) and twice more for i386 (xen and xen-pae). 9# (for xen) and twice more for i386 (xen and xen-pae).
10# Sorry for any inconvenience this may cause, the management. 10# Sorry for any inconvenience this may cause, the management.
11# 11#
12./@MODULEDIR@ base-kernel-modules kmod 12./@MODULEDIR@ base-kernel-modules kmod
13./@MODULEDIR@/aac base-obsolete obsolete 13./@MODULEDIR@/aac base-obsolete obsolete
14./@MODULEDIR@/aac/aac.kmod base-obsolete obsolete 14./@MODULEDIR@/aac/aac.kmod base-obsolete obsolete
@@ -156,26 +156,28 @@ @@ -156,26 +156,28 @@
156./@MODULEDIR@/if_axen/if_axen.kmod base-kernel-modules kmod 156./@MODULEDIR@/if_axen/if_axen.kmod base-kernel-modules kmod
157./@MODULEDIR@/if_faith base-kernel-modules kmod 157./@MODULEDIR@/if_faith base-kernel-modules kmod
158./@MODULEDIR@/if_faith/if_faith.kmod base-kernel-modules kmod 158./@MODULEDIR@/if_faith/if_faith.kmod base-kernel-modules kmod
159./@MODULEDIR@/if_gif base-kernel-modules kmod 159./@MODULEDIR@/if_gif base-kernel-modules kmod
160./@MODULEDIR@/if_gif/if_gif.kmod base-kernel-modules kmod 160./@MODULEDIR@/if_gif/if_gif.kmod base-kernel-modules kmod
161./@MODULEDIR@/if_gre base-kernel-modules kmod 161./@MODULEDIR@/if_gre base-kernel-modules kmod
162./@MODULEDIR@/if_gre/if_gre.kmod base-kernel-modules kmod 162./@MODULEDIR@/if_gre/if_gre.kmod base-kernel-modules kmod
163./@MODULEDIR@/if_l2tp base-kernel-modules kmod 163./@MODULEDIR@/if_l2tp base-kernel-modules kmod
164./@MODULEDIR@/if_l2tp/if_l2tp.kmod base-kernel-modules kmod 164./@MODULEDIR@/if_l2tp/if_l2tp.kmod base-kernel-modules kmod
165./@MODULEDIR@/if_loop base-kernel-modules kmod 165./@MODULEDIR@/if_loop base-kernel-modules kmod
166./@MODULEDIR@/if_loop/if_loop.kmod base-kernel-modules kmod 166./@MODULEDIR@/if_loop/if_loop.kmod base-kernel-modules kmod
167./@MODULEDIR@/if_mpls base-kernel-modules kmod 167./@MODULEDIR@/if_mpls base-kernel-modules kmod
168./@MODULEDIR@/if_mpls/if_mpls.kmod base-kernel-modules kmod 168./@MODULEDIR@/if_mpls/if_mpls.kmod base-kernel-modules kmod
 169./@MODULEDIR@/if_mue base-kernel-modules kmod
 170./@MODULEDIR@/if_mue/if_mue.kmod base-kernel-modules kmod
169./@MODULEDIR@/if_npflog base-kernel-modules kmod 171./@MODULEDIR@/if_npflog base-kernel-modules kmod
170./@MODULEDIR@/if_npflog/if_npflog.kmod base-kernel-modules kmod 172./@MODULEDIR@/if_npflog/if_npflog.kmod base-kernel-modules kmod
171./@MODULEDIR@/if_ppp base-kernel-modules kmod 173./@MODULEDIR@/if_ppp base-kernel-modules kmod
172./@MODULEDIR@/if_ppp/if_ppp.kmod base-kernel-modules kmod 174./@MODULEDIR@/if_ppp/if_ppp.kmod base-kernel-modules kmod
173./@MODULEDIR@/if_pppoe base-kernel-modules kmod 175./@MODULEDIR@/if_pppoe base-kernel-modules kmod
174./@MODULEDIR@/if_pppoe/if_pppoe.kmod base-kernel-modules kmod 176./@MODULEDIR@/if_pppoe/if_pppoe.kmod base-kernel-modules kmod
175./@MODULEDIR@/if_sl base-kernel-modules kmod 177./@MODULEDIR@/if_sl base-kernel-modules kmod
176./@MODULEDIR@/if_sl/if_sl.kmod base-kernel-modules kmod 178./@MODULEDIR@/if_sl/if_sl.kmod base-kernel-modules kmod
177./@MODULEDIR@/if_smsc base-kernel-modules kmod 179./@MODULEDIR@/if_smsc base-kernel-modules kmod
178./@MODULEDIR@/if_smsc/if_smsc.kmod base-kernel-modules kmod 180./@MODULEDIR@/if_smsc/if_smsc.kmod base-kernel-modules kmod
179./@MODULEDIR@/if_srt base-kernel-modules kmod 181./@MODULEDIR@/if_srt base-kernel-modules kmod
180./@MODULEDIR@/if_srt/if_srt.kmod base-kernel-modules kmod 182./@MODULEDIR@/if_srt/if_srt.kmod base-kernel-modules kmod
181./@MODULEDIR@/if_stf base-kernel-modules kmod 183./@MODULEDIR@/if_stf base-kernel-modules kmod

cvs diff -r1.664 -r1.665 src/share/man/man4/Makefile (expand / switch to unified diff)

--- src/share/man/man4/Makefile 2018/08/14 14:49:13 1.664
+++ src/share/man/man4/Makefile 2018/08/25 20:12:21 1.665
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: Makefile,v 1.664 2018/08/14 14:49:13 maxv Exp $ 1# $NetBSD: Makefile,v 1.665 2018/08/25 20:12:21 rin Exp $
2# @(#)Makefile 8.1 (Berkeley) 6/18/93 2# @(#)Makefile 8.1 (Berkeley) 6/18/93
3 3
4MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \ 4MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \
5 adbbt.4 adbkbd.4 adbms.4 \ 5 adbbt.4 adbkbd.4 adbms.4 \
6 adc.4 adm1026hm.4 admtemp.4 adv.4 adw.4 age.4 agp.4 agr.4 ahb.4 ahc.4 \ 6 adc.4 adm1026hm.4 admtemp.4 adv.4 adw.4 age.4 agp.4 agr.4 ahb.4 ahc.4 \
7 ahcisata.4 ahd.4 aibs.4 alc.4 ale.4 alipm.4 altmem.4 altq.4 \ 7 ahcisata.4 ahd.4 aibs.4 alc.4 ale.4 alipm.4 altmem.4 altq.4 \
8 am2315temp.4 amdpm.4 amdtemp.4 amhphy.4 amr.4 aps.4 asus.4 \ 8 am2315temp.4 amdpm.4 amdtemp.4 amhphy.4 amr.4 aps.4 asus.4 \
9 an.4 arcmsr.4 arcofi.4 aria.4 artsata.4 ata.4 atalk.4 ataraid.4 \ 9 an.4 arcmsr.4 arcofi.4 aria.4 artsata.4 ata.4 atalk.4 ataraid.4 \
10 ath.4 athn.4 atphy.4 atppc.4 attimer.4 atw.4 \ 10 ath.4 athn.4 atphy.4 atppc.4 attimer.4 atw.4 \
11 auacer.4 audio.4 audiocs.4 auich.4 \ 11 auacer.4 audio.4 audiocs.4 auich.4 \
12 auixp.4 autri.4 auvia.4 awi.4 azalia.4 \ 12 auixp.4 autri.4 auvia.4 awi.4 azalia.4 \
13 battery_pmu.4 bba.4 bce.4 bcsp.4 be.4 bge.4 bnx.4 bha.4 \ 13 battery_pmu.4 bba.4 bce.4 bcsp.4 be.4 bge.4 bnx.4 bha.4 \
14 bio.4 bktr.4 bluetooth.4 bmtphy.4 bpf.4 bpfjit.4 \ 14 bio.4 bktr.4 bluetooth.4 bmtphy.4 bpf.4 bpfjit.4 \
@@ -65,27 +65,28 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 a @@ -65,27 +65,28 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 a
65 thinkpad.4 ti.4 tl.4 tlp.4 tlphy.4 tpm.4 tprof.4 tr.4 tra.4 \ 65 thinkpad.4 ti.4 tl.4 tlp.4 tlphy.4 tpm.4 tprof.4 tr.4 tra.4 \
66 trm.4 tsllux.4 tty.4 tun.4 tqphy.4 twa.4 twe.4 txp.4 \ 66 trm.4 tsllux.4 tty.4 tun.4 tqphy.4 twa.4 twe.4 txp.4 \
67 uark.4 ubsec.4 udp.4 uep.4 ug.4 uha.4 uk.4 ukphy.4 umb.4 unix.4 userconf.4 \ 67 uark.4 ubsec.4 udp.4 uep.4 ug.4 uha.4 uk.4 ukphy.4 umb.4 unix.4 userconf.4 \
68 vald.4 valz.4 veriexec.4 vga.4 vge.4 viaide.4 video.4 vioif.4 viomb.4 \ 68 vald.4 valz.4 veriexec.4 vga.4 vge.4 viaide.4 video.4 vioif.4 viomb.4 \
69 viornd.4 vioscsi.4 virt.4 \ 69 viornd.4 vioscsi.4 virt.4 \
70 virtio.4 vlan.4 vmmon.4 vmnet.4 vnd.4 voodoofb.4 vr.4 vte.4 \ 70 virtio.4 vlan.4 vmmon.4 vmnet.4 vnd.4 voodoofb.4 vr.4 vte.4 \
71 wapbl.4 wb.4 wbsio.4 wd.4 wdc.4 wi.4 wm.4 wpi.4 \ 71 wapbl.4 wb.4 wbsio.4 wd.4 wdc.4 wi.4 wm.4 wpi.4 \
72 wsbell.4 wscons.4 wsdisplay.4 wsfont.4 wskbd.4 wsmouse.4 wsmux.4 \ 72 wsbell.4 wscons.4 wsdisplay.4 wsfont.4 wskbd.4 wsmouse.4 wsmux.4 \
73 xbox.4 xge.4 \ 73 xbox.4 xge.4 \
74 yds.4 ym.4 \ 74 yds.4 ym.4 \
75 zero.4 zstty.4 zyd.4 75 zero.4 zstty.4 zyd.4
76 76
77# USB devices 77# USB devices
78MAN+= atu.4 aubtfwl.4 aue.4 axe.4 axen.4 cdce.4 cue.4 ehci.4 kue.4 ohci.4 \ 78MAN+= atu.4 aubtfwl.4 aue.4 axe.4 axen.4 cdce.4 cue.4 ehci.4 kue.4 mue.4 \
 79 ohci.4 \
79 slhci.4 stuirda.4 u3g.4 ualea.4 uatp.4 uaudio.4 uberry.4 ubsa.4 ubt.4 \ 80 slhci.4 stuirda.4 u3g.4 ualea.4 uatp.4 uaudio.4 uberry.4 ubsa.4 ubt.4 \
80 uchcom.4 \ 81 uchcom.4 \
81 ucom.4 ucycom.4 udav.4 udsbr.4 uftdi.4 ugen.4 ugensa.4 uhci.4 uhid.4 \ 82 ucom.4 ucycom.4 udav.4 udsbr.4 uftdi.4 ugen.4 ugensa.4 uhci.4 uhid.4 \
82 uhidev.4 uhmodem.4 uhso.4 uipad.4 uipaq.4 uirda.4 ukbd.4 ukyopon.4 \ 83 uhidev.4 uhmodem.4 uhso.4 uipad.4 uipaq.4 uirda.4 ukbd.4 ukyopon.4 \
83 ulpt.4 umass.4 umcs.4 umct.4 umidi.4 umodem.4 ums.4 upgt.4 upl.4 \ 84 ulpt.4 umass.4 umcs.4 umct.4 umidi.4 umodem.4 ums.4 upgt.4 upl.4 \
84 uplcom.4 urio.4 url.4 urndis.4 urtw.4 urtwn.4 \ 85 uplcom.4 urio.4 url.4 urndis.4 urtw.4 urtwn.4 \
85 usb.4 uscanner.4 uslsa.4 usmsc.4 usscanner.4 \ 86 usb.4 uscanner.4 uslsa.4 usmsc.4 usscanner.4 \
86 ustir.4 uthum.4 utoppy.4 uts.4 uvideo.4 uvisor.4 uvscom.4 uyap.4 \ 87 ustir.4 uthum.4 utoppy.4 uts.4 uvideo.4 uvisor.4 uvscom.4 uyap.4 \
87 uyurex.4 \ 88 uyurex.4 \
88 xhci.4 \ 89 xhci.4 \
89 90
90# Ir devices 91# Ir devices
91MAN+= irframe.4 cir.4 irframetty.4 oboe.4 92MAN+= irframe.4 cir.4 irframetty.4 oboe.4

File Added: src/share/man/man4/mue.4
.\"     $NetBSD: mue.4,v 1.1 2018/08/25 20:12:21 rin Exp $
.\"     $OpenBSD: mue.4,v 1.2 2018/08/03 06:13:14 jmc Exp $
.\"
.\" Copyright (c) 2018 Kevin Lo <kevlo@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: August 25 2018 $
.Dt MUE 4
.Os
.Sh NAME
.Nm mue
.Nd Microchip LAN75xx/LAN78xx 10/100/Gigabit USB Ethernet device
.Sh SYNOPSIS
.Cd "mue*   at uhub?"
.Cd "ukphy* at mii?"
.Sh DESCRIPTION
The
.Nm
driver supports Microchip LAN7500/LAN7505/LAN7515/LAN7850 USB 2.0 Gigabit
Ethernet devices and LAN7800/LAN7801 USB 3.0 Gigabit Ethernet devices,
including the following:
.Pp
.Bl -tag -width Ds -offset indent -compact
.It Raspberry Pi 3 Model B+
.It Microchip EVB-LAN7800LC
.It Z-TEK ZE582
.El
.Pp
For more information on configuring this device, see
.Xr ifconfig 8 .
.Sh SEE ALSO
.Xr arp 4 ,
.Xr ifmedia 4 ,
.Xr intro 4 ,
.Xr netintro 4 ,
.Xr ukphy 4 ,
.Xr usb 4 ,
.\".Xr hostname.if 5 ,
.Xr ifconfig 8
.Sh HISTORY
The
.Nm
device driver first appeared in
.Ox 6.3 and
.Nx 9.0 .
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Kevin Lo Aq Mt kevlo@openbsd.org
for
.Ox and ported to
.Nx by
.An Rin Okuyama Aq Mt rin@netbsd.org .
.Sh BUGS
If the media type is set to other than 1000BASE-T full-duplex,
data transmission becomes quite unstable.
Also, ukphy mistakenly recognizes 1000BASE-T half-duplex as a supported media
type, although the adapters do not support it.

cvs diff -r1.151 -r1.152 src/sys/dev/usb/files.usb (expand / switch to unified diff)

--- src/sys/dev/usb/files.usb 2018/07/31 16:44:29 1.151
+++ src/sys/dev/usb/files.usb 2018/08/25 20:12:22 1.152
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: files.usb,v 1.151 2018/07/31 16:44:29 khorben Exp $ 1# $NetBSD: files.usb,v 1.152 2018/08/25 20:12:22 rin Exp $
2# 2#
3# Config file and device description for machine-independent USB code. 3# Config file and device description for machine-independent USB code.
4# Included by ports that need it. Ports that use it must provide 4# Included by ports that need it. Ports that use it must provide
5# their own "major" declarations for the appropriate devices. 5# their own "major" declarations for the appropriate devices.
6 6
7defflag USBVERBOSE 7defflag USBVERBOSE
8defflag opt_usb.h USB_FRAG_DMA_WORKAROUND 8defflag opt_usb.h USB_FRAG_DMA_WORKAROUND
9 9
10# HC controllers 10# HC controllers
11defflag opt_usb.h EHCI_DEBUG: USB_DEBUG 11defflag opt_usb.h EHCI_DEBUG: USB_DEBUG
12defflag opt_usb.h OHCI_DEBUG: USB_DEBUG 12defflag opt_usb.h OHCI_DEBUG: USB_DEBUG
13defflag opt_usb.h UHCI_DEBUG: USB_DEBUG 13defflag opt_usb.h UHCI_DEBUG: USB_DEBUG
14defflag opt_usb.h DWC2_DEBUG: USB_DEBUG 14defflag opt_usb.h DWC2_DEBUG: USB_DEBUG
@@ -359,26 +359,31 @@ device url: arp, ether, ifnet, mii @@ -359,26 +359,31 @@ device url: arp, ether, ifnet, mii
359attach url at usbdevif 359attach url at usbdevif
360file dev/usb/if_url.c url 360file dev/usb/if_url.c url
361 361
362# ASIX AX88172 362# ASIX AX88172
363device axe: arp, ether, ifnet, mii, mii_phy 363device axe: arp, ether, ifnet, mii, mii_phy
364attach axe at usbdevif 364attach axe at usbdevif
365file dev/usb/if_axe.c axe 365file dev/usb/if_axe.c axe
366 366
367# ASIX AX88178a and AX88179 367# ASIX AX88178a and AX88179
368device axen: arp, ether, ifnet, mii 368device axen: arp, ether, ifnet, mii
369attach axen at usbdevif 369attach axen at usbdevif
370file dev/usb/if_axen.c axen 370file dev/usb/if_axen.c axen
371 371
 372# Microchip LAN750x and LAN85xx
 373device mue: arp, ether, ifnet, mii, mii_phy
 374attach mue at usbdevif
 375file dev/usb/if_mue.c mue
 376
372# DAVICOM DM9601 377# DAVICOM DM9601
373device udav: arp, ether, ifnet, mii, mii_phy 378device udav: arp, ether, ifnet, mii, mii_phy
374attach udav at usbdevif 379attach udav at usbdevif
375file dev/usb/if_udav.c udav 380file dev/usb/if_udav.c udav
376 381
377# Atheros AR9170 382# Atheros AR9170
378device otus: arp, ether, firmload, ifnet, wlan 383device otus: arp, ether, firmload, ifnet, wlan
379attach otus at usbdevif 384attach otus at usbdevif
380file dev/usb/if_otus.c otus 385file dev/usb/if_otus.c otus
381 386
382# Mobile Broadband Interface Model 387# Mobile Broadband Interface Model
383device umb: ifnet 388device umb: ifnet
384attach umb at usbifif 389attach umb at usbifif

File Added: src/sys/dev/usb/if_mue.c
/*	$NetBSD: if_mue.c,v 1.1 2018/08/25 20:12:22 rin Exp $	*/
/*	$OpenBSD: if_mue.c,v 1.3 2018/08/04 16:42:46 jsg Exp $	*/

/*
 * Copyright (c) 2018 Kevin Lo <kevlo@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* Driver for Microchip LAN7500/LAN7800 chipsets. */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_mue.c,v 1.1 2018/08/25 20:12:22 rin Exp $");

#ifdef _KERNEL_OPT
#include "opt_usb.h"
#include "opt_inet.h"
#endif

#include <sys/param.h>
#include <sys/cprng.h>
#include <sys/bus.h>
#include <sys/systm.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/socket.h>

#include <sys/device.h>

#include <sys/rndsource.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_ether.h>

#include <net/bpf.h>

#include <netinet/in.h>
#include <netinet/if_inarp.h>

#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>

#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdevs.h>

#include <dev/usb/if_muereg.h>
#include <dev/usb/if_muevar.h>

#define MUE_PRINTF(sc, fmt, args...)					\
	device_printf((sc)->mue_dev, "%s: " fmt, __func__, ##args);

#ifdef USB_DEBUG
int muedebug = 0;
#define DPRINTF(sc, fmt, args...) 					\
	do { 								\
		if (muedebug)						\
			MUE_PRINTF(sc, fmt, ##args);			\
	} while (0 /* CONSTCOND */)
#else
#define DPRINTF(sc, fmt, args...)	/* nothing */
#endif

/*
 * Various supported device vendors/products.
 */
struct mue_type {
	struct usb_devno	mue_dev;
	uint16_t		mue_flags;
#define LAN7500		0x0001	/* LAN7500 */
};

const struct mue_type mue_devs[] = {
	{ { USB_VENDOR_SMSC, USB_PRODUCT_SMSC_LAN7500 }, LAN7500 },
	{ { USB_VENDOR_SMSC, USB_PRODUCT_SMSC_LAN7505 }, LAN7500 },
	{ { USB_VENDOR_SMSC, USB_PRODUCT_SMSC_LAN7800 }, 0 },
	{ { USB_VENDOR_SMSC, USB_PRODUCT_SMSC_LAN7801 }, 0 },
	{ { USB_VENDOR_SMSC, USB_PRODUCT_SMSC_LAN7850 }, 0 }
};

#define MUE_LOOKUP(uaa)	((const struct mue_type *)usb_lookup(mue_devs, \
    uaa->uaa_vendor, uaa->uaa_product))

#define MUE_ENADDR_LO(enaddr) \
    ((enaddr[3] << 24) | (enaddr[2] << 16) | (enaddr[1] << 8) | enaddr[0])
#define MUE_ENADDR_HI(enaddr) \
    ((enaddr[5] << 8) | enaddr[4])

static int	mue_match(device_t, cfdata_t, void *);
static void	mue_attach(device_t, device_t, void *);
static int	mue_detach(device_t, int);
static int	mue_activate(device_t, enum devact);

static uint32_t	mue_csr_read(struct mue_softc *, uint32_t);
static int	mue_csr_write(struct mue_softc *, uint32_t, uint32_t);
static int	mue_wait_for_bits(struct mue_softc *sc, uint32_t, uint32_t,
		    uint32_t, uint32_t);

static void	mue_lock_mii(struct mue_softc *);
static void	mue_unlock_mii(struct mue_softc *);

static int	mue_miibus_readreg(device_t, int, int);
static void	mue_miibus_writereg(device_t, int, int, int);
static void	mue_miibus_statchg(struct ifnet *);
static int	mue_ifmedia_upd(struct ifnet *);
static void	mue_ifmedia_sts(struct ifnet *, struct ifmediareq *);

static uint8_t	mue_eeprom_getbyte(struct mue_softc *, int, uint8_t *);
static int	mue_read_eeprom(struct mue_softc *, uint8_t *, int, int);
static bool	mue_eeprom_present(struct mue_softc *sc);

static int	mue_read_otp_raw(struct mue_softc *, uint8_t *, int, int);
static int	mue_read_otp(struct mue_softc *, uint8_t *, int, int);

static void	mue_dataport_write(struct mue_softc *, uint32_t, uint32_t,
		    uint32_t, uint32_t *);

static void	mue_init_ltm(struct mue_softc *);

static int	mue_chip_init(struct mue_softc *);

static void	mue_set_macaddr(struct mue_softc *);
static int	mue_get_macaddr(struct mue_softc *, prop_dictionary_t);

static int	mue_rx_list_init(struct mue_softc *);
static int	mue_tx_list_init(struct mue_softc *);
static int	mue_open_pipes(struct mue_softc *);
static void	mue_start_rx(struct mue_softc *);

static int	mue_encap(struct mue_softc *, struct mbuf *, int);

static void	mue_setmulti(struct mue_softc *);
static void	mue_sethwcsum(struct mue_softc *);

static void	mue_rxeof(struct usbd_xfer *, void *, usbd_status);
static void	mue_txeof(struct usbd_xfer *, void *, usbd_status);

static int	mue_init(struct ifnet *);
static int	mue_ioctl(struct ifnet *, u_long, void *);
static void	mue_watchdog(struct ifnet *);
static void	mue_reset(struct mue_softc *);
static void	mue_start(struct ifnet *);
static void	mue_stop(struct ifnet *, int);
static void	mue_tick(void *);
static void	mue_tick_task(void *);

static struct mbuf *mue_newbuf(void);

#define MUE_SETBIT(sc, reg, x)	\
	mue_csr_write(sc, reg, mue_csr_read(sc, reg) | (x))

#define MUE_CLRBIT(sc, reg, x)	\
	mue_csr_write(sc, reg, mue_csr_read(sc, reg) & ~(x))

#define MUE_WAIT_SET(sc, reg, set, fail)	\
	mue_wait_for_bits(sc, reg, set, ~0, fail)

#define MUE_WAIT_CLR(sc, reg, clear, fail)	\
	mue_wait_for_bits(sc, reg, 0, clear, fail)

#define ETHER_IS_VALID(addr) \
	(!ETHER_IS_MULTICAST(addr) && !ETHER_IS_ZERO(addr))

#define ETHER_IS_ZERO(addr) \
	(!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]))

#define ETHER_ALIGN 2

CFATTACH_DECL_NEW(mue, sizeof(struct mue_softc), mue_match, mue_attach,
    mue_detach, mue_activate);

static uint32_t
mue_csr_read(struct mue_softc *sc, uint32_t reg)
{
	usb_device_request_t req;
	usbd_status err;
	uDWord val;

	if (sc->mue_dying)
		return 0;

	USETDW(val, 0);
	req.bmRequestType = UT_READ_VENDOR_DEVICE;
	req.bRequest = MUE_UR_READREG;
	USETW(req.wValue, 0);
	USETW(req.wIndex, reg);
	USETW(req.wLength, 4);

	err = usbd_do_request(sc->mue_udev, &req, &val);
	if (err) {
		MUE_PRINTF(sc, "reg = 0x%x: %s\n", reg, usbd_errstr(err));
		return 0;
	}

	return UGETDW(val);
}

static int
mue_csr_write(struct mue_softc *sc, uint32_t reg, uint32_t aval)
{
	usb_device_request_t req;
	usbd_status err;
	uDWord val;

	if (sc->mue_dying)
		return 0;

	USETDW(val, aval);
	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = MUE_UR_WRITEREG;
	USETW(req.wValue, 0);
	USETW(req.wIndex, reg);
	USETW(req.wLength, 4);

	err = usbd_do_request(sc->mue_udev, &req, &val);
	if (err) {
		MUE_PRINTF(sc, "reg = 0x%x: %s\n", reg, usbd_errstr(err));
		return -1;
	}

	return 0;
}

static int
mue_wait_for_bits(struct mue_softc *sc, uint32_t reg,
    uint32_t set, uint32_t clear, uint32_t fail)
{
	uint32_t val;
	int ntries;

	for (ntries = 0; ntries < 1000; ntries++) {
		val = mue_csr_read(sc, reg);
		if ((val & set) || !(val & clear))
			return 0;
		if (val & fail)
			return 1;
		usbd_delay_ms(sc->mue_udev, 1);
	}

	return 1;
}

/* 
 * Get exclusive access to the MII registers.
 */
static void
mue_lock_mii(struct mue_softc *sc)
{
	sc->mue_refcnt++;
	mutex_enter(&sc->mue_mii_lock);
}

static void
mue_unlock_mii(struct mue_softc *sc)
{
	mutex_exit(&sc->mue_mii_lock);
	if (--sc->mue_refcnt < 0)
		usb_detach_wakeupold(sc->mue_dev);
}

static int
mue_miibus_readreg(device_t dev, int phy, int reg)
{
	struct mue_softc *sc = device_private(dev);
	uint32_t val;

	if (sc->mue_dying) {
		DPRINTF(sc, "dying\n");
		return 0;
	}

	if (sc->mue_phyno != phy)
		return 0;

	mue_lock_mii(sc);
	if (MUE_WAIT_CLR(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_BUSY, 0)) {
		mue_unlock_mii(sc);
		MUE_PRINTF(sc, "not ready\n");
		return -1;
	}

	mue_csr_write(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_READ |
	    MUE_MII_ACCESS_BUSY | MUE_MII_ACCESS_REGADDR(reg) |
	    MUE_MII_ACCESS_PHYADDR(phy));

	if (MUE_WAIT_CLR(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_BUSY, 0)) {
		mue_unlock_mii(sc);
		MUE_PRINTF(sc, "timed out\n");
		return -1;
	}

	val = mue_csr_read(sc, MUE_MII_DATA);
	mue_unlock_mii(sc);
	return val & 0xffff;
}

static void
mue_miibus_writereg(device_t dev, int phy, int reg, int data)
{
	struct mue_softc *sc = device_private(dev);

	if (sc->mue_dying) {
		DPRINTF(sc, "dying\n");
		return;
	}

	if (sc->mue_phyno != phy) {
		DPRINTF(sc, "sc->mue_phyno (%d) != phy (%d)\n",
		    sc->mue_phyno, phy);
		return;
	}

	mue_lock_mii(sc);
	if (MUE_WAIT_CLR(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_BUSY, 0)) {
		mue_unlock_mii(sc);
		MUE_PRINTF(sc, "not ready\n");
		return;
	}

	mue_csr_write(sc, MUE_MII_DATA, data);
	mue_csr_write(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_WRITE |
	    MUE_MII_ACCESS_BUSY | MUE_MII_ACCESS_REGADDR(reg) |
	    MUE_MII_ACCESS_PHYADDR(phy));

	if (MUE_WAIT_CLR(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_BUSY, 0))
		MUE_PRINTF(sc, "timed out\n");

	mue_unlock_mii(sc);
}

static void
mue_miibus_statchg(struct ifnet *ifp)
{
	struct mue_softc *sc = ifp->if_softc;
	struct mii_data *mii = GET_MII(sc);
	uint32_t flow, threshold;

	if (mii == NULL || ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
		DPRINTF(sc, "not ready\n");
		return;
	}

	sc->mue_link = 0;
	if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
	    (IFM_ACTIVE | IFM_AVALID)) {
		switch (IFM_SUBTYPE(mii->mii_media_active)) {
		case IFM_10_T:
		case IFM_100_TX:
		case IFM_1000_T:
			sc->mue_link++;
			break;
		default:
			break;
		}
	}

	/* Lost link, do nothing. */
	if (sc->mue_link == 0) {
		DPRINTF(sc, "mii_media_status = 0x%x\n", mii->mii_media_status);
		return;
	}

	if (!(sc->mue_flags & LAN7500)) {
		if (sc->mue_udev->ud_speed == USB_SPEED_SUPER) {
			if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
				/* Disable U2 and enable U1. */
				MUE_CLRBIT(sc, MUE_USB_CFG1,
				    MUE_USB_CFG1_DEV_U2_INIT_EN);
				MUE_SETBIT(sc, MUE_USB_CFG1,
				    MUE_USB_CFG1_DEV_U1_INIT_EN);
			} else {
				/* Enable U1 and U2. */
				MUE_SETBIT(sc, MUE_USB_CFG1,
				    MUE_USB_CFG1_DEV_U1_INIT_EN |
				    MUE_USB_CFG1_DEV_U2_INIT_EN);
			}
		}
	}

	flow = 0;
	/* XXX Linux does not check IFM_FDX flag for 7800. */
	if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) {
		if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE)
			flow |= MUE_FLOW_TX_FCEN | MUE_FLOW_PAUSE_TIME;
		if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE)
			flow |= MUE_FLOW_RX_FCEN;
	}

	/* XXX Magic numbers taken from Linux driver. */
	if (sc->mue_flags & LAN7500)
		threshold = 0x820;
	else
		switch (sc->mue_udev->ud_speed) {
		case USB_SPEED_SUPER:
			threshold = 0x817;
			break;
		case USB_SPEED_HIGH:
			threshold = 0x211;
			break;
		default:
			threshold = 0;
			break;
		}

	/* Threshold value should be set before enabling flow. */
	mue_csr_write(sc, (sc->mue_flags & LAN7500) ?
	    MUE_7500_FCT_FLOW : MUE_7800_FCT_FLOW, threshold);
	mue_csr_write(sc, MUE_FLOW, flow);

	DPRINTF(sc, "done\n");
}

/*
 * Set media options.
 */
static int
mue_ifmedia_upd(struct ifnet *ifp)
{
	struct mue_softc *sc = ifp->if_softc;
	struct mii_data *mii = GET_MII(sc);

	sc->mue_link = 0; /* XXX */

	if (mii->mii_instance) {
		struct mii_softc *miisc;
		LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
			mii_phy_reset(miisc);
	}
	return mii_mediachg(mii);
}

/*
 * Report current media status.
 */
static void
mue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
	struct mue_softc *sc = ifp->if_softc;
	struct mii_data *mii = GET_MII(sc);

	mii_pollstat(mii);
	ifmr->ifm_active = mii->mii_media_active;
	ifmr->ifm_status = mii->mii_media_status;
}

static uint8_t
mue_eeprom_getbyte(struct mue_softc *sc, int off, uint8_t *dest)
{
	uint32_t val;

	if (MUE_WAIT_CLR(sc, MUE_E2P_CMD, MUE_E2P_CMD_BUSY, 0)) {
		MUE_PRINTF(sc, "not ready\n");
		return ETIMEDOUT;
	}

	mue_csr_write(sc, MUE_E2P_CMD, MUE_E2P_CMD_READ | MUE_E2P_CMD_BUSY |
	    (off & MUE_E2P_CMD_ADDR_MASK));

	if (MUE_WAIT_CLR(sc, MUE_E2P_CMD, MUE_E2P_CMD_BUSY,
	    MUE_E2P_CMD_TIMEOUT)) {
		MUE_PRINTF(sc, "timed out\n");
		return ETIMEDOUT;
	}

	val = mue_csr_read(sc, MUE_E2P_DATA);
	*dest = val & 0xff;

	return 0;
}

static int
mue_read_eeprom(struct mue_softc *sc, uint8_t *dest, int off, int cnt)
{
	uint32_t val = 0; /* XXX gcc */
	uint8_t byte;
	int i, err;

	/* 
	 * EEPROM pins are muxed with the LED function on LAN7800 device.
	 */
	if (sc->mue_product == USB_PRODUCT_SMSC_LAN7800) {
		val = mue_csr_read(sc, MUE_HW_CFG);
		mue_csr_write(sc, MUE_HW_CFG,
		    val & ~(MUE_HW_CFG_LED0_EN | MUE_HW_CFG_LED1_EN));
	}

	for (i = 0; i < cnt; i++) {
		err = mue_eeprom_getbyte(sc, off + i, &byte);
		if (err)
			break;
		*(dest + i) = byte;
	}

	if (sc->mue_product == USB_PRODUCT_SMSC_LAN7800)
		mue_csr_write(sc, MUE_HW_CFG, val);

	return err ? 1 : 0;
}

static bool
mue_eeprom_present(struct mue_softc *sc)
{
	uint32_t val;
	uint8_t sig;
	int ret;

	if (sc->mue_flags & LAN7500) {
		val = mue_csr_read(sc, MUE_E2P_CMD);
		return val & MUE_E2P_CMD_LOADED;
	} else {
		ret = mue_read_eeprom(sc, &sig, MUE_E2P_IND_OFFSET, 1);
		return (ret == 0) && (sig == MUE_E2P_IND);
	}
}

static int
mue_read_otp_raw(struct mue_softc *sc, uint8_t *dest, int off, int cnt)
{
	uint32_t val;
	int i, err;

	val = mue_csr_read(sc, MUE_OTP_PWR_DN);

	/* Checking if bit is set. */
	if (val & MUE_OTP_PWR_DN_PWRDN_N) {
		/* Clear it, then wait for it to be cleared. */
		mue_csr_write(sc, MUE_OTP_PWR_DN, 0);
		err = MUE_WAIT_CLR(sc, MUE_OTP_PWR_DN, MUE_OTP_PWR_DN_PWRDN_N,
		    0);
		if (err) {
			MUE_PRINTF(sc, "not ready\n");
			return 1;
		}
	}

	/* Start reading the bytes, one at a time. */
	for (i = 0; i < cnt; i++) {
		mue_csr_write(sc, MUE_OTP_ADDR1,
		    ((off + i) >> 8) & MUE_OTP_ADDR1_MASK);
		mue_csr_write(sc, MUE_OTP_ADDR2,
		    ((off + i) & MUE_OTP_ADDR2_MASK));
		mue_csr_write(sc, MUE_OTP_FUNC_CMD, MUE_OTP_FUNC_CMD_READ);
		mue_csr_write(sc, MUE_OTP_CMD_GO, MUE_OTP_CMD_GO_GO);

		err = MUE_WAIT_CLR(sc, MUE_OTP_STATUS, MUE_OTP_STATUS_BUSY, 0);
		if (err) {
			MUE_PRINTF(sc, "timed out\n");
			return 1;
		}
		val = mue_csr_read(sc, MUE_OTP_RD_DATA);
		*(dest + i) = (uint8_t)(val & 0xff);
	}

	return 0;
}

static int
mue_read_otp(struct mue_softc *sc, uint8_t *dest, int off, int cnt)
{
	uint8_t sig;
	int err;

	if (sc->mue_flags & LAN7500)
		return 1;

	err = mue_read_otp_raw(sc, &sig, MUE_OTP_IND_OFFSET, 1);
	if (err)
		return 1;
	switch (sig) {
	case MUE_OTP_IND_1:
		break;
	case MUE_OTP_IND_2:
		off += 0x100;
		break;
	default:
		DPRINTF(sc, "OTP not found\n");
		return 1;
	}
	err = mue_read_otp_raw(sc, dest, off, cnt);
	return err;
}

static void
mue_dataport_write(struct mue_softc *sc, uint32_t sel, uint32_t addr,
    uint32_t cnt, uint32_t *data)
{
	uint32_t i;

	if (MUE_WAIT_SET(sc, MUE_DP_SEL, MUE_DP_SEL_DPRDY, 0)) {
		MUE_PRINTF(sc, "not ready\n");
		return;
	}

	mue_csr_write(sc, MUE_DP_SEL,
	    (mue_csr_read(sc, MUE_DP_SEL) & ~MUE_DP_SEL_RSEL_MASK) | sel);

	for (i = 0; i < cnt; i++) {
		mue_csr_write(sc, MUE_DP_ADDR, addr + i);
		mue_csr_write(sc, MUE_DP_DATA, data[i]);
		mue_csr_write(sc, MUE_DP_CMD, MUE_DP_CMD_WRITE);
		if (MUE_WAIT_SET(sc, MUE_DP_SEL, MUE_DP_SEL_DPRDY, 0)) {
			MUE_PRINTF(sc, "timed out\n");
			return;
		}
	}
}

static void
mue_init_ltm(struct mue_softc *sc)
{
	uint32_t idx[MUE_NUM_LTM_INDEX] = { 0, 0, 0, 0, 0, 0 };
	uint8_t temp[2];
	size_t i;

	if (mue_csr_read(sc, MUE_USB_CFG1) & MUE_USB_CFG1_LTM_ENABLE) {
		if (mue_eeprom_present(sc) &&
		    (mue_read_eeprom(sc, temp, MUE_E2P_LTM_OFFSET, 2) == 0)) {
			if (temp[0] != sizeof(idx)) {
				DPRINTF(sc, "EEPROM: unexpected size\n");
				goto done;
			}
			if (mue_read_eeprom(sc, (uint8_t *)idx, temp[1] << 1,
				sizeof(idx))) {
				DPRINTF(sc, "EEPROM read failed\n");
				goto done;
			}
			DPRINTF(sc, "success\n");
		} else if (mue_read_otp(sc, temp, MUE_E2P_LTM_OFFSET, 2) == 0) {
			if (temp[0] != sizeof(idx)) {
				DPRINTF(sc, "OTP: unexpected size\n");
				goto done;
			}
			if (mue_read_otp(sc, (uint8_t *)idx, temp[1] << 1,
				sizeof(idx))) {
				DPRINTF(sc, "OTP read failed\n");
				goto done;
			}
			DPRINTF(sc, "success\n");
		} else {
			DPRINTF(sc, "nothing to do\n");
		}
	} else {
		DPRINTF(sc, "nothing to do\n");
	}
done:
	for (i = 0; i < __arraycount(idx); i++)
		mue_csr_write(sc, MUE_LTM_INDEX(i), idx[i]);
}

static int
mue_chip_init(struct mue_softc *sc)
{
	uint32_t val;

	if ((sc->mue_flags & LAN7500) &&
	    MUE_WAIT_SET(sc, MUE_PMT_CTL, MUE_PMT_CTL_READY, 0)) {
		MUE_PRINTF(sc, "not ready\n");
			return ETIMEDOUT;
	}

	MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_LRST);
	if (MUE_WAIT_CLR(sc, MUE_HW_CFG, MUE_HW_CFG_LRST, 0)) {
		MUE_PRINTF(sc, "timed out\n");
		return ETIMEDOUT;
	}

	/* Respond to the IN token with a NAK. */
	if (sc->mue_flags & LAN7500)
		MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_BIR);
	else
		MUE_SETBIT(sc, MUE_USB_CFG0, MUE_USB_CFG0_BIR);

	if (sc->mue_flags & LAN7500) {
		if (sc->mue_udev->ud_speed == USB_SPEED_HIGH)
			val = MUE_7500_HS_BUFSIZE /
			    MUE_HS_USB_PKT_SIZE;
		else
			val = MUE_7500_FS_BUFSIZE /
			    MUE_FS_USB_PKT_SIZE;
		mue_csr_write(sc, MUE_7500_BURST_CAP, val);
		mue_csr_write(sc, MUE_7500_BULKIN_DELAY,
		    MUE_7500_DEFAULT_BULKIN_DELAY);

		MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_BCE | MUE_HW_CFG_MEF);

		/* Set FIFO sizes. */
		val = (MUE_7500_MAX_RX_FIFO_SIZE - 512) / 512;
		mue_csr_write(sc, MUE_7500_FCT_RX_FIFO_END, val);
		val = (MUE_7500_MAX_TX_FIFO_SIZE - 512) / 512;
		mue_csr_write(sc, MUE_7500_FCT_TX_FIFO_END, val);
	} else {
		/* Init LTM. */
		mue_init_ltm(sc);

		val = MUE_7800_BUFSIZE;
		switch (sc->mue_udev->ud_speed) {
		case USB_SPEED_SUPER:
			val /= MUE_SS_USB_PKT_SIZE;
			break;
		case USB_SPEED_HIGH:
			val /= MUE_HS_USB_PKT_SIZE;
			break;
		default:
			val /= MUE_FS_USB_PKT_SIZE;
			break;
		}
		mue_csr_write(sc, MUE_7800_BURST_CAP, val);
		mue_csr_write(sc, MUE_7800_BULKIN_DELAY,
		    MUE_7800_DEFAULT_BULKIN_DELAY);

		MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_MEF);
		MUE_SETBIT(sc, MUE_USB_CFG0, MUE_USB_CFG0_BCE);

		/*
		 * Set FCL's RX and TX FIFO sizes: according to data sheet this
		 * is already the default value. But we initialize it to the
		 * same value anyways, as that's what the Linux driver does.
		 */
		val = (MUE_7800_MAX_RX_FIFO_SIZE - 512) / 512;
		mue_csr_write(sc, MUE_7800_FCT_RX_FIFO_END, val);
		val = (MUE_7800_MAX_TX_FIFO_SIZE - 512) / 512;
		mue_csr_write(sc, MUE_7800_FCT_TX_FIFO_END, val);
	}

	/* Enabling interrupts. */
	mue_csr_write(sc, MUE_INT_STATUS, ~0);

	mue_csr_write(sc, (sc->mue_flags & LAN7500) ?
	    MUE_7500_FCT_FLOW : MUE_7800_FCT_FLOW, 0);
	mue_csr_write(sc, MUE_FLOW, 0);
 
	/* Reset PHY. */
	MUE_SETBIT(sc, MUE_PMT_CTL, MUE_PMT_CTL_PHY_RST);
	if (MUE_WAIT_CLR(sc, MUE_PMT_CTL, MUE_PMT_CTL_PHY_RST, 0)) {
		MUE_PRINTF(sc, "PHY not ready\n");
		return ETIMEDOUT;
	}

	/* LAN7801 only has RGMII mode. */
	if (sc->mue_product == USB_PRODUCT_SMSC_LAN7801)
		MUE_CLRBIT(sc, MUE_MAC_CR, MUE_MAC_CR_GMII_EN);

	if ((sc->mue_flags & LAN7500) ||
	    (sc->mue_product == USB_PRODUCT_SMSC_LAN7800 &&
	    !mue_eeprom_present(sc))) {
		/* Allow MAC to detect speed and duplex from PHY. */
		MUE_SETBIT(sc, MUE_MAC_CR, MUE_MAC_CR_AUTO_SPEED |
		    MUE_MAC_CR_AUTO_DUPLEX);
	}

	MUE_SETBIT(sc, MUE_MAC_TX, MUE_MAC_TX_TXEN);
	MUE_SETBIT(sc, (sc->mue_flags & LAN7500) ?
	    MUE_7500_FCT_TX_CTL : MUE_7800_FCT_TX_CTL, MUE_FCT_TX_CTL_EN);

	/* Set the maximum frame size. */
	MUE_CLRBIT(sc, MUE_MAC_RX, MUE_MAC_RX_RXEN);
	val = mue_csr_read(sc, MUE_MAC_RX);
	val &= ~MUE_MAC_RX_MAX_SIZE_MASK;
	val |= MUE_MAC_RX_MAX_LEN(ETHER_MAX_LEN);
	mue_csr_write(sc, MUE_MAC_RX, val);
	MUE_SETBIT(sc, MUE_MAC_RX, MUE_MAC_RX_RXEN);

	MUE_SETBIT(sc, (sc->mue_flags & LAN7500) ?
	    MUE_7500_FCT_RX_CTL : MUE_7800_FCT_RX_CTL, MUE_FCT_RX_CTL_EN);

	/* Set default GPIO/LED settings only if no EEPROM is detected. */
	if ((sc->mue_flags & LAN7500) && !mue_eeprom_present(sc)) {
		MUE_CLRBIT(sc, MUE_LED_CFG, MUE_LED_CFG_LED10_FUN_SEL);
		MUE_SETBIT(sc, MUE_LED_CFG,
		    MUE_LED_CFG_LEDGPIO_EN | MUE_LED_CFG_LED2_FUN_SEL);
	}

	/* XXX We assume two LEDs at least when EEPROM is missing. */
	if (sc->mue_product == USB_PRODUCT_SMSC_LAN7800 &&
	    !mue_eeprom_present(sc))
		MUE_SETBIT(sc, MUE_HW_CFG,
		    MUE_HW_CFG_LED0_EN | MUE_HW_CFG_LED1_EN);

	return 0;
}

static void
mue_set_macaddr(struct mue_softc *sc)
{
	struct ifnet *ifp = GET_IFP(sc);
	const uint8_t *enaddr = CLLADDR(ifp->if_sadl);
	uint32_t lo, hi;

	lo = MUE_ENADDR_LO(enaddr);
	hi = MUE_ENADDR_HI(enaddr);

	mue_csr_write(sc, MUE_RX_ADDRL, lo);
	mue_csr_write(sc, MUE_RX_ADDRH, hi);
}

static int
mue_get_macaddr(struct mue_softc *sc, prop_dictionary_t dict)
{
	prop_data_t eaprop;
	uint32_t low, high;

	if (!(sc->mue_flags & LAN7500)) {
		low  = mue_csr_read(sc, MUE_RX_ADDRL);
		high = mue_csr_read(sc, MUE_RX_ADDRH);
		sc->mue_enaddr[5] = (uint8_t)((high >> 8) & 0xff);
		sc->mue_enaddr[4] = (uint8_t)((high) & 0xff);
		sc->mue_enaddr[3] = (uint8_t)((low >> 24) & 0xff);
		sc->mue_enaddr[2] = (uint8_t)((low >> 16) & 0xff);
		sc->mue_enaddr[1] = (uint8_t)((low >> 8) & 0xff);
		sc->mue_enaddr[0] = (uint8_t)((low) & 0xff);
		if (ETHER_IS_VALID(sc->mue_enaddr))
			return 0;
		else {
			DPRINTF(sc, "registers: %s\n",
			    ether_sprintf(sc->mue_enaddr));
		}
	}

	if (mue_eeprom_present(sc) && !mue_read_eeprom(sc, sc->mue_enaddr,
	    MUE_E2P_MAC_OFFSET, ETHER_ADDR_LEN)) {
		if (ETHER_IS_VALID(sc->mue_enaddr))
			return 0;
		else {
			DPRINTF(sc, "EEPROM: %s\n",
			    ether_sprintf(sc->mue_enaddr));
		}
	}

	if (mue_read_otp(sc, sc->mue_enaddr, MUE_OTP_MAC_OFFSET,
	    ETHER_ADDR_LEN) == 0) {
		if (ETHER_IS_VALID(sc->mue_enaddr))
			return 0;
		else {
			DPRINTF(sc, "OTP: %s\n",
			    ether_sprintf(sc->mue_enaddr));
		}
	}

	/*
	 * Other MD methods. This should be tried only if other methods fail.
	 * Otherwise, MAC address for internal device can be assinged to
	 * external devices on Raspberry Pi, for example.
	 */
	eaprop = prop_dictionary_get(dict, "mac-address");
	if (eaprop != NULL) {
		KASSERT(prop_object_type(eaprop) == PROP_TYPE_DATA);
		KASSERT(prop_data_size(eaprop) == ETHER_ADDR_LEN);
		memcpy(sc->mue_enaddr, prop_data_data_nocopy(eaprop),
		    ETHER_ADDR_LEN);
		if (ETHER_IS_VALID(sc->mue_enaddr))
			return 0;
		else {
			DPRINTF(sc, "prop_dictionary_get: %s\n",
			    ether_sprintf(sc->mue_enaddr));
		}
	}

	return 1;
}


/* 
 * Probe for a Microchip chip.  */
static int
mue_match(device_t parent, cfdata_t match, void *aux)
{
	struct usb_attach_arg *uaa = aux;

	return (MUE_LOOKUP(uaa) != NULL) ?  UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
}

static void
mue_attach(device_t parent, device_t self, void *aux)
{
	struct mue_softc *sc = device_private(self);
	prop_dictionary_t dict = device_properties(self);
	struct usb_attach_arg *uaa = aux;
	struct usbd_device *dev = uaa->uaa_device;
	usb_interface_descriptor_t *id;
	usb_endpoint_descriptor_t *ed;
	char *devinfop;
	struct mii_data	*mii;
	struct ifnet *ifp;
	usbd_status err;
	int i, s;

	aprint_naive("\n");
	aprint_normal("\n");

	sc->mue_dev = self;
	sc->mue_udev = dev;

	devinfop = usbd_devinfo_alloc(sc->mue_udev, 0);
	aprint_normal_dev(self, "%s\n", devinfop);
	usbd_devinfo_free(devinfop);

#define MUE_CONFIG_NO	1
	err = usbd_set_config_no(dev, MUE_CONFIG_NO, 1);
	if (err) {
		aprint_error_dev(self, "failed to set configuration: %s\n",
		    usbd_errstr(err));
		return;
	}

	mutex_init(&sc->mue_mii_lock, MUTEX_DEFAULT, IPL_NONE);
	usb_init_task(&sc->mue_tick_task, mue_tick_task, sc, 0);
	usb_init_task(&sc->mue_stop_task, (void (*)(void *))mue_stop, sc, 0);

#define MUE_IFACE_IDX	0
	err = usbd_device2interface_handle(dev, MUE_IFACE_IDX, &sc->mue_iface);
	if (err) {
		aprint_error_dev(self, "failed to get interface handle: %s\n",
		    usbd_errstr(err));
		return;
	}

	sc->mue_product = uaa->uaa_product;
	sc->mue_flags = MUE_LOOKUP(uaa)->mue_flags;

	/* Decide on what our bufsize will be. */
	if (sc->mue_flags & LAN7500)
		sc->mue_bufsz = (sc->mue_udev->ud_speed == USB_SPEED_HIGH) ?
		    MUE_7500_HS_BUFSIZE : MUE_7500_FS_BUFSIZE;
	else
		sc->mue_bufsz = MUE_7800_BUFSIZE;

	/* Find endpoints. */
	id = usbd_get_interface_descriptor(sc->mue_iface);
	for (i = 0; i < id->bNumEndpoints; i++) {
		ed = usbd_interface2endpoint_descriptor(sc->mue_iface, i);
		if (ed == NULL) {
			aprint_error_dev(self, "couldn't get ep %d\n", i);
			return;
		}
		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
			sc->mue_ed[MUE_ENDPT_RX] = ed->bEndpointAddress;
		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
			sc->mue_ed[MUE_ENDPT_TX] = ed->bEndpointAddress;
		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
			sc->mue_ed[MUE_ENDPT_INTR] = ed->bEndpointAddress;
		}
	}
	KASSERT(sc->mue_ed[MUE_ENDPT_RX] != 0);
	KASSERT(sc->mue_ed[MUE_ENDPT_TX] != 0);
	KASSERT(sc->mue_ed[MUE_ENDPT_INTR] != 0);

	s = splnet();

	sc->mue_phyno = 1;

	if (mue_chip_init(sc)) {
		aprint_error_dev(self, "chip initialization failed\n");
		splx(s);
		return;
	}

	/* A Microchip chip was detected.  Inform the world. */
	if (sc->mue_flags & LAN7500)
		aprint_normal_dev(self, "LAN7500\n");
	else
		aprint_normal_dev(self, "LAN7800\n");

	if (mue_get_macaddr(sc, dict)) {
		aprint_error_dev(self, "Ethernet address assigned randomly\n");
		cprng_fast(sc->mue_enaddr, ETHER_ADDR_LEN);
		sc->mue_enaddr[0] &= ~0x01;	/* unicast */
		sc->mue_enaddr[0] |= 0x02;	/* locally administered */
	}

	aprint_normal_dev(self, "Ethernet address %s\n",
	    ether_sprintf(sc->mue_enaddr));

	/* Initialize interface info.*/
	ifp = GET_IFP(sc);
	ifp->if_softc = sc;
	strlcpy(ifp->if_xname, device_xname(sc->mue_dev), IFNAMSIZ);
	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
	ifp->if_init = mue_init;
	ifp->if_ioctl = mue_ioctl;
	ifp->if_start = mue_start;
	ifp->if_stop = mue_stop;
	ifp->if_watchdog = mue_watchdog;

	IFQ_SET_READY(&ifp->if_snd);

	sc->mue_ec.ec_capabilities = ETHERCAP_VLAN_MTU;

	/* Initialize MII/media info. */
	mii = GET_MII(sc);
	mii->mii_ifp = ifp;
	mii->mii_readreg = mue_miibus_readreg;
	mii->mii_writereg = mue_miibus_writereg;
	mii->mii_statchg = mue_miibus_statchg;
	mii->mii_flags = MIIF_AUTOTSLEEP;

	sc->mue_ec.ec_mii = mii;
	ifmedia_init(&mii->mii_media, 0, mue_ifmedia_upd, mue_ifmedia_sts);
	mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);

	if (LIST_FIRST(&mii->mii_phys) == NULL) {
		ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
	} else
		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);

	/* Attach the interface. */
	if_attach(ifp);
	ether_ifattach(ifp, sc->mue_enaddr);

	rnd_attach_source(&sc->mue_rnd_source, device_xname(sc->mue_dev),
	    RND_TYPE_NET, RND_FLAG_DEFAULT);

	callout_init(&sc->mue_stat_ch, 0);

	splx(s);

	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->mue_udev, sc->mue_dev);
}

static int
mue_detach(device_t self, int flags)
{
	struct mue_softc *sc = device_private(self);
	struct ifnet *ifp = GET_IFP(sc);
	size_t i;
	int s;

	sc->mue_dying = true;

	callout_halt(&sc->mue_stat_ch, NULL);

	for (i = 0; i < __arraycount(sc->mue_ep); i++)
		if (sc->mue_ep[i] != NULL)
			usbd_abort_pipe(sc->mue_ep[i]);

	/*
	 * Remove any pending tasks.  They cannot be executing because they run
	 * in the same thread as detach.
	 */
	usb_rem_task_wait(sc->mue_udev, &sc->mue_tick_task, USB_TASKQ_DRIVER,
	    NULL);
	usb_rem_task_wait(sc->mue_udev, &sc->mue_stop_task, USB_TASKQ_DRIVER,
	    NULL);

	s = splusb();

	if (ifp->if_flags & IFF_RUNNING)
		mue_stop(ifp, 1);

	rnd_detach_source(&sc->mue_rnd_source);
	mii_detach(&sc->mue_mii, MII_PHY_ANY, MII_OFFSET_ANY);
	ifmedia_delete_instance(&sc->mue_mii.mii_media, IFM_INST_ANY);
	if (ifp->if_softc != NULL) {
		ether_ifdetach(ifp);
		if_detach(ifp);
	}

	if (--sc->mue_refcnt >= 0) {
		/* Wait for processes to go away. */
		usb_detach_waitold(sc->mue_dev);
	}
	splx(s);

	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->mue_udev, sc->mue_dev);
	
	mutex_destroy(&sc->mue_mii_lock);

	return 0;
}

static int
mue_activate(device_t self, enum devact act)
{
	struct mue_softc *sc = device_private(self);
	struct ifnet *ifp = GET_IFP(sc);

	switch (act) {
	case DVACT_DEACTIVATE:
		if_deactivate(ifp);
		sc->mue_dying = true;
		return 0;
	default:
		return EOPNOTSUPP;
	}
	return 0;
}

static int
mue_rx_list_init(struct mue_softc *sc)
{
	struct mue_cdata *cd;
	struct mue_chain *c;
	size_t i;
	int err;

	cd = &sc->mue_cdata;
	for (i = 0; i < __arraycount(cd->mue_rx_chain); i++) {
		c = &cd->mue_rx_chain[i];
		c->mue_sc = sc;
		c->mue_idx = i;
		if (c->mue_xfer == NULL) {
			err = usbd_create_xfer(sc->mue_ep[MUE_ENDPT_RX],
			    sc->mue_bufsz, 0, 0, &c->mue_xfer);
			if (err)
				return err;
			c->mue_buf = usbd_get_buffer(c->mue_xfer);
		}
	}

	return 0;
}

static int
mue_tx_list_init(struct mue_softc *sc)
{
	struct mue_cdata *cd;
	struct mue_chain *c;
	size_t i;
	int err;

	cd = &sc->mue_cdata;
	for (i = 0; i < __arraycount(cd->mue_tx_chain); i++) {
		c = &cd->mue_tx_chain[i];
		c->mue_sc = sc;
		c->mue_idx = i;
		if (c->mue_xfer == NULL) {
			err = usbd_create_xfer(sc->mue_ep[MUE_ENDPT_TX],
			    sc->mue_bufsz, USBD_FORCE_SHORT_XFER, 0,
			    &c->mue_xfer);
			if (err)
				return err;
			c->mue_buf = usbd_get_buffer(c->mue_xfer);
		}
	}

	return 0;
}

static int
mue_open_pipes(struct mue_softc *sc)
{
	usbd_status err;

	/* Open RX and TX pipes. */
	err = usbd_open_pipe(sc->mue_iface, sc->mue_ed[MUE_ENDPT_RX],
	    USBD_EXCLUSIVE_USE, &sc->mue_ep[MUE_ENDPT_RX]);
	if (err) {
		MUE_PRINTF(sc, "rx pipe: %s\n", usbd_errstr(err));
		return EIO;
	}
	err = usbd_open_pipe(sc->mue_iface, sc->mue_ed[MUE_ENDPT_TX],
	    USBD_EXCLUSIVE_USE, &sc->mue_ep[MUE_ENDPT_TX]);
	if (err) {
		MUE_PRINTF(sc, "tx pipe: %s\n", usbd_errstr(err));
		return EIO;
	}
	return 0;
}

static void
mue_start_rx(struct mue_softc *sc)
{
	struct mue_chain *c;
	size_t i;

	/* Start up the receive pipe. */
	for (i = 0; i < __arraycount(sc->mue_cdata.mue_rx_chain); i++) {
		c = &sc->mue_cdata.mue_rx_chain[i];
		usbd_setup_xfer(c->mue_xfer, c, c->mue_buf, sc->mue_bufsz,
		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, mue_rxeof);
		usbd_transfer(c->mue_xfer);
	}
}

static int
mue_encap(struct mue_softc *sc, struct mbuf *m, int idx)
{
	struct ifnet *ifp = GET_IFP(sc);
	struct mue_chain *c;
	usbd_status err;
	struct mue_txbuf_hdr hdr;
	int len;

	c = &sc->mue_cdata.mue_tx_chain[idx];

	hdr.tx_cmd_a = htole32((m->m_pkthdr.len & MUE_TX_CMD_A_LEN_MASK) |
	    MUE_TX_CMD_A_FCS);
	/* Disable segmentation offload. */
	hdr.tx_cmd_b = htole32(0);
	memcpy(c->mue_buf, &hdr, sizeof(hdr)); 
	len = sizeof(hdr);

	m_copydata(m, 0, m->m_pkthdr.len, c->mue_buf + len);
	len += m->m_pkthdr.len;

	usbd_setup_xfer(c->mue_xfer, c, c->mue_buf, len,
	    USBD_FORCE_SHORT_XFER, 10000, mue_txeof);

	/* Transmit */
	err = usbd_transfer(c->mue_xfer);
	if (__predict_false(err != USBD_IN_PROGRESS)) {
		DPRINTF(sc, "%s\n", usbd_errstr(err));
		mue_stop(ifp, 0);
		return EIO;
	}

	sc->mue_cdata.mue_tx_cnt++;

	return 0;
}

static void
mue_setmulti(struct mue_softc *sc)
{
	struct ifnet *ifp = GET_IFP(sc);
	const uint8_t *enaddr = CLLADDR(ifp->if_sadl);
	struct ether_multi *enm;
	struct ether_multistep step;
	uint32_t pfiltbl[MUE_NUM_ADDR_FILTX][2];
	uint32_t hashtbl[MUE_DP_SEL_VHF_HASH_LEN];
	uint32_t reg, rxfilt, h, hireg, loreg;
	int i;

	if (sc->mue_dying)
		return;

	/* Clear perfect filter and hash tables. */
	memset(pfiltbl, 0, sizeof(pfiltbl));
	memset(hashtbl, 0, sizeof(hashtbl));

	reg = (sc->mue_flags & LAN7500) ? MUE_7500_RFE_CTL : MUE_7800_RFE_CTL;
	rxfilt = mue_csr_read(sc, reg);
	rxfilt &= ~(MUE_RFE_CTL_PERFECT | MUE_RFE_CTL_MULTICAST_HASH |
	    MUE_RFE_CTL_UNICAST | MUE_RFE_CTL_MULTICAST);

	/* Always accept broadcast frames. */
	rxfilt |= MUE_RFE_CTL_BROADCAST;

	if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
allmulti:	rxfilt |= MUE_RFE_CTL_MULTICAST;
		if (ifp->if_flags & IFF_PROMISC) {
			rxfilt |= MUE_RFE_CTL_UNICAST;
			DPRINTF(sc, "promisc\n");
		} else {
			DPRINTF(sc, "allmulti\n");
		}
	} else {
		/* Now program new ones. */
		pfiltbl[0][0] = MUE_ENADDR_HI(enaddr) | MUE_ADDR_FILTX_VALID;
		pfiltbl[0][1] = MUE_ENADDR_LO(enaddr);
		i = 1;
		ETHER_FIRST_MULTI(step, &sc->mue_ec, enm);
		while (enm != NULL) {
			if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
			    ETHER_ADDR_LEN)) {
				memset(pfiltbl, 0, sizeof(pfiltbl));
				memset(hashtbl, 0, sizeof(hashtbl));
				rxfilt &= ~MUE_RFE_CTL_MULTICAST_HASH;
				goto allmulti;
			}
			if (i < MUE_NUM_ADDR_FILTX) {
				/* Use perfect address table if possible. */
				pfiltbl[i][0] = MUE_ENADDR_HI(enm->enm_addrlo) |
				    MUE_ADDR_FILTX_VALID;
				pfiltbl[i][1] = MUE_ENADDR_LO(enm->enm_addrlo);
			} else {
				/* Otherwise, use hash table. */
				rxfilt |= MUE_RFE_CTL_MULTICAST_HASH;
				h = (ether_crc32_be(enm->enm_addrlo,
				    ETHER_ADDR_LEN) >> 23) & 0x1ff;
				hashtbl[h / 32] |= 1 << (h % 32); 
			}
			i++;
			ETHER_NEXT_MULTI(step, enm);
		}
		rxfilt |= MUE_RFE_CTL_PERFECT;
		if (rxfilt & MUE_RFE_CTL_MULTICAST_HASH) {
			DPRINTF(sc, "perfect filter and hash tables\n");
		} else {
			DPRINTF(sc, "perfect filter\n");
		}
	}

	for (i = 0; i < MUE_NUM_ADDR_FILTX; i++) {
		hireg = (sc->mue_flags & LAN7500) ?
		    MUE_7500_ADDR_FILTX(i) : MUE_7800_ADDR_FILTX(i);
		loreg = hireg + 4;
		mue_csr_write(sc, hireg, 0);
		mue_csr_write(sc, loreg, pfiltbl[i][1]);
		mue_csr_write(sc, hireg, pfiltbl[i][0]);
	}

	mue_dataport_write(sc, MUE_DP_SEL_VHF, MUE_DP_SEL_VHF_VLAN_LEN,
	    MUE_DP_SEL_VHF_HASH_LEN, hashtbl);

	mue_csr_write(sc, reg, rxfilt);
}

static void
mue_sethwcsum(struct mue_softc *sc)
{
	struct ifnet *ifp = GET_IFP(sc);
	uint32_t reg, val;

	reg = (sc->mue_flags & LAN7500) ? MUE_7500_RFE_CTL : MUE_7800_RFE_CTL;
	val = mue_csr_read(sc, reg);

	if (ifp->if_capabilities & (IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx)) {
		DPRINTF(sc, "enabled\n");;
		val |= MUE_RFE_CTL_IGMP_COE | MUE_RFE_CTL_ICMP_COE;
		val |= MUE_RFE_CTL_TCPUDP_COE | MUE_RFE_CTL_IP_COE;
	} else {
		DPRINTF(sc, "disabled\n");;
		val &=
		    ~(MUE_RFE_CTL_IGMP_COE | MUE_RFE_CTL_ICMP_COE);
		val &=
		    ~(MUE_RFE_CTL_TCPUDP_COE | MUE_RFE_CTL_IP_COE);
        }

	val &= ~MUE_RFE_CTL_VLAN_FILTER;

	mue_csr_write(sc, reg, val);
}


static void
mue_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
{
	struct mue_chain *c = (struct mue_chain *)priv;
	struct mue_softc *sc = c->mue_sc;
	struct ifnet *ifp = GET_IFP(sc);
	struct mbuf *m;
	struct mue_rxbuf_hdr *hdrp;
	uint32_t rx_cmd_a, total_len;
	uint16_t pktlen;
	int s;
	char *buf = c->mue_buf;

	if (__predict_false(sc->mue_dying)) {
		DPRINTF(sc, "dying\n");
		return;
	}

	if (__predict_false(!(ifp->if_flags & IFF_RUNNING))) {
		DPRINTF(sc, "not running\n");
		return;
	}

	if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
		DPRINTF(sc, "%s\n", usbd_errstr(status));
		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
			return;
		if (usbd_ratecheck(&sc->mue_rx_notice))
			MUE_PRINTF(sc, "%s\n", usbd_errstr(status));
		if (status == USBD_STALLED)
			usbd_clear_endpoint_stall_async(
			    sc->mue_ep[MUE_ENDPT_RX]);
		goto done;
	}

	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);

	if (__predict_false(total_len > sc->mue_bufsz)) {
		DPRINTF(sc, "too large transfer\n");
		goto done;
	}

	do {
		if (__predict_false(total_len < sizeof(*hdrp))) {
			DPRINTF(sc, "too short transfer\n");
			ifp->if_ierrors++;
			goto done;
		}

		hdrp = (struct mue_rxbuf_hdr *)buf;
		rx_cmd_a = le32toh(hdrp->rx_cmd_a);

		if (__predict_false(rx_cmd_a & MUE_RX_CMD_A_RED)) {
			DPRINTF(sc, "rx_cmd_a: 0x%x\n", rx_cmd_a);
			ifp->if_ierrors++;
			goto done;
		}

		/* XXX not yet */
		KASSERT((rx_cmd_a & MUE_RX_CMD_A_ICSM) == 0);

		pktlen = (uint16_t)(rx_cmd_a & MUE_RX_CMD_A_LEN_MASK);
		if (sc->mue_flags & LAN7500)
			pktlen -= 2;

		if (__predict_false(pktlen < ETHER_HDR_LEN ||
		    pktlen > MCLBYTES - ETHER_ALIGN ||
		    pktlen + sizeof(*hdrp) > total_len)) {
			DPRINTF(sc, "bad pktlen\n");
			ifp->if_ierrors++;
			goto done;
		}

		m = mue_newbuf();
		if (__predict_false(m == NULL)) {
			DPRINTF(sc, "mbuf allocation failed\n");
			ifp->if_ierrors++;
			goto done;
		}

		m_set_rcvif(m, ifp);
		m->m_pkthdr.len = m->m_len = pktlen;
		m->m_flags |= M_HASFCS;
		memcpy(mtod(m, char *), buf + sizeof(*hdrp), pktlen);

		/* Attention: sizeof(hdr) = 10 */
		pktlen = roundup(pktlen + sizeof(*hdrp), 4);
		if (pktlen > total_len)
			pktlen = total_len;
		total_len -= pktlen;
		buf += pktlen;

		s = splnet();
		if_percpuq_enqueue(ifp->if_percpuq, m);
		splx(s);
	} while (total_len > 0);

done:
	/* Setup new transfer. */
	usbd_setup_xfer(xfer, c, c->mue_buf, sc->mue_bufsz,
	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, mue_rxeof);
	usbd_transfer(xfer);
}

static void
mue_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
{
	struct mue_chain *c = priv;
	struct mue_softc *sc = c->mue_sc;
	struct ifnet *ifp = GET_IFP(sc);
	int s;

	if (__predict_false(sc->mue_dying))
		return;

	s = splnet();


	if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
			splx(s);
			return;
		}
		ifp->if_oerrors++;
		MUE_PRINTF(sc, "%s\n", usbd_errstr(status));
		if (status == USBD_STALLED)
			usbd_clear_endpoint_stall_async(
			    sc->mue_ep[MUE_ENDPT_TX]);
		splx(s);
		return;
	}

	ifp->if_timer = 0;
	ifp->if_flags &= ~IFF_OACTIVE;

	if (!IFQ_IS_EMPTY(&ifp->if_snd))
		mue_start(ifp);

	ifp->if_opackets++;
	splx(s);
}

static int
mue_init(struct ifnet *ifp)
{
	struct mue_softc *sc = ifp->if_softc; 
	int s;

	if (sc->mue_dying) {
		DPRINTF(sc, "dying\n");
		return EIO;
	}

	s = splnet();

	/* Cancel pending I/O and free all TX/RX buffers. */
	if (ifp->if_flags & IFF_RUNNING)
		mue_stop(ifp, 1);

	mue_reset(sc);

	/* Set MAC address. */
	mue_set_macaddr(sc);

	/* Load the multicast filter. */
	mue_setmulti(sc);

	/* TCP/UDP checksum offload engines. */
	mue_sethwcsum(sc);

	if (mue_open_pipes(sc)) {
		splx(s);
		return EIO;
	}

	/* Init RX ring. */
	if (mue_rx_list_init(sc)) {
		MUE_PRINTF(sc, "rx list init failed\n");
		splx(s);
		return ENOBUFS;
	}

	/* Init TX ring. */
	if (mue_tx_list_init(sc)) {
		MUE_PRINTF(sc, "tx list init failed\n");
		splx(s);
		return ENOBUFS;
	}

	mue_start_rx(sc);

	ifp->if_flags |= IFF_RUNNING;
	ifp->if_flags &= ~IFF_OACTIVE;

	splx(s);

	callout_reset(&sc->mue_stat_ch, hz, mue_tick, sc);

	return 0;
}

static int
mue_ioctl(struct ifnet *ifp, u_long cmd, void *data)
{
	struct mue_softc *sc = ifp->if_softc;
	struct ifreq /*const*/ *ifr = data;
	int s, error = 0;

	s = splnet();

	switch(cmd) {
	case SIOCSIFFLAGS:
		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
			break;

		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
		case IFF_RUNNING:
			mue_stop(ifp, 1);
			break;
		case IFF_UP:
			mue_init(ifp);
			break;
		case IFF_UP | IFF_RUNNING:
			if ((ifp->if_flags ^ sc->mue_if_flags) == IFF_PROMISC)
				mue_setmulti(sc);
			else
				mue_init(ifp);
			break;
		}
		sc->mue_if_flags = ifp->if_flags;
		break;
	case SIOCGIFMEDIA:
	case SIOCSIFMEDIA:
		error = ifmedia_ioctl(ifp, ifr, &sc->mue_mii.mii_media, cmd);
		break;
	default:
		if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
			break;
		error = 0;
		if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI)
			mue_setmulti(sc);
		break;
	}
	splx(s);

	return error;
}

static void
mue_watchdog(struct ifnet *ifp)
{
	struct mue_softc *sc = ifp->if_softc;
	struct mue_chain *c;
	usbd_status stat;
	int s;

	ifp->if_oerrors++;
	MUE_PRINTF(sc, "timed out\n");

	s = splusb();
	c = &sc->mue_cdata.mue_tx_chain[0];
	usbd_get_xfer_status(c->mue_xfer, NULL, NULL, NULL, &stat);
	mue_txeof(c->mue_xfer, c, stat);

	if (!IFQ_IS_EMPTY(&ifp->if_snd))
		mue_start(ifp);
	splx(s);
}

static void
mue_reset(struct mue_softc *sc)
{
	if (sc->mue_dying)
		return;

	/* Wait a little while for the chip to get its brains in order. */
	usbd_delay_ms(sc->mue_udev, 1);

//	mue_chip_init(sc); /* XXX */
}

static void
mue_start(struct ifnet *ifp)
{
	struct mue_softc *sc = ifp->if_softc;
	struct mbuf *m;

	if (__predict_false(!sc->mue_link)) {
		DPRINTF(sc, "no link\n");
		return;
	}

	if (__predict_false((ifp->if_flags & (IFF_OACTIVE|IFF_RUNNING))
	    != IFF_RUNNING)) {
		DPRINTF(sc, "not ready\n");
		return;
	}

	IFQ_POLL(&ifp->if_snd, m);
	if (m == NULL)
		return;

	if (__predict_false(mue_encap(sc, m, 0))) {
		DPRINTF(sc, "encap failed\n");
		ifp->if_flags |= IFF_OACTIVE;
		return;
	}
	IFQ_DEQUEUE(&ifp->if_snd, m);

	bpf_mtap(ifp, m, BPF_D_OUT);
	m_freem(m);

	ifp->if_flags |= IFF_OACTIVE;

	/* Set a timeout in case the chip goes out to lunch. */
	ifp->if_timer = 5;
}

static void
mue_stop(struct ifnet *ifp, int disable __unused)
{
	struct mue_softc *sc = ifp->if_softc;
	usbd_status err;
	size_t i;

	mue_reset(sc);

	ifp->if_timer = 0;
	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);

	callout_stop(&sc->mue_stat_ch);

        /* Stop transfers. */
	for (i = 0; i < __arraycount(sc->mue_ep); i++)
		if (sc->mue_ep[i] != NULL) {
			err = usbd_abort_pipe(sc->mue_ep[i]);
			if (err)
				MUE_PRINTF(sc, "abort pipe %zu: %s\n",
				    i, usbd_errstr(err));
		}

	/* Free RX resources. */
	for (i = 0; i < __arraycount(sc->mue_cdata.mue_rx_chain); i++)
		if (sc->mue_cdata.mue_rx_chain[i].mue_xfer != NULL) {
			usbd_destroy_xfer(
			    sc->mue_cdata.mue_rx_chain[i].mue_xfer);
			sc->mue_cdata.mue_rx_chain[i].mue_xfer = NULL;
		}

	/* Free TX resources. */
	for (i = 0; i < __arraycount(sc->mue_cdata.mue_tx_chain); i++)
		if (sc->mue_cdata.mue_tx_chain[i].mue_xfer != NULL) {
			usbd_destroy_xfer(
			    sc->mue_cdata.mue_tx_chain[i].mue_xfer);
			sc->mue_cdata.mue_tx_chain[i].mue_xfer = NULL;
		}

	/* Close pipes */
	for (i = 0; i < __arraycount(sc->mue_ep); i++)
		if (sc->mue_ep[i] != NULL) {
			err = usbd_close_pipe(sc->mue_ep[i]);
			if (err)
				MUE_PRINTF(sc, "close pipe %zu: %s\n",
				    i, usbd_errstr(err));
			sc->mue_ep[i] = NULL;
		}

	sc->mue_link = 0; /* XXX */

	DPRINTF(sc, "done\n");
}

static void
mue_tick(void *xsc)
{
	struct mue_softc *sc = xsc;

	if (sc == NULL)
		return;

	if (sc->mue_dying)
		return;

	/* Perform periodic stuff in process context. */
	usb_add_task(sc->mue_udev, &sc->mue_tick_task, USB_TASKQ_DRIVER);
}

static void
mue_tick_task(void *xsc)
{
	struct mue_softc *sc = xsc;
	struct ifnet *ifp = GET_IFP(sc);
	struct mii_data *mii = GET_MII(sc);
	int s;

	if (sc == NULL)
		return;

	if (sc->mue_dying)
		return;

	s = splnet();
	mii_tick(mii);
	if (sc->mue_link == 0)
		mue_miibus_statchg(ifp);
	callout_reset(&sc->mue_stat_ch, hz, mue_tick, sc);
	splx(s);
}

static struct mbuf *
mue_newbuf(void)
{
	struct mbuf *m;

	MGETHDR(m, M_DONTWAIT, MT_DATA);
	if (__predict_false(m == NULL))
		return NULL;

	MCLGET(m, M_DONTWAIT);
	if (__predict_false(!(m->m_flags & M_EXT))) {
		m_freem(m);
		return NULL;
	}

	m_adj(m, ETHER_ALIGN);

	return m;
}

File Added: src/sys/dev/usb/if_muereg.h
/*	$NetBSD: if_muereg.h,v 1.1 2018/08/25 20:12:22 rin Exp $	*/
/*	$OpenBSD: if_muereg.h,v 1.1 2018/08/03 01:50:15 kevlo Exp $	*/

/*
 * Copyright (c) 2018 Kevin Lo <kevlo@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _IF_MUEREG_H_
#define _IF_MUEREG_H_

/* USB vendor requests */
#define MUE_UR_WRITEREG         0xa0
#define MUE_UR_READREG		0xa1

/* registers */
#define MUE_INT_STATUS			0x00c
#define MUE_HW_CFG			0x010
#define MUE_PMT_CTL			0x014
#define MUE_LED_CFG			0x018
#define MUE_DP_SEL			0x024
#define MUE_DP_CMD			0x028
#define MUE_DP_ADDR			0x02c
#define MUE_DP_DATA			0x030
#define MUE_7500_BURST_CAP		0x034
#define MUE_7500_INT_EP_CTL		0x038
#define MUE_7500_BULKIN_DELAY		0x03c
#define MUE_E2P_CMD			0x040
#define MUE_E2P_DATA			0x044
#define MUE_E2P_IND			0x0a5
#define MUE_7500_RFE_CTL		0x060
#define MUE_USB_CFG0			0x080
#define MUE_USB_CFG1			0x084
#define MUE_7500_FCT_RX_CTL		0x090
#define MUE_7800_BURST_CAP		0x090
#define MUE_7500_FCT_TX_CTL		0x094
#define MUE_7800_BULKIN_DELAY		0x094
#define MUE_7500_FCT_RX_FIFO_END	0x098
#define MUE_7800_INT_EP_CTL		0x098
#define MUE_7500_FCT_TX_FIFO_END	0x09c
#define MUE_7500_FCT_FLOW		0x0a0
#define MUE_7800_RFE_CTL		0x0b0
#define MUE_7800_FCT_RX_CTL		0x0c0
#define MUE_7800_FCT_TX_CTL		0x0c4
#define MUE_7800_FCT_RX_FIFO_END	0x0c8
#define MUE_7800_FCT_TX_FIFO_END	0x0cc
#define MUE_7800_FCT_FLOW		0x0d0
#define MUE_LTM_INDEX(idx)		(0x0e0 + (idx) * 4)
#define MUE_NUM_LTM_INDEX		6
#define MUE_MAC_CR			0x100
#define MUE_MAC_RX			0x104
#define MUE_MAC_TX			0x108
#define MUE_FLOW			0x10c
#define MUE_RX_ADDRH			0x118
#define MUE_RX_ADDRL			0x11c
#define MUE_MII_ACCESS			0x120
#define MUE_MII_DATA			0x124
#define MUE_7500_ADDR_FILTX_BASE	0x300
#define MUE_7500_ADDR_FILTX(i)		(MUE_7500_ADDR_FILTX_BASE + 8 * (i))
#define MUE_7800_ADDR_FILTX_BASE	0x400
#define MUE_7800_ADDR_FILTX(i)		(MUE_7800_ADDR_FILTX_BASE + 8 * (i))
#define MUE_NUM_ADDR_FILTX		33

/* hardware configuration register */
#define MUE_HW_CFG_SRST		0x00000001
#define MUE_HW_CFG_LRST		0x00000002
#define MUE_HW_CFG_BCE		0x00000004
#define MUE_HW_CFG_MEF		0x00000010
#define MUE_HW_CFG_BIR		0x00000080
#define MUE_HW_CFG_LED0_EN	0x00100000
#define MUE_HW_CFG_LED1_EN	0x00200000

/* power management control register */
#define MUE_PMT_CTL_PHY_RST	0x00000010
#define MUE_PMT_CTL_READY	0x00000080

/* LED configuration register */
#define MUE_LED_CFG_LEDGPIO_EN		0x0000f000
#define MUE_LED_CFG_LED10_FUN_SEL	0x40000000
#define MUE_LED_CFG_LED2_FUN_SEL	0x80000000

/* data port select register */
#define MUE_DP_SEL_RSEL_MASK	0x0000000f
#define MUE_DP_SEL_VHF		0x00000001
#define MUE_DP_SEL_DPRDY	0x80000000
#define MUE_DP_SEL_VHF_HASH_LEN	16
#define MUE_DP_SEL_VHF_VLAN_LEN	128

/* data port command register */
#define MUE_DP_CMD_WRITE	0x00000001

/* burst cap register and etc */
#define MUE_SS_USB_PKT_SIZE		1024
#define MUE_HS_USB_PKT_SIZE		512
#define MUE_FS_USB_PKT_SIZE		64
#define MUE_7500_HS_BUFSIZE		\
	(16 * 1024 + 5 * MUE_HS_USB_PKT_SIZE)
#define MUE_7500_FS_BUFSIZE		\
	(6 * 1024 + 33 * MUE_FS_USB_PKT_SIZE)
#define MUE_7500_MAX_RX_FIFO_SIZE	(20 * 1024)
#define MUE_7500_MAX_TX_FIFO_SIZE	(12 * 1024)
#define MUE_7800_BUFSIZE		(12 * 1024)
#define MUE_7800_MAX_RX_FIFO_SIZE	MUE_7800_BUFSIZE
#define MUE_7800_MAX_TX_FIFO_SIZE	MUE_7800_BUFSIZE

/* interrupt endpoint control register */
#define MUE_INT_EP_CTL_PHY_INT		0x20000

/* bulk-in delay register */
#define MUE_7500_DEFAULT_BULKIN_DELAY	0x00002000
#define MUE_7800_DEFAULT_BULKIN_DELAY	0x00000800

/* EEPROM command register */
#define MUE_E2P_CMD_ADDR_MASK	0x000001ff
#define MUE_E2P_CMD_READ	0x00000000
#define MUE_E2P_CMD_LOADED	0x00000200
#define MUE_E2P_CMD_TIMEOUT	0x00000400
#define MUE_E2P_CMD_BUSY	0x80000000
#define MUE_E2P_IND_OFFSET	0x000
#define	MUE_E2P_MAC_OFFSET	0x001
#define	MUE_E2P_LTM_OFFSET	0x03f

/* Receive Filtering Engine control register */
#define MUE_RFE_CTL_PERFECT		0x00000002
#define MUE_RFE_CTL_MULTICAST_HASH	0x00000008
#define MUE_RFE_CTL_VLAN_FILTER		0x00000020
#define MUE_RFE_CTL_UNICAST		0x00000100
#define MUE_RFE_CTL_MULTICAST		0x00000200
#define MUE_RFE_CTL_BROADCAST		0x00000400
#define MUE_RFE_CTL_IP_COE		0x00000800
#define MUE_RFE_CTL_TCPUDP_COE		0x00001000
#define MUE_RFE_CTL_ICMP_COE		0x00002000
#define MUE_RFE_CTL_IGMP_COE		0x00004000

/* USB configuration register 0 */
#define MUE_USB_CFG0_BCE	0x00000020
#define MUE_USB_CFG0_BIR	0x00000040

/* USB configuration register 1 */
#define MUE_USB_CFG1_LTM_ENABLE		0x00000100
#define MUE_USB_CFG1_DEV_U1_INIT_EN	0x00000400
#define MUE_USB_CFG1_DEV_U2_INIT_EN	0x00001000

/* RX FIFO control register */
#define MUE_FCT_RX_CTL_EN	0x80000000

/* TX FIFO control register */
#define MUE_FCT_TX_CTL_EN	0x80000000

/* MAC control register */
#define MUE_MAC_CR_RST		0x00000001
#define MUE_MAC_CR_FULL_DUPLEX	0x00000008
#define MUE_MAC_CR_AUTO_SPEED	0x00000800
#define MUE_MAC_CR_AUTO_DUPLEX	0x00001000
#define MUE_MAC_CR_GMII_EN	0x00080000

/* MAC receive register */
#define MUE_MAC_RX_RXEN			0x00000001
#define MUE_MAC_RX_MAX_SIZE_MASK	0x3fff0000
#define MUE_MAC_RX_MAX_SIZE_SHIFT	16
#define MUE_MAC_RX_MAX_LEN(x)	\
	(((x) << MUE_MAC_RX_MAX_SIZE_SHIFT) & MUE_MAC_RX_MAX_SIZE_MASK)

/* MAC transmit register */
#define MUE_MAC_TX_TXEN		0x00000001

/* flow control register */
#define MUE_FLOW_PAUSE_TIME	0x0000ffff
#define MUE_FLOW_RX_FCEN	0x20000000
#define MUE_FLOW_TX_FCEN	0x40000000

/* MII access register */
#define MUE_MII_ACCESS_READ		0x00000000
#define MUE_MII_ACCESS_BUSY		0x00000001
#define MUE_MII_ACCESS_WRITE		0x00000002
#define MUE_MII_ACCESS_REGADDR_MASK	0x000007c0
#define MUE_MII_ACCESS_REGADDR_SHIFT	6
#define MUE_MII_ACCESS_PHYADDR_MASK	0x0000f800
#define MUE_MII_ACCESS_PHYADDR_SHIFT	11
#define MUE_MII_ACCESS_REGADDR(x)	\
	(((x) << MUE_MII_ACCESS_REGADDR_SHIFT) & MUE_MII_ACCESS_REGADDR_MASK)
#define MUE_MII_ACCESS_PHYADDR(x)	\
	(((x) << MUE_MII_ACCESS_PHYADDR_SHIFT) & MUE_MII_ACCESS_PHYADDR_MASK)

/* MAC address perfect filter register */
#define MUE_ADDR_FILTX_VALID	0x80000000

/* undocumented OTP registers from Linux via FreeBSD */
#define MUE_OTP_BASE_ADDR		0x01000
#define MUE_OTP_ADDR(off)		(MUE_OTP_BASE_ADDR + 4 * (off))
#define MUE_OTP_PWR_DN			MUE_OTP_ADDR(0x00)
#define MUE_OTP_PWR_DN_PWRDN_N		0x01
#define MUE_OTP_ADDR1			MUE_OTP_ADDR(0x01)
#define MUE_OTP_ADDR1_MASK		0x1f
#define MUE_OTP_ADDR2			MUE_OTP_ADDR(0x02)
#define MUE_OTP_ADDR2_MASK		0xff
#define MUE_OTP_ADDR3			MUE_OTP_ADDR(0x03)
#define MUE_OTP_ADDR3_MASK		0x03
#define MUE_OTP_RD_DATA			MUE_OTP_ADDR(0x06)
#define MUE_OTP_FUNC_CMD		MUE_OTP_ADDR(0x08)
#define MUE_OTP_FUNC_CMD_RESET		0x04
#define MUE_OTP_FUNC_CMD_PROGRAM	0x02
#define MUE_OTP_FUNC_CMD_READ		0x01
#define MUE_OTP_MAC_OFFSET		0x01
#define MUE_OTP_IND_OFFSET		0x00
#define MUE_OTP_IND_1			0xf3
#define MUE_OTP_IND_2			0xf7
#define MUE_OTP_CMD_GO			MUE_OTP_ADDR(0x0a)
#define MUE_OTP_CMD_GO_GO		0x01
#define MUE_OTP_STATUS			MUE_OTP_ADDR(0x0a)
#define MUE_OTP_STATUS_OTP_LOCK		0x10
#define MUE_OTP_STATUS_BUSY		0x01

#endif /* _IF_MUEREG_H_ */

File Added: src/sys/dev/usb/if_muevar.h
/*	$NetBSD: if_muevar.h,v 1.1 2018/08/25 20:12:22 rin Exp $	*/
/*	$OpenBSD: if_muereg.h,v 1.1 2018/08/03 01:50:15 kevlo Exp $	*/

/*
 * Copyright (c) 2018 Kevin Lo <kevlo@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _IF_MUEVAR_H_
#define _IF_MUEVAR_H_

#include <sys/rndsource.h>

struct mue_chain {
	struct mue_softc	*mue_sc;
	struct usbd_xfer	*mue_xfer;
	char			*mue_buf;
	int			mue_accum;
	int			mue_idx;
};

struct mue_cdata {
#define MUE_TX_LIST_CNT	1
	struct mue_chain	mue_tx_chain[MUE_TX_LIST_CNT];
#define MUE_RX_LIST_CNT	1
	struct mue_chain	mue_rx_chain[MUE_RX_LIST_CNT];
	int			mue_tx_prod;
	int			mue_tx_cons;
	int			mue_tx_cnt;
	int			mue_rx_prod;
};

struct mue_rxbuf_hdr {
	uint32_t		rx_cmd_a;
#define MUE_RX_CMD_A_LEN_MASK	0x00003fff
#define MUE_RX_CMD_A_ICSM	0x00004000
#define MUE_RX_CMD_A_RED	0x00400000

	uint32_t		rx_cmd_b;
	uint16_t		rx_cmd_c;
} __packed;

struct mue_txbuf_hdr {
	uint32_t		tx_cmd_a;
#define MUE_TX_CMD_A_LEN_MASK	0x000fffff
#define MUE_TX_CMD_A_FCS	0x00400000

	uint32_t		tx_cmd_b;
} __packed;

struct mue_softc {
	device_t		mue_dev;
	bool			mue_dying;

	uint8_t			mue_enaddr[ETHER_ADDR_LEN];
	struct ethercom		mue_ec;
	struct mii_data		mue_mii;
#define GET_MII(sc)	(&(sc)->mue_mii)
#define GET_IFP(sc)	(&(sc)->mue_ec.ec_if)

/* The interrupt endpoint is currently unused by the Moschip part. */
#define MUE_ENDPT_RX	0
#define MUE_ENDPT_TX	1
#define MUE_ENDPT_INTR	2
#define MUE_ENDPT_MAX	3
	int			mue_ed[MUE_ENDPT_MAX];
	struct usbd_pipe	*mue_ep[MUE_ENDPT_MAX];

	struct mue_cdata	mue_cdata;
	callout_t		mue_stat_ch;

	struct usbd_device	*mue_udev;
	struct usbd_interface	*mue_iface;

	struct usb_task		mue_tick_task;
	struct usb_task		mue_stop_task;

	kmutex_t		mue_mii_lock;

	struct timeval		mue_rx_notice;

	uint16_t		mue_product;
	uint16_t		mue_flags;

	int			mue_if_flags;
	int			mue_refcnt;

	krndsource_t		mue_rnd_source;

	int			mue_phyno;
	uint32_t		mue_bufsz;
	int			mue_link;
};

#endif /* _IF_MUEVAR_H_ */

cvs diff -r1.32 -r1.33 src/sys/dev/usb/usbdevices.config (expand / switch to unified diff)

--- src/sys/dev/usb/usbdevices.config 2018/08/13 17:35:31 1.32
+++ src/sys/dev/usb/usbdevices.config 2018/08/25 20:12:22 1.33
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: usbdevices.config,v 1.32 2018/08/13 17:35:31 mrg Exp $ 1# $NetBSD: usbdevices.config,v 1.33 2018/08/25 20:12:22 rin Exp $
2# 2#
3# This file contains all USB related configuration. 3# This file contains all USB related configuration.
4# It is suitable for inclusion in a kernel config(5) file. 4# It is suitable for inclusion in a kernel config(5) file.
5# 5#
6 6
7# USB Controller and Devices 7# USB Controller and Devices
8 8
9# PCI USB controllers 9# PCI USB controllers
10#ehci* at pci? dev ? function ? # Enhanced Host Controller 10#ehci* at pci? dev ? function ? # Enhanced Host Controller
11#ohci* at pci? dev ? function ? # Open Host Controller 11#ohci* at pci? dev ? function ? # Open Host Controller
12#uhci* at pci? dev ? function ? # Universal Host Controller (Intel) 12#uhci* at pci? dev ? function ? # Universal Host Controller (Intel)
13 13
14# CardBus USB controllers 14# CardBus USB controllers
@@ -118,26 +118,27 @@ cir* at irmce? @@ -118,26 +118,27 @@ cir* at irmce?
118 118
119# Toshiba Oboe 119# Toshiba Oboe
120#oboe* at pci? dev ? function ? # broken -- vtophys 120#oboe* at pci? dev ? function ? # broken -- vtophys
121#irframe* at oboe? 121#irframe* at oboe?
122 122
123# USB Ethernet adapters 123# USB Ethernet adapters
124aue* at uhub? port ? # ADMtek AN986 Pegasus based adapters 124aue* at uhub? port ? # ADMtek AN986 Pegasus based adapters
125axe* at uhub? port ? # ASIX AX88172 based adapters 125axe* at uhub? port ? # ASIX AX88172 based adapters
126axen* at uhub? port ? # ASIX AX88178a/AX88179 based adapters 126axen* at uhub? port ? # ASIX AX88178a/AX88179 based adapters
127cdce* at uhub? port ? # CDC, Ethernet Networking Control Model 127cdce* at uhub? port ? # CDC, Ethernet Networking Control Model
128cue* at uhub? port ? # CATC USB-EL1201A based adapters 128cue* at uhub? port ? # CATC USB-EL1201A based adapters
129kue* at uhub? port ? # Kawasaki LSI KL5KUSB101B based adapters 129kue* at uhub? port ? # Kawasaki LSI KL5KUSB101B based adapters
130#mos* at uhub? port ? # Moschip MCS7730/MCS7830/MCS7832 based adapters 130#mos* at uhub? port ? # Moschip MCS7730/MCS7830/MCS7832 based adapters
 131mue* at uhub? port ? # Microchip LAN75xx/LAN78xx based adapters
131udav* at uhub? port ? # Davicom DM9601 based adapters 132udav* at uhub? port ? # Davicom DM9601 based adapters
132#umb* at uhub? port ? # Mobile Broadband Interface Model (EXPERIMENTAL) 133#umb* at uhub? port ? # Mobile Broadband Interface Model (EXPERIMENTAL)
133url* at uhub? port ? # Realtek RTL8150L based adapters 134url* at uhub? port ? # Realtek RTL8150L based adapters
134urndis* at uhub? port ? # Microsoft RNDIS specification 135urndis* at uhub? port ? # Microsoft RNDIS specification
135usmsc* at uhub? port ? # SMSC95xx based adapters 136usmsc* at uhub? port ? # SMSC95xx based adapters
136 137
137# USB 802.11 adapters 138# USB 802.11 adapters
138athn* at uhub? port ? # Atheros AR9002U 139athn* at uhub? port ? # Atheros AR9002U
139atu* at uhub? port ? # Atmel AT76C50XX based adapters 140atu* at uhub? port ? # Atmel AT76C50XX based adapters
140bwfm* at uhub? port ? # Broadcom FullMAC 141bwfm* at uhub? port ? # Broadcom FullMAC
141otus* at uhub? port ? # Atheros AR9001U 142otus* at uhub? port ? # Atheros AR9001U
142rum* at uhub? port ? # Ralink Technology RT2501/RT2601 802.11a/b/g 143rum* at uhub? port ? # Ralink Technology RT2501/RT2601 802.11a/b/g
143run* at uhub? port ? # Ralink Technology RT(2[78]|30)00 802.11a/b/g/n 144run* at uhub? port ? # Ralink Technology RT(2[78]|30)00 802.11a/b/g/n

cvs diff -r1.207 -r1.208 src/sys/modules/Makefile (expand / switch to unified diff)

--- src/sys/modules/Makefile 2018/07/24 09:47:35 1.207
+++ src/sys/modules/Makefile 2018/08/25 20:12:22 1.208
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1# $NetBSD: Makefile,v 1.207 2018/07/24 09:47:35 maxv Exp $ 1# $NetBSD: Makefile,v 1.208 2018/08/25 20:12:22 rin Exp $
2 2
3.include <bsd.own.mk> 3.include <bsd.own.mk>
4 4
5# For all platforms 5# For all platforms
6 6
7SUBDIR= accf_dataready 7SUBDIR= accf_dataready
8SUBDIR+= accf_httpready 8SUBDIR+= accf_httpready
9SUBDIR+= adosfs 9SUBDIR+= adosfs
10SUBDIR+= aio 10SUBDIR+= aio
11SUBDIR+= audio 11SUBDIR+= audio
12SUBDIR+= autofs 12SUBDIR+= autofs
13SUBDIR+= blowfish 13SUBDIR+= blowfish
14SUBDIR+= bpf 14SUBDIR+= bpf
@@ -54,26 +54,27 @@ SUBDIR+= hythygtemp @@ -54,26 +54,27 @@ SUBDIR+= hythygtemp
54SUBDIR+= si70xxtemp 54SUBDIR+= si70xxtemp
55SUBDIR+= am2315temp 55SUBDIR+= am2315temp
56SUBDIR+= i2cexec 56SUBDIR+= i2cexec
57SUBDIR+= i2c_bitbang 57SUBDIR+= i2c_bitbang
58SUBDIR+= if_agr 58SUBDIR+= if_agr
59SUBDIR+= if_axe 59SUBDIR+= if_axe
60SUBDIR+= if_axen 60SUBDIR+= if_axen
61SUBDIR+= if_faith 61SUBDIR+= if_faith
62SUBDIR+= if_gif 62SUBDIR+= if_gif
63SUBDIR+= if_gre 63SUBDIR+= if_gre
64SUBDIR+= if_l2tp 64SUBDIR+= if_l2tp
65SUBDIR+= if_loop 65SUBDIR+= if_loop
66SUBDIR+= if_mpls 66SUBDIR+= if_mpls
 67SUBDIR+= if_mue
67SUBDIR+= if_npflog 68SUBDIR+= if_npflog
68SUBDIR+= if_ppp 69SUBDIR+= if_ppp
69SUBDIR+= if_pppoe 70SUBDIR+= if_pppoe
70SUBDIR+= if_sl 71SUBDIR+= if_sl
71SUBDIR+= if_smsc 72SUBDIR+= if_smsc
72SUBDIR+= if_srt 73SUBDIR+= if_srt
73SUBDIR+= if_stf 74SUBDIR+= if_stf
74SUBDIR+= if_strip 75SUBDIR+= if_strip
75SUBDIR+= if_tun tun 76SUBDIR+= if_tun tun
76SUBDIR+= if_vlan 77SUBDIR+= if_vlan
77SUBDIR+= iic 78SUBDIR+= iic
78SUBDIR+= ip_ecn 79SUBDIR+= ip_ecn
79SUBDIR+= ipl 80SUBDIR+= ipl

File Added: src/sys/modules/if_mue/Makefile
# $NetBSD: Makefile,v 1.1 2018/08/25 20:12:22 rin Exp $

.include "../Makefile.inc"

.PATH:	${S}/dev/usb

KMOD=	if_mue
IOCONF=	if_mue.ioconf
SRCS=	if_mue.c

WARNS=	5

.include <bsd.kmodule.mk>

File Added: src/sys/modules/if_mue/if_mue.ioconf
# $NetBSD: if_mue.ioconf,v 1.1 2018/08/25 20:12:22 rin Exp $

ioconf mue

include "conf/files"
include "dev/usb/files.usb"

pseudo-root usbdevif*

mue* at usbdevif?