[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree

zrouter-src-freebsd at zrouter.org zrouter-src-freebsd at zrouter.org
Wed Aug 15 08:45:57 UTC 2012


details:   http://zrouter.org/hg/FreeBSD/head//rev/49889ad5ef1f
changeset: 525:49889ad5ef1f
user:      Aleksandr Rybalko <ray at ddteam.net>
date:      Wed Aug 15 11:46:11 2012 +0300
description:
FreeBSD HEAD @svn r239290.

diffstat:

 head/Makefile                                  |     6 +-
 head/Makefile.inc1                             |     4 +-
 head/cddl/contrib/opensolaris/cmd/zfs/zfs.8    |    12 +-
 head/contrib/binutils/bfd/config.bfd           |     8 +
 head/contrib/binutils/config.sub               |     2 +-
 head/contrib/binutils/gas/config/tc-arm.c      |     4 +
 head/contrib/gcc/config/arm/freebsd.h          |    16 +-
 head/gnu/usr.bin/binutils/Makefile.inc0        |     6 +-
 head/gnu/usr.bin/binutils/as/Makefile          |     6 +-
 head/gnu/usr.bin/binutils/ld/Makefile.arm      |     4 +-
 head/gnu/usr.bin/binutils/libbfd/Makefile.arm  |     6 +-
 head/gnu/usr.bin/cc/Makefile.inc               |     7 +-
 head/gnu/usr.bin/cc/Makefile.tgt               |     6 +-
 head/gnu/usr.bin/gdb/Makefile.inc              |     4 +-
 head/gnu/usr.bin/gdb/libgdb/Makefile           |     4 +-
 head/lib/libc/arm/gen/__aeabi_read_tp.S        |     8 +-
 head/lib/libc/arm/gen/_set_tp.c                |     6 +-
 head/lib/libc/gen/Makefile.inc                 |     4 +-
 head/lib/libc/gen/aux.c                        |   186 --
 head/lib/libc/gen/auxv.c                       |   186 ++
 head/lib/libthr/arch/arm/include/pthread_md.h  |    16 +-
 head/lib/libthr/thread/thr_cond.c              |    18 +-
 head/lib/libthr/thread/thr_kern.c              |     9 +-
 head/lib/libthr/thread/thr_mutex.c             |    18 +-
 head/lib/libthr/thread/thr_private.h           |    10 +-
 head/lib/libthr/thread/thr_umtx.h              |    18 +-
 head/lib/libusb/libusb20.3                     |    15 +-
 head/lib/libusb/libusb20.c                     |    11 +-
 head/lib/libusb/libusb20.h                     |     3 +-
 head/lib/libusb/libusb20_int.h                 |     4 +-
 head/lib/libusb/libusb20_ugen20.c              |    34 +-
 head/lib/msun/src/e_rem_pio2.c                 |     8 +-
 head/lib/msun/src/e_rem_pio2f.c                |    10 +-
 head/lib/msun/src/k_cosf.c                     |     8 +-
 head/lib/msun/src/k_sinf.c                     |     8 +-
 head/lib/msun/src/k_tanf.c                     |     8 +-
 head/lib/msun/src/math_private.h               |    27 +-
 head/libexec/rtld-elf/arm/reloc.c              |    17 +-
 head/libexec/rtld-elf/rtld.c                   |    36 +-
 head/share/man/man4/sched_ule.4                |     7 +-
 head/share/mk/bsd.cpu.mk                       |     9 +-
 head/share/mk/bsd.endian.mk                    |     4 +-
 head/share/mk/sys.mk                           |     4 +-
 head/sys/amd64/amd64/mp_machdep.c              |    18 +-
 head/sys/amd64/amd64/trap.c                    |    24 +-
 head/sys/amd64/conf/XENHVM                     |     4 +-
 head/sys/amd64/ia32/ia32_sigtramp.S            |    33 +-
 head/sys/amd64/ia32/ia32_syscall.c             |     4 +-
 head/sys/amd64/include/param.h                 |    10 +-
 head/sys/boot/common/disk.c                    |    35 +-
 head/sys/boot/common/disk.h                    |     7 +-
 head/sys/boot/common/loader.8                  |    33 +-
 head/sys/boot/fdt/dts/beaglebone.dts           |   197 ++
 head/sys/boot/fdt/dts/db88f78160.dts           |   311 ++++
 head/sys/boot/fdt/dts/ea3250.dts               |   270 +++
 head/sys/boot/fdt/dts/pandaboard.dts           |   184 ++
 head/sys/boot/fdt/dts/trimslice.dts            |   143 +
 head/sys/boot/i386/libi386/biosdisk.c          |     6 +-
 head/sys/cam/scsi/scsi_all.h                   |     3 +-
 head/sys/cam/scsi/scsi_enc.c                   |    22 +-
 head/sys/cam/scsi/scsi_enc_safte.c             |    12 +-
 head/sys/cam/scsi/scsi_enc_ses.c               |    60 +-
 head/sys/compat/freebsd32/freebsd32_proto.h    |     4 +-
 head/sys/compat/freebsd32/freebsd32_syscall.h  |     6 +-
 head/sys/compat/freebsd32/freebsd32_syscalls.c |     6 +-
 head/sys/compat/freebsd32/freebsd32_sysent.c   |     6 +-
 head/sys/compat/freebsd32/syscalls.master      |     5 +-
 head/sys/conf/Makefile.arm                     |     6 +-
 head/sys/conf/files                            |     6 +-
 head/sys/conf/files.arm                        |    11 +-
 head/sys/conf/kern.pre.mk                      |     4 +-
 head/sys/conf/kmod.mk                          |     4 +-
 head/sys/conf/options.arm                      |    28 +-
 head/sys/conf/options.mips                     |     6 +-
 head/sys/dev/ath/if_ath_tx.c                   |    62 +-
 head/sys/dev/cxgbe/t4_main.c                   |     9 +-
 head/sys/dev/cxgbe/t4_sge.c                    |   129 +-
 head/sys/dev/fdt/fdt_common.c                  |    94 +-
 head/sys/dev/fdt/fdt_common.h                  |     5 +-
 head/sys/dev/fdt/fdtbus.c                      |     4 +-
 head/sys/dev/fdt/simplebus.c                   |    18 +-
 head/sys/dev/isp/isp.c                         |     4 +-
 head/sys/dev/isp/isp_freebsd.c                 |    31 +-
 head/sys/dev/isp/isp_pci.c                     |    24 +-
 head/sys/dev/mge/if_mge.c                      |   110 +-
 head/sys/dev/mge/if_mgevar.h                   |     4 +-
 head/sys/dev/mii/miidevs                       |     6 +-
 head/sys/dev/mii/smcphy.c                      |     5 +-
 head/sys/dev/mii/smscphy.c                     |   237 +++
 head/sys/dev/mmc/mmc.c                         |     3 +-
 head/sys/dev/netmap/ixgbe_netmap.h             |    15 +-
 head/sys/dev/ofw/ofw_iicbus.c                  |     9 +-
 head/sys/dev/re/if_re.c                        |     6 +-
 head/sys/dev/sound/macio/snapper.c             |     4 +-
 head/sys/dev/sound/pci/hda/hdaa.c              |    11 +-
 head/sys/dev/twe/twe.c                         |   162 +-
 head/sys/dev/twe/twe_compat.h                  |    52 +-
 head/sys/dev/twe/twe_freebsd.c                 |   145 +-
 head/sys/dev/twe/twevar.h                      |    25 +-
 head/sys/dev/uart/uart.h                       |     3 +-
 head/sys/dev/uart/uart_bus_fdt.c               |    23 +-
 head/sys/dev/uart/uart_dev_lpc.c               |   891 ++++++++++++
 head/sys/dev/uart/uart_subr.c                  |     3 +-
 head/sys/dev/usb/controller/at91dci.c          |    15 +-
 head/sys/dev/usb/controller/atmegadci.c        |    15 +-
 head/sys/dev/usb/controller/avr32dci.c         |    15 +-
 head/sys/dev/usb/controller/dotg.c             |    49 +-
 head/sys/dev/usb/controller/dotgreg.h          |    11 +
 head/sys/dev/usb/controller/dwc_otg.c          |    15 +-
 head/sys/dev/usb/controller/musb_otg.c         |    15 +-
 head/sys/dev/usb/controller/uss820dci.c        |    15 +-
 head/sys/dev/usb/controller/xhci.c             |   125 +-
 head/sys/dev/usb/controller/xhci.h             |    21 +-
 head/sys/dev/usb/net/if_smsc.c                 |  1756 ++++++++++++++++++++++++
 head/sys/dev/usb/net/if_smscreg.h              |   277 +++
 head/sys/dev/usb/net/if_usie.c                 |    30 +-
 head/sys/dev/usb/net/uhso.c                    |    30 +-
 head/sys/dev/usb/quirk/usb_quirk.c             |     1 +
 head/sys/dev/usb/serial/u3g.c                  |    37 +-
 head/sys/dev/usb/serial/uark.c                 |    30 +-
 head/sys/dev/usb/serial/ubsa.c                 |    30 +-
 head/sys/dev/usb/serial/ubser.c                |    34 +-
 head/sys/dev/usb/serial/uchcom.c               |    31 +-
 head/sys/dev/usb/serial/ucycom.c               |    34 +-
 head/sys/dev/usb/serial/ufoma.c                |    34 +-
 head/sys/dev/usb/serial/uftdi.c                |    34 +-
 head/sys/dev/usb/serial/ugensa.c               |    30 +-
 head/sys/dev/usb/serial/uipaq.c                |    30 +-
 head/sys/dev/usb/serial/ulpt.c                 |     4 +-
 head/sys/dev/usb/serial/umcs.c                 |    30 +-
 head/sys/dev/usb/serial/umct.c                 |    34 +-
 head/sys/dev/usb/serial/umodem.c               |    30 +-
 head/sys/dev/usb/serial/umoscom.c              |    30 +-
 head/sys/dev/usb/serial/uplcom.c               |    30 +-
 head/sys/dev/usb/serial/usb_serial.c           |   238 ++-
 head/sys/dev/usb/serial/usb_serial.h           |    17 +-
 head/sys/dev/usb/serial/uslcom.c               |   141 +-
 head/sys/dev/usb/serial/uvisor.c               |    30 +-
 head/sys/dev/usb/serial/uvscom.c               |    30 +-
 head/sys/dev/usb/usb.h                         |    22 +-
 head/sys/dev/usb/usb_controller.h              |     9 +-
 head/sys/dev/usb/usb_core.h                    |     3 +-
 head/sys/dev/usb/usb_debug.c                   |     8 +-
 head/sys/dev/usb/usb_device.c                  |   112 +-
 head/sys/dev/usb/usb_device.h                  |     4 +-
 head/sys/dev/usb/usb_freebsd.h                 |     4 +-
 head/sys/dev/usb/usb_generic.c                 |     8 +-
 head/sys/dev/usb/usb_hub.c                     |    10 +-
 head/sys/dev/usb/usb_ioctl.h                   |     8 +-
 head/sys/dev/usb/usb_msctest.c                 |    44 +-
 head/sys/dev/usb/usb_request.c                 |    11 +-
 head/sys/dev/usb/usb_transfer.c                |    47 +-
 head/sys/dev/usb/usbdevs                       |     3 +-
 head/sys/dev/usb/usbdi.h                       |    14 +-
 head/sys/fs/nfsclient/nfs_clbio.c              |    14 +-
 head/sys/fs/nwfs/nwfs_io.c                     |     4 +-
 head/sys/fs/smbfs/smbfs_io.c                   |     4 +-
 head/sys/geom/eli/g_eli_key_cache.c            |    29 +-
 head/sys/geom/raid/g_raid.c                    |     4 +-
 head/sys/i386/conf/XENHVM                      |     4 +-
 head/sys/i386/i386/mp_machdep.c                |    18 +-
 head/sys/i386/include/param.h                  |    10 +-
 head/sys/kern/device_if.m                      |    13 +-
 head/sys/kern/kern_environment.c               |    14 +-
 head/sys/kern/kern_umtx.c                      |    28 +-
 head/sys/kern/ksched.c                         |     4 +-
 head/sys/kern/sched_4bsd.c                     |    47 +-
 head/sys/kern/sched_ule.c                      |   100 +-
 head/sys/kern/subr_bus.c                       |    20 +-
 head/sys/mips/atheros/ar71xx_gpio.c            |   130 +-
 head/sys/mips/atheros/ar71xx_gpiovar.h         |     6 +-
 head/sys/mips/atheros/ar71xxreg.h              |    12 +-
 head/sys/mips/cavium/octopci.c                 |    24 +
 head/sys/mips/cavium/octopci_bus_space.c       |    13 +-
 head/sys/mips/include/pmap.h                   |    28 +-
 head/sys/mips/mips/pmap.c                      |   641 +++++---
 head/sys/mips/rt305x/rt305x_gpio.c             |     3 +-
 head/sys/modules/Makefile                      |     4 +-
 head/sys/modules/cpsw/Makefile                 |     8 +
 head/sys/modules/cxgbe/if_cxgbe/Makefile       |    17 +-
 head/sys/modules/cxgbe/tom/Makefile            |    12 +-
 head/sys/modules/mii/Makefile                  |     5 +-
 head/sys/modules/usb/smsc/Makefile             |    37 +
 head/sys/nfsclient/nfs_bio.c                   |    14 +-
 head/sys/sys/bus.h                             |     3 +-
 head/sys/sys/param.h                           |     4 +-
 head/sys/vm/vm_mmap.c                          |    31 +-
 head/sys/vm/vm_page.c                          |    12 +-
 head/sys/vm/vm_page.h                          |     4 +-
 head/sys/vm/vnode_pager.c                      |     4 +-
 head/usr.bin/xlint/Makefile.inc                |     4 +-
 head/usr.sbin/lpr/lpd/lpd.8                    |     4 +-
 192 files changed, 7703 insertions(+), 1614 deletions(-)

diffs (16370 lines):

diff -r a301a330526b -r 49889ad5ef1f head/Makefile
--- a/head/Makefile	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/Makefile	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #
-# $FreeBSD: head/Makefile 238051 2012-07-03 06:41:00Z obrien $
+# $FreeBSD: head/Makefile 239272 2012-08-15 03:21:56Z gonzo $
 #
 # The user-driven targets are:
 #
@@ -135,7 +135,7 @@
 _TARGET_ARCH=	${TARGET:S/pc98/i386/}
 .elif !defined(TARGET) && defined(TARGET_ARCH) && \
     ${TARGET_ARCH} != ${MACHINE_ARCH}
-_TARGET=		${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/}
+_TARGET=		${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/}
 .endif
 # Legacy names, for another transition period mips:mips(n32|64)?eb -> mips:mips\1
 .if defined(TARGET) && defined(TARGET_ARCH) && \
@@ -329,7 +329,7 @@
 #
 .if make(universe) || make(universe_kernels) || make(tinderbox) || make(targets)
 TARGETS?=amd64 arm i386 ia64 mips pc98 powerpc sparc64
-TARGET_ARCHES_arm?=	arm armeb
+TARGET_ARCHES_arm?=	arm armeb armv6 armv6eb
 TARGET_ARCHES_mips?=	mipsel mips mips64el mips64 mipsn32
 TARGET_ARCHES_powerpc?=	powerpc powerpc64
 TARGET_ARCHES_pc98?=	i386
diff -r a301a330526b -r 49889ad5ef1f head/Makefile.inc1
--- a/head/Makefile.inc1	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/Makefile.inc1	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #
-# $FreeBSD: head/Makefile.inc1 238926 2012-07-30 23:14:24Z mm $
+# $FreeBSD: head/Makefile.inc1 239272 2012-08-15 03:21:56Z gonzo $
 #
 # Make command line options:
 #	-DNO_CLEANDIR run ${MAKE} clean, instead of ${MAKE} cleandir
@@ -138,7 +138,7 @@
 VERSION+=	${OSRELDATE}
 .endif
 
-KNOWN_ARCHES?=	amd64 arm armeb/arm i386 i386/pc98 ia64 mips mipsel/mips mips64el/mips mips64/mips mipsn32el/mips mipsn32/mips powerpc powerpc64/powerpc sparc64
+KNOWN_ARCHES?=	amd64 arm armeb/arm armv6/arm armv6eb/arm i386 i386/pc98 ia64 mips mipsel/mips mips64el/mips mips64/mips mipsn32el/mips mipsn32/mips powerpc powerpc64/powerpc sparc64
 .if ${TARGET} == ${TARGET_ARCH}
 _t=		${TARGET}
 .else
diff -r a301a330526b -r 49889ad5ef1f head/cddl/contrib/opensolaris/cmd/zfs/zfs.8
--- a/head/cddl/contrib/opensolaris/cmd/zfs/zfs.8	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/cddl/contrib/opensolaris/cmd/zfs/zfs.8	Wed Aug 15 11:46:11 2012 +0300
@@ -23,9 +23,9 @@
 .\" Copyright (c) 2012, Joyent, Inc. All rights reserved.
 .\" Copyright (c) 2011, Pawel Jakub Dawidek <pjd at FreeBSD.org>
 .\"
-.\" $FreeBSD: head/cddl/contrib/opensolaris/cmd/zfs/zfs.8 235222 2012-05-10 10:39:45Z mm $
+.\" $FreeBSD: head/cddl/contrib/opensolaris/cmd/zfs/zfs.8 239217 2012-08-12 20:30:15Z gjb $
 .\"
-.Dd April 22, 2012
+.Dd August 12, 2012
 .Dt ZFS 8
 .Os
 .Sh NAME
@@ -2249,7 +2249,7 @@
 is received. If the
 .Fl F
 flag is specified when this stream is received, snapshots and file systems that
- do not exist on the sending side are destroyed.
+do not exist on the sending side are destroyed.
 .It Fl D
 Generate a deduplicated stream. Blocks which would have been sent multiple
 times in the send stream will only be sent once.  The receiving system must
@@ -3028,9 +3028,9 @@
 .Li # Ic zfs destroy -r pool/users at 7daysago
 .Li # Ic zfs rename -r pool/users at 6daysago @7daysago
 .Li # Ic zfs rename -r pool/users at 5daysago @6daysago
-.Li # Ic zfs rename -r pool/users at yesterday @5daysago
-.Li # Ic zfs rename -r pool/users at yesterday @4daysago
-.Li # Ic zfs rename -r pool/users at yesterday @3daysago
+.Li # Ic zfs rename -r pool/users at 4daysago @5daysago
+.Li # Ic zfs rename -r pool/users at 3daysago @4daysago
+.Li # Ic zfs rename -r pool/users at 2daysago @3daysago
 .Li # Ic zfs rename -r pool/users at yesterday @2daysago
 .Li # Ic zfs rename -r pool/users at today @yesterday
 .Li # Ic zfs snapshot -r pool/users at today
diff -r a301a330526b -r 49889ad5ef1f head/contrib/binutils/bfd/config.bfd
--- a/head/contrib/binutils/bfd/config.bfd	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/contrib/binutils/bfd/config.bfd	Wed Aug 15 11:46:11 2012 +0300
@@ -277,6 +277,14 @@
     targ_defvec=bfd_elf32_bigarm_vec
     targ_selvecs=bfd_elf32_littlearm_vec
     ;;
+  armv6eb-*-freebsd*)
+    targ_defvec=bfd_elf32_bigarm_vec
+    targ_selvecs=bfd_elf32_littlearm_vec
+    ;;
+  armv6-*-freebsd*)
+    targ_defvec=bfd_elf32_littlearm_vec
+    targ_selvecs=bfd_elf32_bigarm_vec
+    ;;
   arm-*-elf | arm-*-freebsd* | arm*-*-linux-* | arm*-*-conix* | \
   arm*-*-uclinux* | arm-*-kfreebsd*-gnu | \
   arm*-*-eabi* )
diff -r a301a330526b -r 49889ad5ef1f head/contrib/binutils/config.sub
--- a/head/contrib/binutils/config.sub	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/contrib/binutils/config.sub	Wed Aug 15 11:46:11 2012 +0300
@@ -241,7 +241,7 @@
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 	| am33_2.0 \
-	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[23456] | armv[345][lb] | avr | avr32 \
 	| bfin \
 	| c4x | clipper \
 	| d10v | d30v | dlx | dsp16xx \
diff -r a301a330526b -r 49889ad5ef1f head/contrib/binutils/gas/config/tc-arm.c
--- a/head/contrib/binutils/gas/config/tc-arm.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/contrib/binutils/gas/config/tc-arm.c	Wed Aug 15 11:46:11 2012 +0300
@@ -20008,6 +20008,9 @@
   {"cortex-a8",		ARM_ARCH_V7A,	 ARM_FEATURE(0, FPU_VFP_V3
                                                         | FPU_NEON_EXT_V1),
                                                           NULL},
+  {"cortex-a9",		ARM_ARCH_V7A,	 ARM_FEATURE(0, FPU_VFP_V3
+                                                        | FPU_NEON_EXT_V1),
+                                                          NULL},
   {"cortex-r4",		ARM_ARCH_V7R,	 FPU_NONE,	  NULL},
   {"cortex-m3",		ARM_ARCH_V7M,	 FPU_NONE,	  NULL},
   /* ??? XSCALE is really an architecture.  */
@@ -20106,6 +20109,7 @@
   {"vfp",		FPU_ARCH_VFP_V2},
   {"vfp9",		FPU_ARCH_VFP_V2},
   {"vfp3",              FPU_ARCH_VFP_V3},
+  {"vfpv3",             FPU_ARCH_VFP_V3},
   {"vfp10",		FPU_ARCH_VFP_V2},
   {"vfp10-r0",		FPU_ARCH_VFP_V1},
   {"vfpxd",		FPU_ARCH_VFP_V1xD},
diff -r a301a330526b -r 49889ad5ef1f head/contrib/gcc/config/arm/freebsd.h
--- a/head/contrib/gcc/config/arm/freebsd.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/contrib/gcc/config/arm/freebsd.h	Wed Aug 15 11:46:11 2012 +0300
@@ -56,8 +56,6 @@
 
 /************************[  Target stuff  ]***********************************/
 
-#undef  TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (FreeBSD/StrongARM ELF)");
 
 #ifndef TARGET_ENDIAN_DEFAULT
 #define TARGET_ENDIAN_DEFAULT 0
@@ -87,8 +85,22 @@
 /* We use the GCC defaults here.  */
 #undef WCHAR_TYPE
 
+#if defined(FREEBSD_ARCH_armv6)
+#undef  SUBTARGET_CPU_DEFAULT
+#define SUBTARGET_CPU_DEFAULT	TARGET_CPU_arm1176jzs
+#undef FBSD_TARGET_CPU_CPP_BUILTINS
+#define FBSD_TARGET_CPU_CPP_BUILTINS()		\
+  do {						\
+    builtin_define ("__FreeBSD_ARCH_armv6__");	\
+  } while (0)
+#undef  TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (FreeBSD/armv6 ELF)");
+#else
 #undef  SUBTARGET_CPU_DEFAULT
 #define SUBTARGET_CPU_DEFAULT	TARGET_CPU_strongarm
+#undef  TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (FreeBSD/StrongARM ELF)");
+#endif
 
 /* FreeBSD does its profiling differently to the Acorn compiler. We
    don't need a word following the mcount call; and to skip it
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/binutils/Makefile.inc0
--- a/head/gnu/usr.bin/binutils/Makefile.inc0	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/binutils/Makefile.inc0	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/gnu/usr.bin/binutils/Makefile.inc0 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/gnu/usr.bin/binutils/Makefile.inc0 239272 2012-08-15 03:21:56Z gonzo $
 #
 # This is included explicitly at the top of each sub-Makefile.  We can't
 # use the normal "Makefile.inc" mechanism, because we need some of these
@@ -7,7 +7,7 @@
 VERSION=	"2.17.50 [FreeBSD] 2007-07-03"
 
 .if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
 .else
 TARGET_CPUARCH=${MACHINE_CPUARCH}
 .endif
@@ -16,7 +16,7 @@
 TARGET_OS?=	freebsd
 BINUTILS_ARCH=${TARGET_ARCH:C/amd64/x86_64/}
 TARGET_TUPLE?=	${BINUTILS_ARCH}-${TARGET_VENDOR}-${TARGET_OS}
-.if ${TARGET_ARCH} == "armeb" || \
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb" || \
 	(${TARGET_CPUARCH} == "mips" && ${TARGET_ARCH:Mmips*el} == "")
 TARGET_BIG_ENDIAN=t
 .endif
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/binutils/as/Makefile
--- a/head/gnu/usr.bin/binutils/as/Makefile	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/binutils/as/Makefile	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/gnu/usr.bin/binutils/as/Makefile 234782 2012-04-29 09:32:44Z kib $
+# $FreeBSD: head/gnu/usr.bin/binutils/as/Makefile 239272 2012-08-15 03:21:56Z gonzo $
 
 
 # BINDIR
@@ -42,6 +42,10 @@
 # DEO: why not used?
 #SRCS+=	itbl-ops.c
 
+.if ${TARGET_ARCH} == "armv6" || ${TARGET_ARCH} == "armv6eb"
+CFLAGS+=	-DCPU_DEFAULT=ARM_ARCH_V6K
+.endif
+
 .if ${TARGET_CPUARCH} == "mips"
 SRCS+=	itbl-ops.c itbl-parse.y itbl-lex.l
 .if ${TARGET_ARCH:Mmips64*} != ""
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/binutils/ld/Makefile.arm
--- a/head/gnu/usr.bin/binutils/ld/Makefile.arm	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/binutils/ld/Makefile.arm	Wed Aug 15 11:46:11 2012 +0300
@@ -1,6 +1,6 @@
-# $FreeBSD$
+# $FreeBSD: head/gnu/usr.bin/binutils/ld/Makefile.arm 239272 2012-08-15 03:21:56Z gonzo $
 
-.if ${TARGET_ARCH} == "armeb"
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
 NATIVE_EMULATION= armelfb_fbsd
 .else
 NATIVE_EMULATION= armelf_fbsd
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/binutils/libbfd/Makefile.arm
--- a/head/gnu/usr.bin/binutils/libbfd/Makefile.arm	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/binutils/libbfd/Makefile.arm	Wed Aug 15 11:46:11 2012 +0300
@@ -1,6 +1,6 @@
-# $FreeBSD$
+# $FreeBSD: head/gnu/usr.bin/binutils/libbfd/Makefile.arm 239272 2012-08-15 03:21:56Z gonzo $
 
-.if ${TARGET_ARCH} == "armeb"
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
 DEFAULT_VECTOR=	bfd_elf32_bigarm_vec
 .else
 DEFAULT_VECTOR=	bfd_elf32_littlearm_vec
@@ -14,7 +14,7 @@
 	elflink.c
 
 VECS+=	${DEFAULT_VECTOR}
-.if ${TARGET_ARCH} == "armeb"
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
 VECS+=	bfd_elf32_littlearm_vec
 .else
 VECS+=	bfd_elf32_bigarm_vec
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/cc/Makefile.inc
--- a/head/gnu/usr.bin/cc/Makefile.inc	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/cc/Makefile.inc	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/gnu/usr.bin/cc/Makefile.inc 239272 2012-08-15 03:21:56Z gonzo $
 
 .include "../Makefile.inc"
 
@@ -26,9 +26,12 @@
 CFLAGS+=	-DCROSS_COMPILE
 .endif
 
-.if ${TARGET_ARCH} == "armeb"
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
 CFLAGS += -DTARGET_ENDIAN_DEFAULT=MASK_BIG_END
 .endif
+.if ${TARGET_ARCH} == "armv6" || ${TARGET_ARCH} == "armv6eb"
+CFLAGS += -DFREEBSD_ARCH_armv6
+.endif
 
 .if ${TARGET_CPUARCH} == "mips"
 .if ${TARGET_ARCH:Mmips*el} != ""
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/cc/Makefile.tgt
--- a/head/gnu/usr.bin/cc/Makefile.tgt	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/cc/Makefile.tgt	Wed Aug 15 11:46:11 2012 +0300
@@ -1,10 +1,10 @@
-# $FreeBSD: head/gnu/usr.bin/cc/Makefile.tgt 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/gnu/usr.bin/cc/Makefile.tgt 239272 2012-08-15 03:21:56Z gonzo $
 
 # These assignments duplicate much of the functionality of
 # MACHINE_CPUARCH, but there's no easy way to export make functions...
 
 .if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
 .else
 TARGET_CPUARCH=${MACHINE_CPUARCH}
 .endif
@@ -17,7 +17,7 @@
 .if ${TARGET_ARCH} == "sparc64"
 TARGET_CPU_DEFAULT= TARGET_CPU_ultrasparc
 .endif
-.if ${TARGET_ARCH} == "armeb" || \
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb" || \
 	(${TARGET_CPUARCH} == "mips" && ${TARGET_ARCH:Mmips*el} == "")
 TARGET_BIG_ENDIAN=t
 .endif
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/gdb/Makefile.inc
--- a/head/gnu/usr.bin/gdb/Makefile.inc	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/gdb/Makefile.inc	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/gnu/usr.bin/gdb/Makefile.inc 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/gnu/usr.bin/gdb/Makefile.inc 239272 2012-08-15 03:21:56Z gonzo $
 
 VERSION= "6.1.1 [FreeBSD]"
 VENDOR= marcel
@@ -20,7 +20,7 @@
 # MACHINE_CPUARCH, but there's no easy way to export make functions...
 
 .if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
 .else
 TARGET_CPUARCH=${MACHINE_CPUARCH}
 .endif
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/gdb/libgdb/Makefile
--- a/head/gnu/usr.bin/gdb/libgdb/Makefile	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/gdb/libgdb/Makefile	Wed Aug 15 11:46:11 2012 +0300
@@ -1,10 +1,10 @@
-# $FreeBSD: head/gnu/usr.bin/gdb/libgdb/Makefile 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/gnu/usr.bin/gdb/libgdb/Makefile 239272 2012-08-15 03:21:56Z gonzo $
 
 # These assignments duplicate much of the functionality of
 # MACHINE_CPUARCH, but there's no easy way to export make functions...
 
 .if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
 .else
 TARGET_CPUARCH=${MACHINE_CPUARCH}
 .endif
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/arm/gen/__aeabi_read_tp.S
--- a/head/lib/libc/arm/gen/__aeabi_read_tp.S	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libc/arm/gen/__aeabi_read_tp.S	Wed Aug 15 11:46:11 2012 +0300
@@ -26,15 +26,21 @@
  */
 
 #include <machine/asm.h>
-__FBSDID("$FreeBSD: head/lib/libc/arm/gen/__aeabi_read_tp.S 234337 2012-04-16 09:38:20Z andrew $");
+__FBSDID("$FreeBSD: head/lib/libc/arm/gen/__aeabi_read_tp.S 239271 2012-08-15 03:09:00Z gonzo $");
 
 #include <machine/sysarch.h>
 
 ENTRY(__aeabi_read_tp)
+#ifdef ARM_TP_ADDRESS
 	ldr	r0, .Larm_tp_address
 	ldr	r0, [r0]
+#else
+	mrc	p15, 0, r0, c13, c0, 3
+#endif
 	RET
 
+#ifdef ARM_TP_ADDRESS
 .Larm_tp_address:
 	.word ARM_TP_ADDRESS
+#endif
 
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/arm/gen/_set_tp.c
--- a/head/lib/libc/arm/gen/_set_tp.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libc/arm/gen/_set_tp.c	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$FreeBSD: head/lib/libc/arm/gen/_set_tp.c 233107 2012-03-18 08:08:06Z gonzo $
+ *	$FreeBSD: head/lib/libc/arm/gen/_set_tp.c 239271 2012-08-15 03:09:00Z gonzo $
  */
 
 #include <string.h>
@@ -35,5 +35,9 @@
 _set_tp(void *tp)
 {
 
+#ifdef ARM_TP_ADDRESS
 	*((struct tcb **)ARM_TP_ADDRESS) = tp;
+#else
+	sysarch(ARM_SET_TP, tp);
+#endif
 }
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/gen/Makefile.inc
--- a/head/lib/libc/gen/Makefile.inc	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libc/gen/Makefile.inc	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #	@(#)Makefile.inc	8.6 (Berkeley) 5/4/95
-# $FreeBSD: head/lib/libc/gen/Makefile.inc 235647 2012-05-19 12:44:27Z gleb $
+# $FreeBSD: head/lib/libc/gen/Makefile.inc 239193 2012-08-11 12:07:24Z ed $
 
 # machine-independent gen sources
 .PATH: ${.CURDIR}/${LIBC_ARCH}/gen ${.CURDIR}/gen
@@ -7,7 +7,7 @@
 SRCS+=  __getosreldate.c __xuname.c \
 	_once_stub.c _pthread_stubs.c _rand48.c _spinlock_stub.c \
 	_thread_init.c \
-	alarm.c arc4random.c assert.c aux.c basename.c check_utility_compat.c \
+	alarm.c arc4random.c assert.c auxv.c basename.c check_utility_compat.c \
 	clock.c closedir.c confstr.c \
 	crypt.c ctermid.c daemon.c devname.c dirfd.c dirname.c disklabel.c \
 	dlfcn.c drand48.c elf_utils.c erand48.c err.c errlst.c errno.c \
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/gen/aux.c
--- a/head/lib/libc/gen/aux.c	Wed Aug 15 11:16:36 2012 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*-
- * Copyright 2010, 2012 Konstantin Belousov <kib at FreeBSD.ORG>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/libc/gen/aux.c 237434 2012-06-22 07:13:30Z kib $");
-
-#include "namespace.h"
-#include <elf.h>
-#include <errno.h>
-#include <link.h>
-#include <pthread.h>
-#include <string.h>
-#include "un-namespace.h"
-#include "libc_private.h"
-
-extern char **environ;
-extern int _DYNAMIC;
-#pragma weak _DYNAMIC
-
-void *__elf_aux_vector;
-static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT;
-
-static void
-init_aux_vector_once(void)
-{
-	Elf_Addr *sp;
-
-	sp = (Elf_Addr *)environ;
-	while (*sp++ != 0)
-		;
-	__elf_aux_vector = (Elf_Auxinfo *)sp;
-}
-
-void
-__init_elf_aux_vector(void)
-{
-
-	if (&_DYNAMIC != NULL)
-		return;
-	_once(&aux_vector_once, init_aux_vector_once);
-}
-
-static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
-static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
-static char *canary, *pagesizes;
-static void *timekeep;
-
-static void
-init_aux(void)
-{
-	Elf_Auxinfo *aux;
-
-	for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
-		switch (aux->a_type) {
-		case AT_CANARY:
-			canary = (char *)(aux->a_un.a_ptr);
-			break;
-
-		case AT_CANARYLEN:
-			canary_len = aux->a_un.a_val;
-			break;
-
-		case AT_PAGESIZES:
-			pagesizes = (char *)(aux->a_un.a_ptr);
-			break;
-
-		case AT_PAGESIZESLEN:
-			pagesizes_len = aux->a_un.a_val;
-			break;
-
-		case AT_PAGESZ:
-			pagesize = aux->a_un.a_val;
-			break;
-
-		case AT_OSRELDATE:
-			osreldate = aux->a_un.a_val;
-			break;
-
-		case AT_NCPUS:
-			ncpus = aux->a_un.a_val;
-			break;
-
-		case AT_TIMEKEEP:
-			timekeep = aux->a_un.a_ptr;
-			break;
-		}
-	}
-}
-
-int
-_elf_aux_info(int aux, void *buf, int buflen)
-{
-	int res;
-
-	__init_elf_aux_vector();
-	if (__elf_aux_vector == NULL)
-		return (ENOSYS);
-	_once(&aux_once, init_aux);
-
-	switch (aux) {
-	case AT_CANARY:
-		if (canary != NULL && canary_len >= buflen) {
-			memcpy(buf, canary, buflen);
-			memset(canary, 0, canary_len);
-			canary = NULL;
-			res = 0;
-		} else
-			res = ENOENT;
-		break;
-	case AT_PAGESIZES:
-		if (pagesizes != NULL && pagesizes_len >= buflen) {
-			memcpy(buf, pagesizes, buflen);
-			res = 0;
-		} else
-			res = ENOENT;
-		break;
-
-	case AT_PAGESZ:
-		if (buflen == sizeof(int)) {
-			if (pagesize != 0) {
-				*(int *)buf = pagesize;
-				res = 0;
-			} else
-				res = ENOENT;
-		} else
-			res = EINVAL;
-		break;
-	case AT_OSRELDATE:
-		if (buflen == sizeof(int)) {
-			if (osreldate != 0) {
-				*(int *)buf = osreldate;
-				res = 0;
-			} else
-				res = ENOENT;
-		} else
-			res = EINVAL;
-		break;
-	case AT_NCPUS:
-		if (buflen == sizeof(int)) {
-			if (ncpus != 0) {
-				*(int *)buf = ncpus;
-				res = 0;
-			} else
-				res = ENOENT;
-		} else
-			res = EINVAL;
-		break;
-	case AT_TIMEKEEP:
-		if (buflen == sizeof(void *)) {
-			if (timekeep != NULL) {
-				*(void **)buf = timekeep;
-				res = 0;
-			} else
-				res = ENOENT;
-		} else
-			res = EINVAL;
-		break;
-	default:
-		res = ENOENT;
-		break;
-	}
-	return (res);
-}
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/gen/auxv.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/lib/libc/gen/auxv.c	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,186 @@
+/*-
+ * Copyright 2010, 2012 Konstantin Belousov <kib at FreeBSD.ORG>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/gen/auxv.c 239193 2012-08-11 12:07:24Z ed $");
+
+#include "namespace.h"
+#include <elf.h>
+#include <errno.h>
+#include <link.h>
+#include <pthread.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+extern char **environ;
+extern int _DYNAMIC;
+#pragma weak _DYNAMIC
+
+void *__elf_aux_vector;
+static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT;
+
+static void
+init_aux_vector_once(void)
+{
+	Elf_Addr *sp;
+
+	sp = (Elf_Addr *)environ;
+	while (*sp++ != 0)
+		;
+	__elf_aux_vector = (Elf_Auxinfo *)sp;
+}
+
+void
+__init_elf_aux_vector(void)
+{
+
+	if (&_DYNAMIC != NULL)
+		return;
+	_once(&aux_vector_once, init_aux_vector_once);
+}
+
+static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
+static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
+static char *canary, *pagesizes;
+static void *timekeep;
+
+static void
+init_aux(void)
+{
+	Elf_Auxinfo *aux;
+
+	for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
+		switch (aux->a_type) {
+		case AT_CANARY:
+			canary = (char *)(aux->a_un.a_ptr);
+			break;
+
+		case AT_CANARYLEN:
+			canary_len = aux->a_un.a_val;
+			break;
+
+		case AT_PAGESIZES:
+			pagesizes = (char *)(aux->a_un.a_ptr);
+			break;
+
+		case AT_PAGESIZESLEN:
+			pagesizes_len = aux->a_un.a_val;
+			break;
+
+		case AT_PAGESZ:
+			pagesize = aux->a_un.a_val;
+			break;
+
+		case AT_OSRELDATE:
+			osreldate = aux->a_un.a_val;
+			break;
+
+		case AT_NCPUS:
+			ncpus = aux->a_un.a_val;
+			break;
+
+		case AT_TIMEKEEP:
+			timekeep = aux->a_un.a_ptr;
+			break;
+		}
+	}
+}
+
+int
+_elf_aux_info(int aux, void *buf, int buflen)
+{
+	int res;
+
+	__init_elf_aux_vector();
+	if (__elf_aux_vector == NULL)
+		return (ENOSYS);
+	_once(&aux_once, init_aux);
+
+	switch (aux) {
+	case AT_CANARY:
+		if (canary != NULL && canary_len >= buflen) {
+			memcpy(buf, canary, buflen);
+			memset(canary, 0, canary_len);
+			canary = NULL;
+			res = 0;
+		} else
+			res = ENOENT;
+		break;
+	case AT_PAGESIZES:
+		if (pagesizes != NULL && pagesizes_len >= buflen) {
+			memcpy(buf, pagesizes, buflen);
+			res = 0;
+		} else
+			res = ENOENT;
+		break;
+
+	case AT_PAGESZ:
+		if (buflen == sizeof(int)) {
+			if (pagesize != 0) {
+				*(int *)buf = pagesize;
+				res = 0;
+			} else
+				res = ENOENT;
+		} else
+			res = EINVAL;
+		break;
+	case AT_OSRELDATE:
+		if (buflen == sizeof(int)) {
+			if (osreldate != 0) {
+				*(int *)buf = osreldate;
+				res = 0;
+			} else
+				res = ENOENT;
+		} else
+			res = EINVAL;
+		break;
+	case AT_NCPUS:
+		if (buflen == sizeof(int)) {
+			if (ncpus != 0) {
+				*(int *)buf = ncpus;
+				res = 0;
+			} else
+				res = ENOENT;
+		} else
+			res = EINVAL;
+		break;
+	case AT_TIMEKEEP:
+		if (buflen == sizeof(void *)) {
+			if (timekeep != NULL) {
+				*(void **)buf = timekeep;
+				res = 0;
+			} else
+				res = ENOENT;
+		} else
+			res = EINVAL;
+		break;
+	default:
+		res = ENOENT;
+		break;
+	}
+	return (res);
+}
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/arch/arm/include/pthread_md.h
--- a/head/lib/libthr/arch/arm/include/pthread_md.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/arch/arm/include/pthread_md.h	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/libthr/arch/arm/include/pthread_md.h 231619 2012-02-14 00:17:43Z gonzo $
+ * $FreeBSD: head/lib/libthr/arch/arm/include/pthread_md.h 239270 2012-08-15 03:08:29Z gonzo $
  */
 
 /*
@@ -57,7 +57,11 @@
 static __inline void
 _tcb_set(struct tcb *tcb)
 {
-	*((struct tcb **)ARM_TP_ADDRESS) = tcb;
+#ifdef ARM_TP_ADDRESS
+	*((struct tcb **)ARM_TP_ADDRESS) = tcb;	/* avoids a system call */
+#else
+	sysarch(ARM_SET_TP, tcb);
+#endif
 }
 
 /*
@@ -66,7 +70,15 @@
 static __inline struct tcb *
 _tcb_get(void)
 {
+#ifdef ARM_TP_ADDRESS
 	return (*((struct tcb **)ARM_TP_ADDRESS));
+#else
+	struct tcb *tcb;
+
+	__asm __volatile("mrc  p15, 0, %0, c13, c0, 3"		\
+	   		 : "=r" (tcb));
+	return (tcb);
+#endif
 }
 
 extern struct pthread *_thr_initial;
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_cond.c
--- a/head/lib/libthr/thread/thr_cond.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_cond.c	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/lib/libthr/thread/thr_cond.c 239206 2012-08-12 00:56:56Z davidxu $
  */
 
 #include "namespace.h"
@@ -217,6 +217,7 @@
 	struct sleepqueue *sq;
 	int	recurse;
 	int	error;
+	int	defered;
 
 	if (curthread->wchan != NULL)
 		PANIC("thread was already on queue.");
@@ -230,13 +231,24 @@
 	 * us to check it without locking in pthread_cond_signal().
 	 */
 	cvp->__has_user_waiters = 1; 
-	curthread->will_sleep = 1;
-	(void)_mutex_cv_unlock(mp, &recurse);
+	defered = 0;
+	(void)_mutex_cv_unlock(mp, &recurse, &defered);
 	curthread->mutex_obj = mp;
 	_sleepq_add(cvp, curthread);
 	for(;;) {
 		_thr_clear_wake(curthread);
 		_sleepq_unlock(cvp);
+		if (defered) {
+			defered = 0;
+			if ((mp->m_lock.m_owner & UMUTEX_CONTESTED) == 0)
+				(void)_umtx_op_err(&mp->m_lock, UMTX_OP_MUTEX_WAKE2,
+					 mp->m_lock.m_flags, 0, 0);
+		}
+		if (curthread->nwaiter_defer > 0) {
+			_thr_wake_all(curthread->defer_waiters,
+				curthread->nwaiter_defer);
+			curthread->nwaiter_defer = 0;
+		}
 
 		if (cancel) {
 			_thr_cancel_enter2(curthread, 0);
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_kern.c
--- a/head/lib/libthr/thread/thr_kern.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_kern.c	Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/lib/libthr/thread/thr_kern.c 239200 2012-08-11 23:17:02Z davidxu $
  */
 
 #include <sys/types.h>
@@ -199,13 +199,6 @@
 	const struct timespec *abstime)
 {
 
-	curthread->will_sleep = 0;
-	if (curthread->nwaiter_defer > 0) {
-		_thr_wake_all(curthread->defer_waiters,
-			curthread->nwaiter_defer);
-		curthread->nwaiter_defer = 0;
-	}
-
 	if (curthread->wake_addr->value != 0)
 		return (0);
 
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_mutex.c
--- a/head/lib/libthr/thread/thr_mutex.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_mutex.c	Wed Aug 15 11:46:11 2012 +0300
@@ -30,7 +30,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/libthr/thread/thr_mutex.c 236135 2012-05-27 01:24:51Z davidxu $
+ * $FreeBSD: head/lib/libthr/thread/thr_mutex.c 239200 2012-08-11 23:17:02Z davidxu $
  */
 
 #include "namespace.h"
@@ -92,7 +92,7 @@
 static int	mutex_self_trylock(pthread_mutex_t);
 static int	mutex_self_lock(pthread_mutex_t,
 				const struct timespec *abstime);
-static int	mutex_unlock_common(struct pthread_mutex *, int);
+static int	mutex_unlock_common(struct pthread_mutex *, int, int *);
 static int	mutex_lock_sleep(struct pthread *, pthread_mutex_t,
 				const struct timespec *);
 
@@ -461,7 +461,7 @@
 	struct pthread_mutex *mp;
 
 	mp = *mutex;
-	return (mutex_unlock_common(mp, 0));
+	return (mutex_unlock_common(mp, 0, NULL));
 }
 
 int
@@ -476,7 +476,7 @@
 }
 
 int
-_mutex_cv_unlock(struct pthread_mutex *m, int *count)
+_mutex_cv_unlock(struct pthread_mutex *m, int *count, int *defer)
 {
 
 	/*
@@ -484,7 +484,7 @@
 	 */
 	*count = m->m_count;
 	m->m_count = 0;
-	(void)mutex_unlock_common(m, 1);
+	(void)mutex_unlock_common(m, 1, defer);
         return (0);
 }
 
@@ -629,7 +629,7 @@
 }
 
 static int
-mutex_unlock_common(struct pthread_mutex *m, int cv)
+mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer)
 {
 	struct pthread *curthread = _get_curthread();
 	uint32_t id;
@@ -657,12 +657,12 @@
 			defered = 1;
 			m->m_flags &= ~PMUTEX_FLAG_DEFERED;
         	} else
-                	defered = 0;
+			defered = 0;
 
 		DEQUEUE_MUTEX(curthread, m);
-		_thr_umutex_unlock(&m->m_lock, id);
+		_thr_umutex_unlock2(&m->m_lock, id, mtx_defer);
 
-		if (curthread->will_sleep == 0 && defered)  {
+		if (mtx_defer == NULL && defered)  {
 			_thr_wake_all(curthread->defer_waiters,
 				curthread->nwaiter_defer);
 			curthread->nwaiter_defer = 0;
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_private.h
--- a/head/lib/libthr/thread/thr_private.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_private.h	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/libthr/thread/thr_private.h 234947 2012-05-03 09:17:31Z davidxu $
+ * $FreeBSD: head/lib/libthr/thread/thr_private.h 239200 2012-08-11 23:17:02Z davidxu $
  */
 
 #ifndef _THR_PRIVATE_H
@@ -727,10 +727,10 @@
  */
 __BEGIN_DECLS
 int	_thr_setthreaded(int) __hidden;
-int	_mutex_cv_lock(struct pthread_mutex *, int count) __hidden;
-int	_mutex_cv_unlock(struct pthread_mutex *, int *count) __hidden;
-int     _mutex_cv_attach(struct pthread_mutex *, int count) __hidden;
-int     _mutex_cv_detach(struct pthread_mutex *, int *count) __hidden;
+int	_mutex_cv_lock(struct pthread_mutex *, int) __hidden;
+int	_mutex_cv_unlock(struct pthread_mutex *, int *, int *) __hidden;
+int     _mutex_cv_attach(struct pthread_mutex *, int) __hidden;
+int     _mutex_cv_detach(struct pthread_mutex *, int *) __hidden;
 int     _mutex_owned(struct pthread *, const struct pthread_mutex *) __hidden;
 int	_mutex_reinit(pthread_mutex_t *) __hidden;
 void	_mutex_fork(struct pthread *curthread) __hidden;
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_umtx.h
--- a/head/lib/libthr/thread/thr_umtx.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_umtx.h	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/libthr/thread/thr_umtx.h 233912 2012-04-05 02:24:08Z davidxu $
+ * $FreeBSD: head/lib/libthr/thread/thr_umtx.h 239200 2012-08-11 23:17:02Z davidxu $
  */
 
 #ifndef _THR_FBSD_UMTX_H_
@@ -120,7 +120,7 @@
 }
 
 static inline int
-_thr_umutex_unlock(struct umutex *mtx, uint32_t id)
+_thr_umutex_unlock2(struct umutex *mtx, uint32_t id, int *defer)
 {
 	uint32_t flags = mtx->m_flags;
 
@@ -132,8 +132,12 @@
 				return (EPERM);
 		} while (__predict_false(!atomic_cmpset_rel_32(&mtx->m_owner,
 					 owner, UMUTEX_UNOWNED)));
-		if ((owner & UMUTEX_CONTESTED))
-			(void)_umtx_op_err(mtx, UMTX_OP_MUTEX_WAKE2, flags, 0, 0);
+		if ((owner & UMUTEX_CONTESTED)) {
+			if (defer == NULL)
+				(void)_umtx_op_err(mtx, UMTX_OP_MUTEX_WAKE2, flags, 0, 0);
+			else
+				*defer = 1;
+		}
 		return (0);
 	}
     	if (atomic_cmpset_rel_32(&mtx->m_owner, id, UMUTEX_UNOWNED))
@@ -142,6 +146,12 @@
 }
 
 static inline int
+_thr_umutex_unlock(struct umutex *mtx, uint32_t id)
+{
+	return _thr_umutex_unlock2(mtx, id, NULL);
+}
+
+static inline int
 _thr_rwlock_tryrdlock(struct urwlock *rwlock, int flags)
 {
 	int32_t state;
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20.3
--- a/head/lib/libusb/libusb20.3	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20.3	Wed Aug 15 11:46:11 2012 +0300
@@ -24,9 +24,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/lib/libusb/libusb20.3 236438 2012-06-02 08:47:26Z joel $
+.\" $FreeBSD: head/lib/libusb/libusb20.3 239239 2012-08-13 18:10:52Z hselasky $
 .\"
-.Dd October 14, 2010
+.Dd August 13, 2012
 .Dt LIBUSB20 3
 .Os
 .Sh NAME
@@ -48,6 +48,7 @@
 .Fn libusb20_tr_close "struct libusb20_transfer *xfer"
 .Ft int
 .Fn libusb20_tr_open "struct libusb20_transfer *xfer" "uint32_t max_buf_size" "uint32_t max_frame_count" "uint8_t ep_no"
+.Fn libusb20_tr_open_stream "struct libusb20_transfer *xfer" "uint32_t max_buf_size" "uint32_t max_frame_count" "uint8_t ep_no" "uint16_t stream_id"
 .Ft struct libusb20_transfer*
 .Fn libusb20_tr_get_pointer "struct libusb20_device *pdev"  "uint16_t tr_index"
 .Ft uint16_t
@@ -284,6 +285,16 @@
 .
 .Pp
 .
+.Fn libusb20_tr_open_stream
+is identical to
+.Fn libusb20_tr_open
+except that a stream ID can be specified for BULK endpoints having
+such a feature.
+.Fn libusb20_tr_open
+can be used to open stream ID zero.
+.
+.Pp
+.
 .Fn libusb20_tr_get_pointer
 will return a pointer to the allocated USB transfer according to the
 .Fa pdev
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20.c
--- a/head/lib/libusb/libusb20.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/lib/libusb/libusb20.c 234491 2012-04-20 14:29:45Z hselasky $ */
+/* $FreeBSD: head/lib/libusb/libusb20.c 239239 2012-08-13 18:10:52Z hselasky $ */
 /*-
  * Copyright (c) 2008-2009 Hans Petter Selasky. All rights reserved.
  *
@@ -155,6 +155,13 @@
 libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
     uint32_t MaxFrameCount, uint8_t ep_no)
 {
+	return (libusb20_tr_open_stream(xfer, MaxBufSize, MaxFrameCount, ep_no, 0));
+}
+
+int
+libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
+    uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id)
+{
 	uint32_t size;
 	uint8_t pre_scale;
 	int error;
@@ -188,7 +195,7 @@
 	memset(xfer->ppBuffer, 0, size);
 
 	error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
-	    MaxFrameCount, ep_no, pre_scale);
+	    MaxFrameCount, ep_no, stream_id, pre_scale);
 
 	if (error) {
 		free(xfer->ppBuffer);
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20.h
--- a/head/lib/libusb/libusb20.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/lib/libusb/libusb20.h 225659 2011-09-19 08:52:06Z hselasky $ */
+/* $FreeBSD: head/lib/libusb/libusb20.h 239239 2012-08-13 18:10:52Z hselasky $ */
 /*-
  * Copyright (c) 2008-2009 Hans Petter Selasky. All rights reserved.
  * Copyright (c) 2007-2008 Daniel Drake.  All rights reserved.
@@ -202,6 +202,7 @@
 /* USB transfer operations */
 int	libusb20_tr_close(struct libusb20_transfer *xfer);
 int	libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t max_buf_size, uint32_t max_frame_count, uint8_t ep_no);
+int	libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t max_buf_size, uint32_t max_frame_count, uint8_t ep_no, uint16_t stream_id);
 struct libusb20_transfer *libusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t tr_index);
 uint16_t libusb20_tr_get_time_complete(struct libusb20_transfer *xfer);
 uint32_t libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer);
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20_int.h
--- a/head/lib/libusb/libusb20_int.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20_int.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/lib/libusb/libusb20_int.h 223495 2011-06-24 11:14:09Z hselasky $ */
+/* $FreeBSD: head/lib/libusb/libusb20_int.h 239239 2012-08-13 18:10:52Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -110,7 +110,7 @@
 typedef int (libusb20_check_connected_t)(struct libusb20_device *pdev);
 
 /* USB transfer specific */
-typedef int (libusb20_tr_open_t)(struct libusb20_transfer *xfer, uint32_t MaxBufSize, uint32_t MaxFrameCount, uint8_t ep_no, uint8_t pre_scale);
+typedef int (libusb20_tr_open_t)(struct libusb20_transfer *xfer, uint32_t MaxBufSize, uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id, uint8_t pre_scale);
 typedef int (libusb20_tr_close_t)(struct libusb20_transfer *xfer);
 typedef int (libusb20_tr_clear_stall_sync_t)(struct libusb20_transfer *xfer);
 typedef void (libusb20_tr_submit_t)(struct libusb20_transfer *xfer);
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20_ugen20.c
--- a/head/lib/libusb/libusb20_ugen20.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20_ugen20.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/lib/libusb/libusb20_ugen20.c 234491 2012-04-20 14:29:45Z hselasky $ */
+/* $FreeBSD: head/lib/libusb/libusb20_ugen20.c 239239 2012-08-13 18:10:52Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -741,9 +741,13 @@
 
 static int
 ugen20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
-    uint32_t MaxFrameCount, uint8_t ep_no, uint8_t pre_scale)
+    uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id,
+    uint8_t pre_scale)
 {
-	struct usb_fs_open temp;
+	union {
+		struct usb_fs_open fs_open;
+		struct usb_fs_open_stream fs_open_stream;
+	} temp;
 	struct usb_fs_endpoint *fsep;
 
 	if (pre_scale)
@@ -754,20 +758,26 @@
 	fsep = xfer->pdev->privBeData;
 	fsep += xfer->trIndex;
 
-	temp.max_bufsize = MaxBufSize;
-	temp.max_frames = MaxFrameCount;
-	temp.ep_index = xfer->trIndex;
-	temp.ep_no = ep_no;
+	temp.fs_open.max_bufsize = MaxBufSize;
+	temp.fs_open.max_frames = MaxFrameCount;
+	temp.fs_open.ep_index = xfer->trIndex;
+	temp.fs_open.ep_no = ep_no;
 
-	if (ioctl(xfer->pdev->file, USB_FS_OPEN, &temp)) {
-		return (LIBUSB20_ERROR_INVALID_PARAM);
+	if (stream_id != 0) {
+		temp.fs_open_stream.stream_id = stream_id;
+
+		if (ioctl(xfer->pdev->file, USB_FS_OPEN_STREAM, &temp.fs_open_stream))
+			return (LIBUSB20_ERROR_INVALID_PARAM);
+	} else {
+		if (ioctl(xfer->pdev->file, USB_FS_OPEN, &temp.fs_open))
+			return (LIBUSB20_ERROR_INVALID_PARAM);
 	}
 	/* maximums might have changed - update */
-	xfer->maxFrames = temp.max_frames;
+	xfer->maxFrames = temp.fs_open.max_frames;
 
 	/* "max_bufsize" should be multiple of "max_packet_length" */
-	xfer->maxTotalLength = temp.max_bufsize;
-	xfer->maxPacketLen = temp.max_packet_length;
+	xfer->maxTotalLength = temp.fs_open.max_bufsize;
+	xfer->maxPacketLen = temp.fs_open.max_packet_length;
 
 	/* setup buffer and length lists using zero copy */
 	fsep->ppBuffer = libusb20_pass_ptr(xfer->ppBuffer);
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/e_rem_pio2.c
--- a/head/lib/msun/src/e_rem_pio2.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/e_rem_pio2.c	Wed Aug 15 11:46:11 2012 +0300
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2.c 223302 2011-06-19 17:07:58Z kargl $");
+__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2.c 239195 2012-08-11 15:47:22Z dim $");
 
 /* __ieee754_rem_pio2(x,y)
  * 
@@ -48,10 +48,10 @@
 pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
 pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
 
-#ifndef INLINE_REM_PIO2
-extern
+#ifdef INLINE_REM_PIO2
+static __inline __always_inline
 #endif
-__inline int
+int
 __ieee754_rem_pio2(double x, double *y)
 {
 	double z,w,t,r,fn;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/e_rem_pio2f.c
--- a/head/lib/msun/src/e_rem_pio2f.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/e_rem_pio2f.c	Wed Aug 15 11:46:11 2012 +0300
@@ -15,7 +15,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2f.c 239195 2012-08-11 15:47:22Z dim $");
 
 /* __ieee754_rem_pio2f(x,y)
  *
@@ -31,7 +31,7 @@
 
 /*
  * invpio2:  53 bits of 2/pi
- * pio2_1:   first  33 bit of pi/2
+ * pio2_1:   first 25 bits of pi/2
  * pio2_1t:  pi/2 - pio2_1
  */
 
@@ -40,10 +40,10 @@
 pio2_1  =  1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
 pio2_1t =  1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
 
-#ifndef INLINE_REM_PIO2F
-extern
+#ifdef INLINE_REM_PIO2F
+static __inline __always_inline
 #endif
-__inline int
+int
 __ieee754_rem_pio2f(float x, double *y)
 {
 	double w,r,fn;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/k_cosf.c
--- a/head/lib/msun/src/k_cosf.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/k_cosf.c	Wed Aug 15 11:46:11 2012 +0300
@@ -16,7 +16,7 @@
 
 #ifndef INLINE_KERNEL_COSDF
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/k_cosf.c 239192 2012-08-11 11:13:48Z dim $");
 #endif
 
 #include "math.h"
@@ -30,10 +30,10 @@
 C2  = -0x16c087e80f1e27.0p-62,	/* -0.00138867637746099294692 */
 C3  =  0x199342e0ee5069.0p-68;	/*  0.0000243904487962774090654 */
 
-#ifndef INLINE_KERNEL_COSDF
-extern
+#ifdef INLINE_KERNEL_COSDF
+static __inline
 #endif
-__inline float
+float
 __kernel_cosdf(double x)
 {
 	double r, w, z;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/k_sinf.c
--- a/head/lib/msun/src/k_sinf.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/k_sinf.c	Wed Aug 15 11:46:11 2012 +0300
@@ -16,7 +16,7 @@
 
 #ifndef INLINE_KERNEL_SINDF
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/k_sinf.c 239192 2012-08-11 11:13:48Z dim $");
 #endif
 
 #include "math.h"
@@ -29,10 +29,10 @@
 S3 = -0x1a00f9e2cae774.0p-65,	/* -0.000198393348360966317347 */
 S4 =  0x16cd878c3b46a7.0p-71;	/*  0.0000027183114939898219064 */
 
-#ifndef INLINE_KERNEL_SINDF
-extern
+#ifdef INLINE_KERNEL_SINDF
+static __inline
 #endif
-__inline float
+float
 __kernel_sindf(double x)
 {
 	double r, s, w, z;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/k_tanf.c
--- a/head/lib/msun/src/k_tanf.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/k_tanf.c	Wed Aug 15 11:46:11 2012 +0300
@@ -15,7 +15,7 @@
 
 #ifndef INLINE_KERNEL_TANDF
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/k_tanf.c 239192 2012-08-11 11:13:48Z dim $");
 #endif
 
 #include "math.h"
@@ -32,10 +32,10 @@
   0x1362b9bf971bcd.0p-59,	/* 0.00946564784943673166728 */
 };
 
-#ifndef INLINE_KERNEL_TANDF
-extern
+#ifdef INLINE_KERNEL_TANDF
+static __inline
 #endif
-__inline float
+float
 __kernel_tandf(double x, int iy)
 {
 	double z,r,w,s,t,u;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/math_private.h
--- a/head/lib/msun/src/math_private.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/math_private.h	Wed Aug 15 11:46:11 2012 +0300
@@ -11,7 +11,7 @@
 
 /*
  * from: @(#)fdlibm.h 5.1 93/09/24
- * $FreeBSD: head/lib/msun/src/math_private.h 238722 2012-07-23 19:13:55Z kargl $
+ * $FreeBSD: head/lib/msun/src/math_private.h 239192 2012-08-11 11:13:48Z dim $
  */
 
 #ifndef _MATH_PRIVATE_H_
@@ -431,10 +431,9 @@
 int	__kernel_rem_pio2(double*,double*,int,int,int);
 
 /* double precision kernel functions */
-#ifdef INLINE_REM_PIO2
-__inline
+#ifndef INLINE_REM_PIO2
+int	__ieee754_rem_pio2(double,double*);
 #endif
-int	__ieee754_rem_pio2(double,double*);
 double	__kernel_sin(double,double,int);
 double	__kernel_cos(double,double);
 double	__kernel_tan(double,double,int);
@@ -444,22 +443,18 @@
 #endif
 
 /* float precision kernel functions */
-#ifdef INLINE_REM_PIO2F
-__inline
+#ifndef INLINE_REM_PIO2F
+int	__ieee754_rem_pio2f(float,double*);
 #endif
-int	__ieee754_rem_pio2f(float,double*);
-#ifdef INLINE_KERNEL_SINDF
-__inline
+#ifndef INLINE_KERNEL_SINDF
+float	__kernel_sindf(double);
 #endif
-float	__kernel_sindf(double);
-#ifdef INLINE_KERNEL_COSDF
-__inline
+#ifndef INLINE_KERNEL_COSDF
+float	__kernel_cosdf(double);
 #endif
-float	__kernel_cosdf(double);
-#ifdef INLINE_KERNEL_TANDF
-__inline
+#ifndef INLINE_KERNEL_TANDF
+float	__kernel_tandf(double,int);
 #endif
-float	__kernel_tandf(double,int);
 float	__ldexp_expf(float,int);
 #ifdef _COMPLEX_H
 float complex __ldexp_cexpf(float complex,int);
diff -r a301a330526b -r 49889ad5ef1f head/libexec/rtld-elf/arm/reloc.c
--- a/head/libexec/rtld-elf/arm/reloc.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/libexec/rtld-elf/arm/reloc.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
 /*	$NetBSD: mdreloc.c,v 1.23 2003/07/26 15:04:38 mrg Exp $	*/
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/libexec/rtld-elf/arm/reloc.c 234841 2012-04-30 13:31:10Z kib $");
+__FBSDID("$FreeBSD: head/libexec/rtld-elf/arm/reloc.c 239269 2012-08-15 03:07:41Z gonzo $");
 #include <sys/param.h>
 #include <sys/mman.h>
 
@@ -433,7 +433,9 @@
 void
 allocate_initial_tls(Obj_Entry *objs)
 {
+#ifdef ARM_TP_ADDRESS
 	void **_tp = (void **)ARM_TP_ADDRESS;
+#endif
 
 	/*
 	* Fix the size of the static TLS block by using the maximum
@@ -443,16 +445,27 @@
 
 	tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
 
+#ifdef ARM_TP_ADDRESS
 	(*_tp) = (void *) allocate_tls(objs, NULL, TLS_TCB_SIZE, 8);
+#else
+	sysarch(ARM_SET_TP, allocate_tls(objs, NULL, TLS_TCB_SIZE, 8));
+#endif
 }
 
 void *
 __tls_get_addr(tls_index* ti)
 {
+	char *p;
+#ifdef ARM_TP_ADDRESS
 	void **_tp = (void **)ARM_TP_ADDRESS;
-	char *p;
 
 	p = tls_get_addr_common((Elf_Addr **)(*_tp), ti->ti_module, ti->ti_offset);
+#else
+	void *_tp;
+	__asm __volatile("mrc  p15, 0, %0, c13, c0, 3"		\
+	    : "=r" (_tp));
+	p = tls_get_addr_common((Elf_Addr **)(_tp), ti->ti_module, ti->ti_offset);
+#endif
 
 	return (p);
 }
diff -r a301a330526b -r 49889ad5ef1f head/libexec/rtld-elf/rtld.c
--- a/head/libexec/rtld-elf/rtld.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/libexec/rtld-elf/rtld.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: head/libexec/rtld-elf/rtld.c 238471 2012-07-15 10:53:48Z kib $
+ * $FreeBSD: head/libexec/rtld-elf/rtld.c 239253 2012-08-14 13:28:30Z kan $
  */
 
 /*
@@ -1743,6 +1743,26 @@
     root->dag_inited = true;
 }
 
+static void
+process_nodelete(Obj_Entry *root)
+{
+	const Objlist_Entry *elm;
+
+	/*
+	 * Walk over object DAG and process every dependent object that
+	 * is marked as DF_1_NODELETE. They need to grow their own DAG,
+	 * which then should have its reference upped separately.
+	 */
+	STAILQ_FOREACH(elm, &root->dagmembers, link) {
+		if (elm->obj != NULL && elm->obj->z_nodelete &&
+		    !elm->obj->ref_nodel) {
+			dbg("obj %s nodelete", elm->obj->path);
+			init_dag(elm->obj);
+			ref_dag(elm->obj);
+			elm->obj->ref_nodel = true;
+		}
+	}
+}
 /*
  * Initialize the dynamic linker.  The argument is the address at which
  * the dynamic linker has been mapped into memory.  The primary task of
@@ -1932,12 +1952,6 @@
 	  flags & ~RTLD_LO_NOLOAD);
 	if (obj1 == NULL && !ld_tracing && (flags & RTLD_LO_FILTEES) == 0)
 	    return (-1);
-	if (obj1 != NULL && obj1->z_nodelete && !obj1->ref_nodel) {
-	    dbg("obj %s nodelete", obj1->path);
-	    init_dag(obj1);
-	    ref_dag(obj1);
-	    obj1->ref_nodel = true;
-	}
     }
     return (0);
 }
@@ -2833,8 +2847,14 @@
 		/* Make list of init functions to call. */
 		initlist_add_objects(obj, &obj->next, &initlist);
 	    }
+	    /*
+	     * Process all no_delete objects here, given them own
+	     * DAGs to prevent their dependencies from being unloaded.
+	     * This has to be done after we have loaded all of the
+	     * dependencies, so that we do not miss any.
+	     */
+	     process_nodelete(obj);
 	} else {
-
 	    /*
 	     * Bump the reference counts for objects on this DAG.  If
 	     * this is the first dlopen() call for the object that was
diff -r a301a330526b -r 49889ad5ef1f head/share/man/man4/sched_ule.4
--- a/head/share/man/man4/sched_ule.4	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/share/man/man4/sched_ule.4	Wed Aug 15 11:46:11 2012 +0300
@@ -22,9 +22,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/share/man/man4/sched_ule.4 239185 2012-08-10 19:02:49Z mav $
 .\"
-.Dd January 21, 2008
+.Dd August 10, 2012
 .Dt SCHED_ULE 4
 .Os
 .Sh NAME
@@ -59,6 +59,9 @@
 .Bl -tag -width indent
 .It Va kern.sched.name
 This read-only sysctl reports the name of the active scheduler.
+.It Va kern.sched.quantum
+This read-write sysctl reports or sets the length of the quantum (in
+micro-seconds) granted to a thread.
 .El
 .Sh SEE ALSO
 .Xr sched_4bsd 4 ,
diff -r a301a330526b -r 49889ad5ef1f head/share/mk/bsd.cpu.mk
--- a/head/share/mk/bsd.cpu.mk	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/share/mk/bsd.cpu.mk	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/share/mk/bsd.cpu.mk 220863 2011-04-19 18:09:21Z dim $
+# $FreeBSD: head/share/mk/bsd.cpu.mk 239272 2012-08-15 03:21:56Z gonzo $
 
 # Set default CPU compile flags and baseline CPUTYPE for each arch.  The
 # compile flags must support the minimum CPU type for each architecture but
@@ -99,8 +99,13 @@
 #_CPUCFLAGS = -mcpu=xscale
 #_CPUCFLAGS = -march=armv5te -D__XSCALE__
 _CPUCFLAGS = -march=armv5te -mtune=xscale -D__XSCALE__
+_CPUCFLAGS = -march=armv5te -D__XSCALE__ -DARM_WANT_TP_ADDRESS
+. elif ${CPUTYPE} == "armv6"
+_CPUCFLAGS = -march=${CPUTYPE} -DARM_ARCH_6=1
+. elif ${CPUTYPE} == "cortexa"
+_CPUCFLAGS = -march=armv6 -DARM_ARCH_6=1 -mfpu=vfp
 .  else
-_CPUCFLAGS = -mcpu=${CPUTYPE}
+_CPUCFLAGS = -mcpu=${CPUTYPE} -DARM_WANT_TP_ADDRESS
 .  endif
 . elif ${MACHINE_ARCH} == "powerpc"
 .  if ${CPUTYPE} == "e500"
diff -r a301a330526b -r 49889ad5ef1f head/share/mk/bsd.endian.mk
--- a/head/share/mk/bsd.endian.mk	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/share/mk/bsd.endian.mk	Wed Aug 15 11:46:11 2012 +0300
@@ -1,15 +1,17 @@
-# $FreeBSD: head/share/mk/bsd.endian.mk 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/share/mk/bsd.endian.mk 239272 2012-08-15 03:21:56Z gonzo $
 
 .if ${MACHINE_ARCH} == "amd64" || \
     ${MACHINE_ARCH} == "i386" || \
     ${MACHINE_ARCH} == "ia64" || \
     ${MACHINE_ARCH} == "arm"  || \
+    ${MACHINE_ARCH} == "armv6"  || \
     ${MACHINE_ARCH:Mmips*el} != ""
 TARGET_ENDIANNESS= 1234
 .elif ${MACHINE_ARCH} == "powerpc" || \
     ${MACHINE_ARCH} == "powerpc64" || \
     ${MACHINE_ARCH} == "sparc64" || \
     ${MACHINE_ARCH} == "armeb" || \
+    ${MACHINE_ARCH} == "armv6eb" || \
     ${MACHINE_ARCH:Mmips*} != ""
 TARGET_ENDIANNESS= 4321
 .endif
diff -r a301a330526b -r 49889ad5ef1f head/share/mk/sys.mk
--- a/head/share/mk/sys.mk	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/share/mk/sys.mk	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #	from: @(#)sys.mk	8.2 (Berkeley) 3/21/94
-# $FreeBSD: head/share/mk/sys.mk 234575 2012-04-22 17:14:11Z imp $
+# $FreeBSD: head/share/mk/sys.mk 239272 2012-08-15 03:21:56Z gonzo $
 
 unix		?=	We run FreeBSD, not UNIX.
 .FreeBSD	?=	true
@@ -13,7 +13,7 @@
 # and/or endian.  This is called MACHINE_CPU in NetBSD, but that's used
 # for something different in FreeBSD.
 #
-MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
 .endif
 
 # If the special target .POSIX appears (without prerequisites or
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/amd64/mp_machdep.c
--- a/head/sys/amd64/amd64/mp_machdep.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/amd64/mp_machdep.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/mp_machdep.c 237037 2012-06-13 22:53:56Z jkim $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/mp_machdep.c 239241 2012-08-13 18:52:51Z jhb $");
 
 #include "opt_cpu.h"
 #include "opt_kstack_pages.h"
@@ -1036,26 +1036,15 @@
 {
 
 	/*
-	 * first we do an INIT/RESET IPI this INIT IPI might be run, reseting
+	 * first we do an INIT IPI: this INIT IPI might be run, resetting
 	 * and running the target CPU. OR this INIT IPI might be latched (P5
 	 * bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
 	 * ignored.
 	 */
-
-	/* do an INIT IPI: assert RESET */
 	lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
 	    APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
-
-	/* wait for pending status end */
 	lapic_ipi_wait(-1);
-
-	/* do an INIT IPI: deassert RESET */
-	lapic_ipi_raw(APIC_DEST_ALLESELF | APIC_TRIGMOD_LEVEL |
-	    APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, 0);
-
-	/* wait for pending status end */
 	DELAY(10000);		/* wait ~10mS */
-	lapic_ipi_wait(-1);
 
 	/*
 	 * next we do a STARTUP IPI: the previous INIT IPI might still be
@@ -1065,8 +1054,6 @@
 	 * run. OR the previous INIT IPI was ignored. and this STARTUP IPI
 	 * will run.
 	 */
-
-	/* do a STARTUP IPI */
 	lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
 	    APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
 	    vector, apic_id);
@@ -1079,7 +1066,6 @@
 	 * this STARTUP IPI will be ignored, as only ONE STARTUP IPI is
 	 * recognized after hardware RESET or INIT IPI.
 	 */
-
 	lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
 	    APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
 	    vector, apic_id);
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/amd64/trap.c
--- a/head/sys/amd64/amd64/trap.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/amd64/trap.c	Wed Aug 15 11:46:11 2012 +0300
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/trap.c 238623 2012-07-19 19:09:12Z kib $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/trap.c 239252 2012-08-14 12:15:01Z kib $");
 
 /*
  * AMD64 Trap and System call handling
@@ -176,9 +176,14 @@
 SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
 	&panic_on_nmi, 0, "Panic on NMI");
 TUNABLE_INT("machdep.panic_on_nmi", &panic_on_nmi);
-static int prot_fault_translation = 0;
+static int prot_fault_translation;
 SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
-	&prot_fault_translation, 0, "Select signal to deliver on protection fault");
+    &prot_fault_translation, 0,
+    "Select signal to deliver on protection fault");
+static int uprintf_signal;
+SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RW,
+    &uprintf_signal, 0,
+    "Print debugging information on trap signal to ctty");
 
 /*
  * Exception, fault, and trap interface to the FreeBSD kernel.
@@ -610,6 +615,19 @@
 	ksi.ksi_code = ucode;
 	ksi.ksi_trapno = type;
 	ksi.ksi_addr = (void *)addr;
+	if (uprintf_signal) {
+		uprintf("pid %d comm %s: signal %d err %lx code %d type %d "
+		    "addr 0x%lx <%02x %02x %02x %02x %02x %02x %02x %02x>\n",
+		    p->p_pid, p->p_comm, i, frame->tf_err, ucode, type, addr,
+		    fubyte((void *)(frame->tf_rip + 0)),
+		    fubyte((void *)(frame->tf_rip + 1)),
+		    fubyte((void *)(frame->tf_rip + 2)),
+		    fubyte((void *)(frame->tf_rip + 3)),
+		    fubyte((void *)(frame->tf_rip + 4)),
+		    fubyte((void *)(frame->tf_rip + 5)),
+		    fubyte((void *)(frame->tf_rip + 6)),
+		    fubyte((void *)(frame->tf_rip + 7)));
+	}
 	trapsignal(td, &ksi);
 
 user:
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/conf/XENHVM
--- a/head/sys/amd64/conf/XENHVM	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/conf/XENHVM	Wed Aug 15 11:46:11 2012 +0300
@@ -1,13 +1,11 @@
 #
 # XENHVM -- Xen HVM kernel configuration file for FreeBSD/amd64
 #
-# $FreeBSD$
+# $FreeBSD: head/sys/amd64/conf/XENHVM 239228 2012-08-13 07:36:57Z cperciva $
 #
 include		GENERIC
 ident		XENHVM
 
-makeoptions	MODULES_OVERRIDE=""
-
 #
 # Adaptive locks rely on a lock-free pointer read to determine the run state
 # of the thread holding a lock when under contention; under a virtualisation
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/ia32/ia32_sigtramp.S
--- a/head/sys/amd64/ia32/ia32_sigtramp.S	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/ia32/ia32_sigtramp.S	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/amd64/ia32/ia32_sigtramp.S 223254 2011-06-18 12:13:28Z kib $
+ * $FreeBSD: head/sys/amd64/ia32/ia32_sigtramp.S 239251 2012-08-14 12:13:27Z kib $
  */
 
 #include "opt_compat.h"
@@ -91,8 +91,29 @@
  */
 	ALIGN_TEXT
 lcall_tramp:
+	.code64
+	/*
+	 * There, we are in 64bit mode and need to return to 32bit.
+	 * First, convert call frame from 64 to 32 bit format.
+	 */
+	pushq	%rax
+	movl	16(%rsp),%eax
+	movl	%eax,20(%rsp)	/* ret %cs */
+	movl	8(%rsp),%eax
+	movl	%eax,16(%rsp)	/* ret %rip -> %eip */
+	popq	%rax
+	addq	$8,%rsp
+	/* Now return to 32bit */
+	pushq	$0x33 /* _ucode32sel UPL */
+	callq	1f
+1:
+	addq	$2f-1b,(%rsp)
+	lretq
+2:
+	/* Back in 32bit mode */
+	.code32
 	cmpl	$SYS_vfork,%eax
-	je	2f
+	je	4f
 	pushl	%ebp
 	movl	%esp,%ebp
 	pushl	0x24(%ebp) /* arg 6 */
@@ -101,19 +122,19 @@
 	pushl	0x18(%ebp)
 	pushl	0x14(%ebp)
 	pushl	0x10(%ebp) /* arg 1 */
-	pushl	0xc(%ebp) /* gap */
+	pushl	0xc(%ebp)  /* gap */
 	int	$0x80
 	leavel
-1:
+3:
 	lretl
-2:
+4:
 	/*
 	 * vfork handling is special and relies on the libc stub saving
 	 * the return ip in %ecx.  If vfork failed, then there is no
 	 * child which can corrupt the frame created by call gate.
 	 */
 	int	$0x80
-	jb	1b
+	jb	3b
 	addl	$8,%esp
 	jmpl	*%ecx
 #endif
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/ia32/ia32_syscall.c
--- a/head/sys/amd64/ia32/ia32_syscall.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/ia32/ia32_syscall.c	Wed Aug 15 11:46:11 2012 +0300
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_syscall.c 225474 2011-09-11 16:05:09Z kib $");
+__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_syscall.c 239251 2012-08-14 12:13:27Z kib $");
 
 /*
  * 386 Trap and System call handling
@@ -244,7 +244,7 @@
 	bzero(ssd, sizeof(*ssd));
 	ssd->gd_looffset = lcall_addr;
 	ssd->gd_hioffset = lcall_addr >> 16;
-	ssd->gd_selector = _ucode32sel;
+	ssd->gd_selector = _ucodesel;
 	ssd->gd_type = SDT_SYSCGT;
 	ssd->gd_dpl = SEL_UPL;
 	ssd->gd_p = 1;
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/include/param.h
--- a/head/sys/amd64/include/param.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/include/param.h	Wed Aug 15 11:46:11 2012 +0300
@@ -36,7 +36,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)param.h	8.1 (Berkeley) 6/10/93
- * $FreeBSD: head/sys/amd64/include/param.h 224217 2011-07-19 13:00:30Z attilio $
+ * $FreeBSD: head/sys/amd64/include/param.h 239255 2012-08-14 17:01:21Z des $
  */
 
 
@@ -123,14 +123,6 @@
 #define	KSTACK_GUARD_PAGES 1	/* pages of kstack guard; 0 disables */
 
 /*
- * Ceiling on amount of swblock kva space, can be changed via
- * the kern.maxswzone /boot/loader.conf variable.
- */
-#ifndef VM_SWZONE_SIZE_MAX
-#define	VM_SWZONE_SIZE_MAX	(32 * 1024 * 1024)
-#endif
-
-/*
  * Mach derived conversion macros
  */
 #define	round_page(x)	((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK))
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/common/disk.c
--- a/head/sys/boot/common/disk.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/boot/common/disk.c	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/common/disk.c 239058 2012-08-05 12:15:15Z ae $");
+__FBSDID("$FreeBSD: head/sys/boot/common/disk.c 239232 2012-08-13 13:33:21Z ae $");
 
 #include <sys/disk.h>
 #include <stand.h>
@@ -162,7 +162,7 @@
 	dev->d_opendata = od;
 	od->mediasize = mediasize;
 	od->sectorsize = sectorsize;
-	DEBUG("open '%s', unit %d slice %d partition %d",
+	DEBUG("%s unit %d, slice %d, partition %d",
 	    disk_fmtdev(dev), dev->d_unit, dev->d_slice, dev->d_partition);
 
 	/* Determine disk layout. */
@@ -173,16 +173,30 @@
 		rc = ENXIO;
 		goto out;
 	}
-	if (dev->d_slice > 0) {
+	if (ptable_gettype(od->table) == PTABLE_BSD &&
+	    dev->d_partition >= 0) {
+		/* It doesn't matter what value has d_slice */
+		rc = ptable_getpart(od->table, &part, dev->d_partition);
+		if (rc == 0)
+			dev->d_offset = part.start;
+	} else if (dev->d_slice > 0) {
 		/* Try to get information about partition */
 		rc = ptable_getpart(od->table, &part, dev->d_slice);
 		if (rc != 0) /* Partition doesn't exist */
 			goto out;
 		dev->d_offset = part.start;
-		if (dev->d_partition == -1 ||
-		    dev->d_partition == 255)
+		if (dev->d_partition == 255)
 			goto out; /* Nothing more to do */
-
+		if (dev->d_partition == -1) {
+			/*
+			 * If we are looking at a BSD slice, and the
+			 * partition is < 0, assume the 'a' partition.
+			 */
+			if (part.type == PART_FREEBSD)
+				dev->d_partition = 0;
+			else
+				goto out;
+		}
 		/* Try to read BSD label */
 		table = ptable_open(dev, part.end - part.start + 1,
 		    od->sectorsize, ptblread);
@@ -206,10 +220,14 @@
 out:
 	if (table != NULL)
 		ptable_close(table);
+
 	if (rc != 0) {
 		if (od->table != NULL)
 			ptable_close(od->table);
 		free(od);
+		DEBUG("%s could not open", disk_fmtdev(dev));
+	} else {
+		DEBUG("%s offset %lld", disk_fmtdev(dev), dev->d_offset);
 	}
 	return (rc);
 }
@@ -220,6 +238,7 @@
 	struct open_disk *od;
 
 	od = (struct open_disk *)dev->d_opendata;
+	DEBUG("%s closed", disk_fmtdev(dev));
 	ptable_close(od->table);
 	free(od);
 	return (0);
@@ -242,9 +261,9 @@
 #ifdef LOADER_MBR_SUPPORT
 			cp += sprintf(cp, "s%d", dev->d_slice);
 #endif
-		if (dev->d_partition >= 0)
-			cp += sprintf(cp, "%c", dev->d_partition + 'a');
 	}
+	if (dev->d_partition >= 0)
+		cp += sprintf(cp, "%c", dev->d_partition + 'a');
 	strcat(cp, ":");
 	return (buf);
 }
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/common/disk.h
--- a/head/sys/boot/common/disk.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/boot/common/disk.h	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/boot/common/disk.h 239058 2012-08-05 12:15:15Z ae $
+ * $FreeBSD: head/sys/boot/common/disk.h 239230 2012-08-13 13:08:30Z ae $
  */
 
 /*
@@ -45,6 +45,11 @@
  * 	d_slice = MBR slice number (typically 1..4)
  * 	d_partition = disklabel partition (typically 0..7)
  *
+ * BSD disklabel partition on the true dedicated disk:
+ *
+ * 	d_slice = -1
+ * 	d_partition = disklabel partition (typically 0..7)
+ *
  * GPT partition:
  *
  * 	d_slice = GPT partition number (typically 1..N)
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/common/loader.8
--- a/head/sys/boot/common/loader.8	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/boot/common/loader.8	Wed Aug 15 11:46:11 2012 +0300
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/sys/boot/common/loader.8 235873 2012-05-24 02:24:03Z wblock $
+.\" $FreeBSD: head/sys/boot/common/loader.8 239255 2012-08-14 17:01:21Z des $
 .\"
 .Dd January 7, 2012
 .Dt LOADER 8
@@ -613,17 +613,26 @@
 for details.
 .It Va kern.maxswzone
 Limits the amount of KVM to be used to hold swap
-meta information, which directly governs the
-maximum amount of swap the system can support.
-This value is specified in bytes of KVA space
-and defaults to 32MBytes on i386 and amd64.
-Care should be taken
-to not reduce this value such that the actual
-amount of configured swap exceeds 1/2 the
-kernel-supported swap.
-The default of 32MB allows
-the kernel to support a maximum of ~7GB of swap.
-Only change
+metadata, which directly governs the
+maximum amount of swap the system can support,
+at the rate of approximately 200 MB of swap space
+per 1 MB of metadata.
+This value is specified in bytes of KVA space.
+If no value is provided, the system allocates
+enough memory to handle an amount of swap
+that corresponds to eight times the amount of
+physical memory present in the system.
+.Pp
+Note that swap metadata can be fragmented,
+which means that the system can run out of
+space before it reaches the theoretical limit.
+Therefore, care should be taken to not configure
+more swap than approximately half of the
+theoretical maximum.
+.Pp
+Running out of space for swap metadata can leave
+the system in an unrecoverable state.
+Therefore, you should only change
 this parameter if you need to greatly extend the
 KVM reservation for other resources such as the
 buffer cache or
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/beaglebone.dts
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/beaglebone.dts	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at Freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * $FreeBSD: head/sys/boot/fdt/dts/beaglebone.dts 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+	model = "beaglebone";
+	compatible = "beaglebone", "ti,am335x";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	interrupt-parent = <&AINTC>;
+
+	aliases {
+		soc = &SOC;
+		uart0 = &uart0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = < 0x80000000 0x10000000 >;	/* 256MB RAM */
+	};
+
+	SOC: am335x {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		bus-frequency = <0>;
+
+		AINTC: interrupt-controller at 48200000 {
+			compatible = "ti,aintc";
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			reg =	< 0x48200000 0x1000 >;
+		};
+
+		scm at 44e10000 {
+			compatible = "ti,scm";
+			reg =	< 0x44e10000 0x2000 >;
+			/* Set of triplets < padname, muxname, padstate> */
+			scm-pad-config =
+				/* I2C0 */
+				"I2C0_SDA", "I2C0_SDA","i2c",
+				"I2C0_SCL", "I2C0_SCL","i2c",
+				/* Ethernet */
+				"MII1_RX_ER", "gmii1_rxerr", "input_pulldown",
+				"MII1_TX_EN", "gmii1_txen", "output",
+				"MII1_RX_DV", "gmii1_rxdv", "input_pulldown",
+				"MII1_TXD3", "gmii1_txd3", "output",
+				"MII1_TXD2", "gmii1_txd2", "output",
+				"MII1_TXD1", "gmii1_txd1", "output",
+				"MII1_TXD0", "gmii1_txd0", "output",
+				"MII1_TX_CLK", "gmii1_txclk", "input_pulldown",
+				"MII1_RX_CLK", "gmii1_rxclk", "input_pulldown",
+				"MII1_RXD3", "gmii1_rxd3", "input_pulldown",
+				"MII1_RXD2", "gmii1_rxd2", "input_pulldown",
+				"MII1_RXD1", "gmii1_rxd1",  "input_pulldown",
+				"MII1_RXD0", "gmii1_rxd0",  "input_pulldown",
+				"MDIO", "mdio_data", "input_pullup",
+				"MDC", "mdio_clk", "output_pullup",
+				/* MMCSD0 */
+				"MMC0_CMD", "mmc0_cmd", "input_pullup",
+				"MMC0_CLK", "mmc0_clk", "input_pullup",
+				"MMC0_DAT0", "mmc0_dat0", "input_pullup",
+				"MMC0_DAT1", "mmc0_dat1", "input_pullup",
+				"MMC0_DAT2", "mmc0_dat2", "input_pullup",
+				"MMC0_DAT3", "mmc0_dat3", "input_pullup";
+		};
+
+		prcm at 44E00000 {
+			compatible = "am335x,prcm";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = < 0x44E00000 0x1300 >;
+		};
+
+		dmtimers at 44E05000 {
+			compatible = "ti,am335x-dmtimer";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg =	< 0x44E05000 0x1000
+				  0x44E31000 0x1000
+				  0x48040000 0x1000
+				  0x48042000 0x1000
+				  0x48044000 0x1000
+				  0x48046000 0x1000
+				  0x48048000 0x1000
+				  0x4804A000 0x1000 >;
+			interrupts = < 66 67 68 69 92 93 94 95 >;
+			interrupt-parent = <&AINTC>;
+		};
+
+		GPIO: gpio {
+			#gpio-cells = <3>;
+			compatible = "ti,gpio";
+			gpio-controller;
+			reg =<	0x44E07000 0x1000
+				0x4804C000 0x1000
+				0x481AC000 0x1000
+				0x481AE000 0x1000 >;
+			interrupts = < 17 19 21 23 >;
+			interrupt-parent = <&AINTC>;
+		};
+
+
+		uart0: serial at 44E09000 {
+			compatible = "ns16550";
+			reg = <0x44E09000 0x1000>;
+			reg-shift = <2>;
+			interrupts = < 72 >;
+			interrupt-parent = <&AINTC>;
+			clock-frequency = < 48000000 >; /* FIXME */
+		};
+
+		edma3 at 49000000 {
+			compatible = "ti,edma3";
+			reg =<	0x49000000 0x100000	/* Channel Controller Regs */
+				0x49800000 0x100000	/* Transfer Controller 0 Regs */
+				0x49900000 0x100000	/* Transfer Controller 1 Regs */
+				0x49a00000 0x100000 >;	/* Transfer Controller 2 Regs */
+			interrupts = <12 13 14>;
+			interrupt-parent = <&AINTC>;
+		};
+
+		mmchs0 at 4809C000 {
+			compatible = "ti,mmchs";
+			reg =<0x48060000 0x1000 >;
+			interrupts = <64>;
+			interrupt-parent = <&AINTC>;
+			mmchs-device-id = <0>;
+		};
+
+		enet0: ethernet at 4A100000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "ti,cpsw";
+			reg = <0x4A100000 0x3000>;
+			interrupts = <40 41 42 43>;
+			interrupt-parent = <&AINTC>;
+			phy-handle = <&phy0>;
+			mdio at 0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "ti,cpsw-mdio";
+				phy0: ethernet-phy at 0 {
+					reg = <0x0>;
+				};
+			};
+		};
+
+		i2c0: i2c at 44e0b000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "ti,i2c";
+			reg =<	0x44e0b000 0x1000 >;
+			interrupts = <70>;
+			interrupt-parent = <&AINTC>;
+			i2c-device-id = <0>;
+			pmic at 24 {
+				compatible = "ti,am335x-pmic";
+				reg = <0x24>;
+			};
+		};
+	};
+
+	chosen {
+		stdin = "uart0";
+		stdout = "uart0";
+	};
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/db88f78160.dts
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/db88f78160.dts	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * Copyright (c) 2010-2011 Semihalf
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Marvell DB-88F78160 Device Tree Source.
+ *
+ * $FreeBSD: head/sys/boot/fdt/dts/db88f78160.dts 239277 2012-08-15 05:15:49Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+	model = "mrvl,DB-78160";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		serial0 = &serial0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "ARM,88VS584";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;	// L1, 32K
+			i-cache-size = <0x8000>;	// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <200000000>;
+			clock-frequency = <0>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x40000000>;		// 2G at 0x0
+	};
+
+	soc78160 at d0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges = <0x0 0xd0000000 0x00100000>;
+		bus-frequency = <0>;
+
+
+		MPIC: mpic at 20a00 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			reg = <0x20a00 0x500 0x21000 0x800>;
+			compatible = "mrvl,mpic";
+		};
+
+		rtc at 10300 {
+			compatible = "mrvl,rtc";
+			reg = <0x10300 0x08>;
+		};
+
+		timer at 21840 {
+			compatible = "mrvl,timer";
+			reg = <0x21840 0x30>;
+			interrupts = <5>;
+			interrupt-parent = <&MPIC>;
+			mrvl,has-wdt;
+		};
+
+		twsi at 11000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "mrvl,twsi";
+			reg = <0x11000 0x20>;
+			interrupts = <31>;
+			interrupt-parent = <&MPIC>;
+		};
+
+		twsi at 11100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "mrvl,twsi";
+			reg = <0x11100 0x20>;
+			interrupts = <32>;
+			interrupt-parent = <&MPIC>;
+		};
+
+		serial0: serial at 12000 {
+			compatible = "ns16550";
+			reg = <0x12000 0x20>;
+			reg-shift = <2>;
+			current-speed = <115200>;
+			clock-frequency = <200000000>;
+			interrupts = <41>;
+			interrupt-parent = <&MPIC>;
+		};
+
+		serial1: serial at 12100 {
+			compatible = "ns16550";
+			reg = <0x12100 0x20>;
+			reg-shift = <2>;
+			current-speed = <115200>;
+			clock-frequency = <200000000>;
+			interrupts = <42>;
+			interrupt-parent = <&MPIC>;
+		};
+
+		serial2: serial at 12200 {
+			compatible = "ns16550";
+			reg = <0x12200 0x20>;
+			reg-shift = <2>;
+			current-speed = <115200>;
+			clock-frequency = <200000000>;
+			interrupts = <43>;
+			interrupt-parent = <&MPIC>;
+		};
+		
+		serial3: serial at 12300 {
+			compatible = "ns16550";
+			reg = <0x12300 0x20>;
+			reg-shift = <2>;
+			current-speed = <115200>;
+			clock-frequency = <200000000>;
+			interrupts = <44>;
+			interrupt-parent = <&MPIC>;
+		};
+
+		MPP: mpp at 10000 {
+			#pin-cells = <2>;
+			compatible = "mrvl,mpp";
+			reg = <0x18000 0x34>;
+			pin-count = <68>;
+			pin-map = <
+				0  1		/* MPP[0]:  GE1_TXCLK */
+				1  1		/* MPP[1]:  GE1_TXCTL */
+				2  1		/* MPP[2]:  GE1_RXCTL */
+				3  1		/* MPP[3]:  GE1_RXCLK */
+				4  1		/* MPP[4]:  GE1_TXD[0] */
+				5  1		/* MPP[5]:  GE1_TXD[1] */
+				6  1		/* MPP[6]:  GE1_TXD[2] */
+				7  1		/* MPP[7]:  GE1_TXD[3] */
+				8  1		/* MPP[8]:  GE1_RXD[0] */
+				9  1		/* MPP[9]:  GE1_RXD[1] */
+				10 1		/* MPP[10]: GE1_RXD[2] */
+				11 1		/* MPP[11]: GE1_RXD[3] */
+				12 2		/* MPP[13]: SYSRST_OUTn */
+				13 2		/* MPP[13]: SYSRST_OUTn */
+				14 2		/* MPP[14]: SATA1_ACTn */
+				15 2		/* MPP[15]: SATA0_ACTn */
+				16 2		/* MPP[16]: UA2_TXD */
+				17 2		/* MPP[17]: UA2_RXD */
+				18 2		/* MPP[18]: <UNKNOWN> */
+				19 2		/* MPP[19]: <UNKNOWN> */
+				20 2		/* MPP[20]: <UNKNOWN> */
+				21 2		/* MPP[21]: <UNKNOWN> */
+				22 2		/* MPP[22]: UA3_TXD */
+				23 2
+				24 0
+				25 0
+				26 0
+				27 0
+				28 4
+				29 0
+				30 1
+				31 1
+				32 1
+				33 1
+				34 1
+				35 1
+				36 1
+				37 1
+				38 1
+				39 1
+				40 0
+				41 3
+				42 1
+				43 1
+				44 2
+				45 2
+				46 4
+				47 3
+				48 0
+				49 1
+				50 1
+				51 1
+				52 1
+				53 1
+				54 1
+				55 1
+				56 1
+				57 0
+				58 1
+				59 1
+				60 1
+				61 1
+				62 1
+				63 1
+				64 1
+				65 1
+				66 1
+				67 2 >;
+		};
+
+		usb at 50000 {
+			compatible = "mrvl,usb-ehci", "usb-ehci";
+			reg = <0x50000 0x1000>;
+			interrupts = <124 45>;
+			interrupt-parent = <&MPIC>;
+		};
+
+		usb at 51000 {
+			compatible = "mrvl,usb-ehci", "usb-ehci";
+			reg = <0x51000 0x1000>;
+			interrupts = <124 46>;
+			interrupt-parent = <&MPIC>;
+		};
+
+		usb at 52000 {
+			compatible = "mrvl,usb-ehci", "usb-ehci";
+			reg = <0x52000 0x1000>;
+			interrupts = <124 47>;
+			interrupt-parent = <&MPIC>;
+		};
+
+		enet0: ethernet at 72000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			model = "V2";
+			compatible = "mrvl,ge";
+			reg = <0x72000 0x2000>;
+			ranges = <0x0 0x72000 0x2000>;
+			local-mac-address = [ 00 04 01 07 84 60 ];
+			interrupts = <67 68 122 >;
+			interrupt-parent = <&MPIC>;
+			phy-handle = <&phy0>;
+			has-neta;
+
+			mdio at 0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "mrvl,mdio";
+
+				phy0: ethernet-phy at 0 {
+					reg = <0x0>;
+				};
+				phy1: ethernet-phy at 1 {
+					reg = <0x1>;
+				};
+				phy2: ethernet-phy at 2 {
+					reg = <0x19>;
+				};
+				phy3: ethernet-phy at 3 {
+					reg = <0x1b>;
+				};
+			};
+		};
+	};
+
+	pci0: pcie at f1040000 {
+		compatible = "mrvl,pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xf1040000 0x2000>;
+		bus-range = <0 255>;
+		ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xa0000000 0x0 0x08000000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&MPIC>;
+		interrupts = <58>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			0x0800 0x0 0x0 0x1 &MPIC 0x20
+			0x0800 0x0 0x0 0x2 &MPIC 0x21
+			0x0800 0x0 0x0 0x3 &MPIC 0x22
+			0x0800 0x0 0x0 0x4 &MPIC 0x23
+			>;
+	};
+
+	chosen {
+		stdin = "serial0";
+		stdout = "serial0";
+		stddbg = "serial0";
+	};
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/ea3250.dts
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/ea3250.dts	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2011 Jakub Klama <jceel at FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Embedded Artists LPC3250-Kit Device Tree Source.
+ *
+ * $FreeBSD: head/sys/boot/fdt/dts/ea3250.dts 239278 2012-08-15 05:37:10Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+	model = "ea,LPC3250-KIT";
+	compatible = "LPC3250-KIT";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		soc = &soc;
+		serial4 = &serial4;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "ARM,926EJ-S";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x4000>;	// L1, 16K
+			i-cache-size = <0x4000>;	// L1, 16K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x4000000>;		// 64M at 0x80000000
+	};
+
+	soc: ahb7 at 40000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges = <0x0 0x40000000 0x10000000>;
+		bus-frequency = <13000000>;
+
+		pwr at 4000 {
+			compatible = "lpc,pwr";
+			reg = <0x4000 0x4000>;
+		};
+
+		PIC: pic at 8000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			reg = <0x8000 0xc000>;
+			compatible = "lpc,pic";
+		};
+
+		timer at 44000 {
+			compatible = "lpc,timer";
+			reg = <0x44000 0x4000
+			       0x4c000 0x4000>;
+			interrupts = <16 17>;
+			interrupt-parent = <&PIC>;
+		};
+
+		rtc at 24000 {
+			compatible = "lpc,rtc";
+			reg = <0x24000 0x4000>;
+			interrupts = <52>;
+			interrupt-parent = <&PIC>;
+		};
+
+		serial0: serial at 14000 {
+			compatible = "lpc,hsuart";
+			status = "disabled";
+			reg = <0x14000 0x20>;
+			reg-shift = <2>;
+			clock-frequency = <0>;
+			interrupts = <26>;
+			interrupt-parent = <&PIC>;
+		};
+
+		serial1: serial at 18000 {
+			compatible = "lpc,hsuart";
+			status = "disabled";
+			reg = <0x18000 0x20>;
+			reg-shift = <2>;
+			clock-frequency = <0>;
+			interrupts = <25>;
+			interrupt-parent = <&PIC>;
+		};
+
+		serial2: serial at 80000 {
+			compatible = "lpc,uart";
+			status = "disabled";
+			reg = <0x80000 0x20>;
+			reg-shift = <2>;
+			clock-frequency = <13000000>;
+			interrupts = <7>;
+			interrupt-parent = <&PIC>;
+		};
+
+		serial3: serial at 88000 {
+			compatible = "lpc,uart";
+			status = "disabled";
+			reg = <0x88000 0x20>;
+			reg-shift = <2>;
+			clock-frequency = <13000000>;
+			interrupts = <8>;
+			interrupt-parent = <&PIC>;
+		};
+
+		serial4: serial at 90000 {
+			compatible = "lpc,uart";
+			reg = <0x90000 0x20>;
+			reg-shift = <2>;
+			clock-frequency = <13000000>;
+			current-speed = <115200>;
+			interrupts = <9>;
+			interrupt-parent = <&PIC>;
+		};
+
+		serial5: serial at 98000 {
+			compatible = "lpc,uart";
+			status = "disabled";
+			reg = <0x98000 0x20>;
+			reg-shift = <2>;
+			clock-frequency = <13000000>;
+			interrupts = <10>;
+			interrupt-parent = <&PIC>;
+		};
+
+		serial6: serial at 1c000 {
+			compatible = "lpc,uart";
+			status = "disabled";
+			reg = <0x1c000 0x20>;
+			reg-shift = <2>;
+			clock-frequency = <0>;
+			interrupts = <24>;
+			interrupt-parent = <&PIC>;
+		};
+
+		gpio at 28000 {
+			compatible = "lpc,gpio";
+			reg = <0x28000 0x4000>;
+		};
+	};
+
+	ahb6 at 30000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges = <0x0 0x30000000 0x10000000>;
+
+		dmac at 1000000 {
+			compatible = "lpc,dmac";
+			reg = <0x1000000 0x20000>;
+			interrupts = <28>;
+			interrupt-parent = <&PIC>;
+		};
+
+		usb at 1020000 {
+			compatible = "lpc,usb-ohci", "usb-ohci";
+			reg = <0x1020000 0x20000>;
+			interrupts = <59>;
+			interrupt-parent = <&PIC>;
+		};
+
+		lpcfb at 1040000 {
+			compatible = "lpc,fb";
+			reg = <0x1040000 0x20000>;
+			interrupts = <14>;
+			interrupt-parent = <&PIC>;
+			
+			/* Screen parameters: */
+			is-tft = <1>;
+			horizontal-resolution = <240>;
+			vertical-resolution = <320>;
+			bits-per-pixel = <16>;
+			pixel-clock = <121654>;
+			left-margin = <28>;
+			right-margin = <10>;
+			upper-margin = <2>;
+			lower-margin = <2>;
+			hsync-len = <3>;
+			vsync-len = <2>;
+		};
+	
+		lpe at 1060000 {
+			compatible = "lpc,ethernet";
+			reg = <0x1060000 0x20000>;
+			interrupts = <29>;
+			interrupt-parent = <&PIC>;	
+			local-mac-address = [ 00 1a f1 01 1f 23 ];
+
+			mdio at 0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "lpc,mdio";
+
+				phy0: ethernet-phy at 0 {
+					reg = <0x0>;
+                        	};
+			};
+
+		};
+	};
+
+	ahb5 at 20000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges = <0x0 0x20000000 0x10000000>;
+
+		spi0 at 84000 {
+			compatible = "lpc,spi";
+			reg = <0x84000 0x4000>;
+			interrupts = <20>;
+			interrupt-parent = <&PIC>;
+		};
+
+		spi1 at 8c000 {
+			compatible = "lpc,spi";
+			status = "disabled";
+			reg = <0x8c000 0x4000>;
+			interrupts = <21>;
+			interrupt-parent = <&PIC>;
+		};
+
+		lpcmmc at 98000 {
+			compatible = "lpc,mmc";
+			reg = <0x98000 0x4000>;
+			interrupts = <15 13>;
+			interrupt-parent = <&PIC>;
+		};
+	};
+
+	chosen {
+		stdin = "serial4";
+		stdout = "serial4";
+	};
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/pandaboard.dts
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/pandaboard.dts	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,184 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Developed by Damjan Marion <damjan.marion at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * $FreeBSD: head/sys/boot/fdt/dts/pandaboard.dts 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+	model = "pandaboard";
+	compatible = "pandaboard", "ti,omap4430";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	interrupt-parent = <&GIC>;
+
+	aliases {
+		soc = &SOC;
+		uart3 = &uart3;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = < 0x80000000 0x40000000 >;	/* 1GB RAM at 0x0 */
+	};
+
+	SOC: omap4430 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		bus-frequency = <0>;
+
+		GIC: interrupt-controller at 48241000 {
+			compatible = "arm,gic";
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			reg =	< 0x48241000 0x1000 >,	/* Distributor Registers */
+				< 0x48240100 0x0100 >;	/* CPU Interface Registers */
+		};
+
+		pl310 at 48242000 {
+			compatible = "arm,pl310";
+			reg = < 0x48242000 0x1000 >;
+		};
+		mp_tmr at 48240200 {
+			compatible = "arm,mpcore-timers";
+			clock-frequency = < 504000000 >;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg =	< 0x48240200 0x100 >, /* Global Timer Registers */
+				< 0x48240600 0x100 >; /* Private Timer Registers */
+			interrupts = < 27 29 >;
+			interrupt-parent = < &GIC >;
+		};
+
+		uart3: serial at 48020000 {
+			compatible = "ns16550";
+			reg = <0x48020000 0x1000>;
+			reg-shift = <2>;
+			interrupts = < 106 >;
+			interrupt-parent = <&GIC>;
+			clock-frequency = < 48000000 >; /* 48Mhz clock for all uarts */
+							/* (techref 17.3.1.1) */
+		};
+
+		scm at 4a100000 {
+			compatible = "ti,scm";
+			reg =	< 0x4a100000 0x1000 >;
+			/* Set of triplets < padname, muxname, padstate> */
+			scm-pad-config = 
+				"ag19", "usbb1_ulpiphy_stp", "output",
+				"ae18", "usbb1_ulpiphy_clk", "input_pulldown",
+				"af19", "usbb1_ulpiphy_dir", "input_pulldown",
+				"ae19", "usbb1_ulpiphy_nxt", "input_pulldown",
+				"af18", "usbb1_ulpiphy_dat0", "input_pulldown",
+				"ag18", "usbb1_ulpiphy_dat1", "input_pulldown",
+				"ae17", "usbb1_ulpiphy_dat2", "input_pulldown",
+				"af17", "usbb1_ulpiphy_dat3", "input_pulldown",
+				"ah17", "usbb1_ulpiphy_dat4", "input_pulldown",
+				"ae16", "usbb1_ulpiphy_dat5", "input_pulldown",
+				"af16", "usbb1_ulpiphy_dat6", "input_pulldown",
+				"ag16", "usbb1_ulpiphy_dat7", "input_pulldown";
+		};
+
+		omap4_prcm at 4a306000 {
+			compatible = "ti,omap4_prcm";
+			reg =<	0x4a306000 0x2000
+				0x4a004000 0x1000
+				0x4a008000 0x8000>;
+		};
+
+		GPIO: gpio {
+			#gpio-cells = <3>;
+			compatible = "ti,gpio";
+			gpio-controller;
+			reg =<	0x4a310000 0x1000
+				0x48055000 0x1000
+				0x48057000 0x1000
+				0x48059000 0x1000
+				0x4805b000 0x1000
+				0x4805d000 0x1000>;
+			interrupts = <61 62 63 64 65 66>;
+			interrupt-parent = <&GIC>;
+		};
+
+		ehci {
+			compatible = "ti,usb-ehci", "usb-ehci";
+			/* 
+			 * USB port PHY configuration is a tuple: <mode, reset, gpio_pin>
+			 * mode is one of the following values:
+			 *   0 - unknown
+			 *   1 - PHY
+			 *   2 - TLL
+			 *   3 - HSIC
+			 *
+			 * reset indicates (if non-zero) if port reset is required 
+			 * gpio_pin - GPIO pin that is used to perform reset
+			 */
+			phy-config = <  1 0 0
+					0 0 0
+					0 0 0>;
+			reg = < 0x4a064c00 0x100	/* EHCI regs */
+				0x4a064000 0x700	/* UHH regs */
+				0x4a062000 0x1000>;	/* TLL regs */
+			interrupts = <109>;
+			interrupt-parent = <&GIC>;
+		};
+
+		I2C1: i2c at x48070000 {
+			compatible = "ti,i2c";
+			reg =<	0x48070000 0x100 >;
+			interrupts = <88>;
+			interrupt-parent = <&GIC>;
+			i2c-device-id = <1>;
+		};
+
+		sdma at x48070000 {
+			compatible = "ti,sdma";
+			reg =<	0x4A056000 0x1000 >;
+			interrupts = <44 45 46 47>;
+			interrupt-parent = <&GIC>;
+		};
+
+		mmc at x4809C000 {
+			compatible = "ti,mmchs";
+			reg =<0x4809C000 0x1000 >;
+			interrupts = <115>;
+			interrupt-parent = <&GIC>;
+			mmchs-device-id = <1>;
+		};
+
+	};
+
+	chosen {
+		stdin = "uart3";
+		stdout = "uart3";
+	};
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/trimslice.dts
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/trimslice.dts	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,143 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Developed by Damjan Marion <damjan.marion at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * $FreeBSD: head/sys/boot/fdt/dts/trimslice.dts 239280 2012-08-15 06:06:43Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+	model = "CompuLab TrimSlice";
+	compatible = "compulab,trimslice", "nvidia,tegra20";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	interrupt-parent = <&GIC>;
+
+	aliases {
+		serial0 = &serial0;
+		soc = &SOC;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = < 0x00000000 0x40000000 >;	/* 1GB RAM at 0x0 */
+	};
+
+
+	SOC: tegra20 at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		bus-frequency = <0>;
+
+		GIC: interrupt-controller at 50041000 {
+			compatible = "arm,gic";
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			reg =	< 0x50041000 0x1000 >,	/* Distributor Registers */
+				< 0x50040100 0x0100 >;	/* CPU Interface Registers */
+		};
+		mp_tmr at 50040200 {
+			compatible = "arm,mpcore-timers";
+			clock-frequency = < 50040200 >;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg =   < 0x50040200 0x100 >, /* Global Timer Registers */
+				< 0x50040600 0x100 >; /* Private Timer Registers */
+			interrupts = < 27 29 >;
+			interrupt-parent = < &GIC >;
+		};
+
+		tmr1 at 60005000 {
+			compatible = "nvidia,tegra2-timer";
+			reg = <0x60005000 0x8>;
+			interrupts = < 32 >;
+			interrupt-parent = <&GIC>;
+		};
+
+		tmr2 at 60005008 {
+			compatible = "nvidia,tegra2-timer";
+			reg = <0x60005008 0x8>;
+			interrupts = < 33 >;
+			interrupt-parent = <&GIC>;
+		};
+
+		tmrus at 60005010 {
+			compatible = "nvidia,tegra2-timestamp";
+			reg = <0x60005010 0x8>;
+		};
+
+		tmr3 at 60005050 {
+			compatible = "nvidia,tegra2-timer";
+			reg = <0x60005050 0x8>;
+			interrupts = < 73 >;
+			interrupt-parent = <&GIC>;
+		};
+
+		tmr4 at 60005058 {
+			compatible = "nvidia,tegra2-timer";
+			reg = <0x60005058 0x8>;
+			interrupts = < 74 >;
+			interrupt-parent = <&GIC>;
+		};
+
+		serial0: serial at 70006000 {
+			compatible = "ns16550";
+			reg = <0x70006000 0x40>;
+			reg-shift = <2>;
+			interrupts = < 68 >;
+			interrupt-parent = <&GIC>;
+			clock-frequency = < 215654400 >;
+		};
+
+		serial1: serial at 70006040 {
+			compatible = "ns16550";
+			reg = <0x70006040 0x40>;
+			reg-shift = <2>;
+			interrupts = < 69 >;
+			interrupt-parent = <&GIC>;
+			clock-frequency = < 215654400 >;
+		};
+
+		serial2: serial at 70006200 {
+			compatible = "ns16550";
+			reg = <0x70006200 0x100>;
+			reg-shift = <2>;
+			interrupts = < 78 >;
+			interrupt-parent = <&GIC>;
+			clock-frequency = < 215654400 >;
+		};
+	};
+
+	chosen {
+		stdin = "serial0";
+		stdout = "serial0";
+	};
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/i386/libi386/biosdisk.c
--- a/head/sys/boot/i386/libi386/biosdisk.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/boot/i386/libi386/biosdisk.c	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biosdisk.c 239066 2012-08-05 14:37:48Z ae $");
+__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biosdisk.c 239243 2012-08-13 21:04:01Z dim $");
 
 /*
  * BIOS disk device handling.
@@ -215,6 +215,8 @@
 	    bd->bd_hds, bd->bd_sec);
 
 	/* Determine if we can use EDD with this device. */
+	v86.ctl = V86_FLAGS;
+	v86.addr = 0x13;
 	v86.eax = 0x4100;
 	v86.edx = bd->bd_unit;
 	v86.ebx = 0x55aa;
@@ -240,6 +242,8 @@
 		bd->bd_sectors = params.sectors;
 		bd->bd_sectorsize = params.sector_size;
 	}
+	DEBUG("unit 0x%x flags %x, sectors %llu, sectorsize %u",
+	    bd->bd_unit, bd->bd_flags, bd->bd_sectors, bd->bd_sectorsize);
 	return (1);
 }
 
diff -r a301a330526b -r 49889ad5ef1f head/sys/cam/scsi/scsi_all.h
--- a/head/sys/cam/scsi/scsi_all.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/cam/scsi/scsi_all.h	Wed Aug 15 11:46:11 2012 +0300
@@ -14,7 +14,7 @@
  *
  * Ported to run under 386BSD by Julian Elischer (julian at tfs.com) Sept 1992
  *
- * $FreeBSD: head/sys/cam/scsi/scsi_all.h 237478 2012-06-23 12:32:53Z mav $
+ * $FreeBSD: head/sys/cam/scsi/scsi_all.h 239212 2012-08-12 16:58:38Z mjacob $
  */
 
 /*
@@ -984,6 +984,7 @@
 #define	WRITE_10		0x2A
 #define	POSITION_TO_ELEMENT	0x2B
 #define	WRITE_VERIFY_10		0x2E
+#define	VERIFY_10		0x2F
 #define	SYNCHRONIZE_CACHE	0x35
 #define	READ_DEFECT_DATA_10	0x37
 #define	WRITE_BUFFER            0x3B
diff -r a301a330526b -r 49889ad5ef1f head/sys/cam/scsi/scsi_enc.c
--- a/head/sys/cam/scsi/scsi_enc.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/cam/scsi/scsi_enc.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc.c 238894 2012-07-30 03:00:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc.c 239213 2012-08-12 17:01:07Z mjacob $");
 
 #include <sys/param.h>
 
@@ -60,9 +60,6 @@
 
 /* Enclosure type independent driver */
 
-#define	SEN_ID		"UNISYS           SUN_SEN"
-#define	SEN_ID_LEN	24
-
 static	d_open_t	enc_open;
 static	d_close_t	enc_close;
 static	d_ioctl_t	enc_ioctl;
@@ -83,7 +80,7 @@
 	TAILQ_HEAD_INITIALIZER(encdriver.units), /* generation */ 0
 };
 
-PERIPHDRIVER_DECLARE(enc, encdriver);
+PERIPHDRIVER_DECLARE(ses, encdriver);
 
 static struct cdevsw enc_cdevsw = {
 	.d_version =	D_VERSION,
@@ -630,9 +627,8 @@
 /*
  * Is this a device that supports enclosure services?
  *
- * It's a a pretty simple ruleset- if it is device type 0x0D (13), it's
- * an ENC device. If it happens to be an old UNISYS SEN device, we can
- * handle that too.
+ * It's a a pretty simple ruleset- if it is device type
+ * 0x0D (13), it's an ENCLOSURE device.
  */
 
 #define	SAFTE_START	44
@@ -659,13 +655,9 @@
 	iqd = (unsigned char *)&cgd->inq_data;
 	buflen = min(sizeof(cgd->inq_data),
 	    SID_ADDITIONAL_LENGTH(&cgd->inq_data));
-	if (buflen < 8+SEN_ID_LEN)
-		return (ENC_NONE);
 
 	if ((iqd[0] & 0x1f) == T_ENCLOSURE) {
-		if (STRNCMP(&iqd[8], SEN_ID, SEN_ID_LEN) == 0) {
-			return (ENC_SEN);
-		} else if ((iqd[2] & 0x7) > 2) {
+		if ((iqd[2] & 0x7) > 2) {
 			return (ENC_SES);
 		} else {
 			return (ENC_SES_SCSI2);
@@ -920,7 +912,6 @@
 	case ENC_SEMB_SAFT:
 		err = safte_softc_init(enc);
 		break;
-	case ENC_SEN:
 	case ENC_NONE:
 	default:
 		ENC_FREE(enc);
@@ -997,9 +988,6 @@
         case ENC_SES_PASSTHROUGH:
 		tname = "ENC Passthrough Device";
 		break;
-        case ENC_SEN:
-		tname = "UNISYS SEN Device (NOT HANDLED YET)";
-		break;
         case ENC_SAFT:
 		tname = "SAF-TE Compliant Device";
 		break;
diff -r a301a330526b -r 49889ad5ef1f head/sys/cam/scsi/scsi_enc_safte.c
--- a/head/sys/cam/scsi/scsi_enc_safte.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/cam/scsi/scsi_enc_safte.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc_safte.c 238894 2012-07-30 03:00:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc_safte.c 239213 2012-08-12 17:01:07Z mjacob $");
 
 #include <sys/param.h>
 
@@ -220,7 +220,7 @@
 static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
 #define	SAFT_BAIL(r, x)	\
 	if ((r) >= (x)) { \
-		ENC_LOG(enc, safte_2little, x, __LINE__);\
+		ENC_VLOG(enc, safte_2little, x, __LINE__);\
 		return (EIO); \
 	}
 
@@ -269,7 +269,7 @@
 	if (error != 0)
 		return (error);
 	if (xfer_len < 6) {
-		ENC_LOG(enc, "too little data (%d) for configuration\n",
+		ENC_VLOG(enc, "too little data (%d) for configuration\n",
 		    xfer_len);
 		return (EIO);
 	}
@@ -435,7 +435,7 @@
 			break;
 		default:
 			cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
-			ENC_LOG(enc, "Unknown fan%d status 0x%x\n", i,
+			ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i,
 			    buf[r] & 0xff);
 			break;
 		}
@@ -495,7 +495,7 @@
 			cfg->enc_status |= SES_ENCSTAT_INFO;
 			break;
 		default:
-			ENC_LOG(enc, "unknown power supply %d status (0x%x)\n",
+			ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n",
 			    i, buf[r] & 0xff);
 			break;
 		}
@@ -543,7 +543,7 @@
 		default:
 			cache->elm_map[oid].encstat[0] =
 			    SES_OBJSTAT_UNSUPPORTED;
-			ENC_LOG(enc, "unknown lock status 0x%x\n",
+			ENC_VLOG(enc, "unknown lock status 0x%x\n",
 			    buf[r] & 0xff);
 			break;
 		}
diff -r a301a330526b -r 49889ad5ef1f head/sys/cam/scsi/scsi_enc_ses.c
--- a/head/sys/cam/scsi/scsi_enc_ses.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/cam/scsi/scsi_enc_ses.c	Wed Aug 15 11:46:11 2012 +0300
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc_ses.c 238894 2012-07-30 03:00:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc_ses.c 239213 2012-08-12 17:01:07Z mjacob $");
 
 #include <sys/param.h>
 
@@ -1175,7 +1175,7 @@
 	err = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS,
 	    ENC_FLAGS|SF_QUIET_IR, NULL);
 	if (ccb->ccb_h.status != CAM_REQ_CMP) {
-		ENC_LOG(enc, "Timed Completion Unsupported\n");
+		ENC_VLOG(enc, "Timed Completion Unsupported\n");
 		goto release;
 	}
 
@@ -1198,7 +1198,7 @@
 
 	err = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS, ENC_FLAGS, NULL);
 	if (ccb->ccb_h.status != CAM_REQ_CMP) {
-		ENC_LOG(enc, "Timed Completion Set Failed\n");
+		ENC_VLOG(enc, "Timed Completion Set Failed\n");
 		goto release;
 	}
 
@@ -1244,14 +1244,14 @@
 		goto out;
 	}
 	if (xfer_len < sizeof(*page)) {
-		ENC_LOG(enc, "Unable to parse Diag Pages List Header\n");
+		ENC_VLOG(enc, "Unable to parse Diag Pages List Header\n");
 		err = EIO;
 		goto out;
 	}
 	page = (struct scsi_diag_page *)*bufp;
 	length = scsi_2btoul(page->length);
 	if (length + offsetof(struct scsi_diag_page, params) > xfer_len) {
-		ENC_LOG(enc, "Diag Pages List Too Long\n");
+		ENC_VLOG(enc, "Diag Pages List Too Long\n");
 		goto out;
 	}
 	ENC_DLOG(enc, "%s: page length %d, xfer_len %d\n",
@@ -1318,7 +1318,7 @@
 		goto out;
 	}
 	if (xfer_len < sizeof(cfg_page->hdr)) {
-		ENC_LOG(enc, "Unable to parse SES Config Header\n");
+		ENC_VLOG(enc, "Unable to parse SES Config Header\n");
 		err = EIO;
 		goto out;
 	}
@@ -1326,7 +1326,7 @@
 	cfg_page = (struct ses_cfg_page *)buf;
 	length = ses_page_length(&cfg_page->hdr);
 	if (length > xfer_len) {
-		ENC_LOG(enc, "Enclosure Config Page Too Long\n");
+		ENC_VLOG(enc, "Enclosure Config Page Too Long\n");
 		goto out;
 	}
 	last_valid_byte = &buf[length - 1];
@@ -1377,7 +1377,7 @@
 	while (cur_subenc <= last_subenc) {
 
 		if (!ses_enc_desc_is_complete(buf_subenc, last_valid_byte)) {
-			ENC_LOG(enc, "Enclosure %d Beyond End of "
+			ENC_VLOG(enc, "Enclosure %d Beyond End of "
 			    "Descriptors\n", cur_subenc - subencs);
 			err = EIO;
 			goto out;
@@ -1416,7 +1416,7 @@
 	sestype = ses_types;
 	while (cur_buf_type <= last_buf_type) {
 		if (&cur_buf_type->etype_txt_len > last_valid_byte) {
-			ENC_LOG(enc, "Runt Enclosure Type Header %d\n",
+			ENC_VLOG(enc, "Runt Enclosure Type Header %d\n",
 			    sestype - ses_types);
 			err = EIO;
 			goto out;
@@ -1424,7 +1424,7 @@
 		sestype->hdr  = cur_buf_type;
 		sestype->text = type_text;
 		type_text += cur_buf_type->etype_txt_len;
-		ENC_LOG(enc, " Type Desc[%d]: Type 0x%x, MaxElt %d, In Subenc "
+		ENC_VLOG(enc, " Type Desc[%d]: Type 0x%x, MaxElt %d, In Subenc "
 		    "%d, Text Length %d: %.*s\n", sestype - ses_types,
 		    sestype->hdr->etype_elm_type, sestype->hdr->etype_maxelt,
 		    sestype->hdr->etype_subenc, sestype->hdr->etype_txt_len,
@@ -1529,12 +1529,12 @@
 	 * could happen... Need to use dynamic discovery of the size.
 	 */
 	if (length > xfer_len) {
-		ENC_LOG(enc, "Enclosure Status Page Too Long\n");
+		ENC_VLOG(enc, "Enclosure Status Page Too Long\n");
 		goto out;
 	}
 	/* Make sure the length contains at least one header and status */
 	if (length < (sizeof(*page) + sizeof(*page->elements))) {
-		ENC_LOG(enc, "Enclosure Status Page Too Short\n");
+		ENC_VLOG(enc, "Enclosure Status Page Too Short\n");
 		goto out;
 	}
 
@@ -1576,11 +1576,11 @@
 	}
 
 	if (ses_iter_next(&iter) != NULL) {
-		ENC_LOG(enc, "Status page, length insufficient for "
+		ENC_VLOG(enc, "Status page, length insufficient for "
 			"expected number of objects\n");
 	} else {
 		if (cur_stat <= last_stat)
-			ENC_LOG(enc, "Status page, exhausted objects before "
+			ENC_VLOG(enc, "Status page, exhausted objects before "
 				"exhausing page\n");
 		enc_update_request(enc, SES_PUBLISH_CACHE);
 		err = 0;
@@ -1706,11 +1706,11 @@
 	ENC_DLOG(enc, "Additional Element Status Page Length 0x%x\n", length);
 	/* Make sure the length includes at least one header. */
 	if (length < sizeof(*hdr)+sizeof(struct ses_elm_addlstatus_base_hdr)) {
-		ENC_LOG(enc, "Runt Additional Element Status Page\n");
+		ENC_VLOG(enc, "Runt Additional Element Status Page\n");
 		goto out;
 	}
 	if (length > xfer_len) {
-		ENC_LOG(enc, "Additional Element Status Page Too Long\n");
+		ENC_VLOG(enc, "Additional Element Status Page Too Long\n");
 		goto out;
 	}
 
@@ -1763,7 +1763,7 @@
 
 			if (iter.individual_element_index > expected_index
 			 && status_type == TYPE_ADDLSTATUS_MANDATORY) {
-				ENC_LOG(enc, "%s: provided element "
+				ENC_VLOG(enc, "%s: provided element "
 					"index %d skips mandatory status "
 					" element at index %d\n",
 					__func__, eip_hdr->element_index,
@@ -1784,7 +1784,7 @@
 
 		/* Make sure the descriptor is within bounds */
 		if ((offset + elmpriv->addl.hdr->length) > length) {
-			ENC_LOG(enc, "Element %d Beyond End "
+			ENC_VLOG(enc, "Element %d Beyond End "
 			    "of Additional Element Status Descriptors\n",
 			    iter.global_element_index);
 			err = EIO;
@@ -1814,7 +1814,7 @@
 						   iter.global_element_index);
 			break;
 		default:
-			ENC_LOG(enc, "Element %d: Unknown Additional Element "
+			ENC_VLOG(enc, "Element %d: Unknown Additional Element "
 			    "Protocol 0x%x\n", iter.global_element_index,
 			    ses_elm_addlstatus_proto(elmpriv->addl.hdr));
 			goto out;
@@ -1931,11 +1931,11 @@
 	phdr = &ses_cache->elm_descs_page->hdr;
 	plength = ses_page_length(phdr);
 	if (xfer_len < sizeof(struct ses_page_hdr)) {
-		ENC_LOG(enc, "Runt Element Descriptor Page\n");
+		ENC_VLOG(enc, "Runt Element Descriptor Page\n");
 		goto out;
 	}
 	if (plength > xfer_len) {
-		ENC_LOG(enc, "Element Descriptor Page Too Long\n");
+		ENC_VLOG(enc, "Element Descriptor Page Too Long\n");
 		goto out;
 	}
 
@@ -1953,7 +1953,7 @@
 	    && (element = ses_iter_next(&iter)) != NULL) {
 
 		if ((offset + sizeof(struct ses_elm_desc_hdr)) > plength) {
-			ENC_LOG(enc, "Element %d Descriptor Header Past "
+			ENC_VLOG(enc, "Element %d Descriptor Header Past "
 			    "End of Buffer\n", iter.global_element_index);
 			goto out;
 		}
@@ -1963,7 +1963,7 @@
 		    iter.global_element_index, iter.type_index,
 		    iter.type_element_index, length, offset);
 		if ((offset + sizeof(*hdr) + length) > plength) {
-			ENC_LOG(enc, "Element%d Descriptor Past "
+			ENC_VLOG(enc, "Element%d Descriptor Past "
 			    "End of Buffer\n", iter.global_element_index);
 			goto out;
 		}
@@ -2138,7 +2138,7 @@
 ses_get_elm_addlstatus_fc(enc_softc_t *enc, enc_cache_t *enc_cache,
 			  uint8_t *buf, int bufsiz)
 {
-	ENC_LOG(enc, "FC Device Support Stubbed in Additional Status Page\n");
+	ENC_VLOG(enc, "FC Device Support Stubbed in Additional Status Page\n");
 	return (ENODEV);
 }
 
@@ -2385,7 +2385,7 @@
 	physz = addl->proto_hdr.sas->base_hdr.num_phys;
 	physz *= sizeof(struct ses_elm_sas_device_phy);
 	if (physz > (bufsiz - offset + 4)) {
-		ENC_LOG(enc, "Element %d Device Phy List Beyond End Of Buffer\n",
+		ENC_VLOG(enc, "Element %d Device Phy List Beyond End Of Buffer\n",
 		    nobj);
 		err = EIO;
 		goto out;
@@ -2440,7 +2440,7 @@
 		physz = addl->proto_hdr.sas->base_hdr.num_phys *
 		    sizeof(struct ses_elm_sas_expander_phy);
 		if (physz > (bufsiz - offset)) {
-			ENC_LOG(enc, "Element %d: Expander Phy List Beyond "
+			ENC_VLOG(enc, "Element %d: Expander Phy List Beyond "
 			    "End Of Buffer\n", nobj);
 			err = EIO;
 			goto out;
@@ -2452,7 +2452,7 @@
 		physz = addl->proto_hdr.sas->base_hdr.num_phys *
 		    sizeof(struct ses_elm_sas_port_phy);
 		if (physz > (bufsiz - offset + 4)) {
-			ENC_LOG(enc, "Element %d: Port Phy List Beyond End "
+			ENC_VLOG(enc, "Element %d: Port Phy List Beyond End "
 			    "Of Buffer\n", nobj);
 			err = EIO;
 			goto out;
@@ -2504,7 +2504,7 @@
 		case ELMTYP_ARRAY_DEV:
 			break;
 		default:
-			ENC_LOG(enc, "Element %d has Additional Status type 0, "
+			ENC_VLOG(enc, "Element %d has Additional Status type 0, "
 			    "invalid for SES element type 0x%x\n", nobj,
 			    ses_cache->ses_types[tidx].hdr->etype_elm_type);
 			err = ENODEV;
@@ -2522,7 +2522,7 @@
 		case ELMTYP_ESCC:
 			break;
 		default:
-			ENC_LOG(enc, "Element %d has Additional Status type 1, "
+			ENC_VLOG(enc, "Element %d has Additional Status type 1, "
 			    "invalid for SES element type 0x%x\n", nobj,
 			    ses_cache->ses_types[tidx].hdr->etype_elm_type);
 			err = ENODEV;
@@ -2532,7 +2532,7 @@
 						       bufsiz, eip, nobj);
 		break;
 	default:
-		ENC_LOG(enc, "Element %d of type 0x%x has Additional Status "
+		ENC_VLOG(enc, "Element %d of type 0x%x has Additional Status "
 		    "of unknown type 0x%x\n", nobj,
 		    ses_cache->ses_types[tidx].hdr->etype_elm_type, dtype);
 		err = ENODEV;
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/freebsd32_proto.h
--- a/head/sys/compat/freebsd32/freebsd32_proto.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/freebsd32_proto.h	Wed Aug 15 11:46:11 2012 +0300
@@ -2,8 +2,8 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: head/sys/compat/freebsd32/freebsd32_proto.h 236027 2012-05-25 21:52:57Z ed $
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed 
+ * $FreeBSD: head/sys/compat/freebsd32/freebsd32_proto.h 239249 2012-08-14 12:09:36Z kib $
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib 
  */
 
 #ifndef _FREEBSD32_SYSPROTO_H_
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/freebsd32_syscall.h
--- a/head/sys/compat/freebsd32/freebsd32_syscall.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/freebsd32_syscall.h	Wed Aug 15 11:46:11 2012 +0300
@@ -2,8 +2,8 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscall.h 236027 2012-05-25 21:52:57Z ed $
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed 
+ * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscall.h 239249 2012-08-14 12:09:36Z kib $
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib 
  */
 
 #define	FREEBSD32_SYS_syscall	0
@@ -77,7 +77,7 @@
 				/* 68 is obsolete vwrite */
 #define	FREEBSD32_SYS_sbrk	69
 #define	FREEBSD32_SYS_sstk	70
-				/* 71 is obsolete ommap */
+				/* 71 is old mmap */
 #define	FREEBSD32_SYS_vadvise	72
 #define	FREEBSD32_SYS_munmap	73
 #define	FREEBSD32_SYS_freebsd32_mprotect	74
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/head/sys/compat/freebsd32/freebsd32_syscalls.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/freebsd32_syscalls.c	Wed Aug 15 11:46:11 2012 +0300
@@ -2,8 +2,8 @@
  * System call names.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscalls.c 236027 2012-05-25 21:52:57Z ed $
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed 
+ * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscalls.c 239249 2012-08-14 12:09:36Z kib $
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib 
  */
 
 const char *freebsd32_syscallnames[] = {
@@ -81,7 +81,7 @@
 	"obs_vwrite",			/* 68 = obsolete vwrite */
 	"sbrk",			/* 69 = sbrk */
 	"sstk",			/* 70 = sstk */
-	"obs_ommap",			/* 71 = obsolete ommap */
+	"compat.mmap",		/* 71 = old mmap */
 	"vadvise",			/* 72 = vadvise */
 	"munmap",			/* 73 = munmap */
 	"freebsd32_mprotect",			/* 74 = freebsd32_mprotect */
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/freebsd32_sysent.c
--- a/head/sys/compat/freebsd32/freebsd32_sysent.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/freebsd32_sysent.c	Wed Aug 15 11:46:11 2012 +0300
@@ -2,8 +2,8 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: head/sys/compat/freebsd32/freebsd32_sysent.c 236027 2012-05-25 21:52:57Z ed $
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed 
+ * $FreeBSD: head/sys/compat/freebsd32/freebsd32_sysent.c 239249 2012-08-14 12:09:36Z kib $
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib 
  */
 
 #include "opt_compat.h"
@@ -118,7 +118,7 @@
 	{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },			/* 68 = obsolete vwrite */
 	{ AS(sbrk_args), (sy_call_t *)sys_sbrk, AUE_SBRK, NULL, 0, 0, 0, SY_THR_STATIC },	/* 69 = sbrk */
 	{ AS(sstk_args), (sy_call_t *)sys_sstk, AUE_SSTK, NULL, 0, 0, 0, SY_THR_STATIC },	/* 70 = sstk */
-	{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },			/* 71 = obsolete ommap */
+	{ compat(AS(ommap_args),mmap), AUE_MMAP, NULL, 0, 0, 0, SY_THR_STATIC },	/* 71 = old mmap */
 	{ AS(ovadvise_args), (sy_call_t *)sys_ovadvise, AUE_O_VADVISE, NULL, 0, 0, 0, SY_THR_STATIC },	/* 72 = vadvise */
 	{ AS(munmap_args), (sy_call_t *)sys_munmap, AUE_MUNMAP, NULL, 0, 0, 0, SY_THR_STATIC },	/* 73 = munmap */
 	{ AS(freebsd32_mprotect_args), (sy_call_t *)freebsd32_mprotect, AUE_MPROTECT, NULL, 0, 0, 0, SY_THR_STATIC },	/* 74 = freebsd32_mprotect */
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/syscalls.master
--- a/head/sys/compat/freebsd32/syscalls.master	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/syscalls.master	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
- $FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed $
+ $FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib $
 ;	from: @(#)syscalls.master	8.2 (Berkeley) 1/13/94
 ;	from: src/sys/kern/syscalls.master 1.107
 ;
@@ -168,7 +168,8 @@
 68	AUE_NULL	OBSOL	vwrite
 69	AUE_SBRK	NOPROTO	{ int sbrk(int incr); }
 70	AUE_SSTK	NOPROTO	{ int sstk(int incr); }
-71	AUE_MMAP	OBSOL	ommap
+71	AUE_MMAP	COMPAT|NOPROTO	{ int mmap(void *addr, int len, \
+				    int prot, int flags, int fd, int pos); }
 72	AUE_O_VADVISE	NOPROTO	{ int ovadvise(int anom); } vadvise \
 				    ovadvise_args int
 73	AUE_MUNMAP	NOPROTO	{ int munmap(void *addr, size_t len); }
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/Makefile.arm
--- a/head/sys/conf/Makefile.arm	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/Makefile.arm	Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
 # Makefile.arm -- with config changes.
 # Copyright 1990 W. Jolitz
 #	from: @(#)Makefile.i386	7.1 5/10/91
-# $FreeBSD: head/sys/conf/Makefile.arm 238464 2012-07-15 05:38:43Z imp $
+# $FreeBSD: head/sys/conf/Makefile.arm 239268 2012-08-15 03:03:03Z gonzo $
 #
 # Makefile for FreeBSD
 #
@@ -75,7 +75,9 @@
 	$S/$M/$M/cpufunc_asm_sa1.S $S/$M/$M/cpufunc_asm_arm10.S \
 	$S/$M/$M/cpufunc_asm_xscale.S $S/$M/$M/cpufunc_asm.S \
 	$S/$M/$M/cpufunc_asm_xscale_c3.S $S/$M/$M/cpufunc_asm_armv5_ec.S \
-	$S/$M/$M/cpufunc_asm_sheeva.S $S/$M/$M/cpufunc_asm_fa526.S
+	$S/$M/$M/cpufunc_asm_fa526.S $S/$M/$M/cpufunc_asm_sheeva.S \
+	$S/$M/$M/cpufunc_asm_pj4b.S $S/$M/$M/cpufunc_asm_armv7.S
+
 KERNEL_EXTRA=trampoline
 KERNEL_EXTRA_INSTALL=kernel.gz.tramp
 trampoline: ${KERNEL_KO}.tramp
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/files
--- a/head/sys/conf/files	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/files	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/conf/files 239009 2012-08-03 14:00:26Z luigi $
+# $FreeBSD: head/sys/conf/files 239275 2012-08-15 04:03:55Z gonzo $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -1615,6 +1615,7 @@
 dev/mii/rlphy.c			optional miibus | rlphy
 dev/mii/rlswitch.c		optional rlswitch
 dev/mii/smcphy.c		optional miibus | smcphy
+dev/mii/smscphy.c		optional miibus | smscphy
 dev/mii/tdkphy.c		optional miibus | tdkphy
 dev/mii/tlphy.c			optional miibus | tlphy
 dev/mii/truephy.c		optional miibus | truephy
@@ -2135,11 +2136,12 @@
 dev/usb/net/if_kue.c		optional kue
 dev/usb/net/if_mos.c		optional mos
 dev/usb/net/if_rue.c		optional rue
+dev/usb/net/if_smsc.c		optional smsc
 dev/usb/net/if_udav.c		optional udav
 dev/usb/net/if_usie.c		optional usie
 dev/usb/net/ruephy.c		optional rue
 dev/usb/net/usb_ethernet.c	optional aue | axe | cdce | cue | kue | mos | \
-					 rue | udav
+					 rue | smsc | udav
 dev/usb/net/uhso.c		optional uhso
 #
 # USB WLAN drivers
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/files.arm
--- a/head/sys/conf/files.arm	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/files.arm	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/conf/files.arm 237433 2012-06-22 07:06:40Z kib $
+# $FreeBSD: head/sys/conf/files.arm 239268 2012-08-15 03:03:03Z gonzo $
 crypto/blowfish/bf_enc.c	optional	crypto | ipsec 
 crypto/des/des_enc.c		optional	crypto | ipsec | netsmb
 arm/arm/autoconf.c		standard
@@ -7,7 +7,8 @@
 arm/arm/blockio.S		standard
 arm/arm/bootconfig.c		standard
 arm/arm/bus_space_asm_generic.S	standard
-arm/arm/busdma_machdep.c 	standard
+arm/arm/busdma_machdep.c 	optional	cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_sa1100 | cpu_sa1110 | cpu_xscale_80219 | cpu_xscale_80321 | cpu_xscale_81342 | cpu_xscale_ixp425 | cpu_xscale_ixp435 | cpu_xscale_pxa2x0
+arm/arm/busdma_machdep-v6.c 	optional	cpu_arm11 | cpu_cortexa | cpu_mv_pj4b
 arm/arm/copystr.S		standard
 arm/arm/cpufunc.c		standard
 arm/arm/cpufunc_asm.S		standard
@@ -31,8 +32,11 @@
 arm/arm/machdep.c		standard
 arm/arm/mem.c			optional	mem
 arm/arm/minidump_machdep.c	optional	mem
+arm/arm/mp_machdep.c		optional	smp
 arm/arm/nexus.c			standard
-arm/arm/pmap.c			standard
+arm/arm/pl310.c			optional	pl310
+arm/arm/pmap.c			optional	cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_sa1100 | cpu_sa1110 | cpu_xscale_80219 | cpu_xscale_80321 | cpu_xscale_81342 | cpu_xscale_ixp425 | cpu_xscale_ixp435 | cpu_xscale_pxa2x0
+arm/arm/pmap-v6.c		optional	cpu_arm11 | cpu_cortexa | cpu_mv_pj4b
 arm/arm/setcpsr.S		standard
 arm/arm/setstack.s		standard
 arm/arm/stack_machdep.c		optional	ddb | stack
@@ -44,6 +48,7 @@
 arm/arm/undefined.c		standard
 arm/arm/vectors.S		standard
 arm/arm/vm_machdep.c		standard
+arm/arm/vfp.c			optional	vfp
 arm/fpe-arm/armfpe_glue.S	optional	armfpe
 arm/fpe-arm/armfpe_init.c	optional	armfpe
 arm/fpe-arm/armfpe.S		optional	armfpe
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/kern.pre.mk
--- a/head/sys/conf/kern.pre.mk	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/kern.pre.mk	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/conf/kern.pre.mk 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/sys/conf/kern.pre.mk 239272 2012-08-15 03:21:56Z gonzo $
 
 # Part of a unified Makefile for building kernels.  This part contains all
 # of the definitions that need to be before %BEFORE_DEPEND.
@@ -6,7 +6,7 @@
 .include <bsd.own.mk>
 
 # backwards compat option for older systems.
-MACHINE_CPUARCH?=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+MACHINE_CPUARCH?=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
 
 # Can be overridden by makeoptions or /etc/make.conf
 KERNEL_KO?=	kernel
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/kmod.mk
--- a/head/sys/conf/kmod.mk	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/kmod.mk	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #	From: @(#)bsd.prog.mk	5.26 (Berkeley) 6/25/91
-# $FreeBSD: head/sys/conf/kmod.mk 238050 2012-07-03 05:01:00Z obrien $
+# $FreeBSD: head/sys/conf/kmod.mk 239272 2012-08-15 03:21:56Z gonzo $
 #
 # The include file <bsd.kmod.mk> handles building and installing loadable
 # kernel modules.
@@ -61,7 +61,7 @@
 #
 
 # backwards compat option for older systems.
-MACHINE_CPUARCH?=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+MACHINE_CPUARCH?=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
 
 AWK?=		awk
 KMODLOAD?=	/sbin/kldload
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/options.arm
--- a/head/sys/conf/options.arm	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/options.arm	Wed Aug 15 11:46:11 2012 +0300
@@ -1,15 +1,23 @@
-#$FreeBSD: head/sys/conf/options.arm 238189 2012-07-07 05:02:39Z imp $
+#$FreeBSD: head/sys/conf/options.arm 239268 2012-08-15 03:03:03Z gonzo $
 ARM9_CACHE_WRITE_THROUGH	opt_global.h
 ARM_CACHE_LOCK_ENABLE	opt_global.h
 ARMFPE			opt_global.h
 ARM_KERN_DIRECTMAP	opt_vm.h
+ARM_L2_PIPT		opt_global.h
 ARM_MANY_BOARD		opt_global.h
 ARM_USE_SMALL_ALLOC	opt_global.h
+ARM_VFP_SUPPORT		opt_global.h
+ARM_WANT_TP_ADDRESS	opt_global.h
 COUNTS_PER_SEC		opt_timer.h
+CPU_ARM9		opt_global.h
+CPU_ARM9E		opt_global.h
+CPU_ARM11		opt_global.h
+CPU_CORTEXA		opt_global.h
+CPU_FA526		opt_global.h
+CPU_FA626TE		opt_global.h
+CPU_MV_PJ4B		opt_global.h
 CPU_SA1100		opt_global.h
 CPU_SA1110		opt_global.h
-CPU_ARM9		opt_global.h
-CPU_ARM9E		opt_global.h
 CPU_XSCALE_80219	opt_global.h
 CPU_XSCALE_80321	opt_global.h
 CPU_XSCALE_81342	opt_global.h
@@ -17,24 +25,34 @@
 CPU_XSCALE_IXP435	opt_global.h
 CPU_XSCALE_PXA2X0	opt_global.h
 FLASHADDR		opt_global.h
+IPI_IRQ_START		opt_smp.h
+IPI_IRQ_END		opt_smp.h
 FREEBSD_BOOT_LOADER	opt_global.h
 IXP4XX_FLASH_SIZE	opt_global.h
 KERNPHYSADDR		opt_global.h
 KERNVIRTADDR		opt_global.h
 LINUX_BOOT_ABI		opt_global.h
 LOADERRAMADDR		opt_global.h
+NO_EVENTTIMERS		opt_timer.h
 PHYSADDR		opt_global.h
 QEMU_WORKAROUNDS	opt_global.h
+SOC_MV_ARMADAXP		opt_global.h
 SOC_MV_DISCOVERY	opt_global.h
+SOC_MV_DOVE		opt_global.h
+SOC_MV_FREY		opt_global.h
 SOC_MV_KIRKWOOD		opt_global.h
+SOC_MV_LOKIPLUS		opt_global.h
 SOC_MV_ORION		opt_global.h
+SOC_OMAP3		opt_global.h
+SOC_OMAP4		opt_global.h
+SOC_TI_AM335X		opt_global.h
+SOC_TEGRA2		opt_global.h
 STARTUP_PAGETABLE_ADDR	opt_global.h
 XSCALE_CACHE_READ_WRITE_ALLOCATE	opt_global.h
 XSACLE_DISABLE_CCNT	opt_timer.h
 VERBOSE_INIT_ARM	opt_global.h
+VM_MAXUSER_ADDRESS	opt_global.h
 AT91_ATE_USE_RMII	opt_at91.h
 AT91_MCI_HAS_4WIRE	opt_at91.h
 AT91_MCI_SLOT_B		opt_at91.h
 AT91C_MAIN_CLOCK	opt_at91.h
-CPU_FA526		opt_global.h
-CPU_FA626TE		opt_global.h
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/options.mips
--- a/head/sys/conf/options.mips	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/options.mips	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
 # SUCH DAMAGE.
 #
 #	JNPR: options.mips,v 1.2 2006/09/15 12:52:34
-# $FreeBSD: head/sys/conf/options.mips 234862 2012-05-01 06:18:30Z adrian $
+# $FreeBSD: head/sys/conf/options.mips 239236 2012-08-13 17:38:38Z alc $
 
 CPU_MIPS4KC	opt_global.h
 CPU_MIPS32	opt_global.h
@@ -77,3 +77,7 @@
 IF_RT_PHY_SUPPORT		opt_if_rt.h
 IF_RT_RING_DATA_COUNT		opt_if_rt.h
 
+#
+# Options that affect the pmap.
+#
+PV_STATS		opt_pmap.h
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/ath/if_ath_tx.c
--- a/head/sys/dev/ath/if_ath_tx.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/ath/if_ath_tx.c	Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx.c 239205 2012-08-12 00:46:15Z adrian $");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx.c 239290 2012-08-15 08:14:16Z adrian $");
 
 /*
  * Driver for the Atheros Wireless LAN controller.
@@ -302,9 +302,10 @@
 {
 	struct ath_hal *ah = sc->sc_ah;
 	struct ath_desc *ds, *ds0;
-	int i;
+	int i, bp, dsp;
 	HAL_DMA_ADDR bufAddrList[4];
 	uint32_t segLenList[4];
+	int numTxMaps = 1;
 
 	/*
 	 * XXX There's txdma and txdma_mgmt; the descriptor
@@ -315,20 +316,47 @@
 	/*
 	 * Fillin the remainder of the descriptor info.
 	 */
+
+	/*
+	 * For now the HAL doesn't implement halNumTxMaps for non-EDMA
+	 * (ie it's 0.)  So just work around it.
+	 *
+	 * XXX TODO: populate halNumTxMaps for each HAL chip and
+	 * then undo this hack.
+	 */
+	if (sc->sc_ah->ah_magic == 0x19741014)
+		numTxMaps = 4;
+
+	/*
+	 * For EDMA and later chips ensure the TX map is fully populated
+	 * before advancing to the next descriptor.
+	 */
 	ds0 = ds = bf->bf_desc;
-	for (i = 0; i < bf->bf_nseg; i++, ds++) {
-		bufAddrList[0] = bf->bf_segs[i].ds_addr;
-		segLenList[0] = bf->bf_segs[i].ds_len;
-
-		/* Blank this out until multi-buf support is added for AR9300 */
-		bufAddrList[1] = bufAddrList[2] = bufAddrList[3] = 0;
-		segLenList[1] = segLenList[2] = segLenList[3] = 0;
+	bp = dsp = 0;
+	bzero(bufAddrList, sizeof(bufAddrList));
+	bzero(segLenList, sizeof(segLenList));
+	for (i = 0; i < bf->bf_nseg; i++) {
+		bufAddrList[bp] = bf->bf_segs[i].ds_addr;
+		segLenList[bp] = bf->bf_segs[i].ds_len;
+		bp++;
+
+		/*
+		 * Go to the next segment if this isn't the last segment
+		 * and there's space in the current TX map.
+		 */
+		if ((i != bf->bf_nseg - 1) && (bp < numTxMaps))
+			continue;
+
+		/*
+		 * Last segment or we're out of buffer pointers.
+		 */
+		bp = 0;
 
 		if (i == bf->bf_nseg - 1)
 			ath_hal_settxdesclink(ah, ds, 0);
 		else
 			ath_hal_settxdesclink(ah, ds,
-			    bf->bf_daddr + dd->dd_descsize * (i + 1));
+			    bf->bf_daddr + dd->dd_descsize * (dsp + 1));
 
 		/*
 		 * XXX this assumes that bfs_txq is the actual destination
@@ -339,7 +367,7 @@
 		ath_hal_filltxdesc(ah, ds
 			, bufAddrList
 			, segLenList
-			, 0			/* XXX desc id */
+			, bf->bf_descid		/* XXX desc id */
 			, bf->bf_state.bfs_txq->axq_qnum	/* XXX multicast? */
 			, i == 0		/* first segment */
 			, i == bf->bf_nseg - 1	/* last segment */
@@ -350,6 +378,18 @@
 			__func__, i, ds->ds_link, ds->ds_data,
 			ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]);
 		bf->bf_lastds = ds;
+
+		/*
+		 * Don't forget to skip to the next descriptor.
+		 */
+		ds++;
+		dsp++;
+
+		/*
+		 * .. and don't forget to blank these out!
+		 */
+		bzero(bufAddrList, sizeof(bufAddrList));
+		bzero(segLenList, sizeof(segLenList));
 	}
 	bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
 }
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/cxgbe/t4_main.c
--- a/head/sys/dev/cxgbe/t4_main.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/cxgbe/t4_main.c	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/cxgbe/t4_main.c 238054 2012-07-03 06:56:11Z np $");
+__FBSDID("$FreeBSD: head/sys/dev/cxgbe/t4_main.c 239259 2012-08-14 22:15:12Z np $");
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -517,7 +517,9 @@
 		    sc->params.b_wnd);
 		t4_write_reg(sc, A_ULP_RX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
 		t4_set_reg_field(sc, A_TP_PARA_REG3, F_TUNNELCNGDROP0 |
-		    F_TUNNELCNGDROP1 | F_TUNNELCNGDROP2 | F_TUNNELCNGDROP3, 0);
+		    F_TUNNELCNGDROP1 | F_TUNNELCNGDROP2 | F_TUNNELCNGDROP3,
+		    F_TUNNELCNGDROP0 | F_TUNNELCNGDROP1 | F_TUNNELCNGDROP2 |
+		    F_TUNNELCNGDROP3);
 		t4_set_reg_field(sc, A_TP_PARA_REG5,
 		    V_INDICATESIZE(M_INDICATESIZE) |
 		    F_REARMDDPOFFSET | F_RESETDDPOFFSET,
@@ -2942,7 +2944,8 @@
 	ifp->if_omcasts = s->tx_mcast_frames - s->tx_pause;
 	ifp->if_imcasts = s->rx_mcast_frames - s->rx_pause;
 	ifp->if_iqdrops = s->rx_ovflow0 + s->rx_ovflow1 + s->rx_ovflow2 +
-	    s->rx_ovflow3;
+	    s->rx_ovflow3 + s->rx_trunc0 + s->rx_trunc1 + s->rx_trunc2 +
+	    s->rx_trunc3;
 
 	drops = s->tx_drop;
 	for_each_txq(pi, i, txq)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/cxgbe/t4_sge.c
--- a/head/sys/dev/cxgbe/t4_sge.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/cxgbe/t4_sge.c	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/cxgbe/t4_sge.c 238313 2012-07-09 21:53:50Z np $");
+__FBSDID("$FreeBSD: head/sys/dev/cxgbe/t4_sge.c 239266 2012-08-15 01:03:13Z np $");
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -68,12 +68,37 @@
 #define FL_BUF_TYPE(x)	(fl_buf_info[x].type)
 #define FL_BUF_ZONE(x)	(fl_buf_info[x].zone)
 
-enum {
-	FL_PKTSHIFT = 2
-};
-
-static int fl_pad = CACHE_LINE_SIZE;
-static int spg_len = 64;
+/*
+ * Ethernet frames are DMA'd at this byte offset into the freelist buffer.
+ * 0-7 are valid values.
+ */
+static int fl_pktshift = 2;
+TUNABLE_INT("hw.cxgbe.fl_pktshift", &fl_pktshift);
+
+/*
+ * Pad ethernet payload up to this boundary.
+ * -1: driver should figure out a good value.
+ *  Any power of 2, from 32 to 4096 (both inclusive) is a valid value.
+ */
+static int fl_pad = -1;
+TUNABLE_INT("hw.cxgbe.fl_pad", &fl_pad);
+
+/*
+ * Status page length.
+ * -1: driver should figure out a good value.
+ *  64 or 128 are the only other valid values.
+ */
+static int spg_len = -1;
+TUNABLE_INT("hw.cxgbe.spg_len", &spg_len);
+
+/*
+ * Congestion drops.
+ * -1: no congestion feedback (not recommended).
+ *  0: backpressure the channel instead of dropping packets right away.
+ *  1: no backpressure, drop packets for the congested queue immediately.
+ */
+static int cong_drop = 0;
+TUNABLE_INT("hw.cxgbe.cong_drop", &cong_drop);
 
 /* Used to track coalesced tx work request */
 struct txpkts {
@@ -170,7 +195,8 @@
 #endif
 
 /*
- * Called on MOD_LOAD and fills up fl_buf_info[].
+ * Called on MOD_LOAD.  Fills up fl_buf_info[] and validates/calculates the SGE
+ * tunables.
  */
 void
 t4_sge_modload(void)
@@ -191,10 +217,49 @@
 		FL_BUF_ZONE(i) = m_getzone(bufsize[i]);
 	}
 
+	if (fl_pktshift < 0 || fl_pktshift > 7) {
+		printf("Invalid hw.cxgbe.fl_pktshift value (%d),"
+		    " using 2 instead.\n", fl_pktshift);
+		fl_pktshift = 2;
+	}
+
+	if (fl_pad < 32 || fl_pad > 4096 || !powerof2(fl_pad)) {
+		int pad;
+
 #if defined(__i386__) || defined(__amd64__)
-	fl_pad = max(cpu_clflush_line_size, 32);
-	spg_len = cpu_clflush_line_size > 64 ? 128 : 64;
+		pad = max(cpu_clflush_line_size, 32);
+#else
+		pad = max(CACHE_LINE_SIZE, 32);
 #endif
+		pad = min(pad, 4096);
+
+		if (fl_pad != -1) {
+			printf("Invalid hw.cxgbe.fl_pad value (%d),"
+			    " using %d instead.\n", fl_pad, pad);
+		}
+		fl_pad = pad;
+	}
+
+	if (spg_len != 64 && spg_len != 128) {
+		int len;
+
+#if defined(__i386__) || defined(__amd64__)
+		len = cpu_clflush_line_size > 64 ? 128 : 64;
+#else
+		len = 64;
+#endif
+		if (spg_len != -1) {
+			printf("Invalid hw.cxgbe.spg_len value (%d),"
+			    " using %d instead.\n", spg_len, len);
+		}
+		spg_len = len;
+	}
+
+	if (cong_drop < -1 || cong_drop > 1) {
+		printf("Invalid hw.cxgbe.cong_drop value (%d),"
+		    " using 0 instead.\n", cong_drop);
+		cong_drop = 0;
+	}
 }
 
 /**
@@ -215,7 +280,7 @@
 	ctrl_mask = V_PKTSHIFT(M_PKTSHIFT) | F_RXPKTCPLMODE |
 	    V_INGPADBOUNDARY(M_INGPADBOUNDARY) |
 	    F_EGRSTATUSPAGESIZE;
-	ctrl_val = V_PKTSHIFT(FL_PKTSHIFT) | F_RXPKTCPLMODE |
+	ctrl_val = V_PKTSHIFT(fl_pktshift) | F_RXPKTCPLMODE |
 	    V_INGPADBOUNDARY(ilog2(fl_pad) - 5) |
 	    V_EGRSTATUSPAGESIZE(spg_len == 128);
 
@@ -477,6 +542,18 @@
 	return (iq);
 }
 
+static inline int
+mtu_to_bufsize(int mtu)
+{
+	int bufsize;
+
+	/* large enough for a frame even when VLAN extraction is disabled */
+	bufsize = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + mtu;
+	bufsize = roundup(bufsize + fl_pktshift, fl_pad);
+
+	return (bufsize);
+}
+
 int
 t4_setup_port_queues(struct port_info *pi)
 {
@@ -493,6 +570,7 @@
 	struct adapter *sc = pi->adapter;
 	struct sysctl_oid *oid = device_get_sysctl_tree(pi->dev);
 	struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid);
+	int bufsize = mtu_to_bufsize(pi->ifp->if_mtu);
 
 	oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "rxq", CTLFLAG_RD,
 	    NULL, "rx queues");
@@ -522,7 +600,7 @@
 
 		snprintf(name, sizeof(name), "%s rxq%d-fl",
 		    device_get_nameunit(pi->dev), i);
-		init_fl(&rxq->fl, pi->qsize_rxq / 8, pi->ifp->if_mtu, name);
+		init_fl(&rxq->fl, pi->qsize_rxq / 8, bufsize, name);
 
 		if (sc->flags & INTR_DIRECT
 #ifdef TCP_OFFLOAD
@@ -1050,9 +1128,9 @@
 	KASSERT(m0 != NULL, ("%s: no payload with opcode %02x", __func__,
 	    rss->opcode));
 
-	m0->m_pkthdr.len -= FL_PKTSHIFT;
-	m0->m_len -= FL_PKTSHIFT;
-	m0->m_data += FL_PKTSHIFT;
+	m0->m_pkthdr.len -= fl_pktshift;
+	m0->m_len -= fl_pktshift;
+	m0->m_data += fl_pktshift;
 
 	m0->m_pkthdr.rcvif = ifp;
 	m0->m_flags |= M_FLOWID;
@@ -1386,11 +1464,8 @@
 	struct port_info *pi = ifp->if_softc;
 	struct sge_rxq *rxq;
 	struct sge_fl *fl;
-	int i, bufsize;
-
-	/* large enough for a frame even when VLAN extraction is disabled */
-	bufsize = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ifp->if_mtu;
-	bufsize = roundup(bufsize + FL_PKTSHIFT, fl_pad);
+	int i, bufsize = mtu_to_bufsize(ifp->if_mtu);
+
 	for_each_rxq(pi, i, rxq) {
 		fl = &rxq->fl;
 
@@ -1793,6 +1868,18 @@
 	return free_wrq(sc, &sc->sge.mgmtq);
 }
 
+static inline int
+tnl_cong(struct port_info *pi)
+{
+
+	if (cong_drop == -1)
+		return (-1);
+	else if (cong_drop == 1)
+		return (0);
+	else
+		return (1 << pi->tx_chan);
+}
+
 static int
 alloc_rxq(struct port_info *pi, struct sge_rxq *rxq, int intr_idx, int idx,
     struct sysctl_oid *oid)
@@ -1801,7 +1888,7 @@
 	struct sysctl_oid_list *children;
 	char name[16];
 
-	rc = alloc_iq_fl(pi, &rxq->iq, &rxq->fl, intr_idx, 1 << pi->tx_chan);
+	rc = alloc_iq_fl(pi, &rxq->iq, &rxq->fl, intr_idx, tnl_cong(pi));
 	if (rc != 0)
 		return (rc);
 
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/fdt/fdt_common.c
--- a/head/sys/dev/fdt/fdt_common.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/fdt/fdt_common.c	Wed Aug 15 11:46:11 2012 +0300
@@ -28,13 +28,14 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/fdt/fdt_common.c 232518 2012-03-04 19:22:52Z raj $");
+__FBSDID("$FreeBSD: head/sys/dev/fdt/fdt_common.c 239274 2012-08-15 03:49:10Z gonzo $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/bus.h>
+#include <sys/limits.h>
 
 #include <machine/fdt.h>
 #include <machine/resource.h>
@@ -63,30 +64,12 @@
 vm_offset_t fdt_immr_size;
 
 int
-fdt_immr_addr(vm_offset_t immr_va)
+fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size)
 {
 	pcell_t ranges[6], *rangesptr;
-	phandle_t node;
-	u_long base, size;
 	pcell_t addr_cells, size_cells, par_addr_cells;
 	int len, tuple_size, tuples;
 
-	/*
-	 * Try to access the SOC node directly i.e. through /aliases/.
-	 */
-	if ((node = OF_finddevice("soc")) != -1)
-		if (fdt_is_compatible_strict(node, "simple-bus"))
-			goto moveon;
-	/*
-	 * Find the node the long way.
-	 */
-	if ((node = OF_finddevice("/")) == -1)
-		return (ENXIO);
-
-	if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
-		return (ENXIO);
-
-moveon:
 	if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
 		return (ENXIO);
 	/*
@@ -99,6 +82,14 @@
 	len = OF_getproplen(node, "ranges");
 	if (len > sizeof(ranges))
 		return (ENOMEM);
+	if (len == 0) {
+		*base = 0;
+		*size = ULONG_MAX;
+		return (0);
+	}
+
+	if (!(range_id < len))
+		return (ERANGE);
 
 	if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0)
 		return (EINVAL);
@@ -111,21 +102,48 @@
 	    addr_cells, size_cells)) {
 		return (ERANGE);
 	}
-	base = 0;
-	size = 0;
-	rangesptr = &ranges[0];
+	*base = 0;
+	*size = 0;
+	rangesptr = &ranges[range_id];
 
-	base = fdt_data_get((void *)rangesptr, addr_cells);
+	*base = fdt_data_get((void *)rangesptr, addr_cells);
 	rangesptr += addr_cells;
-	base += fdt_data_get((void *)rangesptr, par_addr_cells);
+	*base += fdt_data_get((void *)rangesptr, par_addr_cells);
 	rangesptr += par_addr_cells;
-	size = fdt_data_get((void *)rangesptr, size_cells);
+	*size = fdt_data_get((void *)rangesptr, size_cells);
+	return (0);
+}
 
-	fdt_immr_pa = base;
-	fdt_immr_va = immr_va;
-	fdt_immr_size = size;
+int
+fdt_immr_addr(vm_offset_t immr_va)
+{
+	phandle_t node;
+	u_long base, size;
+	int r;
 
-	return (0);
+	/*
+	 * Try to access the SOC node directly i.e. through /aliases/.
+	 */
+	if ((node = OF_finddevice("soc")) != 0)
+		if (fdt_is_compatible_strict(node, "simple-bus"))
+			goto moveon;
+	/*
+	 * Find the node the long way.
+	 */
+	if ((node = OF_finddevice("/")) == 0)
+		return (ENXIO);
+
+	if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
+		return (ENXIO);
+
+moveon:
+	if ((r = fdt_get_range(node, 0, &base, &size)) == 0) {
+		fdt_immr_pa = base;
+		fdt_immr_va = immr_va;
+		fdt_immr_size = size;
+	}
+
+	return (r);
 }
 
 /*
@@ -401,16 +419,19 @@
 }
 
 int
-fdt_reg_to_rl(phandle_t node, struct resource_list *rl, u_long base)
+fdt_reg_to_rl(phandle_t node, struct resource_list *rl)
 {
 	u_long start, end, count;
 	pcell_t *reg, *regptr;
 	pcell_t addr_cells, size_cells;
 	int tuple_size, tuples;
 	int i, rv;
+	long vaddr;
+	long busaddr, bussize;
 
 	if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
 		return (ENXIO);
+	fdt_get_range(OF_parent(node), 0, &busaddr, &bussize);
 
 	tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
 	tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)&reg);
@@ -432,14 +453,15 @@
 		reg += addr_cells + size_cells;
 
 		/* Calculate address range relative to base. */
-		start &= 0x000ffffful;
-		start = base + start;
-		end = start + count - 1;
+		start += busaddr;
+		if (bus_space_map(fdtbus_bs_tag, start, count, 0, &vaddr) != 0)
+			panic("Couldn't map the device memory");
+		end = vaddr + count - 1;
 
-		debugf("reg addr start = %lx, end = %lx, count = %lx\n", start,
+		debugf("reg addr start = %lx, end = %lx, count = %lx\n", vaddr,
 		    end, count);
 
-		resource_list_add(rl, SYS_RES_MEMORY, i, start, end,
+		resource_list_add(rl, SYS_RES_MEMORY, i, vaddr, end,
 		    count);
 	}
 	rv = 0;
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/fdt/fdt_common.h
--- a/head/sys/dev/fdt/fdt_common.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/fdt/fdt_common.h	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/dev/fdt/fdt_common.h 235778 2012-05-22 08:33:14Z gber $
+ * $FreeBSD: head/sys/dev/fdt/fdt_common.h 239274 2012-08-15 03:49:10Z gonzo $
  */
 
 #ifndef _FDT_COMMON_H_
@@ -91,6 +91,7 @@
 phandle_t fdt_find_compatible(phandle_t, const char *, int);
 int fdt_get_mem_regions(struct mem_region *, int *, uint32_t *);
 int fdt_get_phyaddr(phandle_t, device_t, int *, void **);
+int fdt_get_range(phandle_t, int, u_long *, u_long *);
 int fdt_immr_addr(vm_offset_t);
 int fdt_regsize(phandle_t, u_long *, u_long *);
 int fdt_intr_decode(phandle_t, pcell_t *, int *, int *, int *);
@@ -107,7 +108,7 @@
     struct fdt_pci_range *);
 int fdt_pci_route_intr(int, int, int, int, struct fdt_pci_intr *, int *);
 int fdt_ranges_verify(pcell_t *, int, int, int, int);
-int fdt_reg_to_rl(phandle_t, struct resource_list *, u_long);
+int fdt_reg_to_rl(phandle_t, struct resource_list *);
 int fdt_pm(phandle_t);
 
 #endif /* _FDT_COMMON_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/fdt/fdtbus.c
--- a/head/sys/dev/fdt/fdtbus.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/fdt/fdtbus.c	Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/fdt/fdtbus.c 238043 2012-07-02 23:49:29Z marcel $");
+__FBSDID("$FreeBSD: head/sys/dev/fdt/fdtbus.c 239274 2012-08-15 03:49:10Z gonzo $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -289,7 +289,7 @@
 
 	resource_list_init(&di->di_res);
 
-	if (fdt_reg_to_rl(node, &di->di_res, fdt_immr_va)) {
+	if (fdt_reg_to_rl(node, &di->di_res)) {
 		device_printf(child, "could not process 'reg' property\n");
 		newbus_device_destroy(child);
 		child = NULL;
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/fdt/simplebus.c
--- a/head/sys/dev/fdt/simplebus.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/fdt/simplebus.c	Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/fdt/simplebus.c 238044 2012-07-02 23:53:08Z marcel $");
+__FBSDID("$FreeBSD: head/sys/dev/fdt/simplebus.c 239274 2012-08-15 03:49:10Z gonzo $");
 
 #include "opt_platform.h"
 #include <sys/param.h>
@@ -61,9 +61,6 @@
 struct simplebus_softc {
 	int	sc_addr_cells;
 	int	sc_size_cells;
-	u_long	sc_start_pa;
-	u_long	sc_start_va;
-	u_long	sc_size;
 };
 
 struct simplebus_devinfo {
@@ -155,10 +152,6 @@
 
 	sc = device_get_softc(dev);
 
-	sc->sc_start_pa = fdt_immr_pa;
-	sc->sc_start_va = fdt_immr_va;
-	sc->sc_size = fdt_immr_size;
-
 	/*
 	 * Walk simple-bus and add direct subordinates as our children.
 	 */
@@ -182,10 +175,11 @@
 		}
 
 		resource_list_init(&di->di_res);
-
-		if (fdt_reg_to_rl(dt_child, &di->di_res, sc->sc_start_va)) {
-			device_printf(dev, "%s: could not process 'reg' "
+		if (fdt_reg_to_rl(dt_child, &di->di_res)) {
+			device_printf(dev,
+			    "%s: could not process 'reg' "
 			    "property\n", di->di_ofw.obd_name);
+			/* XXX should unmap */
 			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
 			free(di, M_SIMPLEBUS);
 			continue;
@@ -195,6 +189,7 @@
 			device_printf(dev, "%s: could not process "
 			    "'interrupts' property\n", di->di_ofw.obd_name);
 			resource_list_free(&di->di_res);
+			/* XXX should unmap */
 			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
 			free(di, M_SIMPLEBUS);
 			continue;
@@ -206,6 +201,7 @@
 			device_printf(dev, "could not add child: %s\n",
 			    di->di_ofw.obd_name);
 			resource_list_free(&di->di_res);
+			/* XXX should unmap */
 			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
 			free(di, M_SIMPLEBUS);
 			continue;
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/isp/isp.c
--- a/head/sys/dev/isp/isp.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/isp/isp.c	Wed Aug 15 11:46:11 2012 +0300
@@ -47,7 +47,7 @@
 #endif
 #ifdef	__FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/isp/isp.c 238869 2012-07-28 20:06:29Z mjacob $");
+__FBSDID("$FreeBSD: head/sys/dev/isp/isp.c 239219 2012-08-12 20:49:25Z mjacob $");
 #include <dev/isp/isp_freebsd.h>
 #endif
 #ifdef	__OpenBSD__
@@ -939,7 +939,7 @@
 		MBSINIT(&mbs, MBOX_WRITE_RAM_WORD, MBLOGNONE, 0);
 		mbs.param[1] = code_org;
 		mbs.param[2] = ucd.np[0];
-		isp_prt(isp, ISP_LOGDEBUG1, "WRITE RAM %u words at load address 0x%x\n", ucd.np[3], code_org);
+		isp_prt(isp, ISP_LOGDEBUG1, "WRITE RAM %u words at load address 0x%x", ucd.np[3], code_org);
 		isp_mboxcmd(isp, &mbs);
 		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
 			isp_prt(isp, ISP_LOGERR, "F/W download failed at word %d", isp->isp_mbxwrk1 - code_org);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/isp/isp_freebsd.c
--- a/head/sys/dev/isp/isp_freebsd.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/isp/isp_freebsd.c	Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
  * Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
  */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/isp/isp_freebsd.c 239143 2012-08-08 18:24:33Z mjacob $");
+__FBSDID("$FreeBSD: head/sys/dev/isp/isp_freebsd.c 239218 2012-08-12 20:45:47Z mjacob $");
 #include <dev/isp/isp_freebsd.h>
 #include <sys/unistd.h>
 #include <sys/kthread.h>
@@ -779,8 +779,13 @@
 isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
 {
 	if (ISP_PCMD(ccb)) {
-		memset(ISP_PCMD(ccb), 0, sizeof (struct isp_pcmd));
-		((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free;
+#ifdef	ISP_TARGET_MODE
+		PISP_PCMD(ccb)->datalen = 0;
+		PISP_PCMD(ccb)->totslen = 0;
+		PISP_PCMD(ccb)->cumslen = 0;
+		PISP_PCMD(ccb)->crn = 0;
+#endif
+		PISP_PCMD(ccb)->next = isp->isp_osinfo.pcmd_free;
 		isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb);
 		ISP_PCMD(ccb) = NULL;
 	}
@@ -6326,12 +6331,20 @@
 int
 isp_fcp_next_crn(ispsoftc_t *isp, uint8_t *crnp, XS_T *cmd)
 {
-	uint32_t chan = XS_CHANNEL(cmd);
-	uint32_t tgt = XS_TGT(cmd);
-	uint32_t lun = XS_LUN(cmd);
-	struct isp_fc *fc = &isp->isp_osinfo.pc.fc[chan];
-	int idx = NEXUS_HASH(tgt, lun);
-	struct isp_nexus *nxp = fc->nexus_hash[idx];
+	uint32_t chan, tgt, lun;
+	struct isp_fc *fc;
+	struct isp_nexus *nxp;
+	int idx;
+
+	if (isp->isp_type < ISP_HA_FC_2300)
+		return (0);
+
+	chan = XS_CHANNEL(cmd);
+	tgt = XS_TGT(cmd);
+	lun = XS_LUN(cmd);
+	fc = &isp->isp_osinfo.pc.fc[chan];
+	idx = NEXUS_HASH(tgt, lun);
+	nxp = fc->nexus_hash[idx];
 
 	while (nxp) {
 		if (nxp->tgt == tgt && nxp->lun == lun)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/isp/isp_pci.c
--- a/head/sys/dev/isp/isp_pci.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/isp/isp_pci.c	Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
  * FreeBSD Version.
  */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/isp/isp_pci.c 239010 2012-08-03 14:25:35Z mjacob $");
+__FBSDID("$FreeBSD: head/sys/dev/isp/isp_pci.c 239218 2012-08-12 20:45:47Z mjacob $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1690,18 +1690,20 @@
 				bus_dma_tag_destroy(fc->tdmat);
 				goto bad;
 			}
-			for (i = 0; i < INITIAL_NEXUS_COUNT; i++) {
-				struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO);
-				if (n == NULL) {
-					while (fc->nexus_free_list) {
-						n = fc->nexus_free_list;
-						fc->nexus_free_list = n->next;
-						free(n, M_DEVBUF);
+			if (isp->isp_type >= ISP_HA_FC_2300) {
+				for (i = 0; i < INITIAL_NEXUS_COUNT; i++) {
+					struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO);
+					if (n == NULL) {
+						while (fc->nexus_free_list) {
+							n = fc->nexus_free_list;
+							fc->nexus_free_list = n->next;
+							free(n, M_DEVBUF);
+						}
+						goto bad;
 					}
-					goto bad;
+					n->next = fc->nexus_free_list;
+					fc->nexus_free_list = n;
 				}
-				n->next = fc->nexus_free_list;
-				fc->nexus_free_list = n;
 			}
 		}
 	}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mge/if_mge.c
--- a/head/sys/dev/mge/if_mge.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mge/if_mge.c	Wed Aug 15 11:46:11 2012 +0300
@@ -34,7 +34,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/mge/if_mge.c 238873 2012-07-28 21:56:24Z hrs $");
+__FBSDID("$FreeBSD: head/sys/dev/mge/if_mge.c 239276 2012-08-15 04:07:18Z gonzo $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -104,7 +104,10 @@
 static void mge_ver_params(struct mge_softc *sc);
 
 static void mge_intrs_ctrl(struct mge_softc *sc, int enable);
+static void mge_intr_rxtx(void *arg);
 static void mge_intr_rx(void *arg);
+static void mge_intr_rx_check(struct mge_softc *sc, uint32_t int_cause,
+    uint32_t int_cause_ext);
 static int mge_intr_rx_locked(struct mge_softc *sc, int count);
 static void mge_intr_tx(void *arg);
 static void mge_intr_tx_locked(struct mge_softc *sc);
@@ -171,15 +174,14 @@
 	{ SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
 	{ SYS_RES_IRQ, 1, RF_ACTIVE | RF_SHAREABLE },
 	{ SYS_RES_IRQ, 2, RF_ACTIVE | RF_SHAREABLE },
-	{ SYS_RES_IRQ, 3, RF_ACTIVE | RF_SHAREABLE },
-	{ SYS_RES_IRQ, 4, RF_ACTIVE | RF_SHAREABLE },
 	{ -1, 0 }
 };
 
 static struct {
 	driver_intr_t *handler;
 	char * description;
-} mge_intrs[MGE_INTR_COUNT] = {
+} mge_intrs[MGE_INTR_COUNT + 1] = {
+	{ mge_intr_rxtx,"GbE aggregated interrupt" },
 	{ mge_intr_rx,	"GbE receive interrupt" },
 	{ mge_intr_tx,	"GbE transmit interrupt" },
 	{ mge_intr_misc,"GbE misc interrupt" },
@@ -258,10 +260,11 @@
 	uint32_t d, r;
 
 	soc_id(&d, &r);
-	if (d == MV_DEV_88F6281 ||
+	if (d == MV_DEV_88F6281 || d == MV_DEV_88F6781 ||
 	    d == MV_DEV_88F6282 ||
 	    d == MV_DEV_MV78100 ||
-	    d == MV_DEV_MV78100_Z0) {
+	    d == MV_DEV_MV78100_Z0 ||
+	    (d & MV_DEV_FAMILY_MASK) == MV_DEV_DISCOVERY) {
 		sc->mge_ver = 2;
 		sc->mge_mtu = 0x4e8;
 		sc->mge_tfut_ipg_max = 0xFFFF;
@@ -278,6 +281,15 @@
 		sc->mge_tx_tok_cfg = 0x3FFFFFFF;
 		sc->mge_tx_tok_cnt = 0x3FFFFFFF;
 	}
+	if (d == MV_DEV_88RC8180)
+		sc->mge_intr_cnt = 1;
+	else
+		sc->mge_intr_cnt = 2;
+
+	if (d == MV_DEV_MV78160 || d == MV_DEV_MV78260 || d == MV_DEV_MV78460)
+		sc->mge_hw_csum = 0;
+	else
+		sc->mge_hw_csum = 1;
 }
 
 static void
@@ -442,7 +454,7 @@
 
 	/* Allocate a busdma tag for mbufs. */
 	error = bus_dma_tag_create(bus_get_dma_tag(sc->dev),	/* parent */
-	    8, 0,				/* alignment, boundary */
+	    1, 0,				/* alignment, boundary */
 	    BUS_SPACE_MAXADDR_32BIT,		/* lowaddr */
 	    BUS_SPACE_MAXADDR,			/* highaddr */
 	    NULL, NULL,				/* filtfunc, filtfuncarg */
@@ -681,9 +693,12 @@
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_softc = sc;
 	ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST;
-	ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_MTU;
+	ifp->if_capabilities = IFCAP_VLAN_MTU;
+	if (sc->mge_hw_csum) {
+		ifp->if_capabilities |= IFCAP_HWCSUM;
+		ifp->if_hwassist = MGE_CHECKSUM_FEATURES;
+	}
 	ifp->if_capenable = ifp->if_capabilities;
-	ifp->if_hwassist = MGE_CHECKSUM_FEATURES;
 
 #ifdef DEVICE_POLLING
 	/* Advertise that polling is supported */
@@ -717,13 +732,15 @@
 	MGE_WRITE(sc, MGE_REG_PHYDEV, miisc->mii_phy);
 
 	/* Attach interrupt handlers */
-	for (i = 0; i < 2; ++i) {
-		error = bus_setup_intr(dev, sc->res[1 + i],
-		    INTR_TYPE_NET | INTR_MPSAFE, NULL, *mge_intrs[i].handler,
-		    sc, &sc->ih_cookie[i]);
+	/* TODO: review flags, in part. mark RX as INTR_ENTROPY ? */
+	for (i = 1; i <= sc->mge_intr_cnt; ++i) {
+		error = bus_setup_intr(dev, sc->res[i],
+		    INTR_TYPE_NET | INTR_MPSAFE,
+		    NULL, *mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i)].handler,
+		    sc, &sc->ih_cookie[i - 1]);
 		if (error) {
 			device_printf(dev, "could not setup %s\n",
-			    mge_intrs[i].description);
+			    mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i)].description);
 			mge_detach(dev);
 			return (error);
 		}
@@ -748,14 +765,14 @@
         callout_drain(&sc->wd_callout);
 
 	/* Stop and release all interrupts */
-	for (i = 0; i < 2; ++i) {
+	for (i = 0; i < sc->mge_intr_cnt; ++i) {
 		if (!sc->ih_cookie[i])
 			continue;
 
 		error = bus_teardown_intr(dev, sc->res[1 + i], sc->ih_cookie[i]);
 		if (error)
 			device_printf(dev, "could not release %s\n",
-			    mge_intrs[i].description);
+			    mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i + 1)].description);
 	}
 
 	/* Detach network interface */
@@ -983,6 +1000,41 @@
 }
 
 static void
+mge_intr_rxtx(void *arg)
+{
+	struct mge_softc *sc = arg;
+	uint32_t int_cause, int_cause_ext;
+
+	MGE_GLOBAL_LOCK(sc);
+
+#ifdef DEVICE_POLLING
+	if (sc->ifp->if_capenable & IFCAP_POLLING) {
+		MGE_GLOBAL_UNLOCK(sc);
+		return;
+	}
+#endif
+
+	/* Get interrupt cause */
+	int_cause = MGE_READ(sc, MGE_PORT_INT_CAUSE);
+	int_cause_ext = MGE_READ(sc, MGE_PORT_INT_CAUSE_EXT);
+
+	/* Check for Transmit interrupt */
+	if (int_cause_ext & (MGE_PORT_INT_EXT_TXBUF0 |
+	    MGE_PORT_INT_EXT_TXUR)) {
+		MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT, ~(int_cause_ext &
+		    (MGE_PORT_INT_EXT_TXBUF0 | MGE_PORT_INT_EXT_TXUR)));
+		mge_intr_tx_locked(sc);
+	}
+
+	MGE_TRANSMIT_UNLOCK(sc);
+
+	/* Check for Receive interrupt */
+	mge_intr_rx_check(sc, int_cause, int_cause_ext);
+
+	MGE_RECEIVE_UNLOCK(sc);
+}
+
+static void
 mge_intr_err(void *arg)
 {
 	struct mge_softc *sc = arg;
@@ -1020,11 +1072,20 @@
 	int_cause = MGE_READ(sc, MGE_PORT_INT_CAUSE);
 	int_cause_ext = MGE_READ(sc, MGE_PORT_INT_CAUSE_EXT);
 
+	mge_intr_rx_check(sc, int_cause, int_cause_ext);
+
+	MGE_RECEIVE_UNLOCK(sc);
+}
+
+static void
+mge_intr_rx_check(struct mge_softc *sc, uint32_t int_cause,
+    uint32_t int_cause_ext)
+{
 	/* Check for resource error */
 	if (int_cause & MGE_PORT_INT_RXERRQ0) {
 		mge_reinit_rx(sc);
 		MGE_WRITE(sc, MGE_PORT_INT_CAUSE,
-		    int_cause & ~MGE_PORT_INT_RXERRQ0);
+		    ~(int_cause & MGE_PORT_INT_RXERRQ0));
 	}
 
 	int_cause &= MGE_PORT_INT_RXQ0;
@@ -1035,11 +1096,8 @@
 		MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT, ~int_cause_ext);
 		mge_intr_rx_locked(sc, -1);
 	}
-
-	MGE_RECEIVE_UNLOCK(sc);
 }
 
-
 static int
 mge_intr_rx_locked(struct mge_softc *sc, int count)
 {
@@ -1130,8 +1188,8 @@
 
 	/* Ack the interrupt */
 	int_cause_ext = MGE_READ(sc, MGE_PORT_INT_CAUSE_EXT);
-	MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT,
-	    int_cause_ext & ~MGE_PORT_INT_EXT_TXBUF0);
+	MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT, ~(int_cause_ext &
+	    (MGE_PORT_INT_EXT_TXBUF0 | MGE_PORT_INT_EXT_TXUR)));
 
 	mge_intr_tx_locked(sc);
 
@@ -1401,12 +1459,12 @@
 		dw->mge_desc->byte_count = segs[seg].ds_len;
 		dw->mge_desc->buffer = segs[seg].ds_addr;
 		dw->buffer = m0;
-		dw->mge_desc->cmd_status = MGE_TX_LAST | MGE_TX_FIRST |
+		dw->mge_desc->cmd_status = 0;
+		if (seg == 0)
+			mge_offload_setup_descriptor(sc, dw);
+		dw->mge_desc->cmd_status |= MGE_TX_LAST | MGE_TX_FIRST |
 		    MGE_TX_ETH_CRC | MGE_TX_EN_INT | MGE_TX_PADDING |
 		    MGE_DMA_OWNED;
-
-		if (seg == 0)
-			mge_offload_setup_descriptor(sc, dw);
 	}
 
 	bus_dmamap_sync(sc->mge_desc_dtag, dw->desc_dmap,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mge/if_mgevar.h
--- a/head/sys/dev/mge/if_mgevar.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mge/if_mgevar.h	Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/dev/mge/if_mgevar.h 232518 2012-03-04 19:22:52Z raj $
+ * $FreeBSD: head/sys/dev/mge/if_mgevar.h 239276 2012-08-15 04:07:18Z gonzo $
  */
 
 #ifndef __IF_MGE_H__
@@ -103,6 +103,8 @@
 	uint32_t	mge_tx_tok_cnt;
 	uint16_t	mge_mtu;
 	int		mge_ver;
+	int		mge_intr_cnt;
+	uint8_t		mge_hw_csum;
 
 	struct mge_softc *phy_sc;
 };
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mii/miidevs
--- a/head/sys/dev/mii/miidevs	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mii/miidevs	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-$FreeBSD: head/sys/dev/mii/miidevs 235999 2012-05-25 15:05:17Z raj $
+$FreeBSD: head/sys/dev/mii/miidevs 239275 2012-08-15 04:03:55Z gonzo $
 /*$NetBSD: miidevs,v 1.105 2011/11/25 23:28:14 jakllsch Exp $*/
 
 /*-
@@ -70,6 +70,7 @@
 oui REALTEK			0x00e04c	RealTek Semicondctor
 oui SEEQ			0x00a07d	Seeq Technology
 oui SIS				0x00e006	Silicon Integrated Systems
+oui SMC				0x00800f	SMC
 oui TI				0x080028	Texas Instruments
 oui TSC				0x00c039	TDK Semiconductor
 oui VITESSE			0x0001c1	Vitesse Semiconductor
@@ -331,3 +332,6 @@
 
 /* XaQti Corp. PHYs */
 model xxXAQTI XMACII		0x0000 XaQti Corp. XMAC II gigabit interface
+
+/* SMC */
+model SMC LAN8710A		0x000F SMC LAN8710A 10/100 interface
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mii/smcphy.c
--- a/head/sys/dev/mii/smcphy.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mii/smcphy.c	Wed Aug 15 11:46:11 2012 +0300
@@ -23,10 +23,11 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/mii/smcphy.c 232015 2012-02-23 01:20:21Z yongari $");
+__FBSDID("$FreeBSD: head/sys/dev/mii/smcphy.c 239275 2012-08-15 04:03:55Z gonzo $");
 
 /*
- * Driver for the internal PHY on the SMSC LAN91C111.
+ * Driver for the SEEQ 80220 and 84220.
+ * (Originally developed for the internal PHY on the SMSC LAN91C111.)
  */
 
 #include <sys/param.h>
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mii/smscphy.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/mii/smscphy.c	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,237 @@
+/*-
+ * Copyright (c) 2006 Benno Rice.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/dev/mii/smscphy.c 239275 2012-08-15 04:03:55Z gonzo $");
+
+/*
+ * Driver for the SMSC LAN8710A
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include "miidevs.h"
+
+#include "miibus_if.h"
+
+static int	smscphy_probe(device_t);
+static int	smscphy_attach(device_t);
+
+static int	smscphy_service(struct mii_softc *, struct mii_data *, int);
+static void	smscphy_auto(struct mii_softc *, int);
+static void	smscphy_status(struct mii_softc *);
+
+static device_method_t smscphy_methods[] = {
+	/* device interface */
+	DEVMETHOD(device_probe,		smscphy_probe),
+	DEVMETHOD(device_attach,	smscphy_attach),
+	DEVMETHOD(device_detach,	mii_phy_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD_END
+};
+
+static devclass_t smscphy_devclass;
+
+static driver_t smscphy_driver = {
+	"smscphy",
+	smscphy_methods,
+	sizeof(struct mii_softc)
+};
+
+DRIVER_MODULE(smscphy, miibus, smscphy_driver, smscphy_devclass, 0, 0);
+
+static const struct mii_phydesc smscphys[] = {
+	MII_PHY_DESC(SMC, LAN8710A),
+	MII_PHY_END
+};
+
+static const struct mii_phy_funcs smscphy_funcs = {
+	smscphy_service,
+	smscphy_status,
+	mii_phy_reset
+};
+
+static int
+smscphy_probe(device_t dev)
+{
+
+	return (mii_phy_dev_probe(dev, smscphys, BUS_PROBE_DEFAULT));
+}
+
+static int
+smscphy_attach(device_t dev)
+{
+	struct mii_softc *sc;
+	struct mii_attach_args *ma;
+	const struct mii_phy_funcs *mpf;
+
+	sc = device_get_softc(dev);
+	ma = device_get_ivars(dev);
+	mpf = &smscphy_funcs;
+	mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, mpf, 1);
+	mii_phy_setmedia(sc);
+
+	return (0);
+}
+
+static int
+smscphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
+{
+        struct	ifmedia_entry *ife;
+        int	reg;
+
+	ife = mii->mii_media.ifm_cur;
+
+        switch (cmd) {
+        case MII_POLLSTAT:
+                break;
+
+        case MII_MEDIACHG:
+                /*
+                 * If the interface is not up, don't do anything.
+                 */
+                if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+                        break;
+
+		switch (IFM_SUBTYPE(ife->ifm_media)) {
+		case IFM_AUTO:
+			smscphy_auto(sc, ife->ifm_media);
+			break;
+
+		default:
+                	mii_phy_setmedia(sc);
+			break;
+		}
+
+                break;
+
+        case MII_TICK:
+		if ((mii->mii_ifp->if_flags & IFF_UP) == 0) {
+			return (0);
+		}
+
+		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
+			break;
+		}
+
+		/* I have no idea why BMCR_ISO gets set. */
+		reg = PHY_READ(sc, MII_BMCR);
+		if (reg & BMCR_ISO) {
+			PHY_WRITE(sc, MII_BMCR, reg & ~BMCR_ISO);
+		}
+
+		reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+		if (reg & BMSR_LINK) {
+			sc->mii_ticks = 0;
+			break;
+		}
+
+		if (++sc->mii_ticks <= MII_ANEGTICKS) {
+			break;
+		}
+
+		sc->mii_ticks = 0;
+		PHY_RESET(sc);
+		smscphy_auto(sc, ife->ifm_media);
+                break;
+        }
+
+        /* Update the media status. */
+        PHY_STATUS(sc);
+
+        /* Callback if something changed. */
+        mii_phy_update(sc, cmd);
+        return (0);
+}
+
+static void
+smscphy_auto(struct mii_softc *sc, int media)
+{
+	uint16_t	anar;
+
+	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
+	if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+		anar |= ANAR_FC;
+	PHY_WRITE(sc, MII_ANAR, anar);
+	/* Apparently this helps. */
+	anar = PHY_READ(sc, MII_ANAR);
+	PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
+}
+
+static void
+smscphy_status(struct mii_softc *sc)
+{
+	struct mii_data *mii;
+	uint32_t bmcr, bmsr, status;
+
+	mii = sc->mii_pdata;
+	mii->mii_media_status = IFM_AVALID;
+	mii->mii_media_active = IFM_ETHER;
+
+	bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+	if ((bmsr & BMSR_LINK) != 0)
+		mii->mii_media_status |= IFM_ACTIVE;
+
+	bmcr = PHY_READ(sc, MII_BMCR);
+	if ((bmcr & BMCR_ISO) != 0) {
+		mii->mii_media_active |= IFM_NONE;
+		mii->mii_media_status = 0;
+		return;
+	}
+
+	if ((bmcr & BMCR_LOOP) != 0)
+		mii->mii_media_active |= IFM_LOOP;
+
+	if ((bmcr & BMCR_AUTOEN) != 0) {
+		if ((bmsr & BMSR_ACOMP) == 0) {
+			/* Erg, still trying, I guess... */
+			mii->mii_media_active |= IFM_NONE;
+			return;
+		}
+	}
+
+	status = PHY_READ(sc, 0x1F);
+	if (status & 0x0008)
+		mii->mii_media_active |= IFM_100_TX;
+	else
+		mii->mii_media_active |= IFM_10_T;
+	if (status & 0x0010)
+		mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc);
+	else
+		mii->mii_media_active |= IFM_HDX;
+}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mmc/mmc.c
--- a/head/sys/dev/mmc/mmc.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mmc/mmc.c	Wed Aug 15 11:46:11 2012 +0300
@@ -51,7 +51,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/mmc/mmc.c 236491 2012-06-02 20:47:00Z marius $");
+__FBSDID("$FreeBSD: head/sys/dev/mmc/mmc.c 239281 2012-08-15 06:31:32Z gonzo $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1730,5 +1730,6 @@
 };
 static devclass_t mmc_devclass;
 
+DRIVER_MODULE(mmc, ti_mmchs, mmc_driver, mmc_devclass, NULL, NULL);
 DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
 DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, NULL, NULL);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/netmap/ixgbe_netmap.h
--- a/head/sys/dev/netmap/ixgbe_netmap.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/netmap/ixgbe_netmap.h	Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
  */
 
 /*
- * $FreeBSD: head/sys/dev/netmap/ixgbe_netmap.h 238985 2012-08-02 11:59:43Z luigi $
+ * $FreeBSD: head/sys/dev/netmap/ixgbe_netmap.h 239242 2012-08-13 19:14:45Z emaste $
  * $Id: ixgbe_netmap.h 10627 2012-02-23 19:37:15Z luigi $
  *
  * netmap modifications for ixgbe
@@ -198,14 +198,17 @@
  * Reconcile kernel and user view of the transmit ring.
  * This routine might be called frequently so it must be efficient.
  *
- * Userspace has filled tx slots up to ring->cur (excluded).
- * The last unused slot previously known to the kernel was kring->nkr_hwcur,
- * and the last interrupt reported kring->nr_hwavail slots available.
+ * ring->cur holds the userspace view of the current ring index.  Userspace
+ * has filled the tx slots from the previous call's ring->cur up to but not
+ * including ring->cur for this call.  In this function the kernel updates
+ * kring->nr_hwcur to ring->cur, thus slots [kring->nr_hwcur, ring->cur) are
+ * now ready to transmit.  At the last interrupt kring->nr_hwavail slots were
+ * available.
  *
  * This function runs under lock (acquired from the caller or internally).
  * It must first update ring->avail to what the kernel knows,
- * subtract the newly used slots (ring->cur - kring->nkr_hwcur)
- * from both avail and nr_hwavail, and set ring->nkr_hwcur = ring->cur
+ * subtract the newly used slots (ring->cur - kring->nr_hwcur)
+ * from both avail and nr_hwavail, and set ring->nr_hwcur = ring->cur
  * issuing a dmamap_sync on all slots.
  *
  * Since ring comes from userspace, its content must be read only once,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/ofw/ofw_iicbus.c
--- a/head/sys/dev/ofw/ofw_iicbus.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/ofw/ofw_iicbus.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/ofw/ofw_iicbus.c 233018 2012-03-15 22:53:39Z nwhitehorn $");
+__FBSDID("$FreeBSD: head/sys/dev/ofw/ofw_iicbus.c 239273 2012-08-15 03:33:57Z gonzo $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -35,6 +35,7 @@
 #include <sys/module.h>
 #include <sys/mutex.h>
 
+#include <dev/fdt/fdt_common.h>
 #include <dev/iicbus/iicbus.h>
 #include <dev/iicbus/iiconf.h>
 #include <dev/ofw/ofw_bus.h>
@@ -101,6 +102,7 @@
 	struct iicbus_softc *sc = IICBUS_SOFTC(dev);
 	struct ofw_iicbus_devinfo *dinfo;
 	phandle_t child;
+	pcell_t paddr;
 	device_t childdev;
 	uint32_t addr;
 
@@ -121,10 +123,11 @@
 		 * property, then try the reg property.  It moves around
 		 * on different systems.
 		 */
-		if (OF_getprop(child, "i2c-address", &addr, sizeof(addr)) == -1)
-			if (OF_getprop(child, "reg", &addr, sizeof(addr)) == -1)
+		if (OF_getprop(child, "i2c-address", &paddr, sizeof(paddr)) == -1)
+			if (OF_getprop(child, "reg", &paddr, sizeof(paddr)) == -1)
 				continue;
 
+		addr = fdt32_to_cpu(paddr);
 		/*
 		 * Now set up the I2C and OFW bus layer devinfo and add it
 		 * to the bus.
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/re/if_re.c
--- a/head/sys/dev/re/if_re.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/re/if_re.c	Wed Aug 15 11:46:11 2012 +0300
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/re/if_re.c 237547 2012-06-25 05:47:12Z kevlo $");
+__FBSDID("$FreeBSD: head/sys/dev/re/if_re.c 239234 2012-08-13 16:03:30Z emaste $");
 
 /*
  * RealTek 8139C+/8169/8169S/8110S/8168/8111/8101E PCI NIC driver
@@ -2112,8 +2112,8 @@
 	ifp = sc->rl_ifp;
 #ifdef DEV_NETMAP
 	if (ifp->if_capenable & IFCAP_NETMAP) {
-		NA(ifp)->rx_rings->nr_kflags |= NKR_PENDINTR;
-		selwakeuppri(&NA(ifp)->rx_rings->si, PI_NET);
+		NA(ifp)->rx_rings[0].nr_kflags |= NKR_PENDINTR;
+		selwakeuppri(&NA(ifp)->rx_rings[0].si, PI_NET);
 		return 0;
 	}
 #endif /* DEV_NETMAP */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/sound/macio/snapper.c
--- a/head/sys/dev/sound/macio/snapper.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/sound/macio/snapper.c	Wed Aug 15 11:46:11 2012 +0300
@@ -22,7 +22,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/sound/macio/snapper.c 239245 2012-08-14 05:16:35Z andreast $
  */
 /*-
  * Copyright (c) 2002, 2003 Tsubai Masanari.  All rights reserved.
@@ -174,7 +174,7 @@
 #define  SNAPPER_MCR1_W_16	0x00	/*  16 bit */
 #define  SNAPPER_MCR1_W_18	0x01	/*  18 bit */
 #define  SNAPPER_MCR1_W_20	0x02	/*  20 bit */
-#define  SNAPPER_MCR1_W_24	0x03	/*  20 bit */
+#define  SNAPPER_MCR1_W_24	0x03	/*  24 bit */
 #define SNAPPER_MCR2_DL	0x80	/* Download */
 #define SNAPPER_MCR2_AP	0x02	/* All pass mode */
 #define SNAPPER_ACR_ADM	0x80	/* ADC output mode */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/sound/pci/hda/hdaa.c
--- a/head/sys/dev/sound/pci/hda/hdaa.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/sound/pci/hda/hdaa.c	Wed Aug 15 11:46:11 2012 +0300
@@ -45,7 +45,7 @@
 
 #include "mixer_if.h"
 
-SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa.c 238022 2012-07-02 20:25:50Z mav $");
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa.c 239254 2012-08-14 14:07:34Z mav $");
 
 #define hdaa_lock(devinfo)	snd_mtxlock((devinfo)->lock)
 #define hdaa_unlock(devinfo)	snd_mtxunlock((devinfo)->lock)
@@ -3068,8 +3068,7 @@
 		if ((only == 0 || only == w->nid) && (w->nid >= min) &&
 		    (onlylength == 0 || onlylength == depth)) {
 			m = w->nid;
-			if (length != NULL)
-				*length = depth;
+			*length = depth;
 		}
 		break;
 	case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX:
@@ -3092,12 +3091,12 @@
 				    j, mixed, min, only, depth + 1,
 				    length, onlylength)) != 0) {
 					if (m == 0 || ret < m ||
-					    (ret == m && length != NULL &&
-					     *length < lm)) {
+					    (ret == m && *length < lm)) {
 						m = ret;
 						im = i;
 						lm = *length;
-					}
+					} else
+						*length = lm;
 					if (only)
 						break;
 				}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/twe/twe.c
--- a/head/sys/dev/twe/twe.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/twe/twe.c	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$FreeBSD$
+ *	$FreeBSD: head/sys/dev/twe/twe.c 239244 2012-08-13 21:29:34Z jhb $
  */
 
 /*
@@ -151,8 +151,11 @@
 	/*
 	 * Put command onto the freelist.
 	 */
+	TWE_IO_LOCK(sc);
 	twe_release_request(tr);
+	TWE_IO_UNLOCK(sc);
     }
+    TWE_IO_LOCK(sc);
 
     /*
      * Check status register for errors, clear them.
@@ -164,6 +167,7 @@
      * Wait for the controller to come ready.
      */
     if (twe_wait_status(sc, TWE_STATUS_MICROCONTROLLER_READY, 60)) {
+	TWE_IO_UNLOCK(sc);
 	twe_printf(sc, "microcontroller not ready\n");
 	return(ENXIO);
     }
@@ -185,6 +189,7 @@
 	if (!twe_soft_reset(sc))
 	    break;			/* reset process complete */
     }
+    TWE_IO_UNLOCK(sc);
     /* did we give up? */
     if (i >= TWE_MAX_RESET_TRIES) {
 	twe_printf(sc, "can't initialise controller, giving up\n");
@@ -203,14 +208,17 @@
     TWE_Param			*drives = NULL, *param = NULL;
     TWE_Array_Descriptor	*ud;
 
+    TWE_CONFIG_ASSERT_LOCKED(sc);
     if (unit < 0 || unit > TWE_MAX_UNITS)
 	return (EINVAL);
 
     /*
      * The controller is in a safe state, so try to find drives attached to it.
      */
+    TWE_IO_LOCK(sc);
     if ((drives = twe_get_param(sc, TWE_PARAM_UNITSUMMARY, TWE_PARAM_UNITSUMMARY_Status,
 				TWE_MAX_UNITS, NULL)) == NULL) {
+	TWE_IO_UNLOCK(sc);
 	twe_printf(sc, "can't detect attached units\n");
 	return (EIO);
     }
@@ -218,6 +226,7 @@
     dr = &sc->twe_drive[unit];
     /* check that the drive is online */
     if (!(drives->data[unit] & TWE_PARAM_UNITSTATUS_Online)) {
+	TWE_IO_UNLOCK(sc);
 	error = ENXIO;
 	goto out;
     }
@@ -225,21 +234,25 @@
     table = TWE_PARAM_UNITINFO + unit;
 
     if (twe_get_param_4(sc, table, TWE_PARAM_UNITINFO_Capacity, &dr->td_size)) {
+	TWE_IO_UNLOCK(sc);
 	twe_printf(sc, "error fetching capacity for unit %d\n", unit);
 	error = EIO;
 	goto out;
     }
     if (twe_get_param_1(sc, table, TWE_PARAM_UNITINFO_Status, &dr->td_state)) {
+	TWE_IO_UNLOCK(sc);
 	twe_printf(sc, "error fetching state for unit %d\n", unit);
 	error = EIO;
 	goto out;
     }
     if (twe_get_param_2(sc, table, TWE_PARAM_UNITINFO_DescriptorSize, &dsize)) {
+	TWE_IO_UNLOCK(sc);
 	twe_printf(sc, "error fetching descriptor size for unit %d\n", unit);
 	error = EIO;
 	goto out;
     }
     if ((param = twe_get_param(sc, table, TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL)) == NULL) {
+	TWE_IO_UNLOCK(sc);
 	twe_printf(sc, "error fetching descriptor for unit %d\n", unit);
 	error = EIO;
 	goto out;
@@ -258,6 +271,7 @@
     }
     dr->td_cylinders = dr->td_size / (dr->td_heads * dr->td_sectors);
     dr->td_twe_unit = unit;
+    TWE_IO_UNLOCK(sc);
 
     error = twe_attach_drive(sc, dr);
 
@@ -274,6 +288,7 @@
 {
     int error;
 
+    TWE_CONFIG_ASSERT_LOCKED(sc);
     if (unit < 0 || unit >= TWE_MAX_UNITS)
 	return (ENXIO);
 
@@ -295,12 +310,15 @@
     /*
      * Scan for drives
      */
+    TWE_CONFIG_LOCK(sc);
     for (i = 0; i < TWE_MAX_UNITS; i++)
 	twe_add_unit(sc, i);
+    TWE_CONFIG_UNLOCK(sc);
 
     /*
      * Initialise connection with controller.
      */
+    TWE_IO_LOCK(sc);
     twe_init_connection(sc, TWE_INIT_MESSAGE_CREDITS);
 
 #ifdef TWE_SHUTDOWN_NOTIFICATION
@@ -319,6 +337,7 @@
      * Finally enable interrupts.
      */
     twe_enable_interrupts(sc);
+    TWE_IO_UNLOCK(sc);
 }
 
 /********************************************************************************
@@ -330,6 +349,7 @@
     /*
      * Mark the controller as shutting down, and disable any further interrupts.
      */
+    TWE_IO_ASSERT_LOCKED(sc);
     sc->twe_state |= TWE_STATE_SHUTDOWN;
     twe_disable_interrupts(sc);
 
@@ -385,6 +405,7 @@
 
     debug_called(4);
 
+    TWE_IO_ASSERT_LOCKED(sc);
     if (sc->twe_state & (TWE_STATE_CTLR_BUSY | TWE_STATE_FRZN))
 	return;
 
@@ -500,15 +521,32 @@
     u_int16_t			*aen_code = (u_int16_t *)addr;
     struct twe_request		*tr;
     u_int8_t			srid;
-    int				s, error;
+    int				error;
+    size_t			tr_length;
 
     error = 0;
     switch(ioctlcmd) {
 	/* handle a command from userspace */
     case TWEIO_COMMAND:
+	/*
+	 * if there's a data buffer, allocate and copy it in.
+	 * Must be in multipled of 512 bytes.
+	 */
+	tr_length = roundup2(tu->tu_size, 512);
+	if (tr_length > 0) {
+	    data = malloc(tr_length, M_DEVBUF, M_WAITOK);
+	    error = copyin(tu->tu_data, data, tu->tu_size);
+	    if (error) {
+		free(data, M_DEVBUF);
+		break;
+	    }
+	} else
+	    data = NULL;
+
 	/* get a request */
+	TWE_IO_LOCK(sc);
 	while (twe_get_request(sc, &tr))
-	    tsleep(sc, PPAUSE, "twioctl", hz);
+	    mtx_sleep(sc, &sc->twe_io_lock, PPAUSE, "twioctl", hz);
 
 	/*
 	 * Save the command's request ID, copy the user-supplied command in,
@@ -519,23 +557,15 @@
 	bcopy(&tu->tu_command, cmd, sizeof(TWE_Command));
 	cmd->generic.request_id = srid;
 
-	/*
-	 * if there's a data buffer, allocate and copy it in.
-	 * Must be in multipled of 512 bytes.
-	 */
-	tr->tr_length = (tu->tu_size + 511) & ~511;
+	tr->tr_length = tr_length;
+	tr->tr_data = data;
 	if (tr->tr_length > 0) {
-	    if ((tr->tr_data = malloc(tr->tr_length, M_DEVBUF, M_WAITOK)) == NULL) {
-		error = ENOMEM;
-		goto cmd_done;
-	    }
-	    if ((error = copyin(tu->tu_data, tr->tr_data, tu->tu_size)) != 0)
-		goto cmd_done;
 	    tr->tr_flags |= TWE_CMD_DATAIN | TWE_CMD_DATAOUT;
 	}
 
 	/* run the command */
 	error = twe_wait_request(tr);
+	TWE_IO_UNLOCK(sc);
 	if (error)
 	    goto cmd_done;
 
@@ -550,8 +580,9 @@
 	/* free resources */
 	if (tr->tr_data != NULL)
 	    free(tr->tr_data, M_DEVBUF);
-	if (tr != NULL)
-	    twe_release_request(tr);
+	TWE_IO_LOCK(sc);
+	twe_release_request(tr);
+	TWE_IO_UNLOCK(sc);
 
 	break;
 
@@ -564,7 +595,9 @@
 	case TWEQ_READY:
 	case TWEQ_BUSY:
 	case TWEQ_COMPLETE:
+	    TWE_IO_LOCK(sc);
 	    bcopy(&sc->twe_qstat[ts->ts_item], &ts->ts_qstat, sizeof(struct twe_qstat));
+	    TWE_IO_UNLOCK(sc);
 	    break;
 #endif
 	default:
@@ -575,22 +608,28 @@
 
 	/* poll for an AEN */
     case TWEIO_AEN_POLL:
+	TWE_IO_LOCK(sc);
 	*aen_code = twe_dequeue_aen(sc);
+	TWE_IO_UNLOCK(sc);
 	break;
 
 	/* wait for another AEN to show up */
     case TWEIO_AEN_WAIT:
-	s = splbio();
+	TWE_IO_LOCK(sc);
 	while ((*aen_code = twe_dequeue_aen(sc)) == TWE_AEN_QUEUE_EMPTY) {
-	    error = tsleep(&sc->twe_aen_queue, PRIBIO | PCATCH, "tweaen", 0);
+	    error = mtx_sleep(&sc->twe_aen_queue, &sc->twe_io_lock, PRIBIO | PCATCH,
+		"tweaen", 0);
 	    if (error == EINTR)
 		break;
 	}
-	splx(s);
+	TWE_IO_UNLOCK(sc);
 	break;
 
     case TWEIO_GET_PARAM:
-	if ((param = twe_get_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, NULL)) == NULL) {
+	TWE_IO_LOCK(sc);
+	param = twe_get_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, NULL);
+	TWE_IO_UNLOCK(sc);
+	if (param == NULL) {
 	    twe_printf(sc, "TWEIO_GET_PARAM failed for 0x%x/0x%x/%d\n", 
 		       tp->tp_table_id, tp->tp_param_id, tp->tp_size);
 	    error = EINVAL;
@@ -607,26 +646,32 @@
 	break;
 
     case TWEIO_SET_PARAM:
-	if ((data = malloc(tp->tp_size, M_DEVBUF, M_WAITOK)) == NULL) {
-	    error = ENOMEM;
-	} else {
-	    error = copyin(tp->tp_data, data, tp->tp_size);
-	    if (error == 0)
-		error = twe_set_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, data);
-	    free(data, M_DEVBUF);
+	data = malloc(tp->tp_size, M_DEVBUF, M_WAITOK);
+	error = copyin(tp->tp_data, data, tp->tp_size);
+	if (error == 0) {
+	    TWE_IO_LOCK(sc);
+	    error = twe_set_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, data);
+	    TWE_IO_UNLOCK(sc);
 	}
+	free(data, M_DEVBUF);
 	break;
 
     case TWEIO_RESET:
+	TWE_IO_LOCK(sc);
 	twe_reset(sc);
+	TWE_IO_UNLOCK(sc);
 	break;
 
     case TWEIO_ADD_UNIT:
+	TWE_CONFIG_LOCK(sc);
 	error = twe_add_unit(sc, td->td_unit);
+	TWE_CONFIG_UNLOCK(sc);
 	break;
 
     case TWEIO_DEL_UNIT:
+	TWE_CONFIG_LOCK(sc);
 	error = twe_del_unit(sc, td->td_unit);
+	TWE_CONFIG_UNLOCK(sc);
 	break;
 
 	/* XXX implement ATA PASSTHROUGH */
@@ -724,6 +769,7 @@
 
     debug_called(4);
 
+    TWE_IO_ASSERT_LOCKED(sc);
     tr = NULL;
     param = NULL;
 
@@ -817,6 +863,7 @@
 
     debug_called(4);
 
+    TWE_IO_ASSERT_LOCKED(sc);
     tr = NULL;
     param = NULL;
     error = ENOMEM;
@@ -874,6 +921,8 @@
     
     debug_called(4);
 
+    TWE_IO_ASSERT_LOCKED(sc);
+
     /* get a command */
     if (twe_get_request(sc, &tr))
 	return(0);
@@ -903,18 +952,16 @@
 static int
 twe_wait_request(struct twe_request *tr)
 {
-    int		s;
 
     debug_called(4);
 
+    TWE_IO_ASSERT_LOCKED(tr->tr_sc);
     tr->tr_flags |= TWE_CMD_SLEEPER;
     tr->tr_status = TWE_CMD_BUSY;
     twe_enqueue_ready(tr);
     twe_startio(tr->tr_sc);
-    s = splbio();
     while (tr->tr_status == TWE_CMD_BUSY)
-	tsleep(tr, PRIBIO, "twewait", 0);
-    splx(s);
+	mtx_sleep(tr, &tr->tr_sc->twe_io_lock, PRIBIO, "twewait", 0);
     
     return(tr->tr_status != TWE_CMD_COMPLETE);
 }
@@ -991,12 +1038,12 @@
 twe_reset(struct twe_softc *sc)
 {
     struct twe_request	*tr;
-    int			i, s;
+    int			i;
 
     /*
      * Sleep for a short period to allow AENs to be signalled.
      */
-    tsleep(sc, PRIBIO, "twereset", hz);
+    mtx_sleep(sc, &sc->twe_io_lock, PRIBIO, "twereset", hz);
 
     /*
      * Disable interrupts from the controller, and mask any accidental entry
@@ -1004,7 +1051,6 @@
      */
     twe_printf(sc, "controller reset in progress...\n");
     twe_disable_interrupts(sc);
-    s = splbio();
 
     /*
      * Try to soft-reset the controller.
@@ -1036,11 +1082,9 @@
      * Kick the controller to start things going again, then re-enable interrupts.
      */
     twe_startio(sc);
-    twe_enable_interrupts(sc);
     twe_printf(sc, "controller reset done, %d commands restarted\n", i);
 
 out:
-    splx(s);
     twe_enable_interrupts(sc);
 }
 
@@ -1060,11 +1104,14 @@
 {
     struct twe_softc	*sc = tr->tr_sc;
     TWE_Command		*cmd;
-    int			i, s, done;
+    int			i;
     u_int32_t		status_reg;
 
     debug_called(4);
 
+    if (!dumping)
+	TWE_IO_ASSERT_LOCKED(sc);
+
     /* mark the command as currently being processed */
     tr->tr_status = TWE_CMD_BUSY;
     cmd = TWE_FIND_COMMAND(tr);
@@ -1075,8 +1122,7 @@
      * XXX it might be more efficient to return EBUSY immediately
      *     and let the command be rescheduled.
      */
-    for (i = 100000, done = 0; (i > 0) && !done; i--) {
-	s = splbio();
+    for (i = 100000; (i > 0); i--) {
 	
 	/* check to see if we can post a command */
 	status_reg = TWE_STATUS(sc);
@@ -1086,7 +1132,7 @@
 	    twe_enqueue_busy(tr);
 
 	    TWE_COMMAND_QUEUE(sc, TWE_FIND_COMMANDPHYS(tr));
-	    done = 1;
+
 	    /* move command to work queue */
 #ifdef TWE_DEBUG
 	    if (tr->tr_complete != NULL) {
@@ -1097,14 +1143,10 @@
 		debug(3, "queued request %d for polling caller", cmd->generic.request_id);
 	    }
 #endif
+	    return(0);
 	}
-	splx(s);	/* drop spl to allow completion interrupts */
     }
 
-    /* command is enqueued */
-    if (done)
-	return(0);
-
     /* 
      * We couldn't get the controller to take the command; try submitting it again later.
      * This should only happen if something is wrong with the controller, or if we have
@@ -1125,14 +1167,13 @@
     TWE_Response_Queue	rq;
     TWE_Command		*cmd;
     struct twe_request	*tr;
-    int			s, found;
+    int			found;
     u_int32_t		status_reg;
     
     debug_called(5);
 
     /* loop collecting completed commands */
     found = 0;
-    s = splbio();
     for (;;) {
 	status_reg = TWE_STATUS(sc);
 	twe_check_bits(sc, status_reg);		/* XXX should this fail? */
@@ -1155,7 +1196,6 @@
 	    break;					/* no response ready */
 	}
     }
-    splx(s);
 
     /* if we've completed any commands, try posting some more */
     if (found)
@@ -1259,6 +1299,7 @@
 
     debug_called(2);
 
+    TWE_IO_ASSERT_LOCKED(sc);
     TWE_SOFT_RESET(sc);
 
     if (twe_wait_status(sc, TWE_STATUS_ATTENTION_INTERRUPT, 30)) {
@@ -1396,6 +1437,7 @@
 {
     u_int16_t	aen;
 
+    TWE_IO_ASSERT_LOCKED(sc);
     for (;;) {
 	if (twe_get_param_2(sc, TWE_PARAM_AEN, TWE_PARAM_AEN_UnitCode, &aen))
 	    return(1);
@@ -1417,14 +1459,14 @@
 twe_enqueue_aen(struct twe_softc *sc, u_int16_t aen)
 {
     char	*msg;
-    int		s, next, nextnext;
+    int		next, nextnext;
 
     debug_called(4);
 
+    TWE_IO_ASSERT_LOCKED(sc);
     if ((msg = twe_format_aen(sc, aen)) != NULL)
 	twe_printf(sc, "AEN: <%s>\n", msg);
 
-    s = splbio();
     /* enqueue the AEN */
     next = ((sc->twe_aen_head + 1) % TWE_Q_LENGTH);
     nextnext = ((sc->twe_aen_head + 2) % TWE_Q_LENGTH);
@@ -1447,7 +1489,6 @@
 	sc->twe_wait_aen = -1;
 	wakeup(&sc->twe_wait_aen);
     }
-    splx(s);
 }
 
 /********************************************************************************
@@ -1462,6 +1503,7 @@
     
     debug_called(4);
 
+    TWE_IO_ASSERT_LOCKED(sc);
     if (sc->twe_aen_tail == sc->twe_aen_head) {
 	result = TWE_AEN_QUEUE_EMPTY;
     } else {
@@ -1479,15 +1521,13 @@
 static int
 twe_find_aen(struct twe_softc *sc, u_int16_t aen)
 {
-    int		i, s, missing;
+    int		i, missing;
 
     missing = 1;
-    s = splbio();
     for (i = sc->twe_aen_tail; (i != sc->twe_aen_head) && missing; i = (i + 1) % TWE_Q_LENGTH) {
 	if (sc->twe_aen_queue[i] == aen)
 	    missing = 0;
     }
-    splx(s);
     return(missing);
 }
 
@@ -1504,22 +1544,20 @@
 twe_wait_aen(struct twe_softc *sc, int aen, int timeout)
 {
     time_t	expiry;
-    int		found, s;
+    int		found;
 
     debug_called(4);
 
     expiry = time_second + timeout;
     found = 0;
 
-    s = splbio();
     sc->twe_wait_aen = aen;
     do {
 	twe_fetch_aen(sc);
-	tsleep(&sc->twe_wait_aen, PZERO, "twewaen", hz);
+	mtx_sleep(&sc->twe_wait_aen, &sc->twe_io_lock, PZERO, "twewaen", hz);
 	if (sc->twe_wait_aen == -1)
 	    found = 1;
     } while ((time_second <= expiry) && !found);
-    splx(s);
     return(!found);
 }
 #endif
@@ -1541,6 +1579,9 @@
     TWE_Command		*cmd;
     debug_called(4);
 
+    if (!dumping)
+	TWE_IO_ASSERT_LOCKED(sc);
+
     /* try to reuse an old buffer */
     *tr = twe_dequeue_free(sc);
 
@@ -1567,6 +1608,8 @@
 {
     debug_called(4);
 
+    if (!dumping)
+	TWE_IO_ASSERT_LOCKED(tr->tr_sc);
     if (tr->tr_private != NULL)
 	twe_panic(tr->tr_sc, "tr_private != NULL");
     twe_enqueue_free(tr);
@@ -1591,6 +1634,8 @@
 
     debug_called(2);
 
+    TWE_IO_LOCK(sc);
+
     /* get the port count */
     twe_get_param_1(sc, TWE_PARAM_CONTROLLER, TWE_PARAM_CONTROLLER_PortCount, &ports);
 
@@ -1641,6 +1686,7 @@
 	if (p[0])
 	    free(p[0], M_DEVBUF);
     }
+    TWE_IO_UNLOCK(sc);
 }
 
 /********************************************************************************
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/twe/twe_compat.h
--- a/head/sys/dev/twe/twe_compat.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/twe/twe_compat.h	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/twe/twe_compat.h 239244 2012-08-13 21:29:34Z jhb $
  */
 /*
  * Portability and compatibility interfaces.
@@ -43,8 +43,11 @@
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
+#include <sys/lock.h>
 #include <sys/module.h>
+#include <sys/mutex.h>
 #include <sys/sysctl.h>
+#include <sys/sx.h>
 
 #include <sys/bus.h>
 #include <sys/conf.h>
@@ -65,10 +68,10 @@
 /* 
  * Wrappers for bus-space actions
  */
-#define TWE_CONTROL(sc, val)		bus_space_write_4((sc)->twe_btag, (sc)->twe_bhandle, 0x0, (u_int32_t)val)
-#define TWE_STATUS(sc)			(u_int32_t)bus_space_read_4((sc)->twe_btag, (sc)->twe_bhandle, 0x4)
-#define TWE_COMMAND_QUEUE(sc, val)	bus_space_write_4((sc)->twe_btag, (sc)->twe_bhandle, 0x8, (u_int32_t)val)
-#define TWE_RESPONSE_QUEUE(sc)		(TWE_Response_Queue)bus_space_read_4((sc)->twe_btag, (sc)->twe_bhandle, 0xc)
+#define TWE_CONTROL(sc, val)		bus_write_4((sc)->twe_io, 0x0, (u_int32_t)val)
+#define TWE_STATUS(sc)			(u_int32_t)bus_read_4((sc)->twe_io, 0x4)
+#define TWE_COMMAND_QUEUE(sc, val)	bus_write_4((sc)->twe_io, 0x8, (u_int32_t)val)
+#define TWE_RESPONSE_QUEUE(sc)		(TWE_Response_Queue)bus_read_4((sc)->twe_io, 0xc)
 
 /*
  * FreeBSD-specific softc elements
@@ -79,8 +82,6 @@
     device_t			twe_dev;		/* bus device */		\
     struct cdev *twe_dev_t;		/* control device */		\
     struct resource		*twe_io;		/* register interface window */	\
-    bus_space_handle_t		twe_bhandle;		/* bus space handle */		\
-    bus_space_tag_t		twe_btag;		/* bus space tag */		\
     bus_dma_tag_t		twe_parent_dmat;	/* parent DMA tag */		\
     bus_dma_tag_t		twe_buffer_dmat;	/* data buffer DMA tag */	\
     bus_dma_tag_t		twe_cmd_dmat;		/* command buffer DMA tag */	\
@@ -91,8 +92,8 @@
     void			*twe_cmd;		/* command structures */	\
     void			*twe_immediate;		/* immediate commands */	\
     bus_dmamap_t		twe_immediate_map;					\
-    struct sysctl_ctx_list	sysctl_ctx;						\
-    struct sysctl_oid		*sysctl_tree;
+    struct mtx			twe_io_lock;						\
+    struct sx			twe_config_lock;
 
 /*
  * FreeBSD-specific request elements
@@ -107,31 +108,6 @@
 #define twe_printf(sc, fmt, args...)	device_printf(sc->twe_dev, fmt , ##args)
 #define twed_printf(twed, fmt, args...)	device_printf(twed->twed_dev, fmt , ##args)
 
-#if __FreeBSD_version < 500003
-# include <machine/clock.h>
-# define INTR_ENTROPY			0
-# define FREEBSD_4
-
-# include <sys/buf.h>			/* old buf style */
-typedef struct buf			twe_bio;
-typedef struct buf_queue_head		twe_bioq;
-# define TWE_BIO_QINIT(bq)		bufq_init(&bq);
-# define TWE_BIO_QINSERT(bq, bp)	bufq_insert_tail(&bq, bp)
-# define TWE_BIO_QFIRST(bq)		bufq_first(&bq)
-# define TWE_BIO_QREMOVE(bq, bp)	bufq_remove(&bq, bp)
-# define TWE_BIO_IS_READ(bp)		((bp)->b_flags & B_READ)
-# define TWE_BIO_DATA(bp)		(bp)->b_data
-# define TWE_BIO_LENGTH(bp)		(bp)->b_bcount
-# define TWE_BIO_LBA(bp)		(bp)->b_pblkno
-# define TWE_BIO_SOFTC(bp)		(bp)->b_dev->si_drv1
-# define TWE_BIO_UNIT(bp)		*(int *)((bp)->b_dev->si_drv2)
-# define TWE_BIO_SET_ERROR(bp, err)	do { (bp)->b_error = err; (bp)->b_flags |= B_ERROR;} while(0)
-# define TWE_BIO_HAS_ERROR(bp)		((bp)->b_flags & B_ERROR)
-# define TWE_BIO_RESID(bp)		(bp)->b_resid
-# define TWE_BIO_DONE(bp)		biodone(bp)
-# define TWE_BIO_STATS_START(bp)	devstat_start_transaction(&((struct twed_softc *)TWE_BIO_SOFTC(bp))->twed_stats)
-# define TWE_BIO_STATS_END(bp)		devstat_end_transaction_buf(&((struct twed_softc *)TWE_BIO_SOFTC(bp))->twed_stats, bp)
-#else
 # include <sys/bio.h>
 # include <geom/geom_disk.h>
 typedef struct bio			twe_bio;
@@ -152,7 +128,13 @@
 # define TWE_BIO_DONE(bp)		biodone(bp)
 # define TWE_BIO_STATS_START(bp)
 # define TWE_BIO_STATS_END(bp)
-#endif
+
+#define	TWE_IO_LOCK(sc)			mtx_lock(&(sc)->twe_io_lock)
+#define	TWE_IO_UNLOCK(sc)		mtx_unlock(&(sc)->twe_io_lock)
+#define	TWE_IO_ASSERT_LOCKED(sc)	mtx_assert(&(sc)->twe_io_lock, MA_OWNED)
+#define	TWE_CONFIG_LOCK(sc)		sx_xlock(&(sc)->twe_config_lock)
+#define	TWE_CONFIG_UNLOCK(sc)		sx_xunlock(&(sc)->twe_config_lock)
+#define	TWE_CONFIG_ASSERT_LOCKED(sc)	sx_assert(&(sc)->twe_config_lock, SA_XLOCKED)
 
 #endif /* FreeBSD */
 
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/twe/twe_freebsd.c
--- a/head/sys/dev/twe/twe_freebsd.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/twe/twe_freebsd.c	Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/twe/twe_freebsd.c 232854 2012-03-12 08:03:51Z scottl $");
+__FBSDID("$FreeBSD: head/sys/dev/twe/twe_freebsd.c 239244 2012-08-13 21:29:34Z jhb $");
 
 /*
  * FreeBSD-specific code.
@@ -69,7 +69,6 @@
 
 static struct cdevsw twe_cdevsw = {
 	.d_version =	D_VERSION,
-	.d_flags =	D_NEEDGIANT,
 	.d_open =	twe_open,
 	.d_close =	twe_close,
 	.d_ioctl =	twe_ioctl_wrapper,
@@ -84,7 +83,13 @@
 {
     struct twe_softc		*sc = (struct twe_softc *)dev->si_drv1;
 
+    TWE_IO_LOCK(sc);
+    if (sc->twe_state & TWE_STATE_DETACHING) {
+	TWE_IO_UNLOCK(sc);
+	return (ENXIO);
+    }
     sc->twe_state |= TWE_STATE_OPEN;
+    TWE_IO_UNLOCK(sc);
     return(0);
 }
 
@@ -96,7 +101,9 @@
 {
     struct twe_softc		*sc = (struct twe_softc *)dev->si_drv1;
 
+    TWE_IO_LOCK(sc);
     sc->twe_state &= ~TWE_STATE_OPEN;
+    TWE_IO_UNLOCK(sc);
     return (0);
 }
 
@@ -172,8 +179,8 @@
 twe_attach(device_t dev)
 {
     struct twe_softc	*sc;
+    struct sysctl_oid	*sysctl_tree;
     int			rid, error;
-    u_int32_t		command;
 
     debug_called(4);
 
@@ -182,32 +189,30 @@
      */
     sc = device_get_softc(dev);
     sc->twe_dev = dev;
+    mtx_init(&sc->twe_io_lock, "twe I/O", NULL, MTX_DEF);
+    sx_init(&sc->twe_config_lock, "twe config");
 
-    sysctl_ctx_init(&sc->sysctl_ctx);
-    sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
+    /*
+     * XXX: This sysctl tree must stay at hw.tweX rather than using
+     * the device_get_sysctl_tree() created by new-bus because
+     * existing 3rd party binary tools such as tw_cli and 3dm2 use the
+     * existence of this sysctl node to discover controllers.
+     */
+    sysctl_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev),
 	SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
 	device_get_nameunit(dev), CTLFLAG_RD, 0, "");
-    if (sc->sysctl_tree == NULL) {
+    if (sysctl_tree == NULL) {
 	twe_printf(sc, "cannot add sysctl tree node\n");
 	return (ENXIO);
     }
-    SYSCTL_ADD_STRING(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
+    SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(sysctl_tree),
 	OID_AUTO, "driver_version", CTLFLAG_RD, TWE_DRIVER_VERSION_STRING, 0,
 	"TWE driver version");
 
     /*
-     * Make sure we are going to be able to talk to this board.
-     */
-    command = pci_read_config(dev, PCIR_COMMAND, 2);
-    if ((command & PCIM_CMD_PORTEN) == 0) {
-	twe_printf(sc, "register window not available\n");
-	return(ENXIO);
-    }
-    /*
      * Force the busmaster enable bit on, in case the BIOS forgot.
      */
-    command |= PCIM_CMD_BUSMASTEREN;
-    pci_write_config(dev, PCIR_COMMAND, command, 2);
+    pci_enable_busmaster(dev);
 
     /*
      * Allocate the PCI register window.
@@ -219,8 +224,6 @@
 	twe_free(sc);
 	return(ENXIO);
     }
-    sc->twe_btag = rman_get_bustag(sc->twe_io);
-    sc->twe_bhandle = rman_get_bushandle(sc->twe_io);
 
     /*
      * Allocate the parent bus DMA tag appropriate for PCI.
@@ -251,7 +254,7 @@
 	twe_free(sc);
 	return(ENXIO);
     }
-    if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY,  
+    if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE,  
 		       NULL, twe_pci_intr, sc, &sc->twe_intr)) {
 	twe_printf(sc, "can't set up interrupt\n");
 	twe_free(sc);
@@ -302,7 +305,7 @@
 			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
 			   BUS_DMA_ALLOCNOW,		/* flags */
 			   busdma_lock_mutex,		/* lockfunc */
-			   &Giant,			/* lockarg */
+			   &sc->twe_io_lock,		/* lockarg */
 			   &sc->twe_buffer_dmat)) {
 	twe_printf(sc, "can't allocate data buffer DMA tag\n");
 	twe_free(sc);
@@ -424,7 +427,8 @@
     if (sc->twe_dev_t != (struct cdev *)NULL)
 	destroy_dev(sc->twe_dev_t);
 
-    sysctl_ctx_free(&sc->sysctl_ctx);
+    sx_destroy(&sc->twe_config_lock);
+    mtx_destroy(&sc->twe_io_lock);
 }
 
 /********************************************************************************
@@ -434,27 +438,30 @@
 twe_detach(device_t dev)
 {
     struct twe_softc	*sc = device_get_softc(dev);
-    int			s, error;
 
     debug_called(4);
 
-    error = EBUSY;
-    s = splbio();
-    if (sc->twe_state & TWE_STATE_OPEN)
-	goto out;
+    TWE_IO_LOCK(sc);
+    if (sc->twe_state & TWE_STATE_OPEN) {
+	TWE_IO_UNLOCK(sc);
+	return (EBUSY);
+    }
+    sc->twe_state |= TWE_STATE_DETACHING;
+    TWE_IO_UNLOCK(sc);
 
     /*	
      * Shut the controller down.
      */
-    if (twe_shutdown(dev))
-	goto out;
+    if (twe_shutdown(dev)) {
+	TWE_IO_LOCK(sc);
+	sc->twe_state &= ~TWE_STATE_DETACHING;
+	TWE_IO_UNLOCK(sc);
+	return (EBUSY);
+    }
 
     twe_free(sc);
 
-    error = 0;
- out:
-    splx(s);
-    return(error);
+    return(0);
 }
 
 /********************************************************************************
@@ -467,30 +474,32 @@
 twe_shutdown(device_t dev)
 {
     struct twe_softc	*sc = device_get_softc(dev);
-    int			i, s, error = 0;
+    int			i, error = 0;
 
     debug_called(4);
 
-    s = splbio();
-
     /* 
      * Delete all our child devices.
      */
+    TWE_CONFIG_LOCK(sc);
     for (i = 0; i < TWE_MAX_UNITS; i++) {
 	if (sc->twe_drive[i].td_disk != 0) {
-	    if ((error = twe_detach_drive(sc, i)) != 0)
-		goto out;
+	    if ((error = twe_detach_drive(sc, i)) != 0) {
+		TWE_CONFIG_UNLOCK(sc);
+		return (error);
+	    }
 	}
     }
+    TWE_CONFIG_UNLOCK(sc);
 
     /*
      * Bring the controller down.
      */
+    TWE_IO_LOCK(sc);
     twe_deinit(sc);
+    TWE_IO_UNLOCK(sc);
 
-out:
-    splx(s);
-    return(error);
+    return(0);
 }
 
 /********************************************************************************
@@ -500,15 +509,14 @@
 twe_suspend(device_t dev)
 {
     struct twe_softc	*sc = device_get_softc(dev);
-    int			s;
 
     debug_called(4);
 
-    s = splbio();
+    TWE_IO_LOCK(sc);
     sc->twe_state |= TWE_STATE_SUSPEND;
     
     twe_disable_interrupts(sc);
-    splx(s);
+    TWE_IO_UNLOCK(sc);
 
     return(0);
 }
@@ -523,8 +531,10 @@
 
     debug_called(4);
 
+    TWE_IO_LOCK(sc);
     sc->twe_state &= ~TWE_STATE_SUSPEND;
     twe_enable_interrupts(sc);
+    TWE_IO_UNLOCK(sc);
 
     return(0);
 }
@@ -536,7 +546,11 @@
 static void
 twe_pci_intr(void *arg)
 {
-    twe_intr((struct twe_softc *)arg);
+    struct twe_softc *sc = arg;
+
+    TWE_IO_LOCK(sc);
+    twe_intr(sc);
+    TWE_IO_UNLOCK(sc);
 }
 
 /********************************************************************************
@@ -565,8 +579,10 @@
     char	buf[80];
     int		error;
 
+    mtx_lock(&Giant);
     dr->td_disk =  device_add_child(sc->twe_dev, NULL, -1);
     if (dr->td_disk == NULL) {
+	mtx_unlock(&Giant);
 	twe_printf(sc, "Cannot add unit\n");
 	return (EIO);
     }
@@ -582,7 +598,9 @@
 	    twe_describe_code(twe_table_unitstate, dr->td_state & TWE_PARAM_UNITSTATUS_MASK));
     device_set_desc_copy(dr->td_disk, buf);
 
-    if ((error = bus_generic_attach(sc->twe_dev)) != 0) {
+    error = device_probe_and_attach(dr->td_disk);
+    mtx_unlock(&Giant);
+    if (error != 0) {
 	twe_printf(sc, "Cannot attach unit to controller. error = %d\n", error);
 	return (EIO);
     }
@@ -599,7 +617,11 @@
 {
     int error = 0;
 
-    if ((error = device_delete_child(sc->twe_dev, sc->twe_drive[unit].td_disk)) != 0) {
+    TWE_CONFIG_ASSERT_LOCKED(sc);
+    mtx_lock(&Giant);
+    error = device_delete_child(sc->twe_dev, sc->twe_drive[unit].td_disk);
+    mtx_unlock(&Giant);
+    if (error != 0) {
 	twe_printf(sc, "failed to delete unit %d\n", unit);
 	return(error);
     }
@@ -671,10 +693,6 @@
  * Disk device control interface.
  */
 
-#ifdef FREEBSD_4
-static int		disks_registered = 0;
-#endif
-
 /********************************************************************************
  * Handle open from generic layer.
  *
@@ -724,10 +742,12 @@
     TWE_BIO_STATS_START(bp);
 
     /* queue the bio on the controller */
+    TWE_IO_LOCK(sc->twed_controller);
     twe_enqueue_bio(sc->twed_controller, bp);
 
     /* poke the controller to start I/O */
     twe_startio(sc->twed_controller);
+    TWE_IO_UNLOCK(sc->twed_controller);
     return;
 }
 
@@ -827,14 +847,9 @@
     sc->twed_disk->d_fwsectors = sc->twed_drive->td_sectors;
     sc->twed_disk->d_fwheads = sc->twed_drive->td_heads;
     sc->twed_disk->d_unit = sc->twed_drive->td_sys_unit;
-    sc->twed_disk->d_flags = DISKFLAG_NEEDSGIANT;
 
     disk_create(sc->twed_disk, DISK_VERSION);
 
-#ifdef FREEBSD_4
-    disks_registered++;
-#endif
-
     /* set the maximum I/O size to the theoretical maximum allowed by the S/G list size */
 
     return (0);
@@ -855,10 +870,6 @@
 
     disk_destroy(sc->twed_disk);
 
-#ifdef FREEBSD_4
-    if (--disks_registered == 0)
-	cdevsw_remove(&tweddisk_cdevsw);
-#endif
     return(0);
 }
 
@@ -878,11 +889,7 @@
 {
     struct twe_request	*tr;
 
-    if ((tr = malloc(sizeof(struct twe_request), TWE_MALLOC_CLASS, M_WAITOK)) == NULL) {
-	twe_printf(sc, "unable to allocate memory for tag %d\n", tag);
-	return(NULL);
-    }
-    bzero(tr, sizeof(*tr));
+    tr = malloc(sizeof(struct twe_request), TWE_MALLOC_CLASS, M_WAITOK | M_ZERO);
     tr->tr_sc = sc;
     tr->tr_tag = tag;
     if (bus_dmamap_create(sc->twe_buffer_dmat, 0, &tr->tr_dmamap)) {
@@ -1044,6 +1051,8 @@
 
     debug_called(4);
 
+    if (!dumping)
+	TWE_IO_ASSERT_LOCKED(sc);
     if (sc->twe_state & (TWE_STATE_CTLR_BUSY | TWE_STATE_FRZN)) {
 	twe_requeue_ready(tr);
 	return (EBUSY);
@@ -1101,6 +1110,8 @@
 
     debug_called(4);
 
+    if (!dumping)
+	TWE_IO_ASSERT_LOCKED(sc);
     bus_dmamap_sync(sc->twe_cmd_dmat, sc->twe_cmdmap, BUS_DMASYNC_POSTWRITE);
 
     /*
@@ -1153,12 +1164,10 @@
 twe_report(void)
 {
     struct twe_softc	*sc;
-    int			i, s;
+    int			i;
 
-    s = splbio();
     for (i = 0; (sc = devclass_get_softc(twe_devclass, i)) != NULL; i++)
 	twe_print_controller(sc);
     printf("twed: total bio count in %u  out %u\n", twed_bio_in, twed_bio_out);
-    splx(s);
 }
 #endif
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/twe/twevar.h
--- a/head/sys/dev/twe/twevar.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/twe/twevar.h	Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$FreeBSD$
+ *	$FreeBSD: head/sys/dev/twe/twevar.h 239244 2012-08-13 21:29:34Z jhb $
  */
 
 #define TWE_DRIVER_VERSION_STRING	"1.50.01.002"
@@ -134,6 +134,7 @@
 #define TWE_STATE_SUSPEND	(1<<3)	/* controller is suspended */
 #define TWE_STATE_FRZN		(1<<4)	/* got EINPROGRESS */
 #define TWE_STATE_CTLR_BUSY	(1<<5)	/* controller cmd queue full */
+#define	TWE_STATE_DETACHING	(1<<6)	/* controller is being shut down */
     int			twe_host_id;
     struct twe_qstat	twe_qstat[TWEQ_COUNT];	/* queue statistics */
 
@@ -209,46 +210,31 @@
 static __inline void							\
 twe_enqueue_ ## name (struct twe_request *tr)				\
 {									\
-    int		s;							\
-									\
-    s = splbio();							\
     TAILQ_INSERT_TAIL(&tr->tr_sc->twe_ ## name, tr, tr_link);		\
     TWEQ_ADD(tr->tr_sc, index);						\
-    splx(s);								\
 }									\
 static __inline void							\
 twe_requeue_ ## name (struct twe_request *tr)				\
 {									\
-    int		s;							\
-									\
-    s = splbio();							\
     TAILQ_INSERT_HEAD(&tr->tr_sc->twe_ ## name, tr, tr_link);		\
     TWEQ_ADD(tr->tr_sc, index);						\
-    splx(s);								\
 }									\
 static __inline struct twe_request *					\
 twe_dequeue_ ## name (struct twe_softc *sc)				\
 {									\
     struct twe_request	*tr;						\
-    int			s;						\
 									\
-    s = splbio();							\
     if ((tr = TAILQ_FIRST(&sc->twe_ ## name)) != NULL) {		\
 	TAILQ_REMOVE(&sc->twe_ ## name, tr, tr_link);			\
 	TWEQ_REMOVE(sc, index);						\
     }									\
-    splx(s);								\
     return(tr);								\
 }									\
 static __inline void							\
 twe_remove_ ## name (struct twe_request *tr)				\
 {									\
-    int			s;						\
-									\
-    s = splbio();							\
     TAILQ_REMOVE(&tr->tr_sc->twe_ ## name, tr, tr_link);		\
     TWEQ_REMOVE(tr->tr_sc, index);					\
-    splx(s);								\
 }
 
 TWEQ_REQUEST_QUEUE(free, TWEQ_FREE)
@@ -269,25 +255,18 @@
 static __inline void
 twe_enqueue_bio(struct twe_softc *sc, twe_bio *bp)
 {
-    int		s;
-
-    s = splbio();
     TWE_BIO_QINSERT(sc->twe_bioq, bp);
     TWEQ_ADD(sc, TWEQ_BIO);
-    splx(s);
 }
 
 static __inline twe_bio *
 twe_dequeue_bio(struct twe_softc *sc)
 {
-    int		s;
     twe_bio	*bp;
 
-    s = splbio();
     if ((bp = TWE_BIO_QFIRST(sc->twe_bioq)) != NULL) {
 	TWE_BIO_QREMOVE(sc->twe_bioq, bp);
 	TWEQ_REMOVE(sc, TWEQ_BIO);
     }
-    splx(s);
     return(bp);
 }
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/uart/uart.h
--- a/head/sys/dev/uart/uart.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/uart/uart.h	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/uart/uart.h 239278 2012-08-15 05:37:10Z gonzo $
  */
 
 #ifndef _DEV_UART_H_
@@ -69,6 +69,7 @@
 extern struct uart_class uart_sab82532_class __attribute__((weak));
 extern struct uart_class uart_sbbc_class __attribute__((weak));
 extern struct uart_class uart_z8530_class __attribute__((weak));
+extern struct uart_class uart_lpc_class __attribute__((weak));
 
 #ifdef PC98
 struct uart_class *uart_pc98_getdev(u_long port);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/uart/uart_bus_fdt.c
--- a/head/sys/dev/uart/uart_bus_fdt.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/uart/uart_bus_fdt.c	Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/uart/uart_bus_fdt.c 228983 2011-12-30 03:57:17Z marcel $");
+__FBSDID("$FreeBSD: head/sys/dev/uart/uart_bus_fdt.c 239278 2012-08-15 05:37:10Z gonzo $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -100,12 +100,14 @@
 	pcell_t clock, shift;
 	int err;
 
-	if (!ofw_bus_is_compatible(dev, "ns16550"))
+	sc = device_get_softc(dev);
+	if (ofw_bus_is_compatible(dev, "ns16550"))
+		sc->sc_class = &uart_ns8250_class;
+	else if (ofw_bus_is_compatible(dev, "lpc,uart"))
+		sc->sc_class = &uart_lpc_class;
+	else
 		return (ENXIO);
 
-	sc = device_get_softc(dev);
-	sc->sc_class = &uart_ns8250_class;
-
 	node = ofw_bus_get_node(dev);
 
 	if ((err = uart_fdt_get_clock(node, &clock)) != 0)
@@ -137,7 +139,7 @@
 	struct uart_class *class;
 	phandle_t node, chosen;
 	pcell_t shift, br, rclk;
-	u_long start, size;
+	u_long start, size, pbase, psize;
 	int err;
 
 	uart_bus_space_mem = fdtbus_bs_tag;
@@ -180,7 +182,10 @@
 	/*
 	 * Finalize configuration.
 	 */
-	class = &uart_quicc_class;
+	if (fdt_is_compatible(node, "quicc"))
+		class = &uart_quicc_class;
+	if (fdt_is_compatible(node, "lpc"))
+		class = &uart_lpc_class;
 	if (fdt_is_compatible(node, "ns16550"))
 		class = &uart_ns8250_class;
 
@@ -197,7 +202,9 @@
 	err = fdt_regsize(node, &start, &size);
 	if (err)
 		return (ENXIO);
-	start += fdt_immr_va;
+
+	fdt_get_range(OF_parent(node), 0, &pbase, &psize);
+	start += pbase;
 
 	return (bus_space_map(di->bas.bst, start, size, 0, &di->bas.bsh));
 }
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/uart/uart_dev_lpc.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/uart/uart_dev_lpc.c	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,891 @@
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/dev/uart/uart_dev_lpc.c 239278 2012-08-15 05:37:10Z gonzo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_bus.h>
+
+#include <dev/ic/ns16550.h>
+#include <arm/lpc/lpcreg.h>
+
+#include "uart_if.h"
+
+#define	DEFAULT_RCLK		(13 * 1000 * 1000)
+#define	LPC_UART_NO(_bas)	(((_bas->bsh) - LPC_UART_BASE) >> 15)
+
+#define	lpc_ns8250_get_auxreg(_bas, _reg)	\
+    bus_space_read_4((_bas)->bst, LPC_UART_CONTROL_BASE, _reg)
+#define	lpc_ns8250_set_auxreg(_bas, _reg, _val)	\
+    bus_space_write_4((_bas)->bst, LPC_UART_CONTROL_BASE, _reg, _val);
+#define	lpc_ns8250_get_clkreg(_bas, _reg)	\
+    bus_space_read_4((_bas)->bst, LPC_CLKPWR_BASE, (_reg))
+#define	lpc_ns8250_set_clkreg(_bas, _reg, _val)	\
+    bus_space_write_4((_bas)->bst, LPC_CLKPWR_BASE, (_reg), (_val))
+
+/*
+ * Clear pending interrupts. THRE is cleared by reading IIR. Data
+ * that may have been received gets lost here.
+ */
+static void
+lpc_ns8250_clrint(struct uart_bas *bas)
+{
+	uint8_t iir, lsr;
+
+	iir = uart_getreg(bas, REG_IIR);
+	while ((iir & IIR_NOPEND) == 0) {
+		iir &= IIR_IMASK;
+		if (iir == IIR_RLS) {
+			lsr = uart_getreg(bas, REG_LSR);
+			if (lsr & (LSR_BI|LSR_FE|LSR_PE))
+				(void)uart_getreg(bas, REG_DATA);
+		} else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
+			(void)uart_getreg(bas, REG_DATA);
+		else if (iir == IIR_MLSC)
+			(void)uart_getreg(bas, REG_MSR);
+		uart_barrier(bas);
+		iir = uart_getreg(bas, REG_IIR);
+	}
+}
+
+static int
+lpc_ns8250_delay(struct uart_bas *bas)
+{
+	uint32_t uclk;
+	int x, y;
+
+	uclk = lpc_ns8250_get_clkreg(bas, LPC_CLKPWR_UART_U5CLK);
+	
+	x = (uclk >> 8) & 0xff;
+	y = uclk & 0xff;
+
+	return (16000000 / (bas->rclk * x / y));
+}
+
+static void
+lpc_ns8250_divisor(int rclk, int baudrate, int *x, int *y)
+{
+
+	switch (baudrate) {
+	case 2400:
+		*x = 1;
+		*y = 255;
+		return;
+	case 4800:
+		*x = 1;
+		*y = 169;
+		return;
+	case 9600:
+		*x = 3;
+		*y = 254;
+		return;
+	case 19200:
+		*x = 3;
+		*y = 127;
+		return;
+	case 38400:
+		*x = 6;
+		*y = 127;
+		return;
+	case 57600:
+		*x = 9;
+		*y = 127;
+		return;
+	default:
+	case 115200:
+		*x = 19;
+		*y = 134;
+		return;
+	case 230400:
+		*x = 19;
+		*y = 67;
+		return;	
+	case 460800:
+		*x = 38;
+		*y = 67;
+		return;
+	}
+}
+
+static int
+lpc_ns8250_drain(struct uart_bas *bas, int what)
+{
+	int delay, limit;
+
+	delay = lpc_ns8250_delay(bas);
+
+	if (what & UART_DRAIN_TRANSMITTER) {
+		/*
+		 * Pick an arbitrary high limit to avoid getting stuck in
+		 * an infinite loop when the hardware is broken. Make the
+		 * limit high enough to handle large FIFOs.
+		 */
+		limit = 10*1024;
+		while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
+			DELAY(delay);
+		if (limit == 0) {
+			/* printf("lpc_ns8250: transmitter appears stuck... "); */
+			return (EIO);
+		}
+	}
+
+	if (what & UART_DRAIN_RECEIVER) {
+		/*
+		 * Pick an arbitrary high limit to avoid getting stuck in
+		 * an infinite loop when the hardware is broken. Make the
+		 * limit high enough to handle large FIFOs and integrated
+		 * UARTs. The HP rx2600 for example has 3 UARTs on the
+		 * management board that tend to get a lot of data send
+		 * to it when the UART is first activated.
+		 */
+		limit=10*4096;
+		while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) {
+			(void)uart_getreg(bas, REG_DATA);
+			uart_barrier(bas);
+			DELAY(delay << 2);
+		}
+		if (limit == 0) {
+			/* printf("lpc_ns8250: receiver appears broken... "); */
+			return (EIO);
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * We can only flush UARTs with FIFOs. UARTs without FIFOs should be
+ * drained. WARNING: this function clobbers the FIFO setting!
+ */
+static void
+lpc_ns8250_flush(struct uart_bas *bas, int what)
+{
+	uint8_t fcr;
+
+	fcr = FCR_ENABLE;
+	if (what & UART_FLUSH_TRANSMITTER)
+		fcr |= FCR_XMT_RST;
+	if (what & UART_FLUSH_RECEIVER)
+		fcr |= FCR_RCV_RST;
+	uart_setreg(bas, REG_FCR, fcr);
+	uart_barrier(bas);
+}
+
+static int
+lpc_ns8250_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+    int parity)
+{
+	int xdiv, ydiv;
+	uint8_t lcr;
+
+	lcr = 0;
+	if (databits >= 8)
+		lcr |= LCR_8BITS;
+	else if (databits == 7)
+		lcr |= LCR_7BITS;
+	else if (databits == 6)
+		lcr |= LCR_6BITS;
+	else
+		lcr |= LCR_5BITS;
+	if (stopbits > 1)
+		lcr |= LCR_STOPB;
+	lcr |= parity << 3;
+
+	/* Set baudrate. */
+	if (baudrate > 0) {
+		uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
+		uart_barrier(bas);
+		uart_setreg(bas, REG_DLL, 0x00);
+		uart_setreg(bas, REG_DLH, 0x00);
+		uart_barrier(bas);
+
+		lpc_ns8250_divisor(bas->rclk, baudrate, &xdiv, &ydiv);
+		lpc_ns8250_set_clkreg(bas,
+		    LPC_CLKPWR_UART_U5CLK,
+		    LPC_CLKPWR_UART_UCLK_X(xdiv) |
+		    LPC_CLKPWR_UART_UCLK_Y(ydiv));
+	}
+
+	/* Set LCR and clear DLAB. */
+	uart_setreg(bas, REG_LCR, lcr);
+	uart_barrier(bas);
+	return (0);
+}
+
+/*
+ * Low-level UART interface.
+ */
+static int lpc_ns8250_probe(struct uart_bas *bas);
+static void lpc_ns8250_init(struct uart_bas *bas, int, int, int, int);
+static void lpc_ns8250_term(struct uart_bas *bas);
+static void lpc_ns8250_putc(struct uart_bas *bas, int);
+static int lpc_ns8250_rxready(struct uart_bas *bas);
+static int lpc_ns8250_getc(struct uart_bas *bas, struct mtx *);
+
+static struct uart_ops uart_lpc_ns8250_ops = {
+	.probe = lpc_ns8250_probe,
+	.init = lpc_ns8250_init,
+	.term = lpc_ns8250_term,
+	.putc = lpc_ns8250_putc,
+	.rxready = lpc_ns8250_rxready,
+	.getc = lpc_ns8250_getc,
+};
+
+static int
+lpc_ns8250_probe(struct uart_bas *bas)
+{
+#if 0
+	u_char val;
+
+	/* Check known 0 bits that don't depend on DLAB. */
+	val = uart_getreg(bas, REG_IIR);
+	if (val & 0x30)
+		return (ENXIO);
+	/*
+	 * Bit 6 of the MCR (= 0x40) appears to be 1 for the Sun1699
+	 * chip, but otherwise doesn't seem to have a function. In
+	 * other words, uart(4) works regardless. Ignore that bit so
+	 * the probe succeeds.
+	 */
+	val = uart_getreg(bas, REG_MCR);
+	if (val & 0xa0)
+		return (ENXIO);
+#endif
+	return (0);
+}
+
+static void
+lpc_ns8250_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+    int parity)
+{
+	u_char	ier;
+	u_long	clkmode;
+	
+	/* Enable UART clock */
+	clkmode = lpc_ns8250_get_auxreg(bas, LPC_UART_CLKMODE);
+	lpc_ns8250_set_auxreg(bas, LPC_UART_CLKMODE,
+	    clkmode | LPC_UART_CLKMODE_UART5(1));
+#if 0
+	/* Work around H/W bug */
+	uart_setreg(bas, REG_DATA, 0x00);
+#endif
+	if (bas->rclk == 0)
+		bas->rclk = DEFAULT_RCLK;
+	lpc_ns8250_param(bas, baudrate, databits, stopbits, parity);
+
+	/* Disable all interrupt sources. */
+	/*
+	 * We use 0xe0 instead of 0xf0 as the mask because the XScale PXA
+	 * UARTs split the receive time-out interrupt bit out separately as
+	 * 0x10.  This gets handled by ier_mask and ier_rxbits below.
+	 */
+	ier = uart_getreg(bas, REG_IER) & 0xe0;
+	uart_setreg(bas, REG_IER, ier);
+	uart_barrier(bas);
+
+	/* Disable the FIFO (if present). */
+	uart_setreg(bas, REG_FCR, 0);
+	uart_barrier(bas);
+
+	/* Set RTS & DTR. */
+	uart_setreg(bas, REG_MCR, MCR_IE | MCR_RTS | MCR_DTR);
+	uart_barrier(bas);
+
+	lpc_ns8250_clrint(bas);
+}
+
+static void
+lpc_ns8250_term(struct uart_bas *bas)
+{
+
+	/* Clear RTS & DTR. */
+	uart_setreg(bas, REG_MCR, MCR_IE);
+	uart_barrier(bas);
+}
+
+static void
+lpc_ns8250_putc(struct uart_bas *bas, int c)
+{
+	int limit;
+
+	limit = 250000;
+	while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0 && --limit)
+		DELAY(4);
+	uart_setreg(bas, REG_DATA, c);
+	uart_barrier(bas);
+	limit = 250000;
+	while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
+		DELAY(4);
+}
+
+static int
+lpc_ns8250_rxready(struct uart_bas *bas)
+{
+
+	return ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) != 0 ? 1 : 0);
+}
+
+static int
+lpc_ns8250_getc(struct uart_bas *bas, struct mtx *hwmtx)
+{
+	int c;
+
+	uart_lock(hwmtx);
+
+	while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0) {
+		uart_unlock(hwmtx);
+		DELAY(4);
+		uart_lock(hwmtx);
+	}
+
+	c = uart_getreg(bas, REG_DATA);
+
+	uart_unlock(hwmtx);
+
+	return (c);
+}
+
+/*
+ * High-level UART interface.
+ */
+struct lpc_ns8250_softc {
+	struct uart_softc base;
+	uint8_t		fcr;
+	uint8_t		ier;
+	uint8_t		mcr;
+	
+	uint8_t		ier_mask;
+	uint8_t		ier_rxbits;
+};
+
+static int lpc_ns8250_bus_attach(struct uart_softc *);
+static int lpc_ns8250_bus_detach(struct uart_softc *);
+static int lpc_ns8250_bus_flush(struct uart_softc *, int);
+static int lpc_ns8250_bus_getsig(struct uart_softc *);
+static int lpc_ns8250_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int lpc_ns8250_bus_ipend(struct uart_softc *);
+static int lpc_ns8250_bus_param(struct uart_softc *, int, int, int, int);
+static int lpc_ns8250_bus_probe(struct uart_softc *);
+static int lpc_ns8250_bus_receive(struct uart_softc *);
+static int lpc_ns8250_bus_setsig(struct uart_softc *, int);
+static int lpc_ns8250_bus_transmit(struct uart_softc *);
+
+static kobj_method_t lpc_ns8250_methods[] = {
+	KOBJMETHOD(uart_attach,		lpc_ns8250_bus_attach),
+	KOBJMETHOD(uart_detach,		lpc_ns8250_bus_detach),
+	KOBJMETHOD(uart_flush,		lpc_ns8250_bus_flush),
+	KOBJMETHOD(uart_getsig,		lpc_ns8250_bus_getsig),
+	KOBJMETHOD(uart_ioctl,		lpc_ns8250_bus_ioctl),
+	KOBJMETHOD(uart_ipend,		lpc_ns8250_bus_ipend),
+	KOBJMETHOD(uart_param,		lpc_ns8250_bus_param),
+	KOBJMETHOD(uart_probe,		lpc_ns8250_bus_probe),
+	KOBJMETHOD(uart_receive,	lpc_ns8250_bus_receive),
+	KOBJMETHOD(uart_setsig,		lpc_ns8250_bus_setsig),
+	KOBJMETHOD(uart_transmit,	lpc_ns8250_bus_transmit),
+	{ 0, 0 }
+};
+
+struct uart_class uart_lpc_class = {
+	"lpc_ns8250",
+	lpc_ns8250_methods,
+	sizeof(struct lpc_ns8250_softc),
+	.uc_ops = &uart_lpc_ns8250_ops,
+	.uc_range = 8,
+	.uc_rclk = DEFAULT_RCLK
+};
+
+#define	SIGCHG(c, i, s, d)				\
+	if (c) {					\
+		i |= (i & s) ? s : s | d;		\
+	} else {					\
+		i = (i & s) ? (i & ~s) | d : i;		\
+	}
+
+static int
+lpc_ns8250_bus_attach(struct uart_softc *sc)
+{
+	struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+	struct uart_bas *bas;
+	unsigned int ivar;
+
+	bas = &sc->sc_bas;
+
+	lpc_ns8250->mcr = uart_getreg(bas, REG_MCR);
+	lpc_ns8250->fcr = FCR_ENABLE | FCR_DMA;
+	if (!resource_int_value("uart", device_get_unit(sc->sc_dev), "flags",
+	    &ivar)) {
+		if (UART_FLAGS_FCR_RX_LOW(ivar)) 
+			lpc_ns8250->fcr |= FCR_RX_LOW;
+		else if (UART_FLAGS_FCR_RX_MEDL(ivar)) 
+			lpc_ns8250->fcr |= FCR_RX_MEDL;
+		else if (UART_FLAGS_FCR_RX_HIGH(ivar)) 
+			lpc_ns8250->fcr |= FCR_RX_HIGH;
+		else
+			lpc_ns8250->fcr |= FCR_RX_MEDH;
+	} else 
+		lpc_ns8250->fcr |= FCR_RX_HIGH;
+	
+	/* Get IER mask */
+	ivar = 0xf0;
+	resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_mask",
+	    &ivar);
+	lpc_ns8250->ier_mask = (uint8_t)(ivar & 0xff);
+	
+	/* Get IER RX interrupt bits */
+	ivar = IER_EMSC | IER_ERLS | IER_ERXRDY;
+	resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_rxbits",
+	    &ivar);
+	lpc_ns8250->ier_rxbits = (uint8_t)(ivar & 0xff);
+	
+	uart_setreg(bas, REG_FCR, lpc_ns8250->fcr);
+	uart_barrier(bas);
+	lpc_ns8250_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
+
+	if (lpc_ns8250->mcr & MCR_DTR)
+		sc->sc_hwsig |= SER_DTR;
+	if (lpc_ns8250->mcr & MCR_RTS)
+		sc->sc_hwsig |= SER_RTS;
+	lpc_ns8250_bus_getsig(sc);
+
+	lpc_ns8250_clrint(bas);
+	lpc_ns8250->ier = uart_getreg(bas, REG_IER) & lpc_ns8250->ier_mask;
+	lpc_ns8250->ier |= lpc_ns8250->ier_rxbits;
+	uart_setreg(bas, REG_IER, lpc_ns8250->ier);
+	uart_barrier(bas);
+	
+	return (0);
+}
+
+static int
+lpc_ns8250_bus_detach(struct uart_softc *sc)
+{
+	struct lpc_ns8250_softc *lpc_ns8250;
+	struct uart_bas *bas;
+	u_char ier;
+
+	lpc_ns8250 = (struct lpc_ns8250_softc *)sc;
+	bas = &sc->sc_bas;
+	ier = uart_getreg(bas, REG_IER) & lpc_ns8250->ier_mask;
+	uart_setreg(bas, REG_IER, ier);
+	uart_barrier(bas);
+	lpc_ns8250_clrint(bas);
+	return (0);
+}
+
+static int
+lpc_ns8250_bus_flush(struct uart_softc *sc, int what)
+{
+	struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+	struct uart_bas *bas;
+	int error;
+
+	bas = &sc->sc_bas;
+	uart_lock(sc->sc_hwmtx);
+	if (sc->sc_rxfifosz > 1) {
+		lpc_ns8250_flush(bas, what);
+		uart_setreg(bas, REG_FCR, lpc_ns8250->fcr);
+		uart_barrier(bas);
+		error = 0;
+	} else
+		error = lpc_ns8250_drain(bas, what);
+	uart_unlock(sc->sc_hwmtx);
+	return (error);
+}
+
+static int
+lpc_ns8250_bus_getsig(struct uart_softc *sc)
+{
+	uint32_t new, old, sig;
+	uint8_t msr;
+
+	do {
+		old = sc->sc_hwsig;
+		sig = old;
+		uart_lock(sc->sc_hwmtx);
+		msr = uart_getreg(&sc->sc_bas, REG_MSR);
+		uart_unlock(sc->sc_hwmtx);
+		SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR);
+		SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS);
+		SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD);
+		SIGCHG(msr & MSR_RI,  sig, SER_RI,  SER_DRI);
+		new = sig & ~SER_MASK_DELTA;
+	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+	return (sig);
+}
+
+static int
+lpc_ns8250_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+	struct uart_bas *bas;
+	int baudrate, divisor, error;
+	uint8_t efr, lcr;
+
+	bas = &sc->sc_bas;
+	error = 0;
+	uart_lock(sc->sc_hwmtx);
+	switch (request) {
+	case UART_IOCTL_BREAK:
+		lcr = uart_getreg(bas, REG_LCR);
+		if (data)
+			lcr |= LCR_SBREAK;
+		else
+			lcr &= ~LCR_SBREAK;
+		uart_setreg(bas, REG_LCR, lcr);
+		uart_barrier(bas);
+		break;
+	case UART_IOCTL_IFLOW:
+		lcr = uart_getreg(bas, REG_LCR);
+		uart_barrier(bas);
+		uart_setreg(bas, REG_LCR, 0xbf);
+		uart_barrier(bas);
+		efr = uart_getreg(bas, REG_EFR);
+		if (data)
+			efr |= EFR_RTS;
+		else
+			efr &= ~EFR_RTS;
+		uart_setreg(bas, REG_EFR, efr);
+		uart_barrier(bas);
+		uart_setreg(bas, REG_LCR, lcr);
+		uart_barrier(bas);
+		break;
+	case UART_IOCTL_OFLOW:
+		lcr = uart_getreg(bas, REG_LCR);
+		uart_barrier(bas);
+		uart_setreg(bas, REG_LCR, 0xbf);
+		uart_barrier(bas);
+		efr = uart_getreg(bas, REG_EFR);
+		if (data)
+			efr |= EFR_CTS;
+		else
+			efr &= ~EFR_CTS;
+		uart_setreg(bas, REG_EFR, efr);
+		uart_barrier(bas);
+		uart_setreg(bas, REG_LCR, lcr);
+		uart_barrier(bas);
+		break;
+	case UART_IOCTL_BAUD:
+		lcr = uart_getreg(bas, REG_LCR);
+		uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
+		uart_barrier(bas);
+		divisor = uart_getreg(bas, REG_DLL) |
+		    (uart_getreg(bas, REG_DLH) << 8);
+		uart_barrier(bas);
+		uart_setreg(bas, REG_LCR, lcr);
+		uart_barrier(bas);
+		baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0;
+		if (baudrate > 0)
+			*(int*)data = baudrate;
+		else
+			error = ENXIO;
+		break;
+	default:
+		error = EINVAL;
+		break;
+	}
+	uart_unlock(sc->sc_hwmtx);
+	return (error);
+}
+
+static int
+lpc_ns8250_bus_ipend(struct uart_softc *sc)
+{
+	struct uart_bas *bas;
+	struct lpc_ns8250_softc *lpc_ns8250;
+	int ipend;
+	uint8_t iir, lsr;
+
+	lpc_ns8250 = (struct lpc_ns8250_softc *)sc;
+	bas = &sc->sc_bas;
+	uart_lock(sc->sc_hwmtx);
+	iir = uart_getreg(bas, REG_IIR);
+	if (iir & IIR_NOPEND) {
+		uart_unlock(sc->sc_hwmtx);
+		return (0);
+	}
+	ipend = 0;
+	if (iir & IIR_RXRDY) {
+		lsr = uart_getreg(bas, REG_LSR);
+		if (lsr & LSR_OE)
+			ipend |= SER_INT_OVERRUN;
+		if (lsr & LSR_BI)
+			ipend |= SER_INT_BREAK;
+		if (lsr & LSR_RXRDY)
+			ipend |= SER_INT_RXREADY;
+	} else {
+		if (iir & IIR_TXRDY) {
+			ipend |= SER_INT_TXIDLE;
+			uart_setreg(bas, REG_IER, lpc_ns8250->ier);
+		} else
+			ipend |= SER_INT_SIGCHG;
+	}
+	if (ipend == 0)
+		lpc_ns8250_clrint(bas);
+	uart_unlock(sc->sc_hwmtx);
+	return (ipend);
+}
+
+static int
+lpc_ns8250_bus_param(struct uart_softc *sc, int baudrate, int databits,
+    int stopbits, int parity)
+{
+	struct uart_bas *bas;
+	int error;
+
+	bas = &sc->sc_bas;
+	uart_lock(sc->sc_hwmtx);
+	error = lpc_ns8250_param(bas, baudrate, databits, stopbits, parity);
+	uart_unlock(sc->sc_hwmtx);
+	return (error);
+}
+
+static int
+lpc_ns8250_bus_probe(struct uart_softc *sc)
+{
+	struct lpc_ns8250_softc *lpc_ns8250;
+	struct uart_bas *bas;
+	int count, delay, error, limit;
+	uint8_t lsr, mcr, ier;
+
+	lpc_ns8250 = (struct lpc_ns8250_softc *)sc;
+	bas = &sc->sc_bas;
+
+	error = lpc_ns8250_probe(bas);
+	if (error)
+		return (error);
+
+	mcr = MCR_IE;
+	if (sc->sc_sysdev == NULL) {
+		/* By using lpc_ns8250_init() we also set DTR and RTS. */
+		lpc_ns8250_init(bas, 115200, 8, 1, UART_PARITY_NONE);
+	} else
+		mcr |= MCR_DTR | MCR_RTS;
+
+	error = lpc_ns8250_drain(bas, UART_DRAIN_TRANSMITTER);
+	if (error)
+		return (error);
+
+	/*
+	 * Set loopback mode. This avoids having garbage on the wire and
+	 * also allows us send and receive data. We set DTR and RTS to
+	 * avoid the possibility that automatic flow-control prevents
+	 * any data from being sent.
+	 */
+	uart_setreg(bas, REG_MCR, MCR_LOOPBACK | MCR_IE | MCR_DTR | MCR_RTS);
+	uart_barrier(bas);
+
+	/*
+	 * Enable FIFOs. And check that the UART has them. If not, we're
+	 * done. Since this is the first time we enable the FIFOs, we reset
+	 * them.
+	 */
+	uart_setreg(bas, REG_FCR, FCR_ENABLE);
+	uart_barrier(bas);
+	if (!(uart_getreg(bas, REG_IIR) & IIR_FIFO_MASK)) {
+		/*
+		 * NS16450 or INS8250. We don't bother to differentiate
+		 * between them. They're too old to be interesting.
+		 */
+		uart_setreg(bas, REG_MCR, mcr);
+		uart_barrier(bas);
+		sc->sc_rxfifosz = sc->sc_txfifosz = 1;
+		device_set_desc(sc->sc_dev, "8250 or 16450 or compatible");
+		return (0);
+	}
+
+	uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST);
+	uart_barrier(bas);
+
+	count = 0;
+	delay = lpc_ns8250_delay(bas);
+
+	/* We have FIFOs. Drain the transmitter and receiver. */
+	error = lpc_ns8250_drain(bas, UART_DRAIN_RECEIVER|UART_DRAIN_TRANSMITTER);
+	if (error) {
+		uart_setreg(bas, REG_MCR, mcr);
+		uart_setreg(bas, REG_FCR, 0);
+		uart_barrier(bas);
+		goto done;
+	}
+
+	/*
+	 * We should have a sufficiently clean "pipe" to determine the
+	 * size of the FIFOs. We send as much characters as is reasonable
+	 * and wait for the overflow bit in the LSR register to be
+	 * asserted, counting the characters as we send them. Based on
+	 * that count we know the FIFO size.
+	 */
+	do {
+		uart_setreg(bas, REG_DATA, 0);
+		uart_barrier(bas);
+		count++;
+
+		limit = 30;
+		lsr = 0;
+		/*
+		 * LSR bits are cleared upon read, so we must accumulate
+		 * them to be able to test LSR_OE below.
+		 */
+		while (((lsr |= uart_getreg(bas, REG_LSR)) & LSR_TEMT) == 0 &&
+		    --limit)
+			DELAY(delay);
+		if (limit == 0) {
+			ier = uart_getreg(bas, REG_IER) & lpc_ns8250->ier_mask;
+			uart_setreg(bas, REG_IER, ier);
+			uart_setreg(bas, REG_MCR, mcr);
+			uart_setreg(bas, REG_FCR, 0);
+			uart_barrier(bas);
+			count = 0;
+			goto done;
+		}
+	} while ((lsr & LSR_OE) == 0 && count < 130);
+	count--;
+
+	uart_setreg(bas, REG_MCR, mcr);
+
+	/* Reset FIFOs. */
+	lpc_ns8250_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
+
+done:
+	sc->sc_rxfifosz = 64;
+	device_set_desc(sc->sc_dev, "LPC32x0 UART with FIFOs");
+
+	/*
+	 * Force the Tx FIFO size to 16 bytes for now. We don't program the
+	 * Tx trigger. Also, we assume that all data has been sent when the
+	 * interrupt happens.
+	 */
+	sc->sc_txfifosz = 16;
+
+#if 0
+	/*
+	 * XXX there are some issues related to hardware flow control and
+	 * it's likely that uart(4) is the cause. This basicly needs more
+	 * investigation, but we avoid using for hardware flow control
+	 * until then.
+	 */
+	/* 16650s or higher have automatic flow control. */
+	if (sc->sc_rxfifosz > 16) {
+		sc->sc_hwiflow = 1;
+		sc->sc_hwoflow = 1;
+	}
+#endif
+	return (0);
+}
+
+static int
+lpc_ns8250_bus_receive(struct uart_softc *sc)
+{
+	struct uart_bas *bas;
+	int xc;
+	uint8_t lsr;
+
+	bas = &sc->sc_bas;
+	uart_lock(sc->sc_hwmtx);
+	lsr = uart_getreg(bas, REG_LSR);
+	while (lsr & LSR_RXRDY) {
+		if (uart_rx_full(sc)) {
+			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+			break;
+		}
+		xc = uart_getreg(bas, REG_DATA);
+		if (lsr & LSR_FE)
+			xc |= UART_STAT_FRAMERR;
+		if (lsr & LSR_PE)
+			xc |= UART_STAT_PARERR;
+		uart_rx_put(sc, xc);
+		lsr = uart_getreg(bas, REG_LSR);
+	}
+	/* Discard everything left in the Rx FIFO. */
+	while (lsr & LSR_RXRDY) {
+		(void)uart_getreg(bas, REG_DATA);
+		uart_barrier(bas);
+		lsr = uart_getreg(bas, REG_LSR);
+	}
+	uart_unlock(sc->sc_hwmtx);
+ 	return (0);
+}
+
+static int
+lpc_ns8250_bus_setsig(struct uart_softc *sc, int sig)
+{
+	struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+	struct uart_bas *bas;
+	uint32_t new, old;
+
+	bas = &sc->sc_bas;
+	do {
+		old = sc->sc_hwsig;
+		new = old;
+		if (sig & SER_DDTR) {
+			SIGCHG(sig & SER_DTR, new, SER_DTR,
+			    SER_DDTR);
+		}
+		if (sig & SER_DRTS) {
+			SIGCHG(sig & SER_RTS, new, SER_RTS,
+			    SER_DRTS);
+		}
+	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+	uart_lock(sc->sc_hwmtx);
+	lpc_ns8250->mcr &= ~(MCR_DTR|MCR_RTS);
+	if (new & SER_DTR)
+		lpc_ns8250->mcr |= MCR_DTR;
+	if (new & SER_RTS)
+		lpc_ns8250->mcr |= MCR_RTS;
+	uart_setreg(bas, REG_MCR, lpc_ns8250->mcr);
+	uart_barrier(bas);
+	uart_unlock(sc->sc_hwmtx);
+	return (0);
+}
+
+static int
+lpc_ns8250_bus_transmit(struct uart_softc *sc)
+{
+	struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+	struct uart_bas *bas;
+	int i;
+
+	bas = &sc->sc_bas;
+	uart_lock(sc->sc_hwmtx);
+	while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
+		;
+	uart_setreg(bas, REG_IER, lpc_ns8250->ier | IER_ETXRDY);
+	uart_barrier(bas);
+	for (i = 0; i < sc->sc_txdatasz; i++) {
+		uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
+		uart_barrier(bas);
+	}
+	sc->sc_txbusy = 1;
+	uart_unlock(sc->sc_hwmtx);
+	return (0);
+}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/uart/uart_subr.c
--- a/head/sys/dev/uart/uart_subr.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/uart/uart_subr.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/uart/uart_subr.c 228468 2011-12-13 13:32:56Z ed $");
+__FBSDID("$FreeBSD: head/sys/dev/uart/uart_subr.c 239278 2012-08-15 05:37:10Z gonzo $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -52,6 +52,7 @@
 	&uart_ns8250_class,
 	&uart_sab82532_class,
 	&uart_z8530_class,
+	&uart_lpc_class,
 };
 static size_t uart_nclasses = sizeof(uart_classes) / sizeof(uart_classes[0]);
 
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/at91dci.c
--- a/head/sys/dev/usb/controller/at91dci.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/at91dci.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/at91dci.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/at91dci.c 239215 2012-08-12 19:58:56Z hselasky $");
 
 /*-
  * Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
@@ -1226,7 +1226,13 @@
 }
 
 static void
-at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+at91dci_xfer_stall(struct usb_xfer *xfer)
+{
+	at91dci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+at91dci_set_stall(struct usb_device *udev,
     struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct at91dci_softc *sc;
@@ -1237,10 +1243,6 @@
 
 	DPRINTFN(5, "endpoint=%p\n", ep);
 
-	if (xfer) {
-		/* cancel any ongoing transfers */
-		at91dci_device_done(xfer, USB_ERR_STALLED);
-	}
 	/* set FORCESTALL */
 	sc = AT9100_DCI_BUS2SC(udev->bus);
 	csr_reg = (ep->edesc->bEndpointAddress & UE_ADDR);
@@ -2332,6 +2334,7 @@
 	.xfer_unsetup = &at91dci_xfer_unsetup,
 	.get_hw_ep_profile = &at91dci_get_hw_ep_profile,
 	.set_stall = &at91dci_set_stall,
+	.xfer_stall = &at91dci_xfer_stall,
 	.clear_stall = &at91dci_clear_stall,
 	.roothub_exec = &at91dci_roothub_exec,
 	.xfer_poll = &at91dci_do_poll,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/atmegadci.c
--- a/head/sys/dev/usb/controller/atmegadci.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/atmegadci.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/atmegadci.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/atmegadci.c 239214 2012-08-12 17:53:06Z hselasky $");
 
 /*-
  * Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -1113,7 +1113,13 @@
 }
 
 static void
-atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+atmegadci_xfer_stall(struct usb_xfer *xfer)
+{
+	atmegadci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+atmegadci_set_stall(struct usb_device *udev,
     struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct atmegadci_softc *sc;
@@ -1123,10 +1129,6 @@
 
 	DPRINTFN(5, "endpoint=%p\n", ep);
 
-	if (xfer) {
-		/* cancel any ongoing transfers */
-		atmegadci_device_done(xfer, USB_ERR_STALLED);
-	}
 	sc = ATMEGA_BUS2SC(udev->bus);
 	/* get endpoint number */
 	ep_no = (ep->edesc->bEndpointAddress & UE_ADDR);
@@ -2151,6 +2153,7 @@
 	.xfer_setup = &atmegadci_xfer_setup,
 	.xfer_unsetup = &atmegadci_xfer_unsetup,
 	.get_hw_ep_profile = &atmegadci_get_hw_ep_profile,
+	.xfer_stall = &atmegadci_xfer_stall,
 	.set_stall = &atmegadci_set_stall,
 	.clear_stall = &atmegadci_clear_stall,
 	.roothub_exec = &atmegadci_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/avr32dci.c
--- a/head/sys/dev/usb/controller/avr32dci.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/avr32dci.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/avr32dci.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/avr32dci.c 239214 2012-08-12 17:53:06Z hselasky $");
 
 /*-
  * Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -1080,7 +1080,13 @@
 }
 
 static void
-avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+avr32dci_xfer_stall(struct usb_xfer *xfer)
+{
+	avr32dci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+avr32dci_set_stall(struct usb_device *udev,
     struct usb_endpoint *pipe, uint8_t *did_stall)
 {
 	struct avr32dci_softc *sc;
@@ -1090,10 +1096,6 @@
 
 	DPRINTFN(5, "pipe=%p\n", pipe);
 
-	if (xfer) {
-		/* cancel any ongoing transfers */
-		avr32dci_device_done(xfer, USB_ERR_STALLED);
-	}
 	sc = AVR32_BUS2SC(udev->bus);
 	/* get endpoint number */
 	ep_no = (pipe->edesc->bEndpointAddress & UE_ADDR);
@@ -2096,6 +2098,7 @@
 	.xfer_setup = &avr32dci_xfer_setup,
 	.xfer_unsetup = &avr32dci_xfer_unsetup,
 	.get_hw_ep_profile = &avr32dci_get_hw_ep_profile,
+	.xfer_stall = &avr32dci_xfer_stall,
 	.set_stall = &avr32dci_set_stall,
 	.clear_stall = &avr32dci_clear_stall,
 	.roothub_exec = &avr32dci_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/dotg.c
--- a/head/sys/dev/usb/controller/dotg.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/dotg.c	Wed Aug 15 11:46:11 2012 +0300
@@ -490,7 +490,7 @@
 	else if (hcint & HCINT_FRMOVRUN) {
 
 		td->qh->split_sc_frame = -1;
-		WRITE4(sc, DOTG_HCINT(channel), hcchar | HCCHAR_CHDIS);
+		WRITE4(sc, DOTG_HCCHAR(channel), hcchar | HCCHAR_CHDIS);
 
 		dotg_complete_cb(DOTG_COMPLETE_FRAMEERR, 0, td);
 	}
@@ -657,11 +657,11 @@
 		return (EIO);
 	}
 
-	SETFIELD32(sc,  DOTG_GINTMSK, GINTMSK_SOFMSK, 1);
+	//SETFIELD32(sc,  DOTG_GINTMSK, GINTMSK_SOFMSK, 1);
 
 	hcint = READ4(sc, DOTG_HCINT(td->channel));
 	WRITE4(sc, DOTG_HCINT(td->channel), hcint);
-	WRITE4(sc, DOTG_HCINTMSK(td->channel), 0x7ff);
+//	WRITE4(sc, DOTG_HCINTMSK(td->channel), HCINTMSK_ANY);
 
 	td->qh->this_xfersize = xfersize;
 
@@ -695,10 +695,11 @@
 
 	WRITEDMA(sc, td->channel,
 	    (unsigned int *)(td->qh->fixup_phys + td->qh->fixup_off));
-	WRITE4(sc, DOTG_HAINTMSK, 
+	WRITE4(sc, DOTG_HAINTMSK,
 	    (READ4(sc, DOTG_HAINTMSK) | (1<<td->channel)));
-	WRITE4(sc, DOTG_HCINTMSK(td->channel), 
+	WRITE4(sc, DOTG_HCINTMSK(td->channel),
 	    HCINTMSK_CHHLTDMSK|HCINTMSK_AHBERRMSK);
+	WRITE4(sc, DOTG_HCINTMSK(td->channel), HCINTMSK_ANY);
 	WRITE4(sc, DOTG_HCSPLT(td->channel), hcsplt);
 	WRITE4(sc, DOTG_HCTSIZ(td->channel), hctsiz);
 
@@ -756,13 +757,13 @@
 	/* get softc */
 	sc = td->qh->sc;
 
-#ifdef USB_DEBUG
-	if (dotgdebug) {
-		DPRINTF("\n");
-		hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys),
-		    8, 0, 0);
-	}
-#endif
+//#ifdef USB_DEBUG
+//	if (dotgdebug) {
+//		DPRINTF("\n");
+//		hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys),
+//		    8, 0, 0);
+//	}
+//#endif
 
 	int ret = configure_channel(td, 8, HCTSIZ_PID_SETUP, HCCHAR_EPDIR_OUT);
 	if (ret != 0)
@@ -1034,9 +1035,9 @@
 
 /*---------------------------------------------------------------*/
 	DPRINTF("+++++++++++++++++ rem=%d\n", rem);
-#ifdef USB_DEBUG
-	if (dotgdebug == 0x0fffffff) hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys), rem, 0, 0);
-#endif
+//#ifdef USB_DEBUG
+//	if (dotgdebug == 0x0fffffff) hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys), rem, 0, 0);
+//#endif
 	DPRINTF("\n");
 
 	int ret = configure_channel(td, rem, td->qh->ep_toggle_next?HCTSIZ_PID_DATA1:HCTSIZ_PID_DATA0, HCCHAR_EPDIR_OUT);
@@ -1100,9 +1101,9 @@
 		usb_pc_cpu_invalidate(td->qh->fixup_pc);
 
 		DPRINTF("\n");
-#ifdef USB_DEBUG
-		if (dotgdebug == 0x0fffffff) hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys), td->qh->fixup_actlen, 0, 0);
-#endif
+//#ifdef USB_DEBUG
+//		if (dotgdebug == 0x0fffffff) hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys), td->qh->fixup_actlen, 0, 0);
+//#endif
 		DPRINTF("\n");
 
 		/* verify transfer length */
@@ -1366,10 +1367,11 @@
 		uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata, sizeof(sc->sc_hub_idata));
 
 	}
+
 	{
 		uint32_t haint = READ4(sc, DOTG_HAINT);
 		WRITE4(sc, DOTG_HAINT, haint);
-		haint &= ((1<<sc->channels) - 1);
+		haint &= ((1 << sc->channels) - 1);
 		while (haint) {
 			int		channel;
 			for (channel = 0; channel < sc->channels; channel ++)
@@ -1381,7 +1383,7 @@
 	}
 
 
-	WRITE4(sc, DOTG_GINTSTS, gintsts);
+//	WRITE4(sc, DOTG_GINTSTS, gintsts);
 
 repeat:
 	TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
@@ -1517,8 +1519,8 @@
 	CP;
 	/* Enable interrupts */
 	tmp = READ4(sc, DOTG_GINTMSK);
-//	tmp &= ~(GINTMSK_SOFMSK); ////
-	tmp |= (GINTMSK_SOFMSK);
+//	tmp |= (GINTMSK_SOFMSK);
+	tmp &= ~(GINTMSK_SOFMSK);
 	tmp |= (GINTMSK_OTGINTMSK | GINTMSK_MODEMISMSK | GINTMSK_HCHINTMSK);
 	WRITE4(sc, DOTG_GINTMSK, tmp);
 
@@ -2427,7 +2429,7 @@
 
 	if (usbd_transfer_setup_sub_malloc(
 	    parm, &pc, sizeof(struct dotg_qh),
-	    USB_HOST_ALIGN, 1)) {
+	    USB_HOST_ALIGN*4, 1)) { //XXX
 		parm->err = USB_ERR_NOMEM;
 		return;
 	}
@@ -2551,6 +2553,7 @@
 static void
 dotg_xfer_unsetup(struct usb_xfer *xfer)
 {
+	return;
 }
 
 static void
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/dotgreg.h
--- a/head/sys/dev/usb/controller/dotgreg.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/dotgreg.h	Wed Aug 15 11:46:11 2012 +0300
@@ -479,6 +479,17 @@
 #define HCINTMSK_AHBERRMSK		(1<<2)
 #define HCINTMSK_CHHLTDMSK		(1<<1)
 #define HCINTMSK_XFERCOMPLMSK		(1<<0)
+#define HCINTMSK_ANY			(HCINTMSK_DATATGLERRMSK | \
+					HCINTMSK_FRMOVRUNMSK | \
+					HCINTMSK_BBLERRMSK | \
+					HCINTMSK_XACTERRMSK | \
+					HCINTMSK_NYETMSK | \
+					HCINTMSK_ACKMSK | \
+					HCINTMSK_NAKMSK | \
+					HCINTMSK_STALLMSK | \
+					HCINTMSK_AHBERRMSK | \
+					HCINTMSK_CHHLTDMSK | \
+					HCINTMSK_XFERCOMPLMSK)
 
 #define HCTSIZ_DOPNG			(1<<31)
 #define HCTSIZ_PID_SHIFT		29
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/dwc_otg.c
--- a/head/sys/dev/usb/controller/dwc_otg.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/dwc_otg.c	Wed Aug 15 11:46:11 2012 +0300
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/dwc_otg.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/dwc_otg.c 239214 2012-08-12 17:53:06Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -1524,7 +1524,13 @@
 }
 
 static void
-dwc_otg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+dwc_otg_xfer_stall(struct usb_xfer *xfer)
+{
+	dwc_otg_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+dwc_otg_set_stall(struct usb_device *udev,
     struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct dwc_otg_softc *sc;
@@ -1534,10 +1540,6 @@
 
 	USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
 
-	if (xfer) {
-		/* cancel any ongoing transfers */
-		dwc_otg_device_done(xfer, USB_ERR_STALLED);
-	}
 	sc = DWC_OTG_BUS2SC(udev->bus);
 
 	/* get endpoint address */
@@ -2625,6 +2627,7 @@
 	.xfer_setup = &dwc_otg_xfer_setup,
 	.xfer_unsetup = &dwc_otg_xfer_unsetup,
 	.get_hw_ep_profile = &dwc_otg_get_hw_ep_profile,
+	.xfer_stall = &dwc_otg_xfer_stall,
 	.set_stall = &dwc_otg_set_stall,
 	.clear_stall = &dwc_otg_clear_stall,
 	.roothub_exec = &dwc_otg_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/musb_otg.c
--- a/head/sys/dev/usb/controller/musb_otg.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/musb_otg.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/controller/musb_otg.c 233774 2012-04-02 10:50:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/controller/musb_otg.c 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -1472,7 +1472,13 @@
 }
 
 static void
-musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+musbotg_xfer_stall(struct usb_xfer *xfer)
+{
+	musbotg_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+musbotg_set_stall(struct usb_device *udev,
     struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct musbotg_softc *sc;
@@ -1482,10 +1488,6 @@
 
 	DPRINTFN(4, "endpoint=%p\n", ep);
 
-	if (xfer) {
-		/* cancel any ongoing transfers */
-		musbotg_device_done(xfer, USB_ERR_STALLED);
-	}
 	/* set FORCESTALL */
 	sc = MUSBOTG_BUS2SC(udev->bus);
 
@@ -2801,6 +2803,7 @@
 	.xfer_setup = &musbotg_xfer_setup,
 	.xfer_unsetup = &musbotg_xfer_unsetup,
 	.get_hw_ep_profile = &musbotg_get_hw_ep_profile,
+	.xfer_stall = &musbotg_xfer_stall,
 	.set_stall = &musbotg_set_stall,
 	.clear_stall = &musbotg_clear_stall,
 	.roothub_exec = &musbotg_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/uss820dci.c
--- a/head/sys/dev/usb/controller/uss820dci.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/uss820dci.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/controller/uss820dci.c 233774 2012-04-02 10:50:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/controller/uss820dci.c 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>
  * All rights reserved.
@@ -1210,7 +1210,13 @@
 }
 
 static void
-uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+uss820dci_xfer_stall(struct usb_xfer *xfer)
+{
+	uss820dci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+uss820dci_set_stall(struct usb_device *udev,
     struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct uss820dci_softc *sc;
@@ -1223,10 +1229,6 @@
 
 	DPRINTFN(5, "endpoint=%p\n", ep);
 
-	if (xfer) {
-		/* cancel any ongoing transfers */
-		uss820dci_device_done(xfer, USB_ERR_STALLED);
-	}
 	/* set FORCESTALL */
 	sc = USS820_DCI_BUS2SC(udev->bus);
 	ep_no = (ep->edesc->bEndpointAddress & UE_ADDR);
@@ -2385,6 +2387,7 @@
 	.xfer_setup = &uss820dci_xfer_setup,
 	.xfer_unsetup = &uss820dci_xfer_unsetup,
 	.get_hw_ep_profile = &uss820dci_get_hw_ep_profile,
+	.xfer_stall = &uss820dci_xfer_stall,
 	.set_stall = &uss820dci_set_stall,
 	.clear_stall = &uss820dci_clear_stall,
 	.roothub_exec = &uss820dci_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/xhci.c
--- a/head/sys/dev/usb/controller/xhci.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/xhci.c	Wed Aug 15 11:46:11 2012 +0300
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/xhci.c 234803 2012-04-29 17:12:33Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/xhci.c 239214 2012-08-12 17:53:06Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -128,7 +128,7 @@
 static usb_error_t xhci_configure_device(struct usb_device *);
 static usb_error_t xhci_configure_endpoint(struct usb_device *,
 		    struct usb_endpoint_descriptor *, uint64_t, uint16_t,
-		    uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
+		    uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
 static usb_error_t xhci_configure_mask(struct usb_device *,
 		    uint32_t, uint8_t);
 static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *,
@@ -1245,7 +1245,7 @@
 		    &udev->ctrl_ep_desc);
 		err = xhci_configure_endpoint(udev,
 		    &udev->ctrl_ep_desc, pepext->physaddr,
-		    0, 1, 1, 0, mps, mps);
+		    0, 1, 1, 0, mps, mps, USB_EP_MODE_DEFAULT);
 
 		if (err != 0) {
 			DPRINTF("Could not configure default endpoint\n");
@@ -1800,7 +1800,8 @@
 
 		/* compute multiplier for ISOCHRONOUS transfers */
 		mult = xfer->endpoint->ecomp ?
-		    (xfer->endpoint->ecomp->bmAttributes & 3) : 0;
+		    UE_GET_SS_ISO_MULT(xfer->endpoint->ecomp->bmAttributes)
+		    : 0;
 		/* check for USB 2.0 multiplier */
 		if (mult == 0) {
 			mult = (xfer->endpoint->edesc->
@@ -2055,7 +2056,8 @@
 xhci_configure_endpoint(struct usb_device *udev,
     struct usb_endpoint_descriptor *edesc, uint64_t ring_addr,
     uint16_t interval, uint8_t max_packet_count, uint8_t mult,
-    uint8_t fps_shift, uint16_t max_packet_size, uint16_t max_frame_size)
+    uint8_t fps_shift, uint16_t max_packet_size,
+    uint16_t max_frame_size, uint8_t ep_mode)
 {
 	struct usb_page_search buf_inp;
 	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
@@ -2090,9 +2092,20 @@
 	if (mult == 0)
 		return (USB_ERR_BAD_BUFSIZE);
 
-	temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
-	    XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
-	    XHCI_EPCTX_0_LSA_SET(0);
+	if (ep_mode == USB_EP_MODE_STREAMS) {
+		temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
+		    XHCI_EPCTX_0_MAXP_STREAMS_SET(XHCI_MAX_STREAMS_LOG - 1) |
+		    XHCI_EPCTX_0_LSA_SET(1);
+
+		ring_addr += sizeof(struct xhci_trb) *
+		    XHCI_MAX_TRANSFERS * XHCI_MAX_STREAMS;
+	} else {
+		temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
+		    XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
+		    XHCI_EPCTX_0_LSA_SET(0);
+
+		ring_addr |= XHCI_EPCTX_2_DCS_SET(1);
+	}
 
 	switch (udev->speed) {
 	case USB_SPEED_FULL:
@@ -2160,9 +2173,6 @@
 		temp |= XHCI_EPCTX_1_EPTYPE_SET(4);
 
 	xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx1, temp);
-
-	ring_addr |= XHCI_EPCTX_2_DCS_SET(1);
-
 	xhci_ctx_set_le64(sc, &pinp->ctx_ep[epno - 1].qwEpCtx2, ring_addr);
 
 	switch (edesc->bmAttributes & UE_XFERTYPE) {
@@ -2195,21 +2205,42 @@
 {
 	struct xhci_endpoint_ext *pepext;
 	struct usb_endpoint_ss_comp_descriptor *ecomp;
+	usb_stream_t x;
 
 	pepext = xhci_get_endpoint_ext(xfer->xroot->udev,
 	    xfer->endpoint->edesc);
 
 	ecomp = xfer->endpoint->ecomp;
 
-	pepext->trb[0].dwTrb3 = 0;	/* halt any transfers */
+	for (x = 0; x != XHCI_MAX_STREAMS; x++) {
+		uint64_t temp;
+
+		/* halt any transfers */
+		pepext->trb[x * XHCI_MAX_TRANSFERS].dwTrb3 = 0;
+
+		/* compute start of TRB ring for stream "x" */
+		temp = pepext->physaddr +
+		    (x * XHCI_MAX_TRANSFERS * sizeof(struct xhci_trb)) +
+		    XHCI_SCTX_0_SCT_SEC_TR_RING;
+
+		/* make tree structure */
+		pepext->trb[(XHCI_MAX_TRANSFERS *
+		    XHCI_MAX_STREAMS) + x].qwTrb0 = htole64(temp);
+
+		/* reserved fields */
+		pepext->trb[(XHCI_MAX_TRANSFERS *
+                    XHCI_MAX_STREAMS) + x].dwTrb2 = 0;
+		pepext->trb[(XHCI_MAX_TRANSFERS *
+		    XHCI_MAX_STREAMS) + x].dwTrb3 = 0;
+	}
 	usb_pc_cpu_flush(pepext->page_cache);
 
 	return (xhci_configure_endpoint(xfer->xroot->udev,
 	    xfer->endpoint->edesc, pepext->physaddr,
 	    xfer->interval, xfer->max_packet_count,
-	    (ecomp != NULL) ? (ecomp->bmAttributes & 3) + 1 : 1,
+	    (ecomp != NULL) ? UE_GET_SS_ISO_MULT(ecomp->bmAttributes) + 1 : 1,
 	    usbd_xfer_get_fps_shift(xfer), xfer->max_packet_size,
-	    xfer->max_frame_size));
+	    xfer->max_frame_size, xfer->endpoint->ep_mode));
 }
 
 static usb_error_t
@@ -2500,7 +2531,8 @@
 
 	pc = &sc->sc_hw.devs[index].endpoint_pc;
 
-	usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->trb[epno][0], &buf_ep);
+	usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->
+	    trb[epno][0], &buf_ep);
 
 	pepext = &sc->sc_hw.devs[index].endp[epno];
 	pepext->page_cache = pc;
@@ -2539,7 +2571,7 @@
 		pepext = xhci_get_endpoint_ext(xfer->xroot->udev,
 		    xfer->endpoint->edesc);
 
-		pepext->trb_used--;
+		pepext->trb_used[xfer->stream_id]--;
 
 		pepext->xfer[xfer->qh_pos] = NULL;
 
@@ -2557,12 +2589,15 @@
 	struct xhci_td *td_last;
 	struct xhci_endpoint_ext *pepext;
 	uint64_t addr;
+	usb_stream_t id;
 	uint8_t i;
 	uint8_t inext;
 	uint8_t trb_limit;
 
 	DPRINTFN(8, "\n");
 
+	id = xfer->stream_id;
+
 	/* check if already inserted */
 	if (xfer->flags_int.bandwidth_reclaimed) {
 		DPRINTFN(8, "Already in schedule\n");
@@ -2588,7 +2623,7 @@
 		break;
 	}
 
-	if (pepext->trb_used >= trb_limit) {
+	if (pepext->trb_used[id] >= trb_limit) {
 		DPRINTFN(8, "Too many TDs queued.\n");
 		return (USB_ERR_NOMEM);
 	}
@@ -2605,10 +2640,10 @@
 		return (0);
 	}
 
-	pepext->trb_used++;
+	pepext->trb_used[id]++;
 
 	/* get current TRB index */
-	i = pepext->trb_index;
+	i = pepext->trb_index[id];
 
 	/* get next TRB index */
 	inext = (i + 1);
@@ -2617,8 +2652,12 @@
 	if (inext >= (XHCI_MAX_TRANSFERS - 1))
 		inext = 0;
 
+	/* offset for stream */
+	i += id * XHCI_MAX_TRANSFERS;
+	inext += id * XHCI_MAX_TRANSFERS;
+
 	/* compute terminating return address */
-	addr += inext * sizeof(struct xhci_trb);
+	addr += (inext * sizeof(struct xhci_trb));
 
 	/* update next pointer of last link TRB */
 	td_last->td_trb[td_last->ntrb].qwTrb0 = htole64(addr);
@@ -2662,7 +2701,7 @@
 
 	xfer->flags_int.bandwidth_reclaimed = 1;
 
-	pepext->trb_index = inext;
+	pepext->trb_index[id] = inext;
 
 	xhci_endpoint_doorbell(xfer);
 
@@ -2750,12 +2789,12 @@
 
 static void
 xhci_device_generic_multi_enter(struct usb_endpoint *ep,
-    struct usb_xfer *enter_xfer)
+    usb_stream_t stream_id, struct usb_xfer *enter_xfer)
 {
 	struct usb_xfer *xfer;
 
 	/* check if there is a current transfer */
-	xfer = ep->endpoint_q.curr;
+	xfer = ep->endpoint_q[stream_id].curr;
 	if (xfer == NULL)
 		return;
 
@@ -2767,7 +2806,7 @@
 	if (!xfer->flags_int.bandwidth_reclaimed)
 		return;
 
-	xfer = TAILQ_FIRST(&ep->endpoint_q.head);
+	xfer = TAILQ_FIRST(&ep->endpoint_q[stream_id].head);
 	if (xfer == NULL) {
 		/*
 		 * In case of enter we have to consider that the
@@ -2792,7 +2831,8 @@
 	/* setup TD's and QH */
 	xhci_setup_generic_chain(xfer);
 
-	xhci_device_generic_multi_enter(xfer->endpoint, xfer);
+	xhci_device_generic_multi_enter(xfer->endpoint,
+	    xfer->stream_id, xfer);
 }
 
 static void
@@ -2804,7 +2844,8 @@
 	xhci_transfer_insert(xfer);
 
 	/* try to multi buffer */
-	xhci_device_generic_multi_enter(xfer->endpoint, NULL);
+	xhci_device_generic_multi_enter(xfer->endpoint,
+	    xfer->stream_id, NULL);
 
 	/* add transfer last on interrupt queue */
 	usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
@@ -3465,6 +3506,7 @@
 	struct usb_endpoint_descriptor *edesc;
 	struct usb_page_cache *pcinp;
 	usb_error_t err;
+	usb_stream_t stream_id;
 	uint8_t index;
 	uint8_t epno;
 
@@ -3481,6 +3523,7 @@
 	edesc = xfer->endpoint->edesc;
 
 	epno = edesc->bEndpointAddress;
+	stream_id = xfer->stream_id;
 
 	if ((edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL)
 		epno |= UE_DIR_IN;
@@ -3516,8 +3559,10 @@
 	if (err != 0)
 		DPRINTF("Could not reset endpoint %u\n", epno);
 
-	err = xhci_cmd_set_tr_dequeue_ptr(sc, pepext->physaddr |
-	    XHCI_EPCTX_2_DCS_SET(1), 0, epno, index);
+	err = xhci_cmd_set_tr_dequeue_ptr(sc,
+	    (pepext->physaddr + (stream_id * sizeof(struct xhci_trb) *
+	    XHCI_MAX_TRANSFERS)) | XHCI_EPCTX_2_DCS_SET(1),
+	    stream_id, epno, index);
 
 	if (err != 0)
 		DPRINTF("Could not set dequeue ptr for endpoint %u\n", epno);
@@ -3615,7 +3660,8 @@
 			/* check if halted is still cleared */
 			if (pepext->trb_halted == 0) {
 				pepext->trb_running = 1;
-				pepext->trb_index = 0;
+				memset(pepext->trb_index, 0,
+				    sizeof(pepext->trb_index));
 			}
 			goto restart;
 		}
@@ -3639,7 +3685,8 @@
 		xhci_transfer_insert(xfer);
 
 		/* try to multi buffer */
-		xhci_device_generic_multi_enter(xfer->endpoint, NULL);
+		xhci_device_generic_multi_enter(xfer->endpoint,
+		    xfer->stream_id, NULL);
 	}
 }
 
@@ -3946,6 +3993,23 @@
 	XHCI_CMD_UNLOCK(sc);
 }
 
+static usb_error_t
+xhci_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep,
+    uint8_t ep_mode)
+{
+	switch (ep_mode) {
+	case USB_EP_MODE_DEFAULT:
+		return (0);
+	case USB_EP_MODE_STREAMS:
+		if ((ep->edesc->bmAttributes & UE_XFERTYPE) != UE_BULK ||
+		    udev->speed != USB_SPEED_SUPER)
+			return (USB_ERR_INVAL);
+		return (0);
+	default:
+		return (USB_ERR_INVAL);
+	}
+}
+
 struct usb_bus_methods xhci_bus_methods = {
 	.endpoint_init = xhci_ep_init,
 	.endpoint_uninit = xhci_ep_uninit,
@@ -3964,4 +4028,5 @@
 	.clear_stall = xhci_ep_clear_stall,
 	.device_state_change = xhci_device_state_change,
 	.set_hw_power_sleep = xhci_set_hw_power_sleep,
+	.set_endpoint_mode = xhci_set_endpoint_mode,
 };
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/xhci.h
--- a/head/sys/dev/usb/controller/xhci.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/xhci.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/controller/xhci.h 229086 2011-12-31 13:34:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/controller/xhci.h 239214 2012-08-12 17:53:06Z hselasky $ */
 
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
@@ -35,7 +35,15 @@
 #define	XHCI_MAX_COMMANDS	(16 * 1)
 #define	XHCI_MAX_RSEG		1
 #define	XHCI_MAX_TRANSFERS	4
-
+#if USB_MAX_EP_STREAMS == 8
+#define	XHCI_MAX_STREAMS	8
+#define	XHCI_MAX_STREAMS_LOG	3
+#elif USB_MAX_EP_STREAMS == 1
+#define	XHCI_MAX_STREAMS	1
+#define	XHCI_MAX_STREAMS_LOG	0
+#else
+#error "The USB_MAX_EP_STREAMS value is not supported."
+#endif
 #define	XHCI_DEV_CTX_ADDR_ALIGN		64	/* bytes */
 #define	XHCI_DEV_CTX_ALIGN		64	/* bytes */
 #define	XHCI_INPUT_CTX_ALIGN		64	/* bytes */
@@ -307,7 +315,8 @@
 } __aligned(4);
 
 struct xhci_dev_endpoint_trbs {
-	struct xhci_trb		trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS];
+	struct xhci_trb		trb[XHCI_MAX_ENDPOINTS]
+	    [(XHCI_MAX_STREAMS * XHCI_MAX_TRANSFERS) + XHCI_MAX_STREAMS];
 };
 
 #define	XHCI_TD_PAGE_NBUF	17	/* units, room enough for 64Kbytes */
@@ -353,11 +362,11 @@
 
 struct xhci_endpoint_ext {
 	struct xhci_trb		*trb;
-	struct usb_xfer		*xfer[XHCI_MAX_TRANSFERS - 1];
+	struct usb_xfer		*xfer[XHCI_MAX_TRANSFERS * XHCI_MAX_STREAMS];
 	struct usb_page_cache	*page_cache;
 	uint64_t		physaddr;
-	uint8_t			trb_used;
-	uint8_t			trb_index;
+	uint8_t			trb_used[XHCI_MAX_STREAMS];
+	uint8_t			trb_index[XHCI_MAX_STREAMS];
 	uint8_t			trb_halted;
 	uint8_t			trb_running;
 };
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/net/if_smsc.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/usb/net/if_smsc.c	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,1756 @@
+/*-
+ * Copyright (c) 2012
+ *	Ben Gray <bgray at freebsd.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_smsc.c 239275 2012-08-15 04:03:55Z gonzo $");
+
+/*
+ * SMSC LAN9xxx devices (http://www.smsc.com/)
+ * 
+ * The LAN9500 & LAN9500A devices are stand-alone USB to Ethernet chips that
+ * support USB 2.0 and 10/100 Mbps Ethernet.
+ *
+ * The LAN951x devices are an integrated USB hub and USB to Ethernet adapter.
+ * The driver only covers the Ethernet part, the standard USB hub driver
+ * supports the hub part.
+ *
+ * This driver is closely modelled on the Linux driver written and copyrighted
+ * by SMSC.
+ *
+ *
+ *
+ *
+ * H/W TCP & UDP Checksum Offloading
+ * ---------------------------------
+ * The chip supports both tx and rx offloading of UDP & TCP checksums, this
+ * feature can be dynamically enabled/disabled.  
+ *
+ * RX checksuming is performed across bytes after the IPv4 header to the end of
+ * the Ethernet frame, this means if the frame is padded with non-zero values
+ * the H/W checksum will be incorrect, however the rx code compensates for this.
+ *
+ * TX checksuming is more complicated, the device requires a special header to
+ * be prefixed onto the start of the frame which indicates the start and end
+ * positions of the UDP or TCP frame.  This requires the driver to manually
+ * go through the packet data and decode the headers prior to sending.
+ * On Linux they generally provide cues to the location of the csum and the
+ * area to calculate it over, on FreeBSD we seem to have to do it all ourselves,
+ * hence this is not as optimal and therefore h/w tX checksum is currently not
+ * implemented.
+ *
+ */
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+#include <sys/random.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include "usbdevs.h"
+
+#define	USB_DEBUG_VAR smsc_debug
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+
+#include <dev/usb/usb_device.h>
+#include <dev/usb/net/usb_ethernet.h>
+#include "if_smscreg.h"
+
+#ifdef USB_DEBUG
+static int smsc_debug = 0;
+
+SYSCTL_NODE(_hw_usb, OID_AUTO, smsc, CTLFLAG_RW, 0, "USB smsc");
+SYSCTL_INT(_hw_usb_smsc, OID_AUTO, debug, CTLFLAG_RW, &smsc_debug, 0,
+    "Debug level");
+#endif
+
+/*
+ * Various supported device vendors/products.
+ */
+static const struct usb_device_id smsc_devs[] = {
+#define	SMSC_DEV(p,i) { USB_VPI(USB_VENDOR_SMC2, USB_PRODUCT_SMC2_##p, i) }
+	SMSC_DEV(LAN9514_ETH, 0),
+#undef SMSC_DEV
+};
+
+
+#ifdef USB_DEBUG
+#define smsc_dbg_printf(sc, fmt, args...) \
+	do { \
+		if (smsc_debug > 0) \
+			device_printf((sc)->sc_ue.ue_dev, "debug: " fmt, ##args); \
+	} while(0)
+#else
+#define smsc_dbg_printf(sc, fmt, args...)
+#endif
+
+#define smsc_warn_printf(sc, fmt, args...) \
+	device_printf((sc)->sc_ue.ue_dev, "warning: " fmt, ##args)
+
+#define smsc_err_printf(sc, fmt, args...) \
+	device_printf((sc)->sc_ue.ue_dev, "error: " fmt, ##args)
+	
+
+#define ETHER_IS_ZERO(addr) \
+	(!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]))
+	
+#define ETHER_IS_VALID(addr) \
+	(!ETHER_IS_MULTICAST(addr) && !ETHER_IS_ZERO(addr))
+	
+static device_probe_t smsc_probe;
+static device_attach_t smsc_attach;
+static device_detach_t smsc_detach;
+
+static usb_callback_t smsc_bulk_read_callback;
+static usb_callback_t smsc_bulk_write_callback;
+
+static miibus_readreg_t smsc_miibus_readreg;
+static miibus_writereg_t smsc_miibus_writereg;
+static miibus_statchg_t smsc_miibus_statchg;
+
+#if __FreeBSD_version > 1000000
+static int smsc_attach_post_sub(struct usb_ether *ue);
+#endif
+static uether_fn_t smsc_attach_post;
+static uether_fn_t smsc_init;
+static uether_fn_t smsc_stop;
+static uether_fn_t smsc_start;
+static uether_fn_t smsc_tick;
+static uether_fn_t smsc_setmulti;
+static uether_fn_t smsc_setpromisc;
+
+static int	smsc_ifmedia_upd(struct ifnet *);
+static void	smsc_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+static int smsc_chip_init(struct smsc_softc *sc);
+static int smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
+
+static const struct usb_config smsc_config[SMSC_N_TRANSFER] = {
+
+	[SMSC_BULK_DT_WR] = {
+		.type = UE_BULK,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_OUT,
+		.frames = 16,
+		.bufsize = 16 * (MCLBYTES + 16),
+		.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+		.callback = smsc_bulk_write_callback,
+		.timeout = 10000,	/* 10 seconds */
+	},
+
+	[SMSC_BULK_DT_RD] = {
+		.type = UE_BULK,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_IN,
+		.bufsize = 20480,	/* bytes */
+		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+		.callback = smsc_bulk_read_callback,
+		.timeout = 0,	/* no timeout */
+	},
+
+	/* The SMSC chip supports an interrupt endpoints, however they aren't
+	 * needed as we poll on the MII status.
+	 */
+};
+
+static const struct usb_ether_methods smsc_ue_methods = {
+	.ue_attach_post = smsc_attach_post,
+#if __FreeBSD_version > 1000000
+	.ue_attach_post_sub = smsc_attach_post_sub,
+#endif
+	.ue_start = smsc_start,
+	.ue_ioctl = smsc_ioctl,
+	.ue_init = smsc_init,
+	.ue_stop = smsc_stop,
+	.ue_tick = smsc_tick,
+	.ue_setmulti = smsc_setmulti,
+	.ue_setpromisc = smsc_setpromisc,
+	.ue_mii_upd = smsc_ifmedia_upd,
+	.ue_mii_sts = smsc_ifmedia_sts,
+};
+
+/**
+ *	smsc_read_reg - Reads a 32-bit register on the device
+ *	@sc: driver soft context
+ *	@off: offset of the register
+ *	@data: pointer a value that will be populated with the register value
+ *	
+ *	LOCKING:
+ *	The device lock must be held before calling this function.
+ *
+ *	RETURNS:
+ *	0 on success, a USB_ERR_?? error code on failure.
+ */
+static int
+smsc_read_reg(struct smsc_softc *sc, uint32_t off, uint32_t *data)
+{
+	struct usb_device_request req;
+	uint32_t buf;
+	usb_error_t err;
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	req.bmRequestType = UT_READ_VENDOR_DEVICE;
+	req.bRequest = SMSC_UR_READ_REG;
+	USETW(req.wValue, 0);
+	USETW(req.wIndex, off);
+	USETW(req.wLength, 4);
+
+	err = uether_do_request(&sc->sc_ue, &req, &buf, 1000);
+	if (err != 0)
+		smsc_warn_printf(sc, "Failed to read register 0x%0x\n", off);
+
+	*data = le32toh(buf);
+	
+	return (err);
+}
+
+/**
+ *	smsc_write_reg - Writes a 32-bit register on the device
+ *	@sc: driver soft context
+ *	@off: offset of the register
+ *	@data: the 32-bit value to write into the register
+ *	
+ *	LOCKING:
+ *	The device lock must be held before calling this function.
+ *
+ *	RETURNS:
+ *	0 on success, a USB_ERR_?? error code on failure.
+ */
+static int
+smsc_write_reg(struct smsc_softc *sc, uint32_t off, uint32_t data)
+{
+	struct usb_device_request req;
+	uint32_t buf;
+	usb_error_t err;
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+	
+	buf = htole32(data);
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = SMSC_UR_WRITE_REG;
+	USETW(req.wValue, 0);
+	USETW(req.wIndex, off);
+	USETW(req.wLength, 4);
+
+	err = uether_do_request(&sc->sc_ue, &req, &buf, 1000);
+	if (err != 0)
+		smsc_warn_printf(sc, "Failed to write register 0x%0x\n", off);
+
+	return (err);
+}
+
+/**
+ *	smsc_wait_for_bits - Polls on a register value until bits are cleared
+ *	@sc: soft context
+ *	@reg: offset of the register
+ *	@bits: if the bits are clear the function returns
+ *
+ *	LOCKING:
+ *	The device lock must be held before calling this function.
+ *
+ *	RETURNS:
+ *	0 on success, or a USB_ERR_?? error code on failure.
+ */
+static int
+smsc_wait_for_bits(struct smsc_softc *sc, uint32_t reg, uint32_t bits)
+{
+	usb_ticks_t start_ticks;
+	usb_ticks_t max_ticks = USB_MS_TO_TICKS(1000);
+	uint32_t val;
+	int err;
+	
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	start_ticks = (usb_ticks_t)ticks;
+	do {
+		if ((err = smsc_read_reg(sc, reg, &val)) != 0)
+			return (err);
+		if (!(val & bits))
+			return (0);
+		
+		uether_pause(&sc->sc_ue, hz / 100);
+	} while ((ticks - start_ticks) < max_ticks);
+
+	return (USB_ERR_TIMEOUT);
+}
+
+/**
+ *	smsc_eeprom_read - Reads the attached EEPROM
+ *	@sc: soft context
+ *	@off: the eeprom address offset
+ *	@buf: stores the bytes
+ *	@buflen: the number of bytes to read
+ *
+ *	Simply reads bytes from an attached eeprom.
+ *
+ *	LOCKING:
+ *	The function takes and releases the device lock if it is not already held.
+ *
+ *	RETURNS:
+ *	0 on success, or a USB_ERR_?? error code on failure.
+ */
+static int
+smsc_eeprom_read(struct smsc_softc *sc, uint16_t off, uint8_t *buf, uint16_t buflen)
+{
+	usb_ticks_t start_ticks;
+	usb_ticks_t max_ticks = USB_MS_TO_TICKS(1000);
+	int err;
+	int locked;
+	uint32_t val;
+	uint16_t i;
+
+	locked = mtx_owned(&sc->sc_mtx);
+	if (!locked)
+		SMSC_LOCK(sc);
+
+	err = smsc_wait_for_bits(sc, SMSC_EEPROM_CMD, SMSC_EEPROM_CMD_BUSY);
+	if (err != 0) {
+		smsc_warn_printf(sc, "eeprom busy, failed to read data\n");
+		goto done;
+	}
+
+	/* start reading the bytes, one at a time */
+	for (i = 0; i < buflen; i++) {
+	
+		val = SMSC_EEPROM_CMD_BUSY | (SMSC_EEPROM_CMD_ADDR_MASK & (off + i));
+		if ((err = smsc_write_reg(sc, SMSC_EEPROM_CMD, val)) != 0)
+			goto done;
+		
+		start_ticks = (usb_ticks_t)ticks;
+		do {
+			if ((err = smsc_read_reg(sc, SMSC_EEPROM_CMD, &val)) != 0)
+				goto done;
+			if (!(val & SMSC_EEPROM_CMD_BUSY) || (val & SMSC_EEPROM_CMD_TIMEOUT))
+				break;
+
+			uether_pause(&sc->sc_ue, hz / 100);
+		} while ((ticks - start_ticks) < max_ticks);
+		
+		if (val & (SMSC_EEPROM_CMD_BUSY | SMSC_EEPROM_CMD_TIMEOUT)) {
+			smsc_warn_printf(sc, "eeprom command failed\n");
+			err = USB_ERR_IOERROR;
+			break;
+		}
+			
+		if ((err = smsc_read_reg(sc, SMSC_EEPROM_DATA, &val)) != 0)
+			goto done;
+
+		buf[i] = (val & 0xff);
+	}
+	
+done:
+	if (!locked)
+		SMSC_UNLOCK(sc);
+
+	return (err);
+}
+
+/**
+ *	smsc_miibus_readreg - Reads a MII/MDIO register
+ *	@dev: usb ether device
+ *	@phy: the number of phy reading from
+ *	@reg: the register address
+ *
+ *	Attempts to read a phy register over the MII bus.
+ *
+ *	LOCKING:
+ *	Takes and releases the device mutex lock if not already held.
+ *
+ *	RETURNS:
+ *	Returns the 16-bits read from the MII register, if this function fails 0
+ *	is returned.
+ */
+static int
+smsc_miibus_readreg(device_t dev, int phy, int reg)
+{
+	struct smsc_softc *sc = device_get_softc(dev);
+	int locked;
+	uint32_t addr;
+	uint32_t val = 0;
+
+	locked = mtx_owned(&sc->sc_mtx);
+	if (!locked)
+		SMSC_LOCK(sc);
+
+	if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
+		smsc_warn_printf(sc, "MII is busy\n");
+		goto done;
+	}
+
+	addr = (phy << 11) | (reg << 6) | SMSC_MII_READ;
+	smsc_write_reg(sc, SMSC_MII_ADDR, addr);
+
+	if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0)
+		smsc_warn_printf(sc, "MII read timeout\n");
+
+	smsc_read_reg(sc, SMSC_MII_DATA, &val);
+	val = le32toh(val);
+	
+done:
+	if (!locked)
+		SMSC_UNLOCK(sc);
+
+	return (val & 0xFFFF);
+}
+
+/**
+ *	smsc_miibus_writereg - Writes a MII/MDIO register
+ *	@dev: usb ether device
+ *	@phy: the number of phy writing to
+ *	@reg: the register address
+ *	@val: the value to write
+ *
+ *	Attempts to write a phy register over the MII bus.
+ *
+ *	LOCKING:
+ *	Takes and releases the device mutex lock if not already held.
+ *
+ *	RETURNS:
+ *	Always returns 0 regardless of success or failure.
+ */
+static int
+smsc_miibus_writereg(device_t dev, int phy, int reg, int val)
+{
+	struct smsc_softc *sc = device_get_softc(dev);
+	int locked;
+	uint32_t addr;
+
+	if (sc->sc_phyno != phy)
+		return (0);
+
+	locked = mtx_owned(&sc->sc_mtx);
+	if (!locked)
+		SMSC_LOCK(sc);
+
+	if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
+		smsc_warn_printf(sc, "MII is busy\n");
+		goto done;
+	}
+
+	val = htole32(val);
+	smsc_write_reg(sc, SMSC_MII_DATA, val);
+
+	addr = (phy << 11) | (reg << 6) | SMSC_MII_WRITE;
+	smsc_write_reg(sc, SMSC_MII_ADDR, addr);
+
+	if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0)
+		smsc_warn_printf(sc, "MII write timeout\n");
+
+done:
+	if (!locked)
+		SMSC_UNLOCK(sc);
+	return (0);
+}
+
+
+
+/**
+ *	smsc_miibus_statchg - Called to detect phy status change
+ *	@dev: usb ether device
+ *
+ *	This function is called periodically by the system to poll for status
+ *	changes of the link.
+ *
+ *	LOCKING:
+ *	Takes and releases the device mutex lock if not already held.
+ */
+static void
+smsc_miibus_statchg(device_t dev)
+{
+	struct smsc_softc *sc = device_get_softc(dev);
+	struct mii_data *mii = uether_getmii(&sc->sc_ue);
+	struct ifnet *ifp;
+	int locked;
+	int err;
+	uint32_t flow;
+	uint32_t afc_cfg;
+
+	locked = mtx_owned(&sc->sc_mtx);
+	if (!locked)
+		SMSC_LOCK(sc);
+
+	ifp = uether_getifp(&sc->sc_ue);
+	if (mii == NULL || ifp == NULL ||
+	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+		goto done;
+
+	/* Use the MII status to determine link status */
+	sc->sc_flags &= ~SMSC_FLAG_LINK;
+	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:
+				sc->sc_flags |= SMSC_FLAG_LINK;
+				break;
+			case IFM_1000_T:
+				/* Gigabit ethernet not supported by chipset */
+				break;
+			default:
+				break;
+		}
+	}
+
+	/* Lost link, do nothing. */
+	if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) {
+		smsc_dbg_printf(sc, "link flag not set\n");
+		goto done;
+	}
+	
+	err = smsc_read_reg(sc, SMSC_AFC_CFG, &afc_cfg);
+	if (err) {
+		smsc_warn_printf(sc, "failed to read initial AFC_CFG, error %d\n", err);
+		goto done;
+	}
+	
+	/* Enable/disable full duplex operation and TX/RX pause */
+	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
+		smsc_dbg_printf(sc, "full duplex operation\n");
+		sc->sc_mac_csr &= ~SMSC_MAC_CSR_RCVOWN;
+		sc->sc_mac_csr |= SMSC_MAC_CSR_FDPX;
+
+		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
+			flow = 0xffff0002;
+		else
+			flow = 0;
+			
+		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
+			afc_cfg |= 0xf;
+		else
+			afc_cfg &= ~0xf;
+		
+	} else {
+		smsc_dbg_printf(sc, "half duplex operation\n");
+		sc->sc_mac_csr &= ~SMSC_MAC_CSR_FDPX;
+		sc->sc_mac_csr |= SMSC_MAC_CSR_RCVOWN;
+		
+		flow = 0;
+		afc_cfg |= 0xf;
+	}
+
+	err = smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+	err += smsc_write_reg(sc, SMSC_FLOW, flow);
+	err += smsc_write_reg(sc, SMSC_AFC_CFG, afc_cfg);
+	if (err)
+		smsc_warn_printf(sc, "media change failed, error %d\n", err);
+	
+done:
+	if (!locked)
+		SMSC_UNLOCK(sc);
+}
+
+/**
+ *	smsc_ifmedia_upd - Set media options
+ *	@ifp: interface pointer
+ *
+ *	Basically boilerplate code that simply calls the mii functions to set the
+ *	media options.
+ *
+ *	LOCKING:
+ *	The device lock must be held before this function is called.
+ *
+ *	RETURNS:
+ *	Returns 0 on success or a negative error code.
+ */
+static int
+smsc_ifmedia_upd(struct ifnet *ifp)
+{
+	struct smsc_softc *sc = ifp->if_softc;
+	struct mii_data *mii = uether_getmii(&sc->sc_ue);
+	int err;
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	if (mii->mii_instance) {
+		struct mii_softc *miisc;
+
+		LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+			mii_phy_reset(miisc);
+	}
+	err = mii_mediachg(mii);
+	return (err);
+}
+
+/**
+ *	smsc_ifmedia_sts - Report current media status
+ *	@ifp: inet interface pointer
+ *	@ifmr: interface media request
+ *
+ *	Basically boilerplate code that simply calls the mii functions to get the
+ *	media status.
+ *
+ *	LOCKING:
+ *	Internally takes and releases the device lock.
+ */
+static void
+smsc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+	struct smsc_softc *sc = ifp->if_softc;
+	struct mii_data *mii = uether_getmii(&sc->sc_ue);
+
+	SMSC_LOCK(sc);
+	
+	mii_pollstat(mii);
+	
+	SMSC_UNLOCK(sc);
+	
+	ifmr->ifm_active = mii->mii_media_active;
+	ifmr->ifm_status = mii->mii_media_status;
+}
+
+/**
+ *	smsc_hash - Calculate the hash of a mac address
+ *	@addr: The mac address to calculate the hash on
+ *
+ *	This function is used when configuring a range of m'cast mac addresses to
+ *	filter on.  The hash of the mac address is put in the device's mac hash
+ *	table.
+ *
+ *	RETURNS:
+ *	Returns a value from 0-63 value which is the hash of the mac address.
+ */
+static inline uint32_t
+smsc_hash(uint8_t addr[ETHER_ADDR_LEN])
+{
+	return (ether_crc32_be(addr, ETHER_ADDR_LEN) >> 26) & 0x3f;
+}
+
+/**
+ *	smsc_setmulti - Setup multicast
+ *	@ue: usb ethernet device context
+ *
+ *	Tells the device to either accept frames with a multicast mac address, a
+ *	select group of m'cast mac addresses or just the devices mac address.
+ *
+ *	LOCKING:
+ *	Should be called with the SMSC lock held.
+ */
+static void
+smsc_setmulti(struct usb_ether *ue)
+{
+	struct smsc_softc *sc = uether_getsc(ue);
+	struct ifnet *ifp = uether_getifp(ue);
+	struct ifmultiaddr *ifma;
+	uint32_t hashtbl[2] = { 0, 0 };
+	uint32_t hash;
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
+		smsc_dbg_printf(sc, "receive all multicast enabled\n");
+		sc->sc_mac_csr |= SMSC_MAC_CSR_MCPAS;
+		sc->sc_mac_csr &= ~SMSC_MAC_CSR_HPFILT;
+		
+	} else {
+		/* Take the lock of the mac address list before hashing each of them */
+		if_maddr_rlock(ifp);
+
+		if (!TAILQ_EMPTY(&ifp->if_multiaddrs)) {
+			/* We are filtering on a set of address so calculate hashes of each
+			 * of the address and set the corresponding bits in the register.
+			 */
+			sc->sc_mac_csr |= SMSC_MAC_CSR_HPFILT;
+			sc->sc_mac_csr &= ~(SMSC_MAC_CSR_PRMS | SMSC_MAC_CSR_MCPAS);
+		
+			TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+				if (ifma->ifma_addr->sa_family != AF_LINK)
+					continue;
+
+				hash = smsc_hash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+				hashtbl[hash >> 5] |= 1 << (hash & 0x1F);
+			}
+		} else {
+			/* Only receive packets with destination set to our mac address */
+			sc->sc_mac_csr &= ~(SMSC_MAC_CSR_MCPAS | SMSC_MAC_CSR_HPFILT);
+		}
+
+		if_maddr_runlock(ifp);
+		
+		/* Debug */
+		if (sc->sc_mac_csr & SMSC_MAC_CSR_HPFILT)
+			smsc_dbg_printf(sc, "receive select group of macs\n");
+		else
+			smsc_dbg_printf(sc, "receive own packets only\n");
+	}
+
+	/* Write the hash table and mac control registers */
+	smsc_write_reg(sc, SMSC_HASHH, hashtbl[1]);
+	smsc_write_reg(sc, SMSC_HASHL, hashtbl[0]);
+	smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+}
+
+
+/**
+ *	smsc_setpromisc - Enables/disables promiscuous mode
+ *	@ue: usb ethernet device context
+ *
+ *	LOCKING:
+ *	Should be called with the SMSC lock held.
+ */
+static void
+smsc_setpromisc(struct usb_ether *ue)
+{
+	struct smsc_softc *sc = uether_getsc(ue);
+	struct ifnet *ifp = uether_getifp(ue);
+
+	smsc_dbg_printf(sc, "promiscuous mode %sabled\n",
+	                (ifp->if_flags & IFF_PROMISC) ? "en" : "dis");
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	if (ifp->if_flags & IFF_PROMISC)
+		sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS;
+	else
+		sc->sc_mac_csr &= ~SMSC_MAC_CSR_PRMS;
+
+	smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+}
+
+
+/**
+ *	smsc_sethwcsum - Enable or disable H/W UDP and TCP checksumming
+ *	@sc: driver soft context
+ *
+ *	LOCKING:
+ *	Should be called with the SMSC lock held.
+ *
+ *	RETURNS:
+ *	Returns 0 on success or a negative error code.
+ */
+static int smsc_sethwcsum(struct smsc_softc *sc)
+{
+	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+	uint32_t val;
+	int err;
+
+	if (!ifp)
+		return (-EIO);
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	err = smsc_read_reg(sc, SMSC_COE_CTRL, &val);
+	if (err != 0) {
+		smsc_warn_printf(sc, "failed to read SMSC_COE_CTRL (err=%d)\n", err);
+		return (err);
+	}
+
+	/* Enable/disable the Rx checksum */
+	if ((ifp->if_capabilities & ifp->if_capenable) & IFCAP_RXCSUM)
+		val |= SMSC_COE_CTRL_RX_EN;
+	else
+		val &= ~SMSC_COE_CTRL_RX_EN;
+
+	/* Enable/disable the Tx checksum (currently not supported) */
+	if ((ifp->if_capabilities & ifp->if_capenable) & IFCAP_TXCSUM)
+		val |= SMSC_COE_CTRL_TX_EN;
+	else
+		val &= ~SMSC_COE_CTRL_TX_EN;
+
+	err = smsc_write_reg(sc, SMSC_COE_CTRL, val);
+	if (err != 0) {
+		smsc_warn_printf(sc, "failed to write SMSC_COE_CTRL (err=%d)\n", err);
+		return (err);
+	}
+
+	return (0);
+}
+
+
+/**
+ *	smsc_setmacaddress - Sets the mac address in the device
+ *	@sc: driver soft context
+ *	@addr: pointer to array contain at least 6 bytes of the mac
+ *
+ *	Writes the MAC address into the device, usually the MAC is programmed with
+ *	values from the EEPROM.
+ *
+ *	LOCKING:
+ *	Should be called with the SMSC lock held.
+ *
+ *	RETURNS:
+ *	Returns 0 on success or a negative error code.
+ */
+static int
+smsc_setmacaddress(struct smsc_softc *sc, const uint8_t *addr)
+{
+	int err;
+	uint32_t val;
+
+	smsc_dbg_printf(sc, "setting mac address to %02x:%02x:%02x:%02x:%02x:%02x\n",
+	                addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	val = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
+	if ((err = smsc_write_reg(sc, SMSC_MAC_ADDRL, val)) != 0)
+		goto done;
+		
+	val = (addr[5] << 8) | addr[4];
+	err = smsc_write_reg(sc, SMSC_MAC_ADDRH, val);
+	
+done:
+	return (err);
+}
+
+/**
+ *	smsc_reset - Reset the SMSC chip
+ *	@sc: device soft context
+ *
+ *	LOCKING:
+ *	Should be called with the SMSC lock held.
+ */
+static void
+smsc_reset(struct smsc_softc *sc)
+{
+	struct usb_config_descriptor *cd;
+	usb_error_t err;
+
+	cd = usbd_get_config_descriptor(sc->sc_ue.ue_udev);
+
+	err = usbd_req_set_config(sc->sc_ue.ue_udev, &sc->sc_mtx,
+	                          cd->bConfigurationValue);
+	if (err)
+		smsc_warn_printf(sc, "reset failed (ignored)\n");
+
+	/* Wait a little while for the chip to get its brains in order. */
+	uether_pause(&sc->sc_ue, hz / 100);
+
+	/* Reinitialize controller to achieve full reset. */
+	smsc_chip_init(sc);
+}
+
+
+/**
+ *	smsc_init - Initialises the LAN95xx chip
+ *	@ue: USB ether interface
+ *
+ *	Called when the interface is brought up (i.e. ifconfig ue0 up), this
+ *	initialise the interface and the rx/tx pipes.
+ *
+ *	LOCKING:
+ *	Should be called with the SMSC lock held.
+ */
+static void
+smsc_init(struct usb_ether *ue)
+{
+	struct smsc_softc *sc = uether_getsc(ue);
+	struct ifnet *ifp = uether_getifp(ue);
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+		return;
+
+	/* Cancel pending I/O */
+	smsc_stop(ue);
+
+#if __FreeBSD_version <= 1000000
+	/* On earlier versions this was the first place we could tell the system
+	 * that we supported h/w csuming, however this is only called after the
+	 * the interface has been brought up - not ideal.  
+	 */
+	if (!(ifp->if_capabilities & IFCAP_RXCSUM)) {
+		ifp->if_capabilities |= IFCAP_RXCSUM;
+		ifp->if_capenable |= IFCAP_RXCSUM;
+		ifp->if_hwassist = 0;
+	}
+	
+	/* TX checksuming is disabled for now
+	ifp->if_capabilities |= IFCAP_TXCSUM;
+	ifp->if_capenable |= IFCAP_TXCSUM;
+	ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
+	*/
+#endif
+
+	/* Reset the ethernet interface. */
+	smsc_reset(sc);
+
+	/* Load the multicast filter. */
+	smsc_setmulti(ue);
+
+	/* TCP/UDP checksum offload engines. */
+	smsc_sethwcsum(sc);
+
+	usbd_xfer_set_stall(sc->sc_xfer[SMSC_BULK_DT_WR]);
+
+	/* Indicate we are up and running. */
+	ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+	/* Switch to selected media. */
+	smsc_ifmedia_upd(ifp);
+	smsc_start(ue);
+}
+
+/**
+ *	smsc_bulk_read_callback - Read callback used to process the USB URB
+ *	@xfer: the USB transfer
+ *	@error: 
+ *
+ *	Reads the URB data which can contain one or more ethernet frames, the
+ *	frames are copyed into a mbuf and given to the system.
+ *
+ *	LOCKING:
+ *	No locking required, doesn't access internal driver settings.
+ */
+static void
+smsc_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	struct smsc_softc *sc = usbd_xfer_softc(xfer);
+	struct usb_ether *ue = &sc->sc_ue;
+	struct ifnet *ifp = uether_getifp(ue);
+	struct mbuf *m;
+	struct usb_page_cache *pc;
+	uint32_t rxhdr;
+	uint16_t pktlen;
+	int off;
+	int actlen;
+
+	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+	smsc_dbg_printf(sc, "rx : actlen %d\n", actlen);
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+	
+		/* There is always a zero length frame after bringing the IF up */
+		if (actlen < (sizeof(rxhdr) + ETHER_CRC_LEN))
+			goto tr_setup;
+
+		/* There maybe multiple packets in the USB frame, each will have a 
+		 * header and each needs to have it's own mbuf allocated and populated
+		 * for it.
+		 */
+		pc = usbd_xfer_get_frame(xfer, 0);
+		off = 0;
+		
+		while (off < actlen) {
+		
+			/* The frame header is always aligned on a 4 byte boundary */
+			off = ((off + 0x3) & ~0x3);
+
+			usbd_copy_out(pc, off, &rxhdr, sizeof(rxhdr));
+			off += (sizeof(rxhdr) + ETHER_ALIGN);
+			rxhdr = le32toh(rxhdr);
+		
+			pktlen = (uint16_t)SMSC_RX_STAT_FRM_LENGTH(rxhdr);
+			
+			smsc_dbg_printf(sc, "rx : rxhdr 0x%08x : pktlen %d : actlen %d : "
+			                "off %d\n", rxhdr, pktlen, actlen, off);
+
+			
+			if (rxhdr & SMSC_RX_STAT_ERROR) {
+				smsc_dbg_printf(sc, "rx error (hdr 0x%08x)\n", rxhdr);
+				ifp->if_ierrors++;
+				if (rxhdr & SMSC_RX_STAT_COLLISION)
+					ifp->if_collisions++;
+			} else {
+
+				/* Check if the ethernet frame is too big or too small */
+				if ((pktlen < ETHER_HDR_LEN) || (pktlen > (actlen - off)))
+					goto tr_setup;
+			
+				/* Create a new mbuf to store the packet in */
+				m = uether_newbuf();
+				if (m == NULL) {
+					smsc_warn_printf(sc, "failed to create new mbuf\n");
+					ifp->if_iqdrops++;
+					goto tr_setup;
+				}
+				
+				usbd_copy_out(pc, off, mtod(m, uint8_t *), pktlen);
+
+				/* Check if RX TCP/UDP checksumming is being offloaded */
+				if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
+				
+					/* Remove the extra 2 bytes of the csum */
+					pktlen -= 2;
+
+					/* The checksum appears to be simplistically calculated
+					 * over the udp/tcp header and data up to the end of the
+					 * eth frame.  Which means if the eth frame is padded
+					 * the csum calculation is incorrectly performed over
+					 * the padding bytes as well. Therefore to be safe we
+					 * ignore the H/W csum on frames less than or equal to
+					 * 64 bytes.
+					 */
+					if (pktlen > ETHER_MIN_LEN) {
+					
+						/* Indicate the UDP/TCP csum has been calculated */
+						m->m_pkthdr.csum_flags |= CSUM_DATA_VALID;
+										 
+						/* Copy the TCP/UDP checksum from the last 2 bytes
+						 * of the transfer and put in the csum_data field.
+						 */
+						usbd_copy_out(pc, (off + pktlen),
+									  &m->m_pkthdr.csum_data, 2);
+					
+						/* The data is copied in network order, but the
+						 * csum algorithm in the kernel expects it to be
+						 * in host network order.
+						 */
+						m->m_pkthdr.csum_data = ntohs(m->m_pkthdr.csum_data);
+					
+						smsc_dbg_printf(sc, "RX checksum offloaded (0x%04x)\n",
+										m->m_pkthdr.csum_data);
+					}
+					
+					/* Need to adjust the offset as well or we'll be off
+					 * by 2 because the csum is removed from the packet
+					 * length.
+					 */
+					off += 2;
+				}
+			
+				/* Finally enqueue the mbuf on the receive queue */
+				uether_rxmbuf(ue, m, pktlen);
+			}
+
+			/* Update the offset to move to the next potential packet */
+			off += pktlen;
+		}
+	
+		/* FALLTHROUGH */
+		
+	case USB_ST_SETUP:
+tr_setup:
+		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+		usbd_transfer_submit(xfer);
+		uether_rxflush(ue);
+		return;
+
+	default:
+		if (error != USB_ERR_CANCELLED) {
+			smsc_warn_printf(sc, "bulk read error, %s\n", usbd_errstr(error));
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
+		}
+		return;
+	}
+}
+
+/**
+ *	smsc_bulk_write_callback - Write callback used to send ethernet frame(s)
+ *	@xfer: the USB transfer
+ *	@error: error code if the transfers is in an errored state
+ *
+ *	The main write function that pulls ethernet frames off the queue and sends
+ *	them out.
+ *
+ *	LOCKING:
+ *	
+ */
+static void
+smsc_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	struct smsc_softc *sc = usbd_xfer_softc(xfer);
+	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+	struct usb_page_cache *pc;
+	struct mbuf *m;
+	uint32_t txhdr;
+	uint32_t frm_len = 0;
+	int nframes;
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+		/* FALLTHROUGH */
+
+	case USB_ST_SETUP:
+tr_setup:
+		if ((sc->sc_flags & SMSC_FLAG_LINK) == 0 ||
+			(ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) {
+			/* Don't send anything if there is no link or controller is busy. */
+			return;
+		}
+
+		for (nframes = 0; nframes < 16 &&
+		    !IFQ_DRV_IS_EMPTY(&ifp->if_snd); nframes++) {
+			IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+			if (m == NULL)
+				break;
+			usbd_xfer_set_frame_offset(xfer, nframes * MCLBYTES,
+			    nframes);
+			frm_len = 0;
+			pc = usbd_xfer_get_frame(xfer, nframes);
+
+			/* Each frame is prefixed with two 32-bit values describing the
+			 * length of the packet and buffer.
+			 */
+			txhdr = SMSC_TX_CTRL_0_BUF_SIZE(m->m_pkthdr.len) | 
+					SMSC_TX_CTRL_0_FIRST_SEG | SMSC_TX_CTRL_0_LAST_SEG;
+			txhdr = htole32(txhdr);
+			usbd_copy_in(pc, 0, &txhdr, sizeof(txhdr));
+			
+			txhdr = SMSC_TX_CTRL_1_PKT_LENGTH(m->m_pkthdr.len);
+			txhdr = htole32(txhdr);
+			usbd_copy_in(pc, 4, &txhdr, sizeof(txhdr));
+			
+			frm_len += 8;
+
+			/* Next copy in the actual packet */
+			usbd_m_copy_in(pc, frm_len, m, 0, m->m_pkthdr.len);
+			frm_len += m->m_pkthdr.len;
+
+			ifp->if_opackets++;
+
+			/* If there's a BPF listener, bounce a copy of this frame to him */
+			BPF_MTAP(ifp, m);
+
+			m_freem(m);
+
+			/* Set frame length. */
+			usbd_xfer_set_frame_len(xfer, nframes, frm_len);
+		}
+		if (nframes != 0) {
+			usbd_xfer_set_frames(xfer, nframes);
+			usbd_transfer_submit(xfer);
+			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+		}
+		return;
+
+	default:
+		ifp->if_oerrors++;
+		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+		
+		if (error != USB_ERR_CANCELLED) {
+			smsc_err_printf(sc, "usb error on tx: %s\n", usbd_errstr(error));
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
+		}
+		return;
+	}
+}
+
+/**
+ *	smsc_tick - Called periodically to monitor the state of the LAN95xx chip
+ *	@ue: USB ether interface
+ *
+ *	Simply calls the mii status functions to check the state of the link.
+ *
+ *	LOCKING:
+ *	Should be called with the SMSC lock held.
+ */
+static void
+smsc_tick(struct usb_ether *ue)
+{
+	struct smsc_softc *sc = uether_getsc(ue);
+	struct mii_data *mii = uether_getmii(&sc->sc_ue);;
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	mii_tick(mii);
+	if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) {
+		smsc_miibus_statchg(ue->ue_dev);
+		if ((sc->sc_flags & SMSC_FLAG_LINK) != 0)
+			smsc_start(ue);
+	}
+}
+
+/**
+ *	smsc_start - Starts communication with the LAN95xx chip
+ *	@ue: USB ether interface
+ *
+ *	
+ *
+ */
+static void
+smsc_start(struct usb_ether *ue)
+{
+	struct smsc_softc *sc = uether_getsc(ue);
+
+	/*
+	 * start the USB transfers, if not already started:
+	 */
+	usbd_transfer_start(sc->sc_xfer[SMSC_BULK_DT_RD]);
+	usbd_transfer_start(sc->sc_xfer[SMSC_BULK_DT_WR]);
+}
+
+/**
+ *	smsc_stop - Stops communication with the LAN95xx chip
+ *	@ue: USB ether interface
+ *
+ *	
+ *
+ */
+static void
+smsc_stop(struct usb_ether *ue)
+{
+	struct smsc_softc *sc = uether_getsc(ue);
+	struct ifnet *ifp = uether_getifp(ue);
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+	sc->sc_flags &= ~SMSC_FLAG_LINK;
+
+	/*
+	 * stop all the transfers, if not already stopped:
+	 */
+	usbd_transfer_stop(sc->sc_xfer[SMSC_BULK_DT_WR]);
+	usbd_transfer_stop(sc->sc_xfer[SMSC_BULK_DT_RD]);
+}
+
+/**
+ *	smsc_phy_init - Initialises the in-built SMSC phy
+ *	@sc: driver soft context
+ *
+ *	Resets the PHY part of the chip and then initialises it to default
+ *	values.  The 'link down' and 'auto-negotiation complete' interrupts
+ *	from the PHY are also enabled, however we don't monitor the interrupt
+ *	endpoints for the moment.
+ *
+ *	RETURNS:
+ *	Returns 0 on success or EIO if failed to reset the PHY.
+ */
+static int
+smsc_phy_init(struct smsc_softc *sc)
+{
+	int bmcr;
+	usb_ticks_t start_ticks;
+	usb_ticks_t max_ticks = USB_MS_TO_TICKS(1000);
+
+	SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+	/* Reset phy and wait for reset to complete */
+	smsc_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR, BMCR_RESET);
+
+	start_ticks = ticks;
+	do {
+		uether_pause(&sc->sc_ue, hz / 100);
+		bmcr = smsc_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR);
+	} while ((bmcr & MII_BMCR) && ((ticks - start_ticks) < max_ticks));
+
+	if ((ticks - start_ticks) >= max_ticks) {
+		smsc_err_printf(sc, "PHY reset timed-out");
+		return (EIO);
+	}
+
+	smsc_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_ANAR,
+	                     ANAR_10 | ANAR_10_FD | ANAR_TX | ANAR_TX_FD |  /* all modes */
+	                     ANAR_CSMA | 
+	                     ANAR_FC |
+	                     ANAR_PAUSE_ASYM);
+
+	/* Setup the phy to interrupt when the link goes down or autoneg completes */
+	smsc_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, SMSC_PHY_INTR_STAT);
+	smsc_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, SMSC_PHY_INTR_MASK,
+	                     (SMSC_PHY_INTR_ANEG_COMP | SMSC_PHY_INTR_LINK_DOWN));
+	
+	/* Restart auto-negotation */
+	bmcr = smsc_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR);
+	bmcr |= BMCR_STARTNEG;
+	smsc_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR, bmcr);
+	
+	return (0);
+}
+
+
+/**
+ *	smsc_chip_init - Initialises the chip after power on
+ *	@sc: driver soft context
+ *
+ *	This initialisation sequence is modelled on the procedure in the Linux
+ *	driver.
+ *
+ *	RETURNS:
+ *	Returns 0 on success or an error code on failure.
+ */
+static int
+smsc_chip_init(struct smsc_softc *sc)
+{
+	int err;
+	int locked;
+	uint32_t reg_val;
+	int burst_cap;
+
+	locked = mtx_owned(&sc->sc_mtx);
+	if (!locked)
+		SMSC_LOCK(sc);
+
+	/* Enter H/W config mode */
+	smsc_write_reg(sc, SMSC_HW_CFG, SMSC_HW_CFG_LRST);
+
+	if ((err = smsc_wait_for_bits(sc, SMSC_HW_CFG, SMSC_HW_CFG_LRST)) != 0) {
+		smsc_warn_printf(sc, "timed-out waiting for reset to complete\n");
+		goto init_failed;
+	}
+
+	/* Reset the PHY */
+	smsc_write_reg(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST);
+
+	if ((err = smsc_wait_for_bits(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST) != 0)) {
+		smsc_warn_printf(sc, "timed-out waiting for phy reset to complete\n");
+		goto init_failed;
+	}
+
+	/* Set the mac address */
+	if ((err = smsc_setmacaddress(sc, sc->sc_ue.ue_eaddr)) != 0) {
+		smsc_warn_printf(sc, "failed to set the MAC address\n");
+		goto init_failed;
+	}
+
+	/* Don't know what the HW_CFG_BIR bit is, but following the reset sequence
+	 * as used in the Linux driver.
+	 */
+	if ((err = smsc_read_reg(sc, SMSC_HW_CFG, &reg_val)) != 0) {
+		smsc_warn_printf(sc, "failed to read HW_CFG: %d\n", err);
+		goto init_failed;
+	}
+	reg_val |= SMSC_HW_CFG_BIR;
+	smsc_write_reg(sc, SMSC_HW_CFG, reg_val);
+
+	/* There is a so called 'turbo mode' that the linux driver supports, it
+	 * seems to allow you to jam multiple frames per Rx transaction.  By default
+	 * this driver supports that and therefore allows multiple frames per URB.
+	 *
+	 * The xfer buffer size needs to reflect this as well, therefore based on
+	 * the calculations in the Linux driver the RX bufsize is set to 18944,
+	 *     bufsz = (16 * 1024 + 5 * 512)
+	 *
+	 * Burst capability is the number of URBs that can be in a burst of data/
+	 * ethernet frames.
+	 */
+	if (usbd_get_speed(sc->sc_ue.ue_udev) == USB_SPEED_HIGH)
+		burst_cap = 37;
+	else
+		burst_cap = 128;
+
+	smsc_write_reg(sc, SMSC_BURST_CAP, burst_cap);
+
+	/* Set the default bulk in delay (magic value from Linux driver) */
+	smsc_write_reg(sc, SMSC_BULK_IN_DLY, 0x00002000);
+
+
+
+	/*
+	 * Initialise the RX interface
+	 */
+	if ((err = smsc_read_reg(sc, SMSC_HW_CFG, &reg_val)) < 0) {
+		smsc_warn_printf(sc, "failed to read HW_CFG: (err = %d)\n", err);
+		goto init_failed;
+	}
+
+	/* Adjust the packet offset in the buffer (designed to try and align IP
+	 * header on 4 byte boundary)
+	 */
+	reg_val &= ~SMSC_HW_CFG_RXDOFF;
+	reg_val |= (ETHER_ALIGN << 9) & SMSC_HW_CFG_RXDOFF;
+	
+	/* The following setings are used for 'turbo mode', a.k.a multiple frames
+	 * per Rx transaction (again info taken form Linux driver).
+	 */
+	reg_val |= (SMSC_HW_CFG_MEF | SMSC_HW_CFG_BCE);
+
+	smsc_write_reg(sc, SMSC_HW_CFG, reg_val);
+
+	/* Clear the status register ? */
+	smsc_write_reg(sc, SMSC_INTR_STATUS, 0xffffffff);
+
+	/* Read and display the revision register */
+	if ((err = smsc_read_reg(sc, SMSC_ID_REV, &sc->sc_rev_id)) < 0) {
+		smsc_warn_printf(sc, "failed to read ID_REV (err = %d)\n", err);
+		goto init_failed;
+	}
+
+	device_printf(sc->sc_ue.ue_dev, "chip 0x%04lx, rev. %04lx\n", 
+	    (sc->sc_rev_id & SMSC_ID_REV_CHIP_ID_MASK) >> 16, 
+	    (sc->sc_rev_id & SMSC_ID_REV_CHIP_REV_MASK));
+
+	/* GPIO/LED setup */
+	reg_val = SMSC_LED_GPIO_CFG_SPD_LED | SMSC_LED_GPIO_CFG_LNK_LED | 
+	          SMSC_LED_GPIO_CFG_FDX_LED;
+	smsc_write_reg(sc, SMSC_LED_GPIO_CFG, reg_val);
+
+	/*
+	 * Initialise the TX interface
+	 */
+	smsc_write_reg(sc, SMSC_FLOW, 0);
+
+	smsc_write_reg(sc, SMSC_AFC_CFG, AFC_CFG_DEFAULT);
+
+	/* Read the current MAC configuration */
+	if ((err = smsc_read_reg(sc, SMSC_MAC_CSR, &sc->sc_mac_csr)) < 0) {
+		smsc_warn_printf(sc, "failed to read MAC_CSR (err=%d)\n", err);
+		goto init_failed;
+	}
+	
+	/* Vlan */
+	smsc_write_reg(sc, SMSC_VLAN1, (uint32_t)ETHERTYPE_VLAN);
+
+	/*
+	 * Initialise the PHY
+	 */
+	if ((err = smsc_phy_init(sc)) != 0)
+		goto init_failed;
+
+
+	/*
+	 * Start TX
+	 */
+	sc->sc_mac_csr |= SMSC_MAC_CSR_TXEN;
+	smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+	smsc_write_reg(sc, SMSC_TX_CFG, SMSC_TX_CFG_ON);
+
+	/*
+	 * Start RX
+	 */
+	sc->sc_mac_csr |= SMSC_MAC_CSR_RXEN;
+	smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+
+	if (!locked)
+		SMSC_UNLOCK(sc);
+
+	return (0);
+	
+init_failed:
+	if (!locked)
+		SMSC_UNLOCK(sc);
+
+	smsc_err_printf(sc, "smsc_chip_init failed (err=%d)\n", err);
+	return (err);
+}
+
+
+/**
+ *	smsc_ioctl - ioctl function for the device
+ *	@ifp: interface pointer
+ *	@cmd: the ioctl command
+ *	@data: data passed in the ioctl call, typically a pointer to struct ifreq.
+ *	
+ *	The ioctl routine is overridden to detect change requests for the H/W
+ *	checksum capabilities.
+ *
+ *	RETURNS:
+ *	0 on success and an error code on failure.
+ */
+static int
+smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+	struct usb_ether *ue = ifp->if_softc;
+	struct smsc_softc *sc;
+	struct ifreq *ifr;
+	int rc;
+	int mask;
+	int reinit;
+	
+	if (cmd == SIOCSIFCAP) {
+
+		sc = uether_getsc(ue);
+		ifr = (struct ifreq *)data;
+
+		SMSC_LOCK(sc);
+
+		rc = 0;
+		reinit = 0;
+
+		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+
+		/* Modify the RX CSUM enable bits */
+		if ((mask & IFCAP_RXCSUM) != 0 &&
+		    (ifp->if_capabilities & IFCAP_RXCSUM) != 0) {
+			ifp->if_capenable ^= IFCAP_RXCSUM;
+			
+			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+				reinit = 1;
+			}
+		}
+		
+		SMSC_UNLOCK(sc);
+		if (reinit)
+#if __FreeBSD_version > 1000000
+			uether_init(ue);
+#else
+			ifp->if_init(ue);
+#endif
+
+	} else {
+		rc = uether_ioctl(ifp, cmd, data);
+	}
+
+	return (rc);
+}
+
+
+/**
+ *	smsc_attach_post - Called after the driver attached to the USB interface
+ *	@ue: the USB ethernet device
+ *
+ *	This is where the chip is intialised for the first time.  This is different
+ *	from the smsc_init() function in that that one is designed to setup the
+ *	H/W to match the UE settings and can be called after a reset.
+ *
+ *
+ */
+static void
+smsc_attach_post(struct usb_ether *ue)
+{
+	struct smsc_softc *sc = uether_getsc(ue);
+	uint32_t mac_h, mac_l;
+	int err;
+
+	smsc_dbg_printf(sc, "smsc_attach_post\n");
+
+	/* Setup some of the basics */
+	sc->sc_phyno = 1;
+
+
+	/* Attempt to get the mac address, if an EEPROM is not attached this
+	 * will just return FF:FF:FF:FF:FF:FF, so in such cases we invent a MAC
+	 * address based on urandom.
+	 */
+	memset(sc->sc_ue.ue_eaddr, 0xff, ETHER_ADDR_LEN);
+	
+	/* Check if there is already a MAC address in the register */
+	if ((smsc_read_reg(sc, SMSC_MAC_ADDRL, &mac_l) == 0) &&
+	    (smsc_read_reg(sc, SMSC_MAC_ADDRH, &mac_h) == 0)) {
+		sc->sc_ue.ue_eaddr[5] = (uint8_t)((mac_h >> 8) & 0xff);
+		sc->sc_ue.ue_eaddr[4] = (uint8_t)((mac_h) & 0xff);
+		sc->sc_ue.ue_eaddr[3] = (uint8_t)((mac_l >> 24) & 0xff);
+		sc->sc_ue.ue_eaddr[2] = (uint8_t)((mac_l >> 16) & 0xff);
+		sc->sc_ue.ue_eaddr[1] = (uint8_t)((mac_l >> 8) & 0xff);
+		sc->sc_ue.ue_eaddr[0] = (uint8_t)((mac_l) & 0xff);
+	}
+	
+	/* MAC address is not set so try to read from EEPROM, if that fails generate
+	 * a random MAC address.
+	 */
+	if (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr)) {
+
+		err = smsc_eeprom_read(sc, 0x01, sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
+		if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr))) {
+		
+			read_random(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
+			sc->sc_ue.ue_eaddr[0] &= ~0x01;     /* unicast */
+			sc->sc_ue.ue_eaddr[0] |=  0x02;     /* locally administered */
+		}
+	}
+	
+	/* Initialise the chip for the first time */
+	smsc_chip_init(sc);
+}
+
+
+/**
+ *	smsc_attach_post_sub - Called after the driver attached to the USB interface
+ *	@ue: the USB ethernet device
+ *
+ *	Most of this is boilerplate code and copied from the base USB ethernet
+ *	driver.  It has been overriden so that we can indicate to the system that
+ *	the chip supports H/W checksumming.
+ *
+ *	RETURNS:
+ *	Returns 0 on success or a negative error code.
+ */
+#if __FreeBSD_version > 1000000
+static int
+smsc_attach_post_sub(struct usb_ether *ue)
+{
+	struct smsc_softc *sc;
+	struct ifnet *ifp;
+	int error;
+
+	sc = uether_getsc(ue);
+	ifp = ue->ue_ifp;
+	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	ifp->if_start = uether_start;
+	ifp->if_ioctl = smsc_ioctl;
+	ifp->if_init = uether_init;
+	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+	IFQ_SET_READY(&ifp->if_snd);
+
+	/* The chip supports TCP/UDP checksum offloading on TX and RX paths, however
+	 * currently only RX checksum is supported in the driver (see top of file).
+	 */
+	ifp->if_capabilities |= IFCAP_RXCSUM;
+	ifp->if_hwassist = 0;
+	
+	/* TX checksuming is disabled (for now?)
+	ifp->if_capabilities |= IFCAP_TXCSUM;
+	ifp->if_capenable |= IFCAP_TXCSUM;
+	ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
+	*/
+
+	ifp->if_capenable = ifp->if_capabilities;
+
+	mtx_lock(&Giant);
+	error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
+	    uether_ifmedia_upd, ue->ue_methods->ue_mii_sts,
+	    BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, 0);
+	mtx_unlock(&Giant);
+
+	return (error);
+}
+#endif /* __FreeBSD_version > 1000000 */
+
+
+/**
+ *	smsc_probe - Probe the interface. 
+ *	@dev: smsc device handle
+ *
+ *	Checks if the device is a match for this driver.
+ *
+ *	RETURNS:
+ *	Returns 0 on success or an error code on failure.
+ */
+static int
+smsc_probe(device_t dev)
+{
+	struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+	if (uaa->usb_mode != USB_MODE_HOST)
+		return (ENXIO);
+	if (uaa->info.bConfigIndex != SMSC_CONFIG_INDEX)
+		return (ENXIO);
+	if (uaa->info.bIfaceIndex != SMSC_IFACE_IDX)
+		return (ENXIO);
+
+	return (usbd_lookup_id_by_uaa(smsc_devs, sizeof(smsc_devs), uaa));
+}
+
+
+/**
+ *	smsc_attach - Attach the interface. 
+ *	@dev: smsc device handle
+ *
+ *	Allocate softc structures, do ifmedia setup and ethernet/BPF attach.
+ *
+ *	RETURNS:
+ *	Returns 0 on success or a negative error code.
+ */
+static int
+smsc_attach(device_t dev)
+{
+	struct usb_attach_arg *uaa = device_get_ivars(dev);
+	struct smsc_softc *sc = device_get_softc(dev);
+	struct usb_ether *ue = &sc->sc_ue;
+	uint8_t iface_index;
+	int err;
+
+	sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
+
+	device_set_usb_desc(dev);
+
+	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+	/* Setup the endpoints for the SMSC LAN95xx device(s) */
+	iface_index = SMSC_IFACE_IDX;
+	err = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
+	                          smsc_config, SMSC_N_TRANSFER, sc, &sc->sc_mtx);
+	if (err) {
+		device_printf(dev, "error: allocating USB transfers failed\n");
+		goto detach;
+	}
+
+	ue->ue_sc = sc;
+	ue->ue_dev = dev;
+	ue->ue_udev = uaa->device;
+	ue->ue_mtx = &sc->sc_mtx;
+	ue->ue_methods = &smsc_ue_methods;
+
+	err = uether_ifattach(ue);
+	if (err) {
+		device_printf(dev, "error: could not attach interface\n");
+		goto detach;
+	}
+	return (0);			/* success */
+
+detach:
+	smsc_detach(dev);
+	return (ENXIO);		/* failure */
+}
+
+/**
+ *	smsc_detach - Detach the interface. 
+ *	@dev: smsc device handle
+ *
+ *	RETURNS:
+ *	Returns 0.
+ */
+static int
+smsc_detach(device_t dev)
+{
+	struct smsc_softc *sc = device_get_softc(dev);
+	struct usb_ether *ue = &sc->sc_ue;
+
+	usbd_transfer_unsetup(sc->sc_xfer, SMSC_N_TRANSFER);
+	uether_ifdetach(ue);
+	mtx_destroy(&sc->sc_mtx);
+
+	return (0);
+}
+
+static device_method_t smsc_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, smsc_probe),
+	DEVMETHOD(device_attach, smsc_attach),
+	DEVMETHOD(device_detach, smsc_detach),
+
+	/* bus interface */
+	DEVMETHOD(bus_print_child, bus_generic_print_child),
+	DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+	/* MII interface */
+	DEVMETHOD(miibus_readreg, smsc_miibus_readreg),
+	DEVMETHOD(miibus_writereg, smsc_miibus_writereg),
+	DEVMETHOD(miibus_statchg, smsc_miibus_statchg),
+
+	{0, 0}
+};
+
+static driver_t smsc_driver = {
+	.name = "smsc",
+	.methods = smsc_methods,
+	.size = sizeof(struct smsc_softc),
+};
+
+static devclass_t smsc_devclass;
+
+DRIVER_MODULE(smsc, uhub, smsc_driver, smsc_devclass, NULL, 0);
+DRIVER_MODULE(miibus, smsc, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(smsc, uether, 1, 1, 1);
+MODULE_DEPEND(smsc, usb, 1, 1, 1);
+MODULE_DEPEND(smsc, ether, 1, 1, 1);
+MODULE_DEPEND(smsc, miibus, 1, 1, 1);
+MODULE_VERSION(smsc, 1);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/net/if_smscreg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/usb/net/if_smscreg.h	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,277 @@
+/*-
+ * Copyright (c) 2012
+ *	Ben Gray <bgray at freebsd.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/sys/dev/usb/net/if_smscreg.h 239275 2012-08-15 04:03:55Z gonzo $
+ */
+#ifndef _IF_SMSCREG_H_
+#define _IF_SMSCREG_H_
+
+/*
+ * Definitions for the SMSC LAN9514 and LAN9514 USB to ethernet controllers.
+ *
+ * This information was gleaned from the SMSC driver in the linux kernel, where
+ * it is Copyrighted (C) 2007-2008 SMSC.
+ *
+ */
+
+/**
+ * TRANSMIT FRAMES
+ * ---------------
+ *   Tx frames are prefixed with an 8-byte header which describes the frame
+ *
+ *         4 bytes      4 bytes           variable
+ *      +------------+------------+--- . . . . . . . . . . . . ---+
+ *      | TX_CTRL_0  | TX_CTRL_1  |  Ethernet frame data          |
+ *      +------------+------------+--- . . . . . . . . . . . . ---+
+ *
+ *   Where the headers have the following fields:
+ *
+ *      TX_CTRL_0 <20:16>  Data offset
+ *      TX_CTRL_0 <13>     First segment of frame indicator
+ *      TX_CTRL_0 <12>     Last segment of frame indicator
+ *      TX_CTRL_0 <10:0>   Buffer size (?)
+ *
+ *      TX_CTRL_1 <14>     Perform H/W checksuming on IP packets 
+ *      TX_CTRL_1 <13>     Disable automatic ethernet CRC generation
+ *      TX_CTRL_1 <12>     Disable padding (?)
+ *      TX_CTRL_1 <10:0>   Packet byte length
+ *
+ */
+#define SMSC_TX_CTRL_0_OFFSET(x)         (((x) & 0x1FUL) << 16)
+#define SMSC_TX_CTRL_0_FIRST_SEG         (0x1UL << 13)
+#define SMSC_TX_CTRL_0_LAST_SEG          (0x1UL << 12)
+#define SMSC_TX_CTRL_0_BUF_SIZE(x)       ((x) & 0x000007FFUL)
+
+#define SMSC_TX_CTRL_1_CSUM_ENABLE       (0x1UL << 14)
+#define SMSC_TX_CTRL_1_CRC_DISABLE       (0x1UL << 13)
+#define SMSC_TX_CTRL_1_PADDING_DISABLE   (0x1UL << 12)
+#define SMSC_TX_CTRL_1_PKT_LENGTH(x)     ((x) & 0x000007FFUL)
+
+/**
+ * RECEIVE FRAMES
+ * --------------
+ *   Rx frames are prefixed with an 4-byte status header which describes any
+ *   errors with the frame as well as things like the length
+ *
+ *         4 bytes             variable
+ *      +------------+--- . . . . . . . . . . . . ---+
+ *      |   RX_STAT  |  Ethernet frame data          |
+ *      +------------+--- . . . . . . . . . . . . ---+
+ *
+ *   Where the status header has the following fields:
+ *
+ *      RX_STAT   <30>     Filter Fail
+ *      RX_STAT   <29:16>  Frame Length
+ *      RX_STAT   <15>     Error Summary
+ *      RX_STAT   <13>     Broadcast Frame
+ *      RX_STAT   <12>     Length Error
+ *      RX_STAT   <11>     Runt Frame
+ *      RX_STAT   <10>     Multicast Frame
+ *      RX_STAT   <7>      Frame too long
+ *      RX_STAT   <6>      Collision Seen
+ *      RX_STAT   <5>      Frame Type
+ *      RX_STAT   <4>      Receive Watchdog
+ *      RX_STAT   <3>      Mii Error
+ *      RX_STAT   <2>      Dribbling
+ *      RX_STAT   <1>      CRC Error
+ *
+ */
+#define SMSC_RX_STAT_FILTER_FAIL         (0x1UL << 30)
+#define SMSC_RX_STAT_FRM_LENGTH(x)       (((x) >> 16) & 0x3FFFUL)
+#define SMSC_RX_STAT_ERROR               (0x1UL << 15)
+#define SMSC_RX_STAT_BROADCAST           (0x1UL << 13)
+#define SMSC_RX_STAT_LENGTH_ERROR        (0x1UL << 12)
+#define SMSC_RX_STAT_RUNT                (0x1UL << 11)
+#define SMSC_RX_STAT_MULTICAST           (0x1UL << 10)
+#define SMSC_RX_STAT_FRM_TO_LONG         (0x1UL << 7)
+#define SMSC_RX_STAT_COLLISION           (0x1UL << 6)
+#define SMSC_RX_STAT_FRM_TYPE            (0x1UL << 5)
+#define SMSC_RX_STAT_WATCHDOG            (0x1UL << 4)
+#define SMSC_RX_STAT_MII_ERROR           (0x1UL << 3)
+#define SMSC_RX_STAT_DRIBBLING           (0x1UL << 2)
+#define SMSC_RX_STAT_CRC_ERROR           (0x1UL << 1)
+
+/**
+ * REGISTERS
+ *
+ */
+#define SMSC_ID_REV                 0x000
+#define SMSC_INTR_STATUS            0x008
+#define SMSC_RX_CFG                 0x00C
+#define SMSC_TX_CFG                 0x010
+#define SMSC_HW_CFG                 0x014
+#define SMSC_PM_CTRL                0x020
+#define SMSC_LED_GPIO_CFG           0x024
+#define SMSC_GPIO_CFG               0x028
+#define SMSC_AFC_CFG                0x02C
+#define SMSC_EEPROM_CMD             0x030
+#define SMSC_EEPROM_DATA            0x034
+#define SMSC_BURST_CAP              0x038
+#define SMSC_GPIO_WAKE              0x064
+#define SMSC_INTR_CFG               0x068
+#define SMSC_BULK_IN_DLY            0x06C
+#define SMSC_MAC_CSR                0x100
+#define SMSC_MAC_ADDRH              0x104
+#define SMSC_MAC_ADDRL              0x108
+#define SMSC_HASHH                  0x10C
+#define SMSC_HASHL                  0x110
+#define SMSC_MII_ADDR               0x114
+#define SMSC_MII_DATA               0x118
+#define SMSC_FLOW                   0x11C
+#define SMSC_VLAN1                  0x120
+#define SMSC_VLAN2                  0x124
+#define SMSC_WUFF                   0x128
+#define SMSC_WUCSR                  0x12C
+#define SMSC_COE_CTRL               0x130
+
+/* ID / Revision register */
+#define SMSC_ID_REV_CHIP_ID_MASK    0xFFFF0000UL
+#define SMSC_ID_REV_CHIP_REV_MASK   0x0000FFFFUL
+
+#define SMSC_RX_FIFO_FLUSH          (0x1UL << 0)
+
+#define SMSC_TX_CFG_ON              (0x1UL << 2)
+#define SMSC_TX_CFG_STOP            (0x1UL << 1)
+#define SMSC_TX_CFG_FIFO_FLUSH      (0x1UL << 0)
+
+#define SMSC_HW_CFG_BIR             (0x1UL << 12)
+#define SMSC_HW_CFG_LEDB            (0x1UL << 11)
+#define SMSC_HW_CFG_RXDOFF          (0x3UL << 9)    /* RX pkt alignment */
+#define SMSC_HW_CFG_DRP             (0x1UL << 6)
+#define SMSC_HW_CFG_MEF             (0x1UL << 5)
+#define SMSC_HW_CFG_LRST            (0x1UL << 3)    /* Lite reset */
+#define SMSC_HW_CFG_PSEL            (0x1UL << 2)
+#define SMSC_HW_CFG_BCE             (0x1UL << 1)
+#define SMSC_HW_CFG_SRST            (0x1UL << 0)
+
+#define SMSC_PM_CTRL_PHY_RST        (0x1UL << 4)    /* PHY reset */
+
+#define SMSC_LED_GPIO_CFG_SPD_LED   (0x1UL << 24)
+#define SMSC_LED_GPIO_CFG_LNK_LED   (0x1UL << 20)
+#define SMSC_LED_GPIO_CFG_FDX_LED   (0x1UL << 16)
+
+/* Hi watermark = 15.5Kb (~10 mtu pkts) */
+/* low watermark = 3k (~2 mtu pkts) */
+/* backpressure duration = ~ 350us */
+/* Apply FC on any frame. */
+#define AFC_CFG_DEFAULT             (0x00F830A1)
+
+#define SMSC_EEPROM_CMD_BUSY        (0x1UL << 31)
+#define SMSC_EEPROM_CMD_MASK        (0x7UL << 28)
+#define SMSC_EEPROM_CMD_READ        (0x0UL << 28)
+#define SMSC_EEPROM_CMD_WRITE       (0x3UL << 28)
+#define SMSC_EEPROM_CMD_ERASE       (0x5UL << 28)
+#define SMSC_EEPROM_CMD_RELOAD      (0x7UL << 28)
+#define SMSC_EEPROM_CMD_TIMEOUT     (0x1UL << 10)
+#define SMSC_EEPROM_CMD_ADDR_MASK   0x000001FFUL
+
+/* MAC Control and Status Register */
+#define SMSC_MAC_CSR_RCVOWN         (0x1UL << 23)  /* Half duplex */
+#define SMSC_MAC_CSR_LOOPBK         (0x1UL << 21)  /* Loopback */
+#define SMSC_MAC_CSR_FDPX           (0x1UL << 20)  /* Full duplex */
+#define SMSC_MAC_CSR_MCPAS          (0x1UL << 19)  /* Multicast mode */
+#define SMSC_MAC_CSR_PRMS           (0x1UL << 18)  /* Promiscuous mode */
+#define SMSC_MAC_CSR_INVFILT        (0x1UL << 17)  /* Inverse filtering */
+#define SMSC_MAC_CSR_PASSBAD        (0x1UL << 16)  /* Pass on bad frames */
+#define SMSC_MAC_CSR_HPFILT         (0x1UL << 13)  /* Hash filtering */
+#define SMSC_MAC_CSR_BCAST          (0x1UL << 11)  /* Broadcast */
+#define SMSC_MAC_CSR_TXEN           (0x1UL << 3)   /* TX enable */
+#define SMSC_MAC_CSR_RXEN           (0x1UL << 2)   /* RX enable */
+
+/* Interrupt control register */
+#define SMSC_INTR_NTEP              (0x1UL << 31) 
+#define SMSC_INTR_MACRTO            (0x1UL << 19)
+#define SMSC_INTR_TX_STOP           (0x1UL << 17)
+#define SMSC_INTR_RX_STOP           (0x1UL << 16)
+#define SMSC_INTR_PHY_INT           (0x1UL << 15)
+#define SMSC_INTR_TXE               (0x1UL << 14)
+#define SMSC_INTR_TDFU              (0x1UL << 13)
+#define SMSC_INTR_TDFO              (0x1UL << 12)
+#define SMSC_INTR_RXDF              (0x1UL << 11)
+#define SMSC_INTR_GPIOS             0x000007FFUL
+
+/* Phy MII interface register */
+#define SMSC_MII_WRITE              (0x1UL << 1)
+#define SMSC_MII_READ               (0x0UL << 1)
+#define SMSC_MII_BUSY               (0x1UL << 0)
+
+/* H/W checksum register */
+#define SMSC_COE_CTRL_TX_EN         (0x1UL << 16)  /* Tx H/W csum enable */
+#define SMSC_COE_CTRL_RX_MODE       (0x1UL << 1)
+#define SMSC_COE_CTRL_RX_EN         (0x1UL << 0)   /* Rx H/W csum enable */
+
+/* Registers on the phy, accessed via MII/MDIO */
+#define SMSC_PHY_INTR_STAT          (29)
+#define SMSC_PHY_INTR_MASK          (30)
+
+#define SMSC_PHY_INTR_ENERGY_ON     (0x1U << 7)
+#define SMSC_PHY_INTR_ANEG_COMP     (0x1U << 6)
+#define SMSC_PHY_INTR_REMOTE_FAULT  (0x1U << 5)
+#define SMSC_PHY_INTR_LINK_DOWN     (0x1U << 4)
+
+/* USB Vendor Requests */
+#define SMSC_UR_WRITE_REG   0xA0
+#define SMSC_UR_READ_REG    0xA1
+#define SMSC_UR_GET_STATS   0xA2
+
+#define	SMSC_CONFIG_INDEX	0	/* config number 1 */
+#define	SMSC_IFACE_IDX		0
+
+/*
+ * USB endpoints.
+ */
+enum {
+	SMSC_BULK_DT_RD,
+	SMSC_BULK_DT_WR,
+	/* the LAN9514 device does support interrupt endpoints, however I couldn't
+	 * get then to work reliably and since they are unneeded (poll the mii
+	 * status) they are unused.
+	 * SMSC_INTR_DT_WR,
+	 * SMSC_INTR_DT_RD,
+	 */
+	SMSC_N_TRANSFER,
+};
+
+struct smsc_softc {
+	struct usb_ether  sc_ue;
+	struct mtx        sc_mtx;
+	struct usb_xfer  *sc_xfer[SMSC_N_TRANSFER];
+	int               sc_phyno;
+
+	/* The following stores the settings in the mac control (MAC_CSR) register */
+	uint32_t          sc_mac_csr;
+	uint32_t          sc_rev_id;
+
+	uint32_t          sc_flags;
+#define	SMSC_FLAG_LINK      0x0001
+#define	SMSC_FLAG_LAN9514   0x1000	/* LAN9514 */
+};
+
+#define	SMSC_LOCK(_sc)             mtx_lock(&(_sc)->sc_mtx)
+#define	SMSC_UNLOCK(_sc)           mtx_unlock(&(_sc)->sc_mtx)
+#define	SMSC_LOCK_ASSERT(_sc, t)   mtx_assert(&(_sc)->sc_mtx, t)
+
+#endif  /* _IF_SMSCREG_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/net/if_usie.c
--- a/head/sys/dev/usb/net/if_usie.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/net/if_usie.c	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_usie.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_usie.c 239180 2012-08-10 15:29:41Z hselasky $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -95,7 +95,9 @@
 static device_probe_t usie_probe;
 static device_attach_t usie_attach;
 static device_detach_t usie_detach;
+static device_free_softc_t usie_free_softc;
 
+static void usie_free(struct ucom_softc *);
 static void usie_uc_update_line_state(struct ucom_softc *, uint8_t);
 static void usie_uc_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *);
 static void usie_uc_cfg_set_dtr(struct ucom_softc *, uint8_t);
@@ -189,7 +191,8 @@
 	DEVMETHOD(device_probe, usie_probe),
 	DEVMETHOD(device_attach, usie_attach),
 	DEVMETHOD(device_detach, usie_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, usie_free_softc),
+	DEVMETHOD_END
 };
 
 static driver_t usie_driver = {
@@ -216,6 +219,7 @@
 	.ucom_stop_read = &usie_uc_stop_read,
 	.ucom_start_write = &usie_uc_start_write,
 	.ucom_stop_write = &usie_uc_stop_write,
+	.ucom_free = &usie_free,
 };
 
 static void
@@ -298,6 +302,7 @@
 	sc->sc_dev = self;
 
 	mtx_init(&sc->sc_mtx, "usie", MTX_NETWORK_LOCK, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	TASK_INIT(&sc->sc_if_status_task, 0, usie_if_status_cb, sc);
 	TASK_INIT(&sc->sc_if_sync_task, 0, usie_if_sync_cb, sc);
@@ -482,11 +487,30 @@
 	for (x = 0; x != USIE_UCOM_MAX; x++)
 		usbd_transfer_unsetup(sc->sc_uc_xfer[x], USIE_UC_N_XFER);
 
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(usie);
+
+static void
+usie_free_softc(device_t dev, void *arg)
+{
+	struct usie_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+usie_free(struct ucom_softc *ucom)
+{
+	usie_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 usie_uc_update_line_state(struct ucom_softc *ucom, uint8_t ls)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/net/uhso.c
--- a/head/sys/dev/usb/net/uhso.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/net/uhso.c	Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
  *
  */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/net/uhso.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/net/uhso.c 239180 2012-08-10 15:29:41Z hselasky $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -455,6 +455,7 @@
 static int uhso_radio_sysctl(SYSCTL_HANDLER_ARGS);
 static int uhso_radio_ctrl(struct uhso_softc *, int);
 
+static void uhso_free(struct ucom_softc *);
 static void uhso_ucom_start_read(struct ucom_softc *);
 static void uhso_ucom_stop_read(struct ucom_softc *);
 static void uhso_ucom_start_write(struct ucom_softc *);
@@ -473,11 +474,13 @@
 static device_probe_t uhso_probe;
 static device_attach_t uhso_attach;
 static device_detach_t uhso_detach;
+static device_free_softc_t uhso_free_softc;
 
 static device_method_t uhso_methods[] = {
 	DEVMETHOD(device_probe,		uhso_probe),
 	DEVMETHOD(device_attach,	uhso_attach),
 	DEVMETHOD(device_detach,	uhso_detach),
+	DEVMETHOD(device_free_softc,	uhso_free_softc),
 	{ 0, 0 }
 };
 
@@ -500,7 +503,8 @@
 	.ucom_start_read = uhso_ucom_start_read,
 	.ucom_stop_read = uhso_ucom_stop_read,
 	.ucom_start_write = uhso_ucom_start_write,
-	.ucom_stop_write = uhso_ucom_stop_write
+	.ucom_stop_write = uhso_ucom_stop_write,
+	.ucom_free = &uhso_free,
 };
 
 static int
@@ -552,6 +556,7 @@
 	sc->sc_dev = self;
 	sc->sc_udev = uaa->device;
 	mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_ucom = NULL;
 	sc->sc_ttys = 0;
@@ -692,10 +697,29 @@
 		usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX);
 	}
 
-	mtx_destroy(&sc->sc_mtx);
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(uhso);
+
+static void
+uhso_free_softc(device_t dev, void *arg)
+{
+	struct uhso_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+uhso_free(struct ucom_softc *ucom)
+{
+	uhso_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 uhso_test_autoinst(void *arg, struct usb_device *udev,
     struct usb_attach_arg *uaa)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/quirk/usb_quirk.c
--- a/head/sys/dev/usb/quirk/usb_quirk.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/quirk/usb_quirk.c	Wed Aug 15 11:46:11 2012 +0300
@@ -449,6 +449,7 @@
 
 	USB_QUIRK(TOSHIBA, TRANSMEMORY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
 	USB_QUIRK(VIALABS, USB30SATABRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
+	USB_QUIRK(WETELECOM, ZEROCD, 0x0000, 0xffff, UQ_CFG_INDEX_1),
 
 	/* Non-standard USB MIDI devices */
 	USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/u3g.c
--- a/head/sys/dev/usb/serial/u3g.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/u3g.c	Wed Aug 15 11:46:11 2012 +0300
@@ -16,7 +16,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * $FreeBSD: head/sys/dev/usb/serial/u3g.c 238717 2012-07-23 14:22:45Z rea $
+ * $FreeBSD: head/sys/dev/usb/serial/u3g.c 239182 2012-08-10 17:43:20Z hselasky $
  */
 
 /*
@@ -124,10 +124,12 @@
 static device_probe_t u3g_probe;
 static device_attach_t u3g_attach;
 static device_detach_t u3g_detach;
+static device_free_softc_t u3g_free_softc;
 
 static usb_callback_t u3g_write_callback;
 static usb_callback_t u3g_read_callback;
 
+static void u3g_free(struct ucom_softc *ucom);
 static void u3g_start_read(struct ucom_softc *ucom);
 static void u3g_stop_read(struct ucom_softc *ucom);
 static void u3g_start_write(struct ucom_softc *ucom);
@@ -170,13 +172,15 @@
 	.ucom_stop_write = &u3g_stop_write,
 	.ucom_cfg_set_dtr = &u3g_cfg_set_dtr,
 	.ucom_cfg_set_rts = &u3g_cfg_set_rts,
+	.ucom_free = &u3g_free,
 };
 
 static device_method_t u3g_methods[] = {
 	DEVMETHOD(device_probe, u3g_probe),
 	DEVMETHOD(device_attach, u3g_attach),
 	DEVMETHOD(device_detach, u3g_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, u3g_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t u3g_devclass;
@@ -536,6 +540,7 @@
 	U3G_DEV(TOSHIBA, HSDPA, 0),
 	U3G_DEV(YISO, C893, 0),
 	U3G_DEV(LONGCHEER, MBD_100HU, 0),
+	U3G_DEV(WETELECOM, WM_D300, 0),
 	/* Autoinstallers */
 	U3G_DEV(NOVATEL, ZEROCD, U3GINIT_SCSIEJECT),
 	U3G_DEV(OPTION, GTICON322, U3GINIT_REZERO),
@@ -819,6 +824,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "u3g", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_udev = uaa->device;
 
@@ -908,11 +914,12 @@
 
 	for (subunit = 0; subunit != U3G_MAXPORTS; subunit++)
 		usbd_transfer_unsetup(sc->sc_xfer[subunit], U3G_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(u3g);
+
 static void
 u3g_cfg_request(struct u3g_softc *sc, uint8_t index, uint16_t value)
 {
@@ -970,13 +977,30 @@
 }
 
 static void
+u3g_free_softc(device_t dev, void *arg)
+{
+	struct u3g_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+u3g_free(struct ucom_softc *ucom)
+{
+	u3g_free_softc(NULL, ucom->sc_parent);
+}
+
+static void
 u3g_start_read(struct ucom_softc *ucom)
 {
 	struct u3g_softc *sc = ucom->sc_parent;
 
 	/* start read endpoint */
 	usbd_transfer_start(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_RD]);
-	return;
 }
 
 static void
@@ -986,7 +1010,6 @@
 
 	/* stop read endpoint */
 	usbd_transfer_stop(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_RD]);
-	return;
 }
 
 static void
@@ -995,7 +1018,6 @@
 	struct u3g_softc *sc = ucom->sc_parent;
 
 	usbd_transfer_start(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_WR]);
-	return;
 }
 
 static void
@@ -1004,7 +1026,6 @@
 	struct u3g_softc *sc = ucom->sc_parent;
 
 	usbd_transfer_stop(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_WR]);
-	return;
 }
 
 static void
@@ -1033,7 +1054,6 @@
 		}
 		break;
 	}
-	return;
 }
 
 static void
@@ -1064,5 +1084,4 @@
 		}
 		break;
 	}
-	return;
 }
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uark.c
--- a/head/sys/dev/usb/serial/uark.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uark.c	Wed Aug 15 11:46:11 2012 +0300
@@ -15,7 +15,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * $FreeBSD: head/sys/dev/usb/serial/uark.c 223486 2011-06-24 02:30:02Z hselasky $
+ * $FreeBSD: head/sys/dev/usb/serial/uark.c 239180 2012-08-10 15:29:41Z hselasky $
  */
 
 /*
@@ -99,10 +99,12 @@
 static device_probe_t uark_probe;
 static device_attach_t uark_attach;
 static device_detach_t uark_detach;
+static device_free_softc_t uark_free_softc;
 
 static usb_callback_t uark_bulk_write_callback;
 static usb_callback_t uark_bulk_read_callback;
 
+static void	uark_free(struct ucom_softc *);
 static void	uark_start_read(struct ucom_softc *);
 static void	uark_stop_read(struct ucom_softc *);
 static void	uark_start_write(struct ucom_softc *);
@@ -147,6 +149,7 @@
 	.ucom_start_write = &uark_start_write,
 	.ucom_stop_write = &uark_stop_write,
 	.ucom_poll = &uark_poll,
+	.ucom_free = &uark_free,
 };
 
 static device_method_t uark_methods[] = {
@@ -154,7 +157,8 @@
 	DEVMETHOD(device_probe, uark_probe),
 	DEVMETHOD(device_attach, uark_attach),
 	DEVMETHOD(device_detach, uark_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, uark_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t uark_devclass;
@@ -201,6 +205,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "uark", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_udev = uaa->device;
 
@@ -242,11 +247,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(uark);
+
+static void
+uark_free_softc(device_t dev, void *arg)
+{
+	struct uark_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+uark_free(struct ucom_softc *ucom)
+{
+	uark_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 uark_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ubsa.c
--- a/head/sys/dev/usb/serial/ubsa.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ubsa.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ubsa.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ubsa.c 239180 2012-08-10 15:29:41Z hselasky $");
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -176,12 +176,14 @@
 static device_probe_t ubsa_probe;
 static device_attach_t ubsa_attach;
 static device_detach_t ubsa_detach;
+static device_free_softc_t ubsa_free_softc;
 
 static usb_callback_t ubsa_write_callback;
 static usb_callback_t ubsa_read_callback;
 static usb_callback_t ubsa_intr_callback;
 
 static void	ubsa_cfg_request(struct ubsa_softc *, uint8_t, uint16_t);
+static void	ubsa_free(struct ucom_softc *);
 static void	ubsa_cfg_set_dtr(struct ucom_softc *, uint8_t);
 static void	ubsa_cfg_set_rts(struct ucom_softc *, uint8_t);
 static void	ubsa_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -237,6 +239,7 @@
 	.ucom_start_write = &ubsa_start_write,
 	.ucom_stop_write = &ubsa_stop_write,
 	.ucom_poll = &ubsa_poll,
+	.ucom_free = &ubsa_free,
 };
 
 static const STRUCT_USB_HOST_ID ubsa_devs[] = {
@@ -262,7 +265,8 @@
 	DEVMETHOD(device_probe, ubsa_probe),
 	DEVMETHOD(device_attach, ubsa_attach),
 	DEVMETHOD(device_detach, ubsa_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, ubsa_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t ubsa_devclass;
@@ -306,6 +310,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "ubsa", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_udev = uaa->device;
 	sc->sc_iface_no = uaa->info.bIfaceNum;
@@ -348,11 +353,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UBSA_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(ubsa);
+
+static void
+ubsa_free_softc(device_t dev, void *arg)
+{
+	struct ubsa_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+ubsa_free(struct ucom_softc *ucom)
+{
+	ubsa_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 ubsa_cfg_request(struct ubsa_softc *sc, uint8_t index, uint16_t value)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ubser.c
--- a/head/sys/dev/usb/serial/ubser.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ubser.c	Wed Aug 15 11:46:11 2012 +0300
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ubser.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ubser.c 239181 2012-08-10 17:42:14Z hselasky $");
 
 /*
  * BWCT serial adapter driver
@@ -141,7 +141,6 @@
 	uint8_t	sc_iface_no;
 	uint8_t	sc_iface_index;
 	uint8_t	sc_curr_tx_unit;
-	uint8_t	sc_name[16];
 };
 
 /* prototypes */
@@ -149,10 +148,12 @@
 static device_probe_t ubser_probe;
 static device_attach_t ubser_attach;
 static device_detach_t ubser_detach;
+static device_free_softc_t ubser_free_softc;
 
 static usb_callback_t ubser_write_callback;
 static usb_callback_t ubser_read_callback;
 
+static void	ubser_free(struct ucom_softc *);
 static int	ubser_pre_param(struct ucom_softc *, struct termios *);
 static void	ubser_cfg_set_break(struct ucom_softc *, uint8_t);
 static void	ubser_cfg_get_status(struct ucom_softc *, uint8_t *,
@@ -193,13 +194,15 @@
 	.ucom_start_write = &ubser_start_write,
 	.ucom_stop_write = &ubser_stop_write,
 	.ucom_poll = &ubser_poll,
+	.ucom_free = &ubser_free,
 };
 
 static device_method_t ubser_methods[] = {
 	DEVMETHOD(device_probe, ubser_probe),
 	DEVMETHOD(device_attach, ubser_attach),
 	DEVMETHOD(device_detach, ubser_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, ubser_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t ubser_devclass;
@@ -243,9 +246,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "ubser", NULL, MTX_DEF);
-
-	snprintf(sc->sc_name, sizeof(sc->sc_name), "%s",
-	    device_get_nameunit(dev));
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_iface_no = uaa->info.bIfaceNum;
 	sc->sc_iface_index = uaa->info.bIfaceIndex;
@@ -319,11 +320,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UBSER_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(ubser);
+
+static void
+ubser_free_softc(device_t dev, void *arg)
+{
+	struct ubser_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+ubser_free(struct ucom_softc *ucom)
+{
+	ubser_free_softc(NULL, ucom->sc_parent);
+}
+
 static int
 ubser_pre_param(struct ucom_softc *ucom, struct termios *t)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uchcom.c
--- a/head/sys/dev/usb/serial/uchcom.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uchcom.c	Wed Aug 15 11:46:11 2012 +0300
@@ -63,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uchcom.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uchcom.c 239180 2012-08-10 15:29:41Z hselasky $");
 
 /*
  * Driver for WinChipHead CH341/340, the worst USB-serial chip in the
@@ -211,6 +211,7 @@
 
 /* protypes */
 
+static void	uchcom_free(struct ucom_softc *);
 static int	uchcom_pre_param(struct ucom_softc *, struct termios *);
 static void	uchcom_cfg_get_status(struct ucom_softc *, uint8_t *,
 		    uint8_t *);
@@ -234,6 +235,7 @@
 static device_probe_t uchcom_probe;
 static device_attach_t uchcom_attach;
 static device_detach_t uchcom_detach;
+static device_free_softc_t uchcom_free_softc;
 
 static usb_callback_t uchcom_intr_callback;
 static usb_callback_t uchcom_write_callback;
@@ -282,6 +284,7 @@
 	.ucom_start_write = &uchcom_start_write,
 	.ucom_stop_write = &uchcom_stop_write,
 	.ucom_poll = &uchcom_poll,
+	.ucom_free = &uchcom_free,
 };
 
 /* ----------------------------------------------------------------------
@@ -319,6 +322,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "uchcom", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_udev = uaa->device;
 
@@ -371,11 +375,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UCHCOM_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(uchcom);
+
+static void
+uchcom_free_softc(device_t dev, void *arg)
+{
+	struct uchcom_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+uchcom_free(struct ucom_softc *ucom)
+{
+	uchcom_free_softc(NULL, ucom->sc_parent);
+}
+
 /* ----------------------------------------------------------------------
  * low level i/o
  */
@@ -841,8 +864,8 @@
 	DEVMETHOD(device_probe, uchcom_probe),
 	DEVMETHOD(device_attach, uchcom_attach),
 	DEVMETHOD(device_detach, uchcom_detach),
-
-	{0, 0}
+	DEVMETHOD(device_free_softc, uchcom_free_softc),
+	DEVMETHOD_END
 };
 
 static driver_t uchcom_driver = {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ucycom.c
--- a/head/sys/dev/usb/serial/ucycom.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ucycom.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ucycom.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ucycom.c 239181 2012-08-10 17:42:14Z hselasky $");
 
 /*-
  * Copyright (c) 2004 Dag-Erling Coïdan Smørgrav
@@ -101,7 +101,6 @@
 #define	UCYCOM_CFG_STOPB	0x08
 #define	UCYCOM_CFG_DATAB	0x03
 	uint8_t	sc_ist;			/* status flags from last input */
-	uint8_t	sc_name[16];
 	uint8_t	sc_iface_no;
 	uint8_t	sc_temp_cfg[32];
 };
@@ -111,10 +110,12 @@
 static device_probe_t ucycom_probe;
 static device_attach_t ucycom_attach;
 static device_detach_t ucycom_detach;
+static device_free_softc_t ucycom_free_softc;
 
 static usb_callback_t ucycom_ctrl_write_callback;
 static usb_callback_t ucycom_intr_read_callback;
 
+static void	ucycom_free(struct ucom_softc *);
 static void	ucycom_cfg_open(struct ucom_softc *);
 static void	ucycom_start_read(struct ucom_softc *);
 static void	ucycom_stop_read(struct ucom_softc *);
@@ -155,13 +156,15 @@
 	.ucom_start_write = &ucycom_start_write,
 	.ucom_stop_write = &ucycom_stop_write,
 	.ucom_poll = &ucycom_poll,
+	.ucom_free = &ucycom_free,
 };
 
 static device_method_t ucycom_methods[] = {
 	DEVMETHOD(device_probe, ucycom_probe),
 	DEVMETHOD(device_attach, ucycom_attach),
 	DEVMETHOD(device_detach, ucycom_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, ucycom_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t ucycom_devclass;
@@ -218,9 +221,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "ucycom", NULL, MTX_DEF);
-
-	snprintf(sc->sc_name, sizeof(sc->sc_name),
-	    "%s", device_get_nameunit(dev));
+	ucom_ref(&sc->sc_super_ucom);
 
 	DPRINTF("\n");
 
@@ -297,11 +298,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UCYCOM_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(ucycom);
+
+static void
+ucycom_free_softc(device_t dev, void *arg)
+{
+	struct ucycom_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+ucycom_free(struct ucom_softc *ucom)
+{
+	ucycom_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 ucycom_cfg_open(struct ucom_softc *ucom)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ufoma.c
--- a/head/sys/dev/usb/serial/ufoma.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ufoma.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
 /*	$NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $	*/
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ufoma.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ufoma.c 239181 2012-08-10 17:42:14Z hselasky $");
 #define UFOMA_HANDSFREE
 /*-
  * Copyright (c) 2005, Takanori Watanabe
@@ -195,7 +195,6 @@
 	uint8_t	sc_msr;
 	uint8_t	sc_modetoactivate;
 	uint8_t	sc_currentmode;
-	uint8_t	sc_name[16];
 };
 
 /* prototypes */
@@ -203,6 +202,7 @@
 static device_probe_t ufoma_probe;
 static device_attach_t ufoma_attach;
 static device_detach_t ufoma_detach;
+static device_free_softc_t ufoma_free_softc;
 
 static usb_callback_t ufoma_ctrl_read_callback;
 static usb_callback_t ufoma_ctrl_write_callback;
@@ -214,6 +214,7 @@
 		    struct usb_interface_descriptor *, uint8_t, uint8_t);
 static void	ufoma_cfg_link_state(struct ufoma_softc *);
 static void	ufoma_cfg_activate_state(struct ufoma_softc *, uint16_t);
+static void	ufoma_free(struct ucom_softc *);
 static void	ufoma_cfg_open(struct ucom_softc *);
 static void	ufoma_cfg_close(struct ucom_softc *);
 static void	ufoma_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -304,6 +305,7 @@
 	.ucom_start_write = &ufoma_start_write,
 	.ucom_stop_write = &ufoma_stop_write,
 	.ucom_poll = &ufoma_poll,
+	.ucom_free = &ufoma_free,
 };
 
 static device_method_t ufoma_methods[] = {
@@ -311,7 +313,8 @@
 	DEVMETHOD(device_probe, ufoma_probe),
 	DEVMETHOD(device_attach, ufoma_attach),
 	DEVMETHOD(device_detach, ufoma_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, ufoma_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t ufoma_devclass;
@@ -385,13 +388,11 @@
 	sc->sc_unit = device_get_unit(dev);
 
 	mtx_init(&sc->sc_mtx, "ufoma", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 	cv_init(&sc->sc_cv, "CWAIT");
 
 	device_set_usb_desc(dev);
 
-	snprintf(sc->sc_name, sizeof(sc->sc_name),
-	    "%s", device_get_nameunit(dev));
-
 	DPRINTF("\n");
 
 	/* setup control transfers */
@@ -495,12 +496,31 @@
 	if (sc->sc_modetable) {
 		free(sc->sc_modetable, M_USBDEV);
 	}
-	mtx_destroy(&sc->sc_mtx);
 	cv_destroy(&sc->sc_cv);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(ufoma);
+
+static void
+ufoma_free_softc(device_t dev, void *arg)
+{
+	struct ufoma_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+ufoma_free(struct ucom_softc *ucom)
+{
+	ufoma_free_softc(NULL, ucom->sc_parent);
+}
+
 static void *
 ufoma_get_intconf(struct usb_config_descriptor *cd, struct usb_interface_descriptor *id,
     uint8_t type, uint8_t subtype)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uftdi.c
--- a/head/sys/dev/usb/serial/uftdi.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uftdi.c	Wed Aug 15 11:46:11 2012 +0300
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uftdi.c 239055 2012-08-05 11:50:56Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uftdi.c 239181 2012-08-10 17:42:14Z hselasky $");
 
 /*
  * NOTE: all function names beginning like "uftdi_cfg_" can only
@@ -110,8 +110,6 @@
 	uint8_t	sc_hdrlen;
 	uint8_t	sc_msr;
 	uint8_t	sc_lsr;
-
-	uint8_t	sc_name[16];
 };
 
 struct uftdi_param_config {
@@ -127,10 +125,12 @@
 static device_probe_t uftdi_probe;
 static device_attach_t uftdi_attach;
 static device_detach_t uftdi_detach;
+static device_free_softc_t uftdi_free_softc;
 
 static usb_callback_t uftdi_write_callback;
 static usb_callback_t uftdi_read_callback;
 
+static void	uftdi_free(struct ucom_softc *);
 static void	uftdi_cfg_open(struct ucom_softc *);
 static void	uftdi_cfg_set_dtr(struct ucom_softc *, uint8_t);
 static void	uftdi_cfg_set_rts(struct ucom_softc *, uint8_t);
@@ -182,6 +182,7 @@
 	.ucom_start_write = &uftdi_start_write,
 	.ucom_stop_write = &uftdi_stop_write,
 	.ucom_poll = &uftdi_poll,
+	.ucom_free = &uftdi_free,
 };
 
 static device_method_t uftdi_methods[] = {
@@ -189,7 +190,7 @@
 	DEVMETHOD(device_probe, uftdi_probe),
 	DEVMETHOD(device_attach, uftdi_attach),
 	DEVMETHOD(device_detach, uftdi_detach),
-
+	DEVMETHOD(device_free_softc, uftdi_free_softc),
 	DEVMETHOD_END
 };
 
@@ -885,9 +886,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "uftdi", NULL, MTX_DEF);
-
-	snprintf(sc->sc_name, sizeof(sc->sc_name),
-	    "%s", device_get_nameunit(dev));
+	ucom_ref(&sc->sc_super_ucom);
 
 	DPRINTF("\n");
 
@@ -960,11 +959,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UFTDI_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(uftdi);
+
+static void
+uftdi_free_softc(device_t dev, void *arg)
+{
+	struct uftdi_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+uftdi_free(struct ucom_softc *ucom)
+{
+	uftdi_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 uftdi_cfg_open(struct ucom_softc *ucom)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ugensa.c
--- a/head/sys/dev/usb/serial/ugensa.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ugensa.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/serial/ugensa.c 223486 2011-06-24 02:30:02Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/serial/ugensa.c 239180 2012-08-10 15:29:41Z hselasky $ */
 /*	$NetBSD: ugensa.c,v 1.9.2.1 2007/03/24 14:55:50 yamt Exp $	*/
 
 /*
@@ -94,10 +94,12 @@
 static device_probe_t ugensa_probe;
 static device_attach_t ugensa_attach;
 static device_detach_t ugensa_detach;
+static device_free_softc_t ugensa_free_softc;
 
 static usb_callback_t ugensa_bulk_write_callback;
 static usb_callback_t ugensa_bulk_read_callback;
 
+static void	ugensa_free(struct ucom_softc *);
 static void	ugensa_start_read(struct ucom_softc *);
 static void	ugensa_stop_read(struct ucom_softc *);
 static void	ugensa_start_write(struct ucom_softc *);
@@ -131,6 +133,7 @@
 	.ucom_start_write = &ugensa_start_write,
 	.ucom_stop_write = &ugensa_stop_write,
 	.ucom_poll = &ugensa_poll,
+	.ucom_free = &ugensa_free,
 };
 
 static device_method_t ugensa_methods[] = {
@@ -138,7 +141,8 @@
 	DEVMETHOD(device_probe, ugensa_probe),
 	DEVMETHOD(device_attach, ugensa_attach),
 	DEVMETHOD(device_detach, ugensa_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, ugensa_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t ugensa_devclass;
@@ -192,6 +196,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "ugensa", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	/* Figure out how many interfaces this device has got */
 	for (cnt = 0; cnt < UGENSA_IFACE_MAX; cnt++) {
@@ -266,11 +271,30 @@
 	for (x = 0; x < sc->sc_niface; x++) {
 		usbd_transfer_unsetup(sc->sc_sub[x].sc_xfer, UGENSA_N_TRANSFER);
 	}
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(ugensa);
+
+static void
+ugensa_free_softc(device_t dev, void *arg)
+{
+	struct ugensa_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+ugensa_free(struct ucom_softc *ucom)
+{
+	ugensa_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 ugensa_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uipaq.c
--- a/head/sys/dev/usb/serial/uipaq.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uipaq.c	Wed Aug 15 11:46:11 2012 +0300
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uipaq.c 223486 2011-06-24 02:30:02Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uipaq.c 239180 2012-08-10 15:29:41Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -103,10 +103,12 @@
 static device_probe_t uipaq_probe;
 static device_attach_t uipaq_attach;
 static device_detach_t uipaq_detach;
+static device_free_softc_t uipaq_free_softc;
 
 static usb_callback_t uipaq_write_callback;
 static usb_callback_t uipaq_read_callback;
 
+static void	uipaq_free(struct ucom_softc *);
 static void	uipaq_start_read(struct ucom_softc *);
 static void	uipaq_stop_read(struct ucom_softc *);
 static void	uipaq_start_write(struct ucom_softc *);
@@ -146,6 +148,7 @@
 	.ucom_start_write = &uipaq_start_write,
 	.ucom_stop_write = &uipaq_stop_write,
 	.ucom_poll = &uipaq_poll,
+	.ucom_free = &uipaq_free,
 };
 
 /*
@@ -1070,7 +1073,8 @@
 	DEVMETHOD(device_probe, uipaq_probe),
 	DEVMETHOD(device_attach, uipaq_attach),
 	DEVMETHOD(device_detach, uipaq_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, uipaq_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t uipaq_devclass;
@@ -1121,6 +1125,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "uipaq", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	/*
 	 * Send magic bytes, cribbed from Linux ipaq driver that
@@ -1176,11 +1181,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UIPAQ_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(uipaq);
+
+static void
+uipaq_free_softc(device_t dev, void *arg)
+{
+	struct uipaq_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+uipaq_free(struct ucom_softc *ucom)
+{
+	uipaq_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 uipaq_start_read(struct ucom_softc *ucom)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ulpt.c
--- a/head/sys/dev/usb/serial/ulpt.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ulpt.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ulpt.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ulpt.c 239180 2012-08-10 15:29:41Z hselasky $");
 
 /*	$NetBSD: ulpt.c,v 1.60 2003/10/04 21:19:50 augustss Exp $	*/
 
@@ -747,7 +747,7 @@
 	DEVMETHOD(device_probe, ulpt_probe),
 	DEVMETHOD(device_attach, ulpt_attach),
 	DEVMETHOD(device_detach, ulpt_detach),
-	{0, 0}
+	DEVMETHOD_END
 };
 
 static driver_t ulpt_driver = {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/umcs.c
--- a/head/sys/dev/usb/serial/umcs.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/umcs.c	Wed Aug 15 11:46:11 2012 +0300
@@ -38,7 +38,7 @@
  *
  */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umcs.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umcs.c 239180 2012-08-10 15:29:41Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -154,6 +154,7 @@
 static usb_error_t umcs7840_set_baudrate(struct umcs7840_softc *, uint8_t, uint32_t);
 static usb_error_t umcs7840_calc_baudrate(uint32_t rate, uint16_t *, uint8_t *);
 
+static void	umcs7840_free(struct ucom_softc *);
 static void umcs7840_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *);
 static void umcs7840_cfg_set_dtr(struct ucom_softc *, uint8_t);
 static void umcs7840_cfg_set_rts(struct ucom_softc *, uint8_t);
@@ -175,6 +176,7 @@
 static device_probe_t umcs7840_probe;
 static device_attach_t umcs7840_attach;
 static device_detach_t umcs7840_detach;
+static device_free_softc_t umcs7840_free_softc;
 
 static usb_callback_t umcs7840_intr_callback;
 static usb_callback_t umcs7840_read_callback1;
@@ -251,6 +253,7 @@
 	.ucom_stop_write = &umcs7840_stop_write,
 
 	.ucom_poll = &umcs7840_poll,
+	.ucom_free = &umcs7840_free,
 };
 
 static const STRUCT_USB_HOST_ID umcs7840_devs[] = {
@@ -262,7 +265,8 @@
 	DEVMETHOD(device_probe, umcs7840_probe),
 	DEVMETHOD(device_attach, umcs7840_attach),
 	DEVMETHOD(device_detach, umcs7840_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, umcs7840_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t umcs7840_devclass;
@@ -310,6 +314,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "umcs7840", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_dev = dev;
 	sc->sc_udev = uaa->device;
@@ -408,10 +413,29 @@
 		usbd_transfer_unsetup(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer, UMCS7840_N_TRANSFERS);
 	usbd_transfer_unsetup(&sc->sc_intr_xfer, 1);
 
-	mtx_destroy(&sc->sc_mtx);
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(umcs7840);
+
+static void
+umcs7840_free_softc(device_t dev, void *arg)
+{
+	struct umcs7840_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+umcs7840_free(struct ucom_softc *ucom)
+{
+	umcs7840_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 umcs7840_cfg_open(struct ucom_softc *ucom)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/umct.c
--- a/head/sys/dev/usb/serial/umct.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/umct.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umct.c 223486 2011-06-24 02:30:02Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umct.c 239181 2012-08-10 17:42:14Z hselasky $");
 
 /*-
  * Copyright (c) 2003 Scott Long
@@ -115,7 +115,6 @@
 	uint8_t	sc_mcr;
 	uint8_t	sc_iface_no;
 	uint8_t sc_swap_cb;
-	uint8_t	sc_name[16];
 };
 
 /* prototypes */
@@ -123,6 +122,7 @@
 static device_probe_t umct_probe;
 static device_attach_t umct_attach;
 static device_detach_t umct_detach;
+static device_free_softc_t umct_free_softc;
 
 static usb_callback_t umct_intr_callback;
 static usb_callback_t umct_intr_callback_sub;
@@ -132,6 +132,7 @@
 
 static void	umct_cfg_do_request(struct umct_softc *sc, uint8_t request,
 		    uint16_t len, uint32_t value);
+static void	umct_free(struct ucom_softc *);
 static void	umct_cfg_get_status(struct ucom_softc *, uint8_t *,
 		    uint8_t *);
 static void	umct_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -190,6 +191,7 @@
 	.ucom_start_write = &umct_start_write,
 	.ucom_stop_write = &umct_stop_write,
 	.ucom_poll = &umct_poll,
+	.ucom_free = &umct_free,
 };
 
 static const STRUCT_USB_HOST_ID umct_devs[] = {
@@ -204,7 +206,8 @@
 	DEVMETHOD(device_probe, umct_probe),
 	DEVMETHOD(device_attach, umct_attach),
 	DEVMETHOD(device_detach, umct_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, umct_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t umct_devclass;
@@ -251,9 +254,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "umct", NULL, MTX_DEF);
-
-	snprintf(sc->sc_name, sizeof(sc->sc_name),
-	    "%s", device_get_nameunit(dev));
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_iface_no = uaa->info.bIfaceNum;
 
@@ -312,11 +313,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UMCT_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(umct);
+
+static void
+umct_free_softc(device_t dev, void *arg)
+{
+	struct umct_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+umct_free(struct ucom_softc *ucom)
+{
+	umct_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 umct_cfg_do_request(struct umct_softc *sc, uint8_t request,
     uint16_t len, uint32_t value)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/umodem.c
--- a/head/sys/dev/usb/serial/umodem.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/umodem.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
 /*	$NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $	*/
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umodem.c 234418 2012-04-18 12:50:13Z thomas $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umodem.c 239180 2012-08-10 15:29:41Z hselasky $");
 
 /*-
  * Copyright (c) 2003, M. Warner Losh <imp at FreeBSD.org>.
@@ -178,11 +178,13 @@
 static device_probe_t umodem_probe;
 static device_attach_t umodem_attach;
 static device_detach_t umodem_detach;
+static device_free_softc_t umodem_free_softc;
 
 static usb_callback_t umodem_intr_callback;
 static usb_callback_t umodem_write_callback;
 static usb_callback_t umodem_read_callback;
 
+static void	umodem_free(struct ucom_softc *);
 static void	umodem_start_read(struct ucom_softc *);
 static void	umodem_stop_read(struct ucom_softc *);
 static void	umodem_start_write(struct ucom_softc *);
@@ -250,13 +252,15 @@
 	.ucom_start_write = &umodem_start_write,
 	.ucom_stop_write = &umodem_stop_write,
 	.ucom_poll = &umodem_poll,
+	.ucom_free = &umodem_free,
 };
 
 static device_method_t umodem_methods[] = {
 	DEVMETHOD(device_probe, umodem_probe),
 	DEVMETHOD(device_attach, umodem_attach),
 	DEVMETHOD(device_detach, umodem_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, umodem_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t umodem_devclass;
@@ -302,6 +306,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "umodem", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_ctrl_iface_no = uaa->info.bIfaceNum;
 	sc->sc_iface_index[1] = uaa->info.bIfaceIndex;
@@ -875,11 +880,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UMODEM_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(umodem);
+
+static void
+umodem_free_softc(device_t dev, void *arg)
+{
+	struct umodem_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+umodem_free(struct ucom_softc *ucom)
+{
+	umodem_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 umodem_poll(struct ucom_softc *ucom)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/umoscom.c
--- a/head/sys/dev/usb/serial/umoscom.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/umoscom.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/serial/umoscom.c 227309 2011-11-07 15:43:11Z ed $ */
+/* $FreeBSD: head/sys/dev/usb/serial/umoscom.c 239180 2012-08-10 15:29:41Z hselasky $ */
 /*	$OpenBSD: umoscom.c,v 1.2 2006/10/26 06:02:43 jsg Exp $	*/
 
 /*
@@ -189,11 +189,13 @@
 static device_probe_t umoscom_probe;
 static device_attach_t umoscom_attach;
 static device_detach_t umoscom_detach;
+static device_free_softc_t umoscom_free_softc;
 
 static usb_callback_t umoscom_write_callback;
 static usb_callback_t umoscom_read_callback;
 static usb_callback_t umoscom_intr_callback;
 
+static void	umoscom_free(struct ucom_softc *);
 static void	umoscom_cfg_open(struct ucom_softc *);
 static void	umoscom_cfg_close(struct ucom_softc *);
 static void	umoscom_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -258,13 +260,15 @@
 	.ucom_start_write = &umoscom_start_write,
 	.ucom_stop_write = &umoscom_stop_write,
 	.ucom_poll = &umoscom_poll,
+	.ucom_free = &umoscom_free,
 };
 
 static device_method_t umoscom_methods[] = {
 	DEVMETHOD(device_probe, umoscom_probe),
 	DEVMETHOD(device_attach, umoscom_attach),
 	DEVMETHOD(device_detach, umoscom_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, umoscom_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t umoscom_devclass;
@@ -317,6 +321,7 @@
 	device_printf(dev, "<MOSCHIP USB Serial Port Adapter>\n");
 
 	mtx_init(&sc->sc_mtx, "umoscom", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	iface_index = UMOSCOM_IFACE_INDEX;
 	error = usbd_transfer_setup(uaa->device, &iface_index,
@@ -354,11 +359,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UMOSCOM_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(umoscom);
+
+static void
+umoscom_free_softc(device_t dev, void *arg)
+{
+	struct umoscom_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+umoscom_free(struct ucom_softc *ucom)
+{
+	umoscom_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 umoscom_cfg_open(struct ucom_softc *ucom)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uplcom.c
--- a/head/sys/dev/usb/serial/uplcom.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uplcom.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
 /*	$NetBSD: uplcom.c,v 1.21 2001/11/13 06:24:56 lukem Exp $	*/
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uplcom.c 238766 2012-07-25 11:33:43Z gavin $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uplcom.c 239180 2012-08-10 15:29:41Z hselasky $");
 
 /*-
  * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -176,6 +176,7 @@
 static usb_error_t uplcom_pl2303_do(struct usb_device *, int8_t, uint8_t,
 			uint16_t, uint16_t, uint16_t);
 static int	uplcom_pl2303_init(struct usb_device *, uint8_t);
+static void	uplcom_free(struct ucom_softc *);
 static void	uplcom_cfg_set_dtr(struct ucom_softc *, uint8_t);
 static void	uplcom_cfg_set_rts(struct ucom_softc *, uint8_t);
 static void	uplcom_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -192,6 +193,7 @@
 static device_probe_t uplcom_probe;
 static device_attach_t uplcom_attach;
 static device_detach_t uplcom_detach;
+static device_free_softc_t uplcom_free_softc;
 
 static usb_callback_t uplcom_intr_callback;
 static usb_callback_t uplcom_write_callback;
@@ -242,6 +244,7 @@
 	.ucom_start_write = &uplcom_start_write,
 	.ucom_stop_write = &uplcom_stop_write,
 	.ucom_poll = &uplcom_poll,
+	.ucom_free = &uplcom_free,
 };
 
 #define	UPLCOM_DEV(v,p)				\
@@ -315,7 +318,8 @@
 	DEVMETHOD(device_probe, uplcom_probe),
 	DEVMETHOD(device_attach, uplcom_attach),
 	DEVMETHOD(device_detach, uplcom_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, uplcom_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t uplcom_devclass;
@@ -364,6 +368,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "uplcom", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	DPRINTF("sc = %p\n", sc);
 
@@ -465,11 +470,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UPLCOM_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(uplcom);
+
+static void
+uplcom_free_softc(device_t dev, void *arg)
+{
+	struct uplcom_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+uplcom_free(struct ucom_softc *ucom)
+{
+	uplcom_free_softc(NULL, ucom->sc_parent);
+}
+
 static usb_error_t
 uplcom_reset(struct uplcom_softc *sc, struct usb_device *udev)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/usb_serial.c
--- a/head/sys/dev/usb/serial/usb_serial.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/usb_serial.c	Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/usb_serial.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/usb_serial.c 239179 2012-08-10 15:21:12Z hselasky $");
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -146,7 +146,7 @@
 static int	ucom_unit_alloc(void);
 static void	ucom_unit_free(int);
 static int	ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *);
-static void	ucom_detach_tty(struct ucom_softc *);
+static void	ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *);
 static void	ucom_queue_command(struct ucom_softc *,
 		    usb_proc_callback_t *, struct termios *pt,
 		    struct usb_proc_msg *t0, struct usb_proc_msg *t1);
@@ -178,13 +178,37 @@
 MODULE_DEPEND(ucom, usb, 1, 1, 1);
 MODULE_VERSION(ucom, 1);
 
-#define	UCOM_UNIT_MAX 		128	/* limits size of ucom_bitmap */
+#define	UCOM_UNIT_MAX 		128	/* maximum number of units */
+#define	UCOM_TTY_PREFIX		"U"
 
-static uint8_t ucom_bitmap[(UCOM_UNIT_MAX + 7) / 8];
-static struct mtx ucom_bitmap_mtx;
-MTX_SYSINIT(ucom_bitmap_mtx, &ucom_bitmap_mtx, "ucom bitmap", MTX_DEF);
+static struct unrhdr *ucom_unrhdr;
+static struct mtx ucom_mtx;
+static int ucom_close_refs;
 
-#define UCOM_TTY_PREFIX		"U"
+static void
+ucom_init(void *arg)
+{
+	DPRINTF("\n");
+	ucom_unrhdr = new_unrhdr(0, UCOM_UNIT_MAX - 1, NULL);
+	mtx_init(&ucom_mtx, "UCOM MTX", NULL, MTX_DEF);
+}
+SYSINIT(ucom_init, SI_SUB_KLD - 1, SI_ORDER_ANY, ucom_init, NULL);
+
+static void
+ucom_uninit(void *arg)
+{
+	struct unrhdr *hdr;
+	hdr = ucom_unrhdr;
+	ucom_unrhdr = NULL;
+
+	DPRINTF("\n");
+
+	if (hdr != NULL)
+		delete_unrhdr(hdr);
+
+	mtx_destroy(&ucom_mtx);
+}
+SYSUNINIT(ucom_uninit, SI_SUB_KLD - 2, SI_ORDER_ANY, ucom_uninit, NULL);
 
 /*
  * Mark a unit number (the X in cuaUX) as in use.
@@ -197,21 +221,14 @@
 {
 	int unit;
 
-	mtx_lock(&ucom_bitmap_mtx);
-
-	for (unit = 0; unit < UCOM_UNIT_MAX; unit++) {
-		if ((ucom_bitmap[unit / 8] & (1 << (unit % 8))) == 0) {
-			ucom_bitmap[unit / 8] |= (1 << (unit % 8));
-			break;
-		}
+	/* sanity checks */
+	if (ucom_unrhdr == NULL) {
+		DPRINTF("ucom_unrhdr is NULL\n");
+		return (-1);
 	}
-
-	mtx_unlock(&ucom_bitmap_mtx);
-
-	if (unit == UCOM_UNIT_MAX)
-		return -1;
-	else
-		return unit;
+	unit = alloc_unr(ucom_unrhdr);
+	DPRINTF("unit %d is allocated\n", unit);
+	return (unit);
 }
 
 /*
@@ -220,11 +237,13 @@
 static void
 ucom_unit_free(int unit)
 {
-	mtx_lock(&ucom_bitmap_mtx);
-
-	ucom_bitmap[unit / 8] &= ~(1 << (unit % 8));
-
-	mtx_unlock(&ucom_bitmap_mtx);
+	/* sanity checks */
+	if (unit < 0 || unit >= UCOM_UNIT_MAX || ucom_unrhdr == NULL) {
+		DPRINTF("cannot free unit number\n");
+		return;
+	}
+	DPRINTF("unit %d is freed\n", unit);
+	free_unr(ucom_unrhdr, unit);
 }
 
 /*
@@ -244,7 +263,8 @@
 
 	if ((sc == NULL) ||
 	    (subunits <= 0) ||
-	    (callback == NULL)) {
+	    (callback == NULL) ||
+	    (mtx == NULL)) {
 		return (EINVAL);
 	}
 
@@ -265,6 +285,11 @@
 	}
 	ssc->sc_subunits = subunits;
 
+	if (callback->ucom_free == NULL) {
+		ssc->sc_wait_refs = 1;
+		ucom_ref(ssc);
+	}
+
 	for (subunit = 0; subunit < ssc->sc_subunits; subunit++) {
 		sc[subunit].sc_subunit = subunit;
 		sc[subunit].sc_super = ssc;
@@ -277,6 +302,10 @@
 			ucom_detach(ssc, &sc[0]);
 			return (error);
 		}
+		/* increment reference count */
+		ucom_ref(ssc);
+
+		/* set subunit attached */
 		sc[subunit].sc_flag |= UCOM_FLAG_ATTACHED;
 	}
 
@@ -313,14 +342,41 @@
 	for (subunit = 0; subunit < ssc->sc_subunits; subunit++) {
 		if (sc[subunit].sc_flag & UCOM_FLAG_ATTACHED) {
 
-			ucom_detach_tty(&sc[subunit]);
+			ucom_detach_tty(ssc, &sc[subunit]);
 
 			/* avoid duplicate detach */
 			sc[subunit].sc_flag &= ~UCOM_FLAG_ATTACHED;
 		}
 	}
-	ucom_unit_free(ssc->sc_unit);
 	usb_proc_free(&ssc->sc_tq);
+
+	if (ssc->sc_wait_refs != 0) {
+		ucom_unref(ssc);
+		ucom_drain(ssc);
+	}
+}
+
+void
+ucom_drain(struct ucom_super_softc *ssc)
+{
+	mtx_lock(&ucom_mtx);
+	while (ssc->sc_refs >= 2) {
+		printf("ucom: Waiting for a TTY device to close.\n");
+		usb_pause_mtx(&ucom_mtx, hz);
+	}
+	mtx_unlock(&ucom_mtx);
+}
+
+void
+ucom_drain_all(void *arg)
+{
+	mtx_lock(&ucom_mtx);
+	while (ucom_close_refs > 0) {
+		printf("ucom: Waiting for all detached TTY "
+		    "devices to have open fds closed.\n");
+		usb_pause_mtx(&ucom_mtx, hz);
+	}
+	mtx_unlock(&ucom_mtx);
 }
 
 static int
@@ -349,7 +405,6 @@
 	sc->sc_tty = tp;
 
 	DPRINTF("ttycreate: %s\n", buf);
-	cv_init(&sc->sc_cv, "ucom");
 
 	/* Check if this device should be a console */
 	if ((ucom_cons_softc == NULL) && 
@@ -366,7 +421,7 @@
 		t.c_ospeed = t.c_ispeed;
 		t.c_cflag = CS8;
 
-		mtx_lock(ucom_cons_softc->sc_mtx);
+		UCOM_MTX_LOCK(ucom_cons_softc);
 		ucom_cons_rx_low = 0;
 		ucom_cons_rx_high = 0;
 		ucom_cons_tx_low = 0;
@@ -374,56 +429,55 @@
 		sc->sc_flag |= UCOM_FLAG_CONSOLE;
 		ucom_open(ucom_cons_softc->sc_tty);
 		ucom_param(ucom_cons_softc->sc_tty, &t);
-		mtx_unlock(ucom_cons_softc->sc_mtx);
+		UCOM_MTX_UNLOCK(ucom_cons_softc);
 	}
 
 	return (0);
 }
 
 static void
-ucom_detach_tty(struct ucom_softc *sc)
+ucom_detach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc)
 {
 	struct tty *tp = sc->sc_tty;
 
 	DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty);
 
 	if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
-		mtx_lock(ucom_cons_softc->sc_mtx);
+		UCOM_MTX_LOCK(ucom_cons_softc);
 		ucom_close(ucom_cons_softc->sc_tty);
 		sc->sc_flag &= ~UCOM_FLAG_CONSOLE;
-		mtx_unlock(ucom_cons_softc->sc_mtx);
+		UCOM_MTX_UNLOCK(ucom_cons_softc);
 		ucom_cons_softc = NULL;
 	}
 
 	/* the config thread has been stopped when we get here */
 
-	mtx_lock(sc->sc_mtx);
+	UCOM_MTX_LOCK(sc);
 	sc->sc_flag |= UCOM_FLAG_GONE;
 	sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_LL_READY);
-	mtx_unlock(sc->sc_mtx);
+	UCOM_MTX_UNLOCK(sc);
+
 	if (tp) {
+		mtx_lock(&ucom_mtx);
+		ucom_close_refs++;
+		mtx_unlock(&ucom_mtx);
+
 		tty_lock(tp);
 
 		ucom_close(tp);	/* close, if any */
 
 		tty_rel_gone(tp);
 
-		mtx_lock(sc->sc_mtx);
-		/* Wait for the callback after the TTY is torn down */
-		while (sc->sc_ttyfreed == 0)
-			cv_wait(&sc->sc_cv, sc->sc_mtx);
+		UCOM_MTX_LOCK(sc);
 		/*
 		 * make sure that read and write transfers are stopped
 		 */
-		if (sc->sc_callback->ucom_stop_read) {
+		if (sc->sc_callback->ucom_stop_read)
 			(sc->sc_callback->ucom_stop_read) (sc);
-		}
-		if (sc->sc_callback->ucom_stop_write) {
+		if (sc->sc_callback->ucom_stop_write)
 			(sc->sc_callback->ucom_stop_write) (sc);
-		}
-		mtx_unlock(sc->sc_mtx);
+		UCOM_MTX_UNLOCK(sc);
 	}
-	cv_destroy(&sc->sc_cv);
 }
 
 void
@@ -469,7 +523,7 @@
 	struct ucom_super_softc *ssc = sc->sc_super;
 	struct ucom_param_task *task;
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	if (usb_proc_is_gone(&ssc->sc_tq)) {
 		DPRINTF("proc is gone\n");
@@ -513,7 +567,7 @@
 {
 	struct tty *tp = sc->sc_tty;
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	DPRINTF("\n");
 
@@ -614,7 +668,7 @@
 	struct ucom_softc *sc = tty_softc(tp);
 	int error;
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	if (sc->sc_flag & UCOM_FLAG_GONE) {
 		return (ENXIO);
@@ -692,7 +746,7 @@
 {
 	struct ucom_softc *sc = tty_softc(tp);
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	DPRINTF("tp=%p\n", tp);
 
@@ -719,7 +773,7 @@
 	struct ucom_softc *sc = tty_softc(tp);
 	int error;
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
 		return (EIO);
@@ -763,7 +817,7 @@
 	struct ucom_softc *sc = tty_softc(tp);
 	uint8_t onoff;
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
 		return (0);
@@ -882,7 +936,7 @@
 ucom_line_state(struct ucom_softc *sc,
     uint8_t set_bits, uint8_t clear_bits)
 {
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
 		return;
@@ -960,7 +1014,7 @@
 
 	tp = sc->sc_tty;
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
 		return;
@@ -1022,7 +1076,7 @@
 void
 ucom_status_change(struct ucom_softc *sc)
 {
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	if (sc->sc_flag & UCOM_FLAG_CONSOLE)
 		return;		/* not supported */
@@ -1064,7 +1118,7 @@
 	uint8_t opened;
 	int error;
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	opened = 0;
 	error = 0;
@@ -1131,7 +1185,7 @@
 {
 	struct ucom_softc *sc = tty_softc(tp);
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	DPRINTF("sc = %p\n", sc);
 
@@ -1158,7 +1212,7 @@
 	uint32_t cnt;
 	uint32_t offset_orig;
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
 		unsigned int temp;
@@ -1237,7 +1291,7 @@
 	char *buf;
 	uint32_t cnt;
 
-	mtx_assert(sc->sc_mtx, MA_OWNED);
+	UCOM_MTX_ASSERT(sc, MA_OWNED);
 
 	if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
 		unsigned int temp;
@@ -1318,10 +1372,14 @@
 {
 	struct ucom_softc *sc = xsc;
 
-	mtx_lock(sc->sc_mtx);
-	sc->sc_ttyfreed = 1;
-	cv_signal(&sc->sc_cv);
-	mtx_unlock(sc->sc_mtx);
+	if (sc->sc_callback->ucom_free != NULL)
+		sc->sc_callback->ucom_free(sc);
+	else
+		ucom_unref(sc->sc_super);
+
+	mtx_lock(&ucom_mtx);
+	ucom_close_refs--;
+	mtx_unlock(&ucom_mtx);
 }
 
 static cn_probe_t ucom_cnprobe;
@@ -1374,7 +1432,7 @@
 	if (sc == NULL)
 		return (-1);
 
-	mtx_lock(sc->sc_mtx);
+	UCOM_MTX_LOCK(sc);
 
 	if (ucom_cons_rx_low != ucom_cons_rx_high) {
 		c = ucom_cons_rx_buf[ucom_cons_rx_low];
@@ -1387,7 +1445,7 @@
 	/* start USB transfers */
 	ucom_outwakeup(sc->sc_tty);
 
-	mtx_unlock(sc->sc_mtx);
+	UCOM_MTX_UNLOCK(sc);
 
 	/* poll if necessary */
 	if (kdb_active && sc->sc_callback->ucom_poll)
@@ -1407,7 +1465,7 @@
 
  repeat:
 
-	mtx_lock(sc->sc_mtx);
+	UCOM_MTX_LOCK(sc);
 
 	/* compute maximum TX length */
 
@@ -1423,7 +1481,7 @@
 	/* start USB transfers */
 	ucom_outwakeup(sc->sc_tty);
 
-	mtx_unlock(sc->sc_mtx);
+	UCOM_MTX_UNLOCK(sc);
 
 	/* poll if necessary */
 	if (kdb_active && sc->sc_callback->ucom_poll) {
@@ -1434,6 +1492,50 @@
 	}
 }
 
+/*------------------------------------------------------------------------*
+ *	ucom_ref
+ *
+ * This function will increment the super UCOM reference count.
+ *------------------------------------------------------------------------*/
+void
+ucom_ref(struct ucom_super_softc *ssc)
+{
+	mtx_lock(&ucom_mtx);
+	ssc->sc_refs++;
+	mtx_unlock(&ucom_mtx);
+}
+
+/*------------------------------------------------------------------------*
+ *	ucom_unref
+ *
+ * This function will decrement the super UCOM reference count.
+ *
+ * Return values:
+ * 0: UCOM structures are still referenced.
+ * Else: UCOM structures are no longer referenced.
+ *------------------------------------------------------------------------*/
+int
+ucom_unref(struct ucom_super_softc *ssc)
+{
+	int retval;
+	int free_unit;
+
+	mtx_lock(&ucom_mtx);
+	retval = (ssc->sc_refs < 2);
+	free_unit = (ssc->sc_refs == 1);
+	ssc->sc_refs--;
+	mtx_unlock(&ucom_mtx);
+
+	/*
+	 * This function might be called when the "ssc" is only zero
+	 * initialized and in that case the unit number should not be
+	 * freed.
+	 */
+	if (free_unit)
+		ucom_unit_free(ssc->sc_unit);
+	return (retval);
+}
+
 #if defined(GDB)
 
 #include <gdb/gdb.h>
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/usb_serial.h
--- a/head/sys/dev/usb/serial/usb_serial.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/usb_serial.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 /*	$NetBSD: ucomvar.h,v 1.9 2001/01/23 21:56:17 augustss Exp $	*/
-/*	$FreeBSD: head/sys/dev/usb/serial/usb_serial.h 233774 2012-04-02 10:50:42Z hselasky $	*/
+/*	$FreeBSD: head/sys/dev/usb/serial/usb_serial.h 239179 2012-08-10 15:21:12Z hselasky $	*/
 
 /*-
  * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -107,6 +107,7 @@
 	void    (*ucom_stop_write) (struct ucom_softc *);
 	void    (*ucom_tty_name) (struct ucom_softc *, char *pbuf, uint16_t buflen, uint16_t unit, uint16_t subunit);
 	void    (*ucom_poll) (struct ucom_softc *);
+	void	(*ucom_free) (struct ucom_softc *);
 };
 
 /* Line status register */
@@ -135,6 +136,8 @@
 	struct usb_process sc_tq;
 	int sc_unit;
 	int sc_subunits;
+	int sc_refs;
+	int sc_wait_refs;
 	struct sysctl_oid *sc_sysctl_ttyname;
 	struct sysctl_oid *sc_sysctl_ttyports;
 	char sc_ttyname[16];
@@ -158,7 +161,6 @@
 	struct ucom_cfg_task	sc_line_state_task[2];
 	struct ucom_cfg_task	sc_status_task[2];
 	struct ucom_param_task	sc_param_task[2];
-	struct cv sc_cv;
 	/* Used to set "UCOM_FLAG_GP_DATA" flag: */
 	struct usb_proc_msg	*sc_last_start_xfer;
 	const struct ucom_callback *sc_callback;
@@ -179,7 +181,6 @@
 	uint8_t	sc_lsr;
 	uint8_t	sc_msr;
 	uint8_t	sc_mcr;
-	uint8_t	sc_ttyfreed;		/* set when TTY has been freed */
 	/* programmed line state bits */
 	uint8_t sc_pls_set;		/* set bits */
 	uint8_t sc_pls_clr;		/* cleared bits */
@@ -190,6 +191,12 @@
 #define	UCOM_LS_RING	0x08
 };
 
+#define	UCOM_MTX_ASSERT(sc, what) mtx_assert((sc)->sc_mtx, what)
+#define	UCOM_MTX_LOCK(sc) mtx_lock((sc)->sc_mtx)
+#define	UCOM_MTX_UNLOCK(sc) mtx_unlock((sc)->sc_mtx)
+#define	UCOM_UNLOAD_DRAIN(x) \
+SYSUNINIT(var, SI_SUB_KLD - 3, SI_ORDER_ANY, ucom_drain_all, 0)
+
 #define	ucom_cfg_do_request(udev,com,req,ptr,flags,timo) \
     usbd_do_request_proc(udev,&(com)->sc_super->sc_tq,req,ptr,flags,NULL,timo)
 
@@ -204,4 +211,8 @@
 void	ucom_put_data(struct ucom_softc *, struct usb_page_cache *,
 	    uint32_t, uint32_t);
 uint8_t	ucom_cfg_is_gone(struct ucom_softc *);
+void	ucom_drain(struct ucom_super_softc *);
+void	ucom_drain_all(void *);
+void	ucom_ref(struct ucom_super_softc *);
+int	ucom_unref(struct ucom_super_softc *);
 #endif					/* _USB_SERIAL_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uslcom.c
--- a/head/sys/dev/usb/serial/uslcom.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uslcom.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
 /*	$OpenBSD: uslcom.c,v 1.17 2007/11/24 10:52:12 jsg Exp $	*/
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uslcom.c 239050 2012-08-05 08:56:29Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uslcom.c 239260 2012-08-14 22:21:46Z gavin $");
 
 /*
  * Copyright (c) 2006 Jonathan Gray <jsg at openbsd.org>
@@ -19,6 +19,12 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * Driver for Silicon Laboratories CP2101/CP2102/CP2103/CP2104/CP2105
+ * USB-Serial adapters.  Based on datasheet AN571, publicly available from
+ * http://www.silabs.com/Support%20Documents/TechnicalDocs/AN571.pdf
+ */
+
 #include <sys/stdint.h>
 #include <sys/stddef.h>
 #include <sys/param.h>
@@ -61,55 +67,54 @@
 #define	USLCOM_BULK_BUF_SIZE		1024
 #define	USLCOM_CONFIG_INDEX	0
 
-#define	USLCOM_SET_DATA_BITS(x)	((x) << 8)
-
 /* Request types */
 #define	USLCOM_WRITE		0x41
 #define	USLCOM_READ		0xc1
 
 /* Request codes */
-#define	USLCOM_UART		0x00
-#define	USLCOM_SET_BAUD_DIV	0x01	
-#define	USLCOM_DATA		0x03
-#define	USLCOM_BREAK		0x05
-#define	USLCOM_CTRL		0x07
-#define	USLCOM_RCTRL            0x08
-#define	USLCOM_SET_FLOWCTRL     0x13
-#define	USLCOM_SET_BAUD_RATE	0x1e	
+#define	USLCOM_IFC_ENABLE	0x00
+#define	USLCOM_SET_BAUDDIV	0x01	
+#define	USLCOM_SET_LINE_CTL	0x03
+#define	USLCOM_SET_BREAK	0x05
+#define	USLCOM_SET_MHS		0x07
+#define	USLCOM_GET_MDMSTS	0x08
+#define	USLCOM_SET_FLOW		0x13
+#define	USLCOM_SET_BAUDRATE	0x1e	
 #define	USLCOM_VENDOR_SPECIFIC	0xff
 
-/* USLCOM_UART values */
-#define	USLCOM_UART_DISABLE	0x00
-#define	USLCOM_UART_ENABLE	0x01
+/* USLCOM_IFC_ENABLE values */
+#define	USLCOM_IFC_ENABLE_DIS	0x00
+#define	USLCOM_IFC_ENABLE_EN	0x01
 
-/* USLCOM_CTRL/USLCOM_RCTRL values */
-#define	USLCOM_CTRL_DTR_ON	0x0001	
-#define	USLCOM_CTRL_DTR_SET	0x0100
-#define	USLCOM_CTRL_RTS_ON	0x0002
-#define	USLCOM_CTRL_RTS_SET	0x0200
-#define	USLCOM_CTRL_CTS		0x0010
-#define	USLCOM_CTRL_DSR		0x0020
-#define	USLCOM_CTRL_RI          0x0040
-#define	USLCOM_CTRL_DCD		0x0080
+/* USLCOM_SET_MHS/USLCOM_GET_MDMSTS values */
+#define	USLCOM_MHS_DTR_ON	0x0001	
+#define	USLCOM_MHS_DTR_SET	0x0100
+#define	USLCOM_MHS_RTS_ON	0x0002
+#define	USLCOM_MHS_RTS_SET	0x0200
+#define	USLCOM_MHS_CTS		0x0010
+#define	USLCOM_MHS_DSR		0x0020
+#define	USLCOM_MHS_RI		0x0040
+#define	USLCOM_MHS_DCD		0x0080
 
-/* USLCOM_SET_BAUD_DIV values */
-#define	USLCOM_BAUD_REF		3686400 /* 3.6864 MHz */
+/* USLCOM_SET_BAUDDIV values */
+#define	USLCOM_BAUDDIV_REF	3686400 /* 3.6864 MHz */
 
-/* USLCOM_DATA values */
+/* USLCOM_SET_LINE_CTL values */
 #define	USLCOM_STOP_BITS_1	0x00
 #define	USLCOM_STOP_BITS_2	0x02
 #define	USLCOM_PARITY_NONE	0x00
 #define	USLCOM_PARITY_ODD	0x10
 #define	USLCOM_PARITY_EVEN	0x20
+#define	USLCOM_SET_DATA_BITS(x)	((x) << 8)
 
-/* USLCOM_BREAK values */
-#define	USLCOM_BREAK_OFF	0x00
-#define	USLCOM_BREAK_ON		0x01
+/* USLCOM_SET_BREAK values */
+#define	USLCOM_SET_BREAK_OFF	0x00
+#define	USLCOM_SET_BREAK_ON	0x01
 
-/* USLCOM_SET_FLOWCTRL values - 1st word */
+/* USLCOM_SET_FLOW values - 1st word */
 #define	USLCOM_FLOW_DTR_ON      0x00000001 /* DTR static active */
 #define	USLCOM_FLOW_CTS_HS      0x00000008 /* CTS handshake */
-/* USLCOM_SET_FLOWCTRL values - 2nd word */
+/* USLCOM_SET_FLOW values - 2nd word */
 #define	USLCOM_FLOW_RTS_ON      0x00000040 /* RTS static active */
 #define	USLCOM_FLOW_RTS_HS      0x00000080 /* RTS handshake */
 
@@ -141,11 +146,13 @@
 static device_probe_t uslcom_probe;
 static device_attach_t uslcom_attach;
 static device_detach_t uslcom_detach;
+static device_free_softc_t uslcom_free_softc;
 
 static usb_callback_t uslcom_write_callback;
 static usb_callback_t uslcom_read_callback;
 static usb_callback_t uslcom_control_callback;
 
+static void	uslcom_free(struct ucom_softc *);
 static void uslcom_open(struct ucom_softc *);
 static void uslcom_close(struct ucom_softc *);
 static void uslcom_set_dtr(struct ucom_softc *, uint8_t);
@@ -207,6 +214,7 @@
 	.ucom_start_write = &uslcom_start_write,
 	.ucom_stop_write = &uslcom_stop_write,
 	.ucom_poll = &uslcom_poll,
+	.ucom_free = &uslcom_free,
 };
 
 static const STRUCT_USB_HOST_ID uslcom_devs[] = {
@@ -323,7 +331,8 @@
 	DEVMETHOD(device_probe, uslcom_probe),
 	DEVMETHOD(device_attach, uslcom_attach),
 	DEVMETHOD(device_detach, uslcom_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, uslcom_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t uslcom_devclass;
@@ -379,6 +388,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "uslcom", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 	usb_callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
 
 	sc->sc_udev = uaa->device;
@@ -424,11 +434,30 @@
 	usbd_transfer_unsetup(sc->sc_xfer, USLCOM_N_TRANSFER);
 
 	usb_callout_drain(&sc->sc_watchdog);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(uslcom);
+
+static void
+uslcom_free_softc(device_t dev, void *arg)
+{
+	struct uslcom_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+uslcom_free(struct ucom_softc *ucom)
+{
+	uslcom_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 uslcom_open(struct ucom_softc *ucom)
 {
@@ -436,8 +465,8 @@
 	struct usb_device_request req;
 
 	req.bmRequestType = USLCOM_WRITE;
-	req.bRequest = USLCOM_UART;
-	USETW(req.wValue, USLCOM_UART_ENABLE);
+	req.bRequest = USLCOM_IFC_ENABLE;
+	USETW(req.wValue, USLCOM_IFC_ENABLE_EN);
 	USETW(req.wIndex, sc->sc_iface_no);
 	USETW(req.wLength, 0);
 
@@ -460,8 +489,8 @@
 	usb_callout_stop(&sc->sc_watchdog);
 
 	req.bmRequestType = USLCOM_WRITE;
-	req.bRequest = USLCOM_UART;
-	USETW(req.wValue, USLCOM_UART_DISABLE);
+	req.bRequest = USLCOM_IFC_ENABLE;
+	USETW(req.wValue, USLCOM_IFC_ENABLE_DIS);
 	USETW(req.wIndex, sc->sc_iface_no);
 	USETW(req.wLength, 0);
 
@@ -480,11 +509,11 @@
 
         DPRINTF("onoff = %d\n", onoff);
 
-	ctl = onoff ? USLCOM_CTRL_DTR_ON : 0;
-	ctl |= USLCOM_CTRL_DTR_SET;
+	ctl = onoff ? USLCOM_MHS_DTR_ON : 0;
+	ctl |= USLCOM_MHS_DTR_SET;
 
 	req.bmRequestType = USLCOM_WRITE;
-	req.bRequest = USLCOM_CTRL;
+	req.bRequest = USLCOM_SET_MHS;
 	USETW(req.wValue, ctl);
 	USETW(req.wIndex, sc->sc_iface_no);
 	USETW(req.wLength, 0);
@@ -504,11 +533,11 @@
 
         DPRINTF("onoff = %d\n", onoff);
 
-	ctl = onoff ? USLCOM_CTRL_RTS_ON : 0;
-	ctl |= USLCOM_CTRL_RTS_SET;
+	ctl = onoff ? USLCOM_MHS_RTS_ON : 0;
+	ctl |= USLCOM_MHS_RTS_SET;
 
 	req.bmRequestType = USLCOM_WRITE;
-	req.bRequest = USLCOM_CTRL;
+	req.bRequest = USLCOM_SET_MHS;
 	USETW(req.wValue, ctl);
 	USETW(req.wIndex, sc->sc_iface_no);
 	USETW(req.wLength, 0);
@@ -539,7 +568,7 @@
 
 	baudrate = t->c_ospeed;
 	req.bmRequestType = USLCOM_WRITE;
-	req.bRequest = USLCOM_SET_BAUD_RATE;
+	req.bRequest = USLCOM_SET_BAUDRATE;
 	USETW(req.wValue, 0);
 	USETW(req.wIndex, sc->sc_iface_no);
 	USETW(req.wLength, sizeof(baudrate));
@@ -576,7 +605,7 @@
 	}
 
 	req.bmRequestType = USLCOM_WRITE;
-	req.bRequest = USLCOM_DATA;
+	req.bRequest = USLCOM_SET_LINE_CTL;
 	USETW(req.wValue, data);
 	USETW(req.wIndex, sc->sc_iface_no);
 	USETW(req.wLength, 0);
@@ -589,16 +618,14 @@
 	if (t->c_cflag & CRTSCTS) {
 		flowctrl[0] = htole32(USLCOM_FLOW_DTR_ON | USLCOM_FLOW_CTS_HS);
 		flowctrl[1] = htole32(USLCOM_FLOW_RTS_HS);
-		flowctrl[2] = 0;
-		flowctrl[3] = 0;
 	} else {
 		flowctrl[0] = htole32(USLCOM_FLOW_DTR_ON);
 		flowctrl[1] = htole32(USLCOM_FLOW_RTS_ON);
-		flowctrl[2] = 0;
-		flowctrl[3] = 0;
 	}
+	flowctrl[2] = 0;
+	flowctrl[3] = 0;
 	req.bmRequestType = USLCOM_WRITE;
-	req.bRequest = USLCOM_SET_FLOWCTRL;
+	req.bRequest = USLCOM_SET_FLOW;
 	USETW(req.wValue, 0);
 	USETW(req.wIndex, sc->sc_iface_no);
 	USETW(req.wLength, sizeof(flowctrl));
@@ -625,10 +652,10 @@
 {
         struct uslcom_softc *sc = ucom->sc_parent;
 	struct usb_device_request req;
-	uint16_t brk = onoff ? USLCOM_BREAK_ON : USLCOM_BREAK_OFF;
+	uint16_t brk = onoff ? USLCOM_SET_BREAK_ON : USLCOM_SET_BREAK_OFF;
 
 	req.bmRequestType = USLCOM_WRITE;
-	req.bRequest = USLCOM_BREAK;
+	req.bRequest = USLCOM_SET_BREAK;
 	USETW(req.wValue, brk);
 	USETW(req.wIndex, sc->sc_iface_no);
 	USETW(req.wLength, 0);
@@ -763,13 +790,13 @@
 	case USB_ST_TRANSFERRED:
 		pc = usbd_xfer_get_frame(xfer, 1);
 		usbd_copy_out(pc, 0, &buf, sizeof(buf));
-		if (buf & USLCOM_CTRL_CTS)
+		if (buf & USLCOM_MHS_CTS)
 			msr |= SER_CTS;
-		if (buf & USLCOM_CTRL_DSR)
+		if (buf & USLCOM_MHS_DSR)
 			msr |= SER_DSR;
-		if (buf & USLCOM_CTRL_RI)
+		if (buf & USLCOM_MHS_RI)
 			msr |= SER_RI;
-		if (buf & USLCOM_CTRL_DCD)
+		if (buf & USLCOM_MHS_DCD)
 			msr |= SER_DCD;
 
 		if (msr != sc->sc_msr) {
@@ -782,7 +809,7 @@
 
 	case USB_ST_SETUP:
 		req.bmRequestType = USLCOM_READ;
-		req.bRequest = USLCOM_RCTRL;
+		req.bRequest = USLCOM_GET_MDMSTS;
 		USETW(req.wValue, 0);
 		USETW(req.wIndex, sc->sc_iface_no);
 		USETW(req.wLength, sizeof(buf));
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uvisor.c
--- a/head/sys/dev/usb/serial/uvisor.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uvisor.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 /*	$NetBSD: uvisor.c,v 1.9 2001/01/23 14:04:14 augustss Exp $	*/
-/*      $FreeBSD: head/sys/dev/usb/serial/uvisor.c 227461 2011-11-12 08:16:45Z hselasky $ */
+/*      $FreeBSD: head/sys/dev/usb/serial/uvisor.c 239180 2012-08-10 15:29:41Z hselasky $ */
 
 /* Also already merged from NetBSD:
  *	$NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $
@@ -189,12 +189,14 @@
 static device_probe_t uvisor_probe;
 static device_attach_t uvisor_attach;
 static device_detach_t uvisor_detach;
+static device_free_softc_t uvisor_free_softc;
 
 static usb_callback_t uvisor_write_callback;
 static usb_callback_t uvisor_read_callback;
 
 static usb_error_t uvisor_init(struct uvisor_softc *, struct usb_device *,
 		    struct usb_config *);
+static void	uvisor_free(struct ucom_softc *);
 static void	uvisor_cfg_open(struct ucom_softc *);
 static void	uvisor_cfg_close(struct ucom_softc *);
 static void	uvisor_start_read(struct ucom_softc *);
@@ -231,13 +233,15 @@
 	.ucom_stop_read = &uvisor_stop_read,
 	.ucom_start_write = &uvisor_start_write,
 	.ucom_stop_write = &uvisor_stop_write,
+	.ucom_free = &uvisor_free,
 };
 
 static device_method_t uvisor_methods[] = {
 	DEVMETHOD(device_probe, uvisor_probe),
 	DEVMETHOD(device_attach, uvisor_attach),
 	DEVMETHOD(device_detach, uvisor_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, uvisor_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t uvisor_devclass;
@@ -317,6 +321,7 @@
 	device_set_usb_desc(dev);
 
 	mtx_init(&sc->sc_mtx, "uvisor", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_udev = uaa->device;
 
@@ -365,11 +370,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UVISOR_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(uvisor);
+
+static void
+uvisor_free_softc(device_t dev, void *arg)
+{
+	struct uvisor_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+uvisor_free(struct ucom_softc *ucom)
+{
+	uvisor_free_softc(NULL, ucom->sc_parent);
+}
+
 static usb_error_t
 uvisor_init(struct uvisor_softc *sc, struct usb_device *udev, struct usb_config *config)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uvscom.c
--- a/head/sys/dev/usb/serial/uvscom.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uvscom.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
 /*	$NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $	*/
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uvscom.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uvscom.c 239180 2012-08-10 15:29:41Z hselasky $");
 
 /*-
  * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -163,11 +163,13 @@
 static device_probe_t uvscom_probe;
 static device_attach_t uvscom_attach;
 static device_detach_t uvscom_detach;
+static device_free_softc_t uvscom_free_softc;
 
 static usb_callback_t uvscom_write_callback;
 static usb_callback_t uvscom_read_callback;
 static usb_callback_t uvscom_intr_callback;
 
+static void	uvscom_free(struct ucom_softc *);
 static void	uvscom_cfg_set_dtr(struct ucom_softc *, uint8_t);
 static void	uvscom_cfg_set_rts(struct ucom_softc *, uint8_t);
 static void	uvscom_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -231,6 +233,7 @@
 	.ucom_start_write = &uvscom_start_write,
 	.ucom_stop_write = &uvscom_stop_write,
 	.ucom_poll = &uvscom_poll,
+	.ucom_free = &uvscom_free,
 };
 
 static const STRUCT_USB_HOST_ID uvscom_devs[] = {
@@ -250,7 +253,8 @@
 	DEVMETHOD(device_probe, uvscom_probe),
 	DEVMETHOD(device_attach, uvscom_attach),
 	DEVMETHOD(device_detach, uvscom_detach),
-	{0, 0}
+	DEVMETHOD(device_free_softc, uvscom_free_softc),
+	DEVMETHOD_END
 };
 
 static devclass_t uvscom_devclass;
@@ -292,6 +296,7 @@
 
 	device_set_usb_desc(dev);
 	mtx_init(&sc->sc_mtx, "uvscom", NULL, MTX_DEF);
+	ucom_ref(&sc->sc_super_ucom);
 
 	sc->sc_udev = uaa->device;
 
@@ -348,11 +353,30 @@
 
 	ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
 	usbd_transfer_unsetup(sc->sc_xfer, UVSCOM_N_TRANSFER);
-	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
 }
 
+UCOM_UNLOAD_DRAIN(uvscom);
+
+static void
+uvscom_free_softc(device_t dev, void *arg)
+{
+	struct uvscom_softc *sc = arg;
+
+	if (ucom_unref(&sc->sc_super_ucom)) {
+		if (mtx_initialized(&sc->sc_mtx))
+			mtx_destroy(&sc->sc_mtx);
+		device_free_softc(dev, sc);
+	}
+}
+
+static void
+uvscom_free(struct ucom_softc *ucom)
+{
+	uvscom_free_softc(NULL, ucom->sc_parent);
+}
+
 static void
 uvscom_write_callback(struct usb_xfer *xfer, usb_error_t error)
 {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb.h
--- a/head/sys/dev/usb/usb.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb.h 233771 2012-04-02 07:51:30Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb.h 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -546,6 +546,8 @@
 	uByte	bDescriptorType;
 	uByte	bMaxBurst;
 	uByte	bmAttributes;
+#define	UE_GET_BULK_STREAMS(x) ((x) & 0x0F)
+#define	UE_GET_SS_ISO_MULT(x) ((x) & 0x03)
 	uWord	wBytesPerInterval;
 } __packed;
 typedef struct usb_endpoint_ss_comp_descriptor
@@ -744,7 +746,7 @@
 #define	USB_REV_MAX	(USB_REV_3_0+1)
 
 /*
- * Supported host contoller modes.
+ * Supported host controller modes.
  */
 enum usb_hc_mode {
 	USB_MODE_HOST,		/* initiates transfers */
@@ -754,7 +756,7 @@
 #define	USB_MODE_MAX	(USB_MODE_DUAL+1)
 
 /*
- * The "USB_MODE" macros defines all the supported device states.
+ * The "USB_STATE" enums define all the supported device states.
  */
 enum usb_dev_state {
 	USB_STATE_DETACHED,
@@ -764,4 +766,18 @@
 	USB_STATE_CONFIGURED,
 };
 #define	USB_STATE_MAX	(USB_STATE_CONFIGURED+1)
+
+/*
+ * The "USB_EP_MODE" macros define all the currently supported
+ * endpoint modes.
+ */
+enum usb_ep_mode {
+	USB_EP_MODE_DEFAULT,
+	USB_EP_MODE_STREAMS,	/* USB3.0 specific */
+	USB_EP_MODE_HW_MASS_STORAGE,
+	USB_EP_MODE_HW_SERIAL,
+	USB_EP_MODE_HW_ETHERNET_CDC,
+	USB_EP_MODE_HW_ETHERNET_NCM,
+	USB_EP_MODE_MAX
+};
 #endif					/* _USB_STANDARD_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_controller.h
--- a/head/sys/dev/usb/usb_controller.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_controller.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_controller.h 234803 2012-04-29 17:12:33Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_controller.h 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -108,7 +108,8 @@
 	/* USB Device mode only - Mandatory */
 
 	void    (*get_hw_ep_profile) (struct usb_device *udev, const struct usb_hw_ep_profile **ppf, uint8_t ep_addr);
-	void    (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, struct usb_endpoint *ep, uint8_t *did_stall);
+	void    (*xfer_stall) (struct usb_xfer *xfer);
+	void    (*set_stall) (struct usb_device *udev, struct usb_endpoint *ep, uint8_t *did_stall);
 
 	/* USB Device mode mandatory. USB Host mode optional. */
 
@@ -143,6 +144,10 @@
 	/* Optional for host mode */
 
 	usb_error_t	(*set_address) (struct usb_device *, struct mtx *, uint16_t);
+
+	/* Optional for device and host mode */
+
+	usb_error_t	(*set_endpoint_mode) (struct usb_device *, struct usb_endpoint *, uint8_t);
 };
 
 /*
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_core.h
--- a/head/sys/dev/usb/usb_core.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_core.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD$ */
+/* $FreeBSD: head/sys/dev/usb/usb_core.h 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -151,6 +151,7 @@
 	usb_frcount_t nframes;		/* number of USB frames to transfer */
 	usb_frcount_t aframes;		/* actual number of USB frames
 					 * transferred */
+	usb_stream_t stream_id;		/* USB3.0 specific field */
 
 	uint16_t max_packet_size;
 	uint16_t max_frame_size;
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_debug.c
--- a/head/sys/dev/usb/usb_debug.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_debug.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD$ */
+/* $FreeBSD: head/sys/dev/usb/usb_debug.c 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -113,10 +113,12 @@
 usb_dump_queue(struct usb_endpoint *ep)
 {
 	struct usb_xfer *xfer;
+	usb_stream_t x;
 
 	printf("usb_dump_queue: endpoint=%p xfer: ", ep);
-	TAILQ_FOREACH(xfer, &ep->endpoint_q.head, wait_entry) {
-		printf(" %p", xfer);
+	for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+		TAILQ_FOREACH(xfer, &ep->endpoint_q[x].head, wait_entry)
+			printf(" %p", xfer);
 	}
 	printf("\n");
 }
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_device.c
--- a/head/sys/dev/usb/usb_device.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_device.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_device.c 236407 2012-06-01 16:30:54Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_device.c 239240 2012-08-13 18:34:04Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -79,6 +79,8 @@
 #include <dev/usb/usb_controller.h>
 #include <dev/usb/usb_bus.h>
 
+#include <dev/led/led.h>
+
 /* function prototypes  */
 
 static void	usb_init_endpoint(struct usb_device *, uint8_t,
@@ -202,7 +204,7 @@
 	/*
 	 * The default endpoint is always present and is checked separately:
 	 */
-	if ((udev->ctrl_ep.edesc) &&
+	if ((udev->ctrl_ep.edesc != NULL) &&
 	    ((udev->ctrl_ep.edesc->bEndpointAddress & EA_MASK) == ea_val)) {
 		ep = &udev->ctrl_ep;
 		goto found;
@@ -320,7 +322,7 @@
 	 * address" and "any direction" returns the first endpoint of the
 	 * interface. "iface_index" and "direction" is ignored:
 	 */
-	if ((udev->ctrl_ep.edesc) &&
+	if ((udev->ctrl_ep.edesc != NULL) &&
 	    ((udev->ctrl_ep.edesc->bEndpointAddress & ea_mask) == ea_val) &&
 	    ((udev->ctrl_ep.edesc->bmAttributes & type_mask) == type_val) &&
 	    (!index)) {
@@ -355,7 +357,6 @@
 	return (USB_ERR_NORMAL_COMPLETION);
 }
 
-
 /*------------------------------------------------------------------------*
  *	usb_init_endpoint
  *
@@ -370,6 +371,7 @@
     struct usb_endpoint *ep)
 {
 	struct usb_bus_methods *methods;
+	usb_stream_t x;
 
 	methods = udev->bus->methods;
 
@@ -379,13 +381,26 @@
 	ep->edesc = edesc;
 	ep->ecomp = ecomp;
 	ep->iface_index = iface_index;
-	TAILQ_INIT(&ep->endpoint_q.head);
-	ep->endpoint_q.command = &usbd_pipe_start;
+
+	/* setup USB stream queues */
+	for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+		TAILQ_INIT(&ep->endpoint_q[x].head);
+		ep->endpoint_q[x].command = &usbd_pipe_start;
+	}
 
 	/* the pipe is not supported by the hardware */
  	if (ep->methods == NULL)
 		return;
 
+	/* check for SUPER-speed streams mode endpoint */
+	if (udev->speed == USB_SPEED_SUPER && ecomp != NULL &&
+	    (edesc->bmAttributes & UE_XFERTYPE) == UE_BULK &&
+	    (UE_GET_BULK_STREAMS(ecomp->bmAttributes) != 0)) {
+		usbd_set_endpoint_mode(udev, ep, USB_EP_MODE_STREAMS);
+	} else {
+		usbd_set_endpoint_mode(udev, ep, USB_EP_MODE_DEFAULT);
+	}
+
 	/* clear stall, if any */
 	if (methods->clear_stall != NULL) {
 		USB_BUS_LOCK(udev->bus);
@@ -933,6 +948,7 @@
     uint8_t do_stall)
 {
 	struct usb_xfer *xfer;
+	usb_stream_t x;
 	uint8_t et;
 	uint8_t was_stalled;
 
@@ -975,18 +991,22 @@
 
 	if (do_stall || (!was_stalled)) {
 		if (!was_stalled) {
-			/* lookup the current USB transfer, if any */
-			xfer = ep->endpoint_q.curr;
-		} else {
-			xfer = NULL;
+			for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+				/* lookup the current USB transfer, if any */
+				xfer = ep->endpoint_q[x].curr;
+				if (xfer != NULL) {
+					/*
+					 * The "xfer_stall" method
+					 * will complete the USB
+					 * transfer like in case of a
+					 * timeout setting the error
+					 * code "USB_ERR_STALLED".
+					 */
+					(udev->bus->methods->xfer_stall) (xfer);
+				}
+			}
 		}
-
-		/*
-		 * If "xfer" is non-NULL the "set_stall" method will
-		 * complete the USB transfer like in case of a timeout
-		 * setting the error code "USB_ERR_STALLED".
-		 */
-		(udev->bus->methods->set_stall) (udev, xfer, ep, &do_stall);
+		(udev->bus->methods->set_stall) (udev, ep, &do_stall);
 	}
 	if (!do_stall) {
 		ep->toggle_next = 0;	/* reset data toggle */
@@ -994,8 +1014,11 @@
 
 		(udev->bus->methods->clear_stall) (udev, ep);
 
-		/* start up the current or next transfer, if any */
-		usb_command_wrapper(&ep->endpoint_q, ep->endpoint_q.curr);
+		/* start the current or next transfer, if any */
+		for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+			usb_command_wrapper(&ep->endpoint_q[x],
+			    ep->endpoint_q[x].curr);
+		}
 	}
 	USB_BUS_UNLOCK(udev->bus);
 	return (0);
@@ -1891,6 +1914,9 @@
 #if USB_HAVE_DEVCTL
 	usb_notify_addq("ATTACH", udev);
 #endif
+	/* Enable USB LED if new device is not USB HUB */
+	if (udev->ddesc.bDeviceClass != UDCLASS_HUB)
+		led_set("usb", "0");
 done:
 	if (err) {
 		/*
@@ -2050,6 +2076,10 @@
 	bus = udev->bus;
 	usb_set_device_state(udev, USB_STATE_DETACHED);
 
+	/* Disable USB LED if new device is not USB HUB */
+	if (udev->ddesc.bDeviceClass != UDCLASS_HUB)
+		led_set("usb", "1");
+
 #if USB_HAVE_DEVCTL
 	usb_notify_addq("DETACH", udev);
 #endif
@@ -2745,3 +2775,47 @@
 	}
 	return (USB_ERR_NOMEM);
 }
+
+/*
+ * The following function is used to select the endpoint mode. It
+ * should not be called outside enumeration context.
+ */
+
+usb_error_t
+usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep,
+    uint8_t ep_mode)
+{   
+	usb_error_t error;
+	uint8_t do_unlock;
+
+	/* automatic locking */
+	if (usbd_enum_is_locked(udev)) {
+		do_unlock = 0;
+	} else {
+		do_unlock = 1;
+		usbd_enum_lock(udev);
+	}
+
+	if (udev->bus->methods->set_endpoint_mode != NULL) {
+		error = (udev->bus->methods->set_endpoint_mode) (
+		    udev, ep, ep_mode);
+	} else if (ep_mode != USB_EP_MODE_DEFAULT) {
+		error = USB_ERR_INVAL;
+	} else {
+		error = 0;
+	}
+
+	/* only set new mode regardless of error */
+	ep->ep_mode = ep_mode;
+
+	if (do_unlock)
+		usbd_enum_unlock(udev);
+
+	return (error);
+}
+
+uint8_t
+usbd_get_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep)
+{
+	return (ep->ep_mode);
+}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_device.h
--- a/head/sys/dev/usb/usb_device.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_device.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_device.h 225350 2011-09-02 18:50:44Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_device.h 239176 2012-08-10 14:44:04Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -33,7 +33,7 @@
 
 #define	USB_CTRL_XFER_MAX 2
 
-/* "usb_parse_config()" commands */
+/* "usb_config_parse()" commands */
 
 #define	USB_CFG_ALLOC 0
 #define	USB_CFG_FREE 1
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_freebsd.h
--- a/head/sys/dev/usb/usb_freebsd.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_freebsd.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_freebsd.h 225350 2011-09-02 18:50:44Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_freebsd.h 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -60,6 +60,7 @@
 #define	USB_MAX_DEVICES 128		/* units */
 #define	USB_IFACE_MAX 32		/* units */
 #define	USB_FIFO_MAX 128		/* units */
+#define	USB_MAX_EP_STREAMS 8		/* units */
 
 #define	USB_MAX_FS_ISOC_FRAMES_PER_XFER (120)	/* units */
 #define	USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120)	/* units */
@@ -76,5 +77,6 @@
 typedef uint32_t usb_size_t;		/* bytes */
 typedef uint32_t usb_ticks_t;		/* system defined */
 typedef uint16_t usb_power_mask_t;	/* see "USB_HW_POWER_XXX" */
+typedef uint16_t usb_stream_t;		/* stream ID */
 
 #endif	/* _USB_FREEBSD_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_generic.c
--- a/head/sys/dev/usb/usb_generic.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_generic.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_generic.c 236407 2012-06-01 16:30:54Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_generic.c 239238 2012-08-13 18:09:19Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -253,6 +253,7 @@
 
 	usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
 	usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
+	usb_config[0].stream_id = 0;	/* XXX support more stream ID's */
 	usb_config[0].direction = UE_DIR_TX;
 	usb_config[0].interval = USB_DEFAULT_INTERVAL;
 	usb_config[0].flags.proxy_buffer = 1;
@@ -321,6 +322,7 @@
 
 	usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
 	usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
+	usb_config[0].stream_id = 0;	/* XXX support more stream ID's */
 	usb_config[0].direction = UE_DIR_RX;
 	usb_config[0].interval = USB_DEFAULT_INTERVAL;
 	usb_config[0].flags.proxy_buffer = 1;
@@ -1391,6 +1393,7 @@
 		struct usb_fs_start *pstart;
 		struct usb_fs_stop *pstop;
 		struct usb_fs_open *popen;
+		struct usb_fs_open_stream *popen_stream;
 		struct usb_fs_close *pclose;
 		struct usb_fs_clear_stall_sync *pstall;
 		void   *addr;
@@ -1455,6 +1458,7 @@
 		break;
 
 	case USB_FS_OPEN:
+	case USB_FS_OPEN_STREAM:
 		if (u.popen->ep_index >= f->fs_ep_max) {
 			error = EINVAL;
 			break;
@@ -1506,6 +1510,8 @@
 		usb_config[0].frames = u.popen->max_frames;
 		usb_config[0].bufsize = u.popen->max_bufsize;
 		usb_config[0].usb_mode = USB_MODE_DUAL;	/* both modes */
+		if (cmd == USB_FS_OPEN_STREAM)
+			usb_config[0].stream_id = u.popen_stream->stream_id;
 
 		if (usb_config[0].type == UE_CONTROL) {
 			if (f->udev->flags.usb_mode != USB_MODE_HOST) {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_hub.c
--- a/head/sys/dev/usb/usb_hub.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_hub.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_hub.c 234803 2012-04-29 17:12:33Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_hub.c 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -1757,9 +1757,11 @@
 			data_len += len;
 		}
 
-		/* check double buffered transfers */
-
-		TAILQ_FOREACH(pipe_xfer, &xfer->endpoint->endpoint_q.head,
+		/*
+		 * Check double buffered transfers. Only stream ID
+		 * equal to zero is valid here!
+		 */
+		TAILQ_FOREACH(pipe_xfer, &xfer->endpoint->endpoint_q[0].head,
 		    wait_entry) {
 
 			/* skip self, if any */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_ioctl.h
--- a/head/sys/dev/usb/usb_ioctl.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_ioctl.h	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_ioctl.h 227463 2011-11-12 08:40:52Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_ioctl.h 239238 2012-08-13 18:09:19Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -206,6 +206,11 @@
 	uint8_t	ep_no;			/* bEndpointNumber */
 };
 
+struct usb_fs_open_stream {
+	struct usb_fs_open fs_open;
+	uint16_t stream_id;
+};
+
 struct usb_fs_close {
 	uint8_t	ep_index;
 };
@@ -302,6 +307,7 @@
 #define	USB_FS_OPEN		_IOWR('U', 197, struct usb_fs_open)
 #define	USB_FS_CLOSE		_IOW ('U', 198, struct usb_fs_close)
 #define	USB_FS_CLEAR_STALL_SYNC _IOW ('U', 199, struct usb_fs_clear_stall_sync)
+#define	USB_FS_OPEN_STREAM	_IOWR('U', 200, struct usb_fs_open_stream)
 
 /* USB quirk system interface */
 #define	USB_DEV_QUIRK_GET	_IOWR('Q', 0, struct usb_gen_quirk)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_msctest.c
--- a/head/sys/dev/usb/usb_msctest.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_msctest.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_msctest.c 233774 2012-04-02 10:50:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_msctest.c 239237 2012-08-13 18:00:34Z hselasky $ */
 /*-
  * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved.
  *
@@ -103,6 +103,8 @@
 					  0x00, 0x00, 0x00, 0x00 };
 static uint8_t scsi_request_sense[] =	{ 0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
 					  0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_read_capacity[] =	{ 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
+					  0x00, 0x00, 0x00, 0x00 };
 
 #define	BULK_SIZE		64	/* dummy */
 #define	ERR_CSW_FAILED		-1
@@ -652,7 +654,7 @@
 	}
 
 	is_no_direct = 1;
-	for (timeout = 4; timeout; timeout--) {
+	for (timeout = 4; timeout != 0; timeout--) {
 		err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
 		    SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
 		    USB_MS_HZ);
@@ -681,7 +683,9 @@
 		if (err != ERR_CSW_FAILED)
 			goto error;
 	}
+	timeout = 1;
 
+retry_sync_cache:
 	err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
 	    &scsi_sync_cache, sizeof(scsi_sync_cache),
 	    USB_MS_HZ);
@@ -694,6 +698,42 @@
 		DPRINTF("Device doesn't handle synchronize cache\n");
 
 		usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+
+	} else {
+
+		/*
+		 * Certain Kingston memory sticks fail the first
+		 * read capacity after a synchronize cache command
+		 * has been issued. Disable the synchronize cache
+		 * command for such devices.
+		 */
+
+		err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+		    &scsi_read_capacity, sizeof(scsi_read_capacity),
+		    USB_MS_HZ);
+
+		if (err != 0) {
+			if (err != ERR_CSW_FAILED)
+				goto error;
+
+			err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+			    &scsi_read_capacity, sizeof(scsi_read_capacity),
+			    USB_MS_HZ);
+
+			if (err == 0) {
+				if (timeout--)
+					goto retry_sync_cache;
+
+				DPRINTF("Device most likely doesn't "
+				    "handle synchronize cache\n");
+
+				usbd_add_dynamic_quirk(udev,
+				    UQ_MSC_NO_SYNC_CACHE);
+			} else {
+				if (err != ERR_CSW_FAILED)
+					goto error;
+			}
+		}
 	}
 
 	/* clear sense status of any failed commands on the device */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_request.c
--- a/head/sys/dev/usb/usb_request.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_request.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_request.c 233774 2012-04-02 10:50:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_request.c 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -228,6 +228,7 @@
 	struct usb_endpoint *ep;
 	struct usb_endpoint *ep_end;
 	struct usb_endpoint *ep_first;
+	usb_stream_t x;
 	uint8_t to;
 
 	udev = xfer->xroot->udev;
@@ -255,9 +256,11 @@
 			ep->is_stalled = 0;
 			/* some hardware needs a callback to clear the data toggle */
 			usbd_clear_stall_locked(udev, ep);
-			/* start up the current or next transfer, if any */
-			usb_command_wrapper(&ep->endpoint_q,
-			    ep->endpoint_q.curr);
+			for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+				/* start the current or next transfer, if any */
+				usb_command_wrapper(&ep->endpoint_q[x],
+				    ep->endpoint_q[x].curr);
+			}
 		}
 		ep++;
 
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_transfer.c
--- a/head/sys/dev/usb/usb_transfer.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_transfer.c	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_transfer.c 236070 2012-05-26 08:33:53Z marius $ */
+/* $FreeBSD: head/sys/dev/usb/usb_transfer.c 239214 2012-08-12 17:53:06Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -358,7 +358,8 @@
 		switch (type) {
 		case UE_ISOCHRONOUS:
 		case UE_INTERRUPT:
-			xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
+			xfer->max_packet_count +=
+			    (xfer->max_packet_size >> 11) & 3;
 
 			/* check for invalid max packet count */
 			if (xfer->max_packet_count > 3)
@@ -387,7 +388,8 @@
 			if (ecomp != NULL) {
 				uint8_t mult;
 
-				mult = (ecomp->bmAttributes & 3) + 1;
+				mult = UE_GET_SS_ISO_MULT(
+				    ecomp->bmAttributes) + 1;
 				if (mult > 3)
 					mult = 3;
 
@@ -946,7 +948,20 @@
 			ep = usbd_get_endpoint(udev,
 			    ifaces[setup->if_index], setup);
 
-			if ((ep == NULL) || (ep->methods == NULL)) {
+			/*
+			 * Check that the USB PIPE is valid and that
+			 * the endpoint mode is proper.
+			 *
+			 * Make sure we don't allocate a streams
+			 * transfer when such a combination is not
+			 * valid.
+			 */
+			if ((ep == NULL) || (ep->methods == NULL) ||
+			    ((ep->ep_mode != USB_EP_MODE_STREAMS) &&
+			    (ep->ep_mode != USB_EP_MODE_DEFAULT)) ||
+			    (setup->stream_id != 0 &&
+			    (setup->stream_id >= USB_MAX_EP_STREAMS ||
+			    (ep->ep_mode != USB_EP_MODE_STREAMS)))) {
 				if (setup->flags.no_pipe_ok)
 					continue;
 				if ((setup->usb_mode != USB_MODE_DUAL) &&
@@ -990,6 +1005,9 @@
 			/* set transfer endpoint pointer */
 			xfer->endpoint = ep;
 
+			/* set transfer stream ID */
+			xfer->stream_id = setup->stream_id;
+
 			parm.size[0] += sizeof(xfer[0]);
 			parm.methods = xfer->endpoint->methods;
 			parm.curr_xfer = xfer;
@@ -1575,7 +1593,8 @@
 			USB_BUS_LOCK(bus);
 			xfer->flags_int.can_cancel_immed = 1;
 			/* start the transfer */
-			usb_command_wrapper(&xfer->endpoint->endpoint_q, xfer);
+			usb_command_wrapper(&xfer->endpoint->
+			    endpoint_q[xfer->stream_id], xfer);
 			USB_BUS_UNLOCK(bus);
 			return;
 		}
@@ -1696,7 +1715,7 @@
 	}
 
 	/* start the transfer */
-	usb_command_wrapper(&ep->endpoint_q, xfer);
+	usb_command_wrapper(&ep->endpoint_q[xfer->stream_id], xfer);
 	USB_BUS_UNLOCK(xfer->xroot->bus);
 }
 
@@ -1817,8 +1836,9 @@
 		 * If the current USB transfer is completing we need
 		 * to start the next one:
 		 */
-		if (ep->endpoint_q.curr == xfer) {
-			usb_command_wrapper(&ep->endpoint_q, NULL);
+		if (ep->endpoint_q[xfer->stream_id].curr == xfer) {
+			usb_command_wrapper(
+			    &ep->endpoint_q[xfer->stream_id], NULL);
 		}
 	}
 
@@ -2533,7 +2553,7 @@
 
 			if (udev->flags.usb_mode == USB_MODE_DEVICE) {
 				(udev->bus->methods->set_stall) (
-				    udev, NULL, ep, &did_stall);
+				    udev, ep, &did_stall);
 			} else if (udev->ctrl_xfer[1]) {
 				info = udev->ctrl_xfer[1]->xroot;
 				usb_proc_msignal(
@@ -2800,10 +2820,11 @@
 	 * next one:
 	 */
 	USB_BUS_LOCK(bus);
-	if (ep->endpoint_q.curr == xfer) {
-		usb_command_wrapper(&ep->endpoint_q, NULL);
-
-		if (ep->endpoint_q.curr || TAILQ_FIRST(&ep->endpoint_q.head)) {
+	if (ep->endpoint_q[xfer->stream_id].curr == xfer) {
+		usb_command_wrapper(&ep->endpoint_q[xfer->stream_id], NULL);
+
+		if (ep->endpoint_q[xfer->stream_id].curr != NULL ||
+		    TAILQ_FIRST(&ep->endpoint_q[xfer->stream_id].head) != NULL) {
 			/* there is another USB transfer waiting */
 		} else {
 			/* this is the last USB transfer */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usbdevs
--- a/head/sys/dev/usb/usbdevs	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usbdevs	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-$FreeBSD: head/sys/dev/usb/usbdevs 239055 2012-08-05 11:50:56Z hselasky $
+$FreeBSD: head/sys/dev/usb/usbdevs 239275 2012-08-15 04:03:55Z gonzo $
 /* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
 
 /*-
@@ -3858,6 +3858,7 @@
 product SMC2 2020HUB		0x2020	USB Hub
 product SMC2 2514HUB		0x2514	USB Hub
 product SMC3 2662WUSB		0xa002	2662W-AR Wireless
+product SMC2 LAN9514_ETH	0xec00	USB/Ethernet
 
 /* SOHOware products */
 product SOHOWARE NUB100		0x9100	10/100 USB Ethernet
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usbdi.h
--- a/head/sys/dev/usb/usbdi.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usbdi.h	Wed Aug 15 11:46:11 2012 +0300
@@ -21,7 +21,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/dev/usb/usbdi.h 233774 2012-04-02 10:50:42Z hselasky $
+ * $FreeBSD: head/sys/dev/usb/usbdi.h 239214 2012-08-12 17:53:06Z hselasky $
  */
 #ifndef _USB_USBDI_H_
 #define _USB_USBDI_H_
@@ -133,7 +133,8 @@
  * USB endpoint.
  */
 struct usb_endpoint {
-	struct usb_xfer_queue endpoint_q;	/* queue of USB transfers */
+	/* queue of USB transfers */
+	struct usb_xfer_queue endpoint_q[USB_MAX_EP_STREAMS];
 
 	struct usb_endpoint_descriptor *edesc;
 	struct usb_endpoint_ss_comp_descriptor *ecomp;
@@ -156,6 +157,10 @@
 	uint8_t	usb_smask;		/* USB start mask */
 	uint8_t	usb_cmask;		/* USB complete mask */
 	uint8_t	usb_uframe;		/* USB microframe */
+
+	/* USB endpoint mode, see USB_EP_MODE_XXX */
+
+	uint8_t ep_mode;
 };
 
 /*
@@ -220,6 +225,7 @@
 #define	USB_DEFAULT_INTERVAL	0
 	usb_timeout_t timeout;		/* transfer timeout in milliseconds */
 	struct usb_xfer_flags flags;	/* transfer flags */
+	usb_stream_t stream_id;		/* USB3.0 specific */
 	enum usb_hc_mode usb_mode;	/* host or device mode */
 	uint8_t	type;			/* pipe type */
 	uint8_t	endpoint;		/* pipe number */
@@ -477,6 +483,10 @@
 			uint8_t iface_index, const char *pnpinfo);
 usb_error_t	usbd_add_dynamic_quirk(struct usb_device *udev,
 			uint16_t quirk);
+usb_error_t	usbd_set_endpoint_mode(struct usb_device *udev,
+			struct usb_endpoint *ep, uint8_t ep_mode);
+uint8_t		usbd_get_endpoint_mode(struct usb_device *udev,
+			struct usb_endpoint *ep);
 
 const struct usb_device_id *usbd_lookup_id_by_info(
 	    const struct usb_device_id *id, usb_size_t sizeof_id,
diff -r a301a330526b -r 49889ad5ef1f head/sys/fs/nfsclient/nfs_clbio.c
--- a/head/sys/fs/nfsclient/nfs_clbio.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/fs/nfsclient/nfs_clbio.c	Wed Aug 15 11:46:11 2012 +0300
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clbio.c 239065 2012-08-05 14:11:42Z kib $");
+__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clbio.c 239246 2012-08-14 11:45:47Z kib $");
 
 #include "opt_kdtrace.h"
 
@@ -218,14 +218,18 @@
 			    ("nfs_getpages: page %p is dirty", m));
 		} else {
 			/*
-			 * Read operation was short.  If no error occured
-			 * we may have hit a zero-fill section.   We simply
-			 * leave valid set to 0.
+			 * Read operation was short.  If no error
+			 * occured we may have hit a zero-fill
+			 * section.  We leave valid set to 0, and page
+			 * is freed by vm_page_readahead_finish() if
+			 * its index is not equal to requested, or
+			 * page is zeroed and set valid by
+			 * vm_pager_get_pages() for requested page.
 			 */
 			;
 		}
 		if (i != ap->a_reqpage)
-			vm_page_readahead_finish(m, error);
+			vm_page_readahead_finish(m);
 	}
 	VM_OBJECT_UNLOCK(object);
 	return (0);
diff -r a301a330526b -r 49889ad5ef1f head/sys/fs/nwfs/nwfs_io.c
--- a/head/sys/fs/nwfs/nwfs_io.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/fs/nwfs/nwfs_io.c	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/fs/nwfs/nwfs_io.c 239065 2012-08-05 14:11:42Z kib $
+ * $FreeBSD: head/sys/fs/nwfs/nwfs_io.c 239246 2012-08-14 11:45:47Z kib $
  *
  */
 #include <sys/param.h>
@@ -459,7 +459,7 @@
 		}
 
 		if (i != ap->a_reqpage)
-			vm_page_readahead_finish(m, error);
+			vm_page_readahead_finish(m);
 	}
 	VM_OBJECT_UNLOCK(object);
 	return 0;
diff -r a301a330526b -r 49889ad5ef1f head/sys/fs/smbfs/smbfs_io.c
--- a/head/sys/fs/smbfs/smbfs_io.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/fs/smbfs/smbfs_io.c	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/fs/smbfs/smbfs_io.c 239065 2012-08-05 14:11:42Z kib $
+ * $FreeBSD: head/sys/fs/smbfs/smbfs_io.c 239246 2012-08-14 11:45:47Z kib $
  *
  */
 #include <sys/param.h>
@@ -523,7 +523,7 @@
 		}
 
 		if (i != reqpage)
-			vm_page_readahead_finish(m, error);
+			vm_page_readahead_finish(m);
 	}
 	VM_OBJECT_UNLOCK(object);
 	return 0;
diff -r a301a330526b -r 49889ad5ef1f head/sys/geom/eli/g_eli_key_cache.c
--- a/head/sys/geom/eli/g_eli_key_cache.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/geom/eli/g_eli_key_cache.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/geom/eli/g_eli_key_cache.c 238116 2012-07-04 17:54:17Z pjd $");
+__FBSDID("$FreeBSD: head/sys/geom/eli/g_eli_key_cache.c 239184 2012-08-10 18:43:29Z pjd $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -193,24 +193,24 @@
 void
 g_eli_key_init(struct g_eli_softc *sc)
 {
+	uint8_t *mkey;
 
 	mtx_lock(&sc->sc_ekeys_lock);
+
+	mkey = sc->sc_mkey + sizeof(sc->sc_ivkey);
+	if ((sc->sc_flags & G_ELI_FLAG_AUTH) == 0)
+		bcopy(mkey, sc->sc_ekey, G_ELI_DATAKEYLEN);
+	else {
+		/*
+		 * The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
+		 */
+		g_eli_crypto_hmac(mkey, G_ELI_MAXKEYLEN, "\x10", 1,
+		    sc->sc_ekey, 0);
+	}
+
 	if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0) {
-		uint8_t *mkey;
-
-		mkey = sc->sc_mkey + sizeof(sc->sc_ivkey);
-
 		sc->sc_ekeys_total = 1;
 		sc->sc_ekeys_allocated = 0;
-		if ((sc->sc_flags & G_ELI_FLAG_AUTH) == 0)
-			bcopy(mkey, sc->sc_ekey, G_ELI_DATAKEYLEN);
-		else {
-			/*
-			 * The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
-			 */
-			g_eli_crypto_hmac(mkey, G_ELI_MAXKEYLEN, "\x10", 1,
-			    sc->sc_ekey, 0);
-		}
 	} else {
 		off_t mediasize;
 		size_t blocksize;
@@ -241,6 +241,7 @@
 			    (uintmax_t)sc->sc_ekeys_allocated));
 		}
 	}
+
 	mtx_unlock(&sc->sc_ekeys_lock);
 }
 
diff -r a301a330526b -r 49889ad5ef1f head/sys/geom/raid/g_raid.c
--- a/head/sys/geom/raid/g_raid.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/geom/raid/g_raid.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/geom/raid/g_raid.c 235076 2012-05-06 11:32:36Z mav $");
+__FBSDID("$FreeBSD: head/sys/geom/raid/g_raid.c 239175 2012-08-10 13:36:33Z mav $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -218,6 +218,8 @@
 	switch (event) {
 	case G_RAID_SUBDISK_E_NEW:
 		return ("NEW");
+	case G_RAID_SUBDISK_E_FAILED:
+		return ("FAILED");
 	case G_RAID_SUBDISK_E_DISCONNECTED:
 		return ("DISCONNECTED");
 	default:
diff -r a301a330526b -r 49889ad5ef1f head/sys/i386/conf/XENHVM
--- a/head/sys/i386/conf/XENHVM	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/i386/conf/XENHVM	Wed Aug 15 11:46:11 2012 +0300
@@ -1,13 +1,11 @@
 #
 # XENHVM -- Xen HVM kernel configuration file for FreeBSD/i386
 #
-# $FreeBSD: head/sys/i386/conf/XENHVM 230185 2012-01-16 02:42:41Z cperciva $
+# $FreeBSD: head/sys/i386/conf/XENHVM 239228 2012-08-13 07:36:57Z cperciva $
 #
 include		GENERIC
 ident		XENHVM
 
-makeoptions	MODULES_OVERRIDE=""
-
 #
 # Adaptive locks rely on a lock-free pointer read to determine the run state
 # of the thread holding a lock when under contention; under a virtualisation
diff -r a301a330526b -r 49889ad5ef1f head/sys/i386/i386/mp_machdep.c
--- a/head/sys/i386/i386/mp_machdep.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/i386/i386/mp_machdep.c	Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/i386/i386/mp_machdep.c 236938 2012-06-12 00:14:54Z iwasaki $");
+__FBSDID("$FreeBSD: head/sys/i386/i386/mp_machdep.c 239241 2012-08-13 18:52:51Z jhb $");
 
 #include "opt_apic.h"
 #include "opt_cpu.h"
@@ -1136,26 +1136,15 @@
 {
 
 	/*
-	 * first we do an INIT/RESET IPI this INIT IPI might be run, reseting
+	 * first we do an INIT IPI: this INIT IPI might be run, resetting
 	 * and running the target CPU. OR this INIT IPI might be latched (P5
 	 * bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
 	 * ignored.
 	 */
-
-	/* do an INIT IPI: assert RESET */
 	lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
 	    APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
-
-	/* wait for pending status end */
 	lapic_ipi_wait(-1);
-
-	/* do an INIT IPI: deassert RESET */
-	lapic_ipi_raw(APIC_DEST_ALLESELF | APIC_TRIGMOD_LEVEL |
-	    APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, 0);
-
-	/* wait for pending status end */
 	DELAY(10000);		/* wait ~10mS */
-	lapic_ipi_wait(-1);
 
 	/*
 	 * next we do a STARTUP IPI: the previous INIT IPI might still be
@@ -1165,8 +1154,6 @@
 	 * run. OR the previous INIT IPI was ignored. and this STARTUP IPI
 	 * will run.
 	 */
-
-	/* do a STARTUP IPI */
 	lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
 	    APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
 	    vector, apic_id);
@@ -1179,7 +1166,6 @@
 	 * this STARTUP IPI will be ignored, as only ONE STARTUP IPI is
 	 * recognized after hardware RESET or INIT IPI.
 	 */
-
 	lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
 	    APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
 	    vector, apic_id);
diff -r a301a330526b -r 49889ad5ef1f head/sys/i386/include/param.h
--- a/head/sys/i386/include/param.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/i386/include/param.h	Wed Aug 15 11:46:11 2012 +0300
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	from: @(#)param.h	5.8 (Berkeley) 6/28/91
- * $FreeBSD: head/sys/i386/include/param.h 224207 2011-07-19 00:37:24Z attilio $
+ * $FreeBSD: head/sys/i386/include/param.h 239255 2012-08-14 17:01:21Z des $
  */
 
 #include <machine/_align.h>
@@ -123,14 +123,6 @@
 #define KSTACK_GUARD_PAGES 1	/* pages of kstack guard; 0 disables */
 
 /*
- * Ceiling on amount of swblock kva space, can be changed via
- * the kern.maxswzone /boot/loader.conf variable.
- */
-#ifndef VM_SWZONE_SIZE_MAX
-#define VM_SWZONE_SIZE_MAX	(32 * 1024 * 1024)
-#endif
-
-/*
  * Ceiling on size of buffer cache (really only effects write queueing,
  * the VM page cache is not effected), can be changed via
  * the kern.maxbcache /boot/loader.conf variable.
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/device_if.m
--- a/head/sys/kern/device_if.m	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/device_if.m	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/sys/kern/device_if.m 222253 2011-05-24 13:22:40Z jhb $
+# $FreeBSD: head/sys/kern/device_if.m 239178 2012-08-10 15:02:49Z hselasky $
 #
 
 #include <sys/bus.h>
@@ -316,3 +316,14 @@
 METHOD int quiesce {
 	device_t dev;
 } DEFAULT null_quiesce;
+
+/**
+ * @brief Free the device softc
+ *
+ * @param _dev		device pointer
+ * @param _softc	pointer to softc
+ */
+METHOD void free_softc {
+	device_t	_dev;
+	void		*_softc;
+} DEFAULT device_free_softc;
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/kern_environment.c
--- a/head/sys/kern/kern_environment.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/kern_environment.c	Wed Aug 15 11:46:11 2012 +0300
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/kern_environment.c 225617 2011-09-16 13:58:51Z kmacy $");
+__FBSDID("$FreeBSD: head/sys/kern/kern_environment.c 239257 2012-08-14 19:16:30Z jh $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -143,9 +143,9 @@
 		break;
 	}
 
-	name = malloc(KENV_MNAMELEN, M_TEMP, M_WAITOK);
+	name = malloc(KENV_MNAMELEN + 1, M_TEMP, M_WAITOK);
 
-	error = copyinstr(uap->name, name, KENV_MNAMELEN, NULL);
+	error = copyinstr(uap->name, name, KENV_MNAMELEN + 1, NULL);
 	if (error)
 		goto done;
 
@@ -176,8 +176,8 @@
 			error = EINVAL;
 			goto done;
 		}
-		if (len > KENV_MVALLEN)
-			len = KENV_MVALLEN;
+		if (len > KENV_MVALLEN + 1)
+			len = KENV_MVALLEN + 1;
 		value = malloc(len, M_TEMP, M_WAITOK);
 		error = copyinstr(uap->value, value, len, NULL);
 		if (error) {
@@ -389,10 +389,10 @@
 	KENV_CHECK;
 
 	namelen = strlen(name) + 1;
-	if (namelen > KENV_MNAMELEN)
+	if (namelen > KENV_MNAMELEN + 1)
 		return (-1);
 	vallen = strlen(value) + 1;
-	if (vallen > KENV_MVALLEN)
+	if (vallen > KENV_MVALLEN + 1)
 		return (-1);
 	buf = malloc(namelen + vallen, M_KENV, M_WAITOK);
 	sprintf(buf, "%s=%s", name, value);
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/kern_umtx.c
--- a/head/sys/kern/kern_umtx.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/kern_umtx.c	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/kern_umtx.c 234302 2012-04-14 23:53:31Z davide $");
+__FBSDID("$FreeBSD: head/sys/kern/kern_umtx.c 239202 2012-08-11 23:48:39Z davidxu $");
 
 #include "opt_compat.h"
 #include "opt_umtx_profiling.h"
@@ -587,11 +587,10 @@
 		&umtxtime->_timeout);
 }
 
-static int
+static inline void
 abs_timeout_update(struct abs_timeout *timo)
 {
 	kern_clock_gettime(curthread, timo->clockid, &timo->cur);
-	return (timespeccmp(&timo->cur, &timo->end, >=));
 }
 
 static int
@@ -599,6 +598,8 @@
 {
 	struct timespec tts;
 
+	if (timespeccmp(&timo->end, &timo->cur, <=))
+		return (-1); 
 	tts = timo->end;
 	timespecsub(&tts, &timo->cur);
 	return (tstohz(&tts));
@@ -609,26 +610,29 @@
  * thread was removed from umtx queue.
  */
 static inline int
-umtxq_sleep(struct umtx_q *uq, const char *wmesg, struct abs_timeout *timo)
+umtxq_sleep(struct umtx_q *uq, const char *wmesg, struct abs_timeout *abstime)
 {
 	struct umtxq_chain *uc;
-	int error;
+	int error, timo;
 
 	uc = umtxq_getchain(&uq->uq_key);
 	UMTXQ_LOCKED_ASSERT(uc);
 	for (;;) {
 		if (!(uq->uq_flags & UQF_UMTXQ))
 			return (0);
-		error = msleep(uq, &uc->uc_lock, PCATCH, wmesg,
-		    timo == NULL ? 0 : abs_timeout_gethz(timo));
-		if (error != EWOULDBLOCK)
-			break;
-		umtxq_unlock(&uq->uq_key);
-		if (abs_timeout_update(timo)) {
-			error = ETIMEDOUT;
+		if (abstime != NULL) {
+			timo = abs_timeout_gethz(abstime);
+			if (timo < 0)
+				return (ETIMEDOUT);
+		} else
+			timo = 0;
+		error = msleep(uq, &uc->uc_lock, PCATCH | PDROP, wmesg, timo);
+		if (error != EWOULDBLOCK) {
 			umtxq_lock(&uq->uq_key);
 			break;
 		}
+		if (abstime != NULL)
+			abs_timeout_update(abstime);
 		umtxq_lock(&uq->uq_key);
 	}
 	return (error);
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/ksched.c
--- a/head/sys/kern/ksched.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/ksched.c	Wed Aug 15 11:46:11 2012 +0300
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/ksched.c 222802 2011-06-07 02:50:14Z davidxu $");
+__FBSDID("$FreeBSD: head/sys/kern/ksched.c 239183 2012-08-10 18:19:57Z mav $");
 
 #include "opt_posix.h"
 
@@ -64,7 +64,7 @@
 	struct ksched *ksched= p31b_malloc(sizeof(*ksched));
 
 	ksched->rr_interval.tv_sec = 0;
-	ksched->rr_interval.tv_nsec = 1000000000L / sched_rr_interval();
+	ksched->rr_interval.tv_nsec = 1000000000L / hz * sched_rr_interval();
 
 	*p = ksched;
 	return 0;
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/sched_4bsd.c
--- a/head/sys/kern/sched_4bsd.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/sched_4bsd.c	Wed Aug 15 11:46:11 2012 +0300
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/sched_4bsd.c 239157 2012-08-09 19:26:13Z mav $");
+__FBSDID("$FreeBSD: head/sys/kern/sched_4bsd.c 239196 2012-08-11 20:24:39Z mav $");
 
 #include "opt_hwpmc_hooks.h"
 #include "opt_sched.h"
@@ -119,9 +119,9 @@
 static struct td_sched td_sched0;
 struct mtx sched_lock;
 
-static int	realstathz;	/* stathz is sometimes 0 and run off of hz. */
+static int	realstathz = 127; /* stathz is sometimes 0 and run off of hz. */
 static int	sched_tdcnt;	/* Total runnable threads in the system. */
-static int	sched_slice = 1; /* Thread run time before rescheduling. */
+static int	sched_slice = 12; /* Thread run time before rescheduling. */
 
 static void	setup_runqs(void);
 static void	schedcpu(void);
@@ -185,12 +185,33 @@
 	runq_init(&runq);
 }
 
+static int
+sysctl_kern_quantum(SYSCTL_HANDLER_ARGS)
+{
+	int error, new_val, period;
+
+	period = 1000000 / realstathz;
+	new_val = period * sched_slice;
+	error = sysctl_handle_int(oidp, &new_val, 0, req);
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+	if (new_val <= 0)
+		return (EINVAL);
+	sched_slice = imax(1, (new_val + period / 2) / period);
+	hogticks = imax(1, (2 * hz * sched_slice + realstathz / 2) /
+	    realstathz);
+	return (0);
+}
+
 SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RD, 0, "Scheduler");
 
 SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "4BSD", 0,
     "Scheduler name");
+SYSCTL_PROC(_kern_sched, OID_AUTO, quantum, CTLTYPE_INT | CTLFLAG_RW,
+    NULL, 0, sysctl_kern_quantum, "I",
+    "Quantum for timeshare threads in microseconds");
 SYSCTL_INT(_kern_sched, OID_AUTO, slice, CTLFLAG_RW, &sched_slice, 0,
-    "Slice size for timeshare threads");
+    "Quantum for timeshare threads in stathz ticks");
 #ifdef SMP
 /* Enable forwarding of wakeups to all other cpus */
 static SYSCTL_NODE(_kern_sched, OID_AUTO, ipiwakeup, CTLFLAG_RD, NULL,
@@ -629,21 +650,15 @@
 static void
 sched_setup(void *dummy)
 {
+
 	setup_runqs();
 
-	/*
-	 * To avoid divide-by-zero, we set realstathz a dummy value
-	 * in case which sched_clock() called before sched_initticks().
-	 */
-	realstathz = hz;
-	sched_slice = realstathz / 10;	/* ~100ms */
-
 	/* Account for thread0. */
 	sched_load_add();
 }
 
 /*
- * This routine determines the sched_slice after stathz and hz are setup.
+ * This routine determines time constants after stathz and hz are setup.
  */
 static void
 sched_initticks(void *dummy)
@@ -651,6 +666,8 @@
 
 	realstathz = stathz ? stathz : hz;
 	sched_slice = realstathz / 10;	/* ~100ms */
+	hogticks = imax(1, (2 * hz * sched_slice + realstathz / 2) /
+	    realstathz);
 }
 
 /* External interfaces start here */
@@ -689,7 +706,7 @@
 {
 
 	/* Convert sched_slice from stathz to hz. */
-	return (hz / (realstathz / sched_slice));
+	return (imax(1, (sched_slice * hz + realstathz / 2) / realstathz));
 }
 
 /*
@@ -724,9 +741,9 @@
 
 	/*
 	 * Force a context switch if the current thread has used up a full
-	 * quantum (default quantum is 100ms).
+	 * time slice (default is 100ms).
 	 */
-	if (!TD_IS_IDLETHREAD(td) && (--ts->ts_slice <= 0)) {
+	if (!TD_IS_IDLETHREAD(td) && --ts->ts_slice <= 0) {
 		ts->ts_slice = sched_slice;
 		td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
 	}
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/sched_ule.c
--- a/head/sys/kern/sched_ule.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/sched_ule.c	Wed Aug 15 11:46:11 2012 +0300
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/sched_ule.c 239157 2012-08-09 19:26:13Z mav $");
+__FBSDID("$FreeBSD: head/sys/kern/sched_ule.c 239196 2012-08-11 20:24:39Z mav $");
 
 #include "opt_hwpmc_hooks.h"
 #include "opt_kdtrace.h"
@@ -201,9 +201,9 @@
  * preempt_thresh:	Priority threshold for preemption and remote IPIs.
  */
 static int sched_interact = SCHED_INTERACT_THRESH;
-static int realstathz;
-static int tickincr;
-static int sched_slice = 1;
+static int realstathz = 127;
+static int tickincr = 8 << SCHED_TICK_SHIFT;;
+static int sched_slice = 12;
 #ifdef PREEMPTION
 #ifdef FULL_PREEMPTION
 static int preempt_thresh = PRI_MAX_IDLE;
@@ -1363,13 +1363,6 @@
 #else
 	tdq_setup(tdq);
 #endif
-	/*
-	 * To avoid divide-by-zero, we set realstathz a dummy value
-	 * in case which sched_clock() called before sched_initticks().
-	 */
-	realstathz = hz;
-	sched_slice = (realstathz/10);	/* ~100ms */
-	tickincr = 1 << SCHED_TICK_SHIFT;
 
 	/* Add thread0's load since it's running. */
 	TDQ_LOCK(tdq);
@@ -1380,7 +1373,7 @@
 }
 
 /*
- * This routine determines the tickincr after stathz and hz are setup.
+ * This routine determines time constants after stathz and hz are setup.
  */
 /* ARGSUSED */
 static void
@@ -1389,7 +1382,9 @@
 	int incr;
 
 	realstathz = stathz ? stathz : hz;
-	sched_slice = (realstathz/10);	/* ~100ms */
+	sched_slice = realstathz / 10;	/* ~100ms */
+	hogticks = imax(1, (2 * hz * sched_slice + realstathz / 2) /
+	    realstathz);
 
 	/*
 	 * tickincr is shifted out by 10 to avoid rounding errors due to
@@ -1409,16 +1404,10 @@
 	 * what realstathz is.
 	 */
 	balance_interval = realstathz;
-	/*
-	 * Set steal thresh to roughly log2(mp_ncpu) but no greater than 4. 
-	 * This prevents excess thrashing on large machines and excess idle 
-	 * on smaller machines.
-	 */
-	steal_thresh = min(fls(mp_ncpus) - 1, 3);
 	affinity = SCHED_AFFINITY_DEFAULT;
 #endif
 	if (sched_idlespinthresh < 0)
-		sched_idlespinthresh = max(16, 2 * hz / realstathz);
+		sched_idlespinthresh = imax(16, 2 * hz / realstathz);
 }
 
 
@@ -1606,8 +1595,8 @@
 sched_rr_interval(void)
 {
 
-	/* Convert sched_slice to hz */
-	return (hz/(realstathz/sched_slice));
+	/* Convert sched_slice from stathz to hz. */
+	return (imax(1, (sched_slice * hz + realstathz / 2) / realstathz));
 }
 
 /*
@@ -2231,16 +2220,15 @@
 		sched_interact_update(td);
 		sched_priority(td);
 	}
+
 	/*
-	 * We used up one time slice.
+	 * Force a context switch if the current thread has used up a full
+	 * time slice (default is 100ms).
 	 */
-	if (--ts->ts_slice > 0)
-		return;
-	/*
-	 * We're out of time, force a requeue at userret().
-	 */
-	ts->ts_slice = sched_slice;
-	td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
+	if (!TD_IS_IDLETHREAD(td) && --ts->ts_slice <= 0) {
+		ts->ts_slice = sched_slice;
+		td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
+	}
 }
 
 /*
@@ -2795,21 +2783,44 @@
 
 #endif
 
+static int
+sysctl_kern_quantum(SYSCTL_HANDLER_ARGS)
+{
+	int error, new_val, period;
+
+	period = 1000000 / realstathz;
+	new_val = period * sched_slice;
+	error = sysctl_handle_int(oidp, &new_val, 0, req);
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+	if (new_val <= 0)
+		return (EINVAL);
+	sched_slice = imax(1, (new_val + period / 2) / period);
+	hogticks = imax(1, (2 * hz * sched_slice + realstathz / 2) /
+	    realstathz);
+	return (0);
+}
+
 SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RW, 0, "Scheduler");
 SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "ULE", 0,
     "Scheduler name");
+SYSCTL_PROC(_kern_sched, OID_AUTO, quantum, CTLTYPE_INT | CTLFLAG_RW,
+    NULL, 0, sysctl_kern_quantum, "I",
+    "Quantum for timeshare threads in microseconds");
 SYSCTL_INT(_kern_sched, OID_AUTO, slice, CTLFLAG_RW, &sched_slice, 0,
-    "Slice size for timeshare threads");
+    "Quantum for timeshare threads in stathz ticks");
 SYSCTL_INT(_kern_sched, OID_AUTO, interact, CTLFLAG_RW, &sched_interact, 0,
-     "Interactivity score threshold");
-SYSCTL_INT(_kern_sched, OID_AUTO, preempt_thresh, CTLFLAG_RW, &preempt_thresh,
-     0,"Min priority for preemption, lower priorities have greater precedence");
-SYSCTL_INT(_kern_sched, OID_AUTO, static_boost, CTLFLAG_RW, &static_boost,
-     0,"Controls whether static kernel priorities are assigned to sleeping threads.");
-SYSCTL_INT(_kern_sched, OID_AUTO, idlespins, CTLFLAG_RW, &sched_idlespins,
-     0,"Number of times idle will spin waiting for new work.");
-SYSCTL_INT(_kern_sched, OID_AUTO, idlespinthresh, CTLFLAG_RW, &sched_idlespinthresh,
-     0,"Threshold before we will permit idle spinning.");
+    "Interactivity score threshold");
+SYSCTL_INT(_kern_sched, OID_AUTO, preempt_thresh, CTLFLAG_RW,
+    &preempt_thresh, 0,
+    "Maximal (lowest) priority for preemption");
+SYSCTL_INT(_kern_sched, OID_AUTO, static_boost, CTLFLAG_RW, &static_boost, 0,
+    "Assign static kernel priorities to sleeping threads");
+SYSCTL_INT(_kern_sched, OID_AUTO, idlespins, CTLFLAG_RW, &sched_idlespins, 0,
+    "Number of times idle thread will spin waiting for new work");
+SYSCTL_INT(_kern_sched, OID_AUTO, idlespinthresh, CTLFLAG_RW,
+    &sched_idlespinthresh, 0,
+    "Threshold before we will permit idle thread spinning");
 #ifdef SMP
 SYSCTL_INT(_kern_sched, OID_AUTO, affinity, CTLFLAG_RW, &affinity, 0,
     "Number of hz ticks to keep thread affinity for");
@@ -2817,17 +2828,14 @@
     "Enables the long-term load balancer");
 SYSCTL_INT(_kern_sched, OID_AUTO, balance_interval, CTLFLAG_RW,
     &balance_interval, 0,
-    "Average frequency in stathz ticks to run the long-term balancer");
+    "Average period in stathz ticks to run the long-term balancer");
 SYSCTL_INT(_kern_sched, OID_AUTO, steal_idle, CTLFLAG_RW, &steal_idle, 0,
     "Attempts to steal work from other cores before idling");
 SYSCTL_INT(_kern_sched, OID_AUTO, steal_thresh, CTLFLAG_RW, &steal_thresh, 0,
-    "Minimum load on remote cpu before we'll steal");
-
-/* Retrieve SMP topology */
+    "Minimum load on remote CPU before we'll steal");
 SYSCTL_PROC(_kern_sched, OID_AUTO, topology_spec, CTLTYPE_STRING |
-    CTLFLAG_RD, NULL, 0, sysctl_kern_sched_topology_spec, "A", 
+    CTLFLAG_RD, NULL, 0, sysctl_kern_sched_topology_spec, "A",
     "XML dump of detected CPU topology");
-
 #endif
 
 /* ps compat.  All cpu percentages from ULE are weighted. */
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/subr_bus.c
--- a/head/sys/kern/subr_bus.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/subr_bus.c	Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/subr_bus.c 235978 2012-05-25 07:32:26Z avg $");
+__FBSDID("$FreeBSD: head/sys/kern/subr_bus.c 239178 2012-08-10 15:02:49Z hselasky $");
 
 #include "opt_bus.h"
 
@@ -2505,8 +2505,8 @@
 void
 device_set_softc(device_t dev, void *softc)
 {
-	if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC))
-		free(dev->softc, M_BUS_SC);
+	if (dev->softc != NULL && !(dev->flags & DF_EXTERNALSOFTC))
+		DEVICE_FREE_SOFTC(dev, dev->softc);
 	dev->softc = softc;
 	if (dev->softc)
 		dev->flags |= DF_EXTERNALSOFTC;
@@ -2703,8 +2703,8 @@
 	if (dev->driver == driver)
 		return (0);
 
-	if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) {
-		free(dev->softc, M_BUS_SC);
+	if (dev->softc != NULL && !(dev->flags & DF_EXTERNALSOFTC)) {
+		DEVICE_FREE_SOFTC(dev, dev->softc);
 		dev->softc = NULL;
 	}
 	device_set_desc(dev, NULL);
@@ -4899,3 +4899,13 @@
 		return (0);
 	return (bus_release_resource(dev, type, rman_get_rid(r), r));
 }
+
+/*
+ * The "dev" argument passed to "device_free_softc()" is allowed to be
+ * NULL, if the device freeing the soft is not available.
+ */
+void
+device_free_softc(device_t dev, void *softc)
+{
+	free(softc, M_BUS_SC);
+}
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/atheros/ar71xx_gpio.c
--- a/head/sys/mips/atheros/ar71xx_gpio.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/atheros/ar71xx_gpio.c	Wed Aug 15 11:46:11 2012 +0300
@@ -53,7 +53,12 @@
 
 #include "gpio_if.h"
 
-#define	DEFAULT_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
+#ifndef GPIO_PIN_REPORT
+#define GPIO_PIN_REPORT	0x0400  /* report interrupt on pin */
+#endif
+
+#define	DEFAULT_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
+			GPIO_PIN_REPORT)
 
 /*
  * Helpers
@@ -87,6 +92,10 @@
 static int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
 static int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin);
 
+static int ar71xx_gpio_register_irq_handler(device_t dev, device_t bus,
+    int (*isr)(device_t bus, device_t dev, int pin, int rise));
+static int ar71xx_gpio_unregister_irq_handler(device_t dev, device_t bus);
+
 static void
 ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask)
 {
@@ -127,6 +136,32 @@
 		}
 	}
 
+	/* Don't touch Polarity for INVIN when we !IN */
+	if (flags & GPIO_PIN_INPUT) {
+		if (flags & GPIO_PIN_INVIN) {
+			pin->gp_flags |= GPIO_PIN_INVIN;
+			GPIO_SET_BITS(sc, AR71XX_GPIO_INT_POLARITY, mask);
+		}
+		else {
+			pin->gp_flags &= ~GPIO_PIN_INVIN;
+			GPIO_CLEAR_BITS(sc, AR71XX_GPIO_INT_POLARITY, mask);
+		}
+	}
+
+	if (flags & GPIO_PIN_REPORT) {
+		pin->gp_flags |= GPIO_PIN_REPORT;
+		GPIO_SET_BITS(sc, AR71XX_GPIO_INT, mask);
+		GPIO_SET_BITS(sc, AR71XX_GPIO_INT_MASK, mask);
+		device_printf(sc->dev, "Will report interrupt on pin %d\n",
+		    pin->gp_pin);
+
+	}
+	else {
+		pin->gp_flags &= ~GPIO_PIN_REPORT;
+		GPIO_CLEAR_BITS(sc, AR71XX_GPIO_INT, mask);
+		GPIO_CLEAR_BITS(sc, AR71XX_GPIO_INT_MASK, mask);
+	}
+
 	GPIO_UNLOCK(sc);
 }
 
@@ -313,9 +348,32 @@
 static int
 ar71xx_gpio_filter(void *arg)
 {
+	struct ar71xx_gpio_softc *sc = arg;
+	uint32_t i;
+	uint64_t input, value;
 
-	/* TODO: something useful */
-	return (FILTER_STRAY);
+	/* Read all reported pins */
+	input  = GPIO_READ(sc, AR71XX_GPIO_INT_PENDING);
+	/* Clear int status */
+	GPIO_WRITE(sc, AR71XX_GPIO_INT_PENDING, input);
+	/* Clear report for OUTs */
+	input &= ~GPIO_READ(sc, AR71XX_GPIO_OE);
+	value = input & GPIO_READ(sc, AR71XX_GPIO_IN);
+
+	if (!input)
+		return (FILTER_HANDLED);
+
+	for ( i = 0; i < sc->npins; i ++ )
+	{
+		/* Next if output pin */
+		if ( !(( input >> i) & 1) ) continue;
+
+		if (!sc->isr)  continue;
+
+		sc->isr(sc->bus, sc->dev, i, (value >> i) & 1);
+	}
+
+	return (FILTER_HANDLED);
 }
 
 
@@ -323,7 +381,9 @@
 static void
 ar71xx_gpio_intr(void *arg)
 {
-	struct ar71xx_gpio_softc *sc = arg;
+	struct ar71xx_gpio_softc *sc;
+
+	sc = arg;
 	GPIO_LOCK(sc);
 	/* TODO: something useful */
 	GPIO_UNLOCK(sc);
@@ -342,7 +402,7 @@
 {
 	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
 	int error = 0;
-	int i, j, npins;
+	int i, j;
 	int mask, pinon;
 	int old = 0;
 
@@ -392,7 +452,17 @@
 	}
 	/* Handle previous behaviour */
 	if (old == 0) {
-		ar71xx_gpio_function_enable(sc, AR724X_GPIO_FUNC_JTAG_DISABLE);
+		switch (ar71xx_soc) {
+			case AR71XX_SOC_AR7240:
+			case AR71XX_SOC_AR7241:
+			case AR71XX_SOC_AR7242:
+				ar71xx_gpio_function_enable(sc,
+				    AR724X_GPIO_FUNC_JTAG_DISABLE);
+				break;
+			default:
+				/* Nothing to do */
+				break;
+		}
 	}
 
 	/* Configure all pins as input */
@@ -400,17 +470,21 @@
 	GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0);
 
 	/* Initialise all pins specified in the mask, up to the pin count */
-	(void) ar71xx_gpio_pin_max(dev, &npins);
+	(void) ar71xx_gpio_pin_max(dev, &sc->npins);
 	/* gpio_pin_max method return max ID, but not count, so increment */
-	npins ++;
+	sc->npins ++;
+
 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
 	    "pinmask", &mask) != 0)
-		mask = ((1 << npins) - 1);
+		mask = ((1 << sc->npins) - 1);
+
 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
 	    "pinon", &pinon) != 0)
 		pinon = 0;
+
 	device_printf(dev, "gpio pinmask=0x%x\n", mask);
-	for (i = 0, j = 0; j < npins; j++) {
+
+	for (i = 0, j = 0; j < sc->npins; j++) {
 		if ((mask & (1 << j)) == 0)
 			continue;
 		snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
@@ -418,15 +492,18 @@
 		sc->gpio_pins[i].gp_pin = j;
 		sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
 		sc->gpio_pins[i].gp_flags = 0;
-		ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], DEFAULT_CAPS);
+		ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], GPIO_PIN_INPUT);
 		i++;
 	}
+
 	sc->gpio_npins = i;
+
 	for (i = 0; i < sc->gpio_npins; i++) {
 		j = sc->gpio_pins[i].gp_pin;
 		if ((pinon & (1 << j)) != 0)
 			ar71xx_gpio_pin_set(dev, j, 1);
 	}
+
 	device_add_child(dev, "gpiobus", device_get_unit(dev));
 	return (bus_generic_attach(dev));
 }
@@ -451,6 +528,33 @@
 	return(0);
 }
 
+static int
+ar71xx_gpio_register_irq_handler(device_t dev, device_t bus,
+    int (*isr)(device_t bus, device_t dev, int pin, int rise))
+{
+	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
+
+	if (sc->isr)
+		/* We already have ISR, use unregister first */
+		return (-1);
+
+	sc->bus = bus;
+	sc->isr = isr;
+
+	return (0);
+}
+
+static int
+ar71xx_gpio_unregister_irq_handler(device_t dev, device_t bus)
+{
+	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
+
+	sc->isr = 0;
+	sc->bus = 0;
+
+	return (0);
+}
+
 static device_method_t ar71xx_gpio_methods[] = {
 	DEVMETHOD(device_probe, ar71xx_gpio_probe),
 	DEVMETHOD(device_attach, ar71xx_gpio_attach),
@@ -465,6 +569,10 @@
 	DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get),
 	DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set),
 	DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle),
+	DEVMETHOD(gpio_register_irq_handler,
+	    ar71xx_gpio_register_irq_handler),
+	DEVMETHOD(gpio_unregister_irq_handler,
+	    ar71xx_gpio_unregister_irq_handler),
 	DEVMETHOD_END
 };
 
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/atheros/ar71xx_gpiovar.h
--- a/head/sys/mips/atheros/ar71xx_gpiovar.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/atheros/ar71xx_gpiovar.h	Wed Aug 15 11:46:11 2012 +0300
@@ -63,8 +63,12 @@
         struct resource		*gpio_irq_res;
         int			gpio_irq_rid;
         void			*gpio_ih;
-	int			gpio_npins;
+	int			npins;		/* Number of all pins */
+	int			gpio_npins;	/* Number of configured pins */
 	struct gpio_pin		gpio_pins[AR91XX_GPIO_PINS];
+	device_t		bus;
+	int 			(*isr)(device_t bus, device_t dev, int pin,
+				    int rise);
 };
 
 #endif	/* __AR71XX_GPIOVAR_H__ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/atheros/ar71xxreg.h
--- a/head/sys/mips/atheros/ar71xxreg.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/atheros/ar71xxreg.h	Wed Aug 15 11:46:11 2012 +0300
@@ -145,7 +145,11 @@
 #define		AR71XX_GPIO_CLEAR		0x10
 #define		AR71XX_GPIO_INT			0x14
 #define		AR71XX_GPIO_INT_TYPE		0x18
+#define			GPIO_INT_TYPE_EDGE	0
+#define			GPIO_INT_TYPE_LEVEL	1
 #define		AR71XX_GPIO_INT_POLARITY	0x1c
+#define			GPIO_INT_POLARITY_NORM	0
+#define			GPIO_INT_POLARITY_INV	1
 #define		AR71XX_GPIO_INT_PENDING		0x20
 #define		AR71XX_GPIO_INT_MASK		0x24
 #define		AR71XX_GPIO_FUNCTION		0x28
@@ -158,7 +162,13 @@
 				/* CS1 is shared with GPIO_0 */
 #define			GPIO_FUNC_UART_EN       (1 << 8)
 #define			GPIO_FUNC_USB_OC_EN     (1 << 4)
-#define			GPIO_FUNC_XXX2		(1 << 1) /* XXX: must be 724x */
+#define			GPIO_FUNC_724x_SWLED4	(1 << 7)
+#define			GPIO_FUNC_724x_SWLED3	(1 << 6)
+#define			GPIO_FUNC_724x_SWLED2	(1 << 5)
+#define			GPIO_FUNC_724x_SWLED1	(1 << 4)
+#define			GPIO_FUNC_724x_SWLED0	(1 << 3)
+#define			GPIO_FUNC_UART_RTS_CTS	(1 << 2)
+#define			GPIO_FUNC_UART_9_10	(1 << 1) /* XXX: must be 724x */
 #define			GPIO_FUNC_USB_CLK_EN    (0)
 
 #define	AR71XX_BASE_FREQ		40000000
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/cavium/octopci.c
--- a/head/sys/mips/cavium/octopci.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/cavium/octopci.c	Wed Aug 15 11:46:11 2012 +0300
@@ -71,6 +71,8 @@
 	unsigned sc_domain;
 	unsigned sc_bus;
 
+//	bus_dma_tag_t	sc_pci_dmat;	/* PCI DMA tag pointer */
+
 	bus_addr_t sc_io_base;
 	unsigned sc_io_next;
 	struct rman sc_io;
@@ -80,6 +82,15 @@
 	struct rman sc_mem1;
 };
 
+//static bus_dma_tag_t
+//octopci_pci_get_dma_tag(device_t bus, device_t child)
+//{
+//	struct octopci_softc *sc;
+//
+//	sc = device_get_softc(bus);
+//	return (sc->sc_pci_dmat);
+//}
+
 static void		octopci_identify(driver_t *, device_t);
 static int		octopci_probe(device_t);
 static int		octopci_attach(device_t);
@@ -203,6 +214,11 @@
 	subbus = octopci_init_bus(dev, sc->sc_bus);
 	octopci_write_config(dev, sc->sc_bus, 0, 0, PCIR_SUBBUS_1, subbus, 1);
 
+//	if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
+//	    0x003fffff, ~0, NULL, NULL, 0x003fffff,
+//	    0xff, 0x003fffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0)
+//		panic("%s: bus_dma_tag_create failed", __func__);
+
 	device_add_child(dev, "pci", device_get_unit(dev));
 
 	return (bus_generic_attach(dev));
@@ -457,6 +473,12 @@
 		}
 		break;
 #endif
+	case CVMX_BOARD_TYPE_CUST_DLINK_DSR500:
+	case CVMX_BOARD_TYPE_CUST_DLINK_DSR500N:
+	case CVMX_BOARD_TYPE_CUST_DLINK_DSR1000:
+	case CVMX_BOARD_TYPE_CUST_DLINK_DSR1000N:
+		return (OCTEON_IRQ_PCI_INT0 + pin + 1);
+		break;
 	default:
 		break;
 	}
@@ -893,6 +915,7 @@
 		pci_cfg56.s.dpere = 1;
 		pci_cfg56.s.ncp = 0xe8;
 		pci_cfg56.s.pxcid = 7;
+		pci_cfg56.s.mmbc = 1;
 		NPI_WRITE(CVMX_NPI_PCI_CFG56, pci_cfg56.u32);
 		NPI_READ(CVMX_NPI_PCI_CFG56);
 	}
@@ -970,6 +993,7 @@
 	DEVMETHOD(bus_deactivate_resource,bus_generic_deactivate_resource),
 	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
 	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+//	DEVMETHOD(bus_get_dma_tag,	octopci_pci_get_dma_tag),
 
 	DEVMETHOD(bus_add_child,	bus_generic_add_child),
 
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/cavium/octopci_bus_space.c
--- a/head/sys/mips/cavium/octopci_bus_space.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/cavium/octopci_bus_space.c	Wed Aug 15 11:46:11 2012 +0300
@@ -218,6 +218,7 @@
 {
 
 	*bshp = addr;
+//	*bshp = addr | 0x1000000000000000ull;
 	return (0);
 }
 
@@ -244,7 +245,7 @@
     bus_size_t offset)
 {
 
-	return (rd8(handle + offset));
+	return (rd8((handle + offset) | 0x1000000000000000ull));
 }
 
 uint16_t
@@ -252,7 +253,7 @@
     bus_size_t offset)
 {
 
-	return (rd16(handle + offset));
+	return (rd16((handle + offset) | 0x1000000000000000ull));
 }
 
 uint32_t
@@ -260,7 +261,7 @@
     bus_size_t offset)
 {
 
-	return (rd32(handle + offset));
+	return (rd32((handle + offset) | 0x1000000000000000ull));
 }
 
 
@@ -344,7 +345,7 @@
     bus_size_t offset, uint8_t value)
 {
 
-	wr8(bsh + offset, value);
+	wr8((bsh + offset) | 0x1000000000000000ull, value);
 }
 
 void
@@ -352,7 +353,7 @@
     bus_size_t offset, uint16_t value)
 {
 
-	wr16(bsh + offset, value);
+	wr16((bsh + offset) | 0x1000000000000000ull, value);
 }
 
 void
@@ -360,7 +361,7 @@
     bus_size_t offset, uint32_t value)
 {
 
-	wr32(bsh + offset, value);
+	wr32((bsh + offset) | 0x1000000000000000ull, value);
 }
 
 /*
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/include/pmap.h
--- a/head/sys/mips/include/pmap.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/include/pmap.h	Wed Aug 15 11:46:11 2012 +0300
@@ -40,7 +40,7 @@
  *	from: @(#)pmap.h	7.4 (Berkeley) 5/12/91
  *	from: src/sys/i386/include/pmap.h,v 1.65.2.2 2000/11/30 01:54:42 peter
  *	JNPR: pmap.h,v 1.7.2.1 2007/09/10 07:44:12 girish
- *      $FreeBSD: head/sys/mips/include/pmap.h 239152 2012-08-09 16:38:17Z alc $
+ *      $FreeBSD: head/sys/mips/include/pmap.h 239236 2012-08-13 17:38:38Z alc $
  */
 
 #ifndef _MACHINE_PMAP_H_
@@ -66,9 +66,9 @@
  * Pmap stuff
  */
 struct pv_entry;
+struct pv_chunk;
 
 struct md_page {
-	int pv_list_count;
 	int pv_flags;
 	TAILQ_HEAD(, pv_entry) pv_list;
 };
@@ -82,8 +82,7 @@
 
 struct pmap {
 	pd_entry_t *pm_segtab;	/* KVA of segment table */
-	TAILQ_HEAD(, pv_entry) pm_pvlist;	/* list of mappings in
-						 * pmap */
+	TAILQ_HEAD(, pv_chunk)	pm_pvchunk;	/* list of mappings in pmap */
 	cpuset_t	pm_active;		/* active on cpus */
 	struct {
 		u_int32_t asid:ASID_BITS;	/* TLB address space tag */
@@ -121,13 +120,30 @@
  * mappings of that page.  An entry is a pv_entry_t, the list is pv_table.
  */
 typedef struct pv_entry {
-	pmap_t pv_pmap;		/* pmap where mapping lies */
 	vm_offset_t pv_va;	/* virtual address for mapping */
 	TAILQ_ENTRY(pv_entry) pv_list;
-	TAILQ_ENTRY(pv_entry) pv_plist;
 }       *pv_entry_t;
 
 /*
+ * pv_entries are allocated in chunks per-process.  This avoids the
+ * need to track per-pmap assignments.
+ */
+#ifdef __mips_n64
+#define	_NPCM	3
+#define	_NPCPV	168
+#else
+#define	_NPCM	11
+#define	_NPCPV	336
+#endif
+struct pv_chunk {
+	pmap_t			pc_pmap;
+	TAILQ_ENTRY(pv_chunk)	pc_list;
+	u_long			pc_map[_NPCM];	/* bitmap; 1 = free */
+	TAILQ_ENTRY(pv_chunk)	pc_lru;
+	struct pv_entry		pc_pventry[_NPCPV];
+};
+
+/*
  * physmem_desc[] is a superset of phys_avail[] and describes all the
  * memory present in the system.
  *
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/mips/pmap.c
--- a/head/sys/mips/mips/pmap.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/mips/pmap.c	Wed Aug 15 11:46:11 2012 +0300
@@ -66,9 +66,10 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/mips/mips/pmap.c 239170 2012-08-10 05:00:50Z alc $");
+__FBSDID("$FreeBSD: head/sys/mips/mips/pmap.c 239236 2012-08-13 17:38:38Z alc $");
 
 #include "opt_ddb.h"
+#include "opt_pmap.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -77,6 +78,7 @@
 #include <sys/vmmeter.h>
 #include <sys/mman.h>
 #include <sys/smp.h>
+#include <sys/sysctl.h>
 #ifdef DDB
 #include <ddb/ddb.h>
 #endif
@@ -116,6 +118,12 @@
 #define	PMAP_INLINE
 #endif
 
+#ifdef PV_STATS
+#define PV_STAT(x)	do { x ; } while (0)
+#else
+#define PV_STAT(x)	do { } while (0)
+#endif
+
 /*
  * Get PDEs and PTEs for user/kernel address space
  */
@@ -152,12 +160,13 @@
 /*
  * Data for the pv entry allocation mechanism
  */
-static uma_zone_t pvzone;
-static struct vm_object pvzone_obj;
-static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
-
-static PMAP_INLINE void free_pv_entry(pv_entry_t pv);
-static pv_entry_t get_pv_entry(pmap_t locked_pmap);
+static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks);
+static int pv_entry_count;
+
+static void free_pv_chunk(struct pv_chunk *pc);
+static void free_pv_entry(pmap_t pmap, pv_entry_t pv);
+static pv_entry_t get_pv_entry(pmap_t pmap, boolean_t try);
+static vm_page_t pmap_pv_reclaim(pmap_t locked_pmap);
 static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va);
 static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap,
     vm_offset_t va);
@@ -472,7 +481,7 @@
 	PMAP_LOCK_INIT(kernel_pmap);
 	kernel_pmap->pm_segtab = kernel_segmap;
 	CPU_FILL(&kernel_pmap->pm_active);
-	TAILQ_INIT(&kernel_pmap->pm_pvlist);
+	TAILQ_INIT(&kernel_pmap->pm_pvchunk);
 	kernel_pmap->pm_asid[0].asid = PMAP_ASID_RESERVED;
 	kernel_pmap->pm_asid[0].gen = 0;
 	kernel_vm_end += nkpt * NPTEPG * PAGE_SIZE;
@@ -591,7 +600,6 @@
 {
 
 	TAILQ_INIT(&m->md.pv_list);
-	m->md.pv_list_count = 0;
 	m->md.pv_flags = 0;
 }
 
@@ -599,23 +607,10 @@
  *	Initialize the pmap module.
  *	Called by vm_init, to initialize any structures that the pmap
  *	system needs to map virtual memory.
- *	pmap_init has been enhanced to support in a fairly consistant
- *	way, discontiguous physical memory.
  */
 void
 pmap_init(void)
 {
-
-	/*
-	 * Initialize the address space (zone) for the pv entries.  Set a
-	 * high water mark so that the system can recover from excessive
-	 * numbers of pv entries.
-	 */
-	pvzone = uma_zcreate("PV ENTRY", sizeof(struct pv_entry), NULL, NULL,
-	    NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
-	pv_entry_max = PMAP_SHPGPERPROC * maxproc + cnt.v_page_count;
-	pv_entry_high_water = 9 * (pv_entry_max / 10);
-	uma_zone_set_obj(pvzone, &pvzone_obj, pv_entry_max);
 }
 
 /***************************************************
@@ -1012,7 +1007,7 @@
 		pmap->pm_asid[i].gen = 0;
 	}
 	PCPU_SET(curpmap, pmap);
-	TAILQ_INIT(&pmap->pm_pvlist);
+	TAILQ_INIT(&pmap->pm_pvchunk);
 	bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
 }
 
@@ -1070,7 +1065,7 @@
 		pmap->pm_asid[i].asid = PMAP_ASID_RESERVED;
 		pmap->pm_asid[i].gen = 0;
 	}
-	TAILQ_INIT(&pmap->pm_pvlist);
+	TAILQ_INIT(&pmap->pm_pvchunk);
 	bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
 
 	return (1);
@@ -1296,127 +1291,320 @@
 }
 
 /***************************************************
-* page management routines.
+ * page management routines.
  ***************************************************/
 
+CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE);
+#ifdef __mips_n64
+CTASSERT(_NPCM == 3);
+CTASSERT(_NPCPV == 168);
+#else
+CTASSERT(_NPCM == 11);
+CTASSERT(_NPCPV == 336);
+#endif
+
+static __inline struct pv_chunk *
+pv_to_chunk(pv_entry_t pv)
+{
+
+	return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK));
+}
+
+#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap)
+
+#ifdef __mips_n64
+#define	PC_FREE0_1	0xfffffffffffffffful
+#define	PC_FREE2	0x000000fffffffffful
+#else
+#define	PC_FREE0_9	0xfffffffful	/* Free values for index 0 through 9 */
+#define	PC_FREE10	0x0000fffful	/* Free values for index 10 */
+#endif
+
+static const u_long pc_freemask[_NPCM] = {
+#ifdef __mips_n64
+	PC_FREE0_1, PC_FREE0_1, PC_FREE2
+#else
+	PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
+	PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
+	PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
+	PC_FREE0_9, PC_FREE10
+#endif
+};
+
+static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0,
+    "Current number of pv entries");
+
+#ifdef PV_STATS
+static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail;
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0,
+    "Current number of pv entry chunks");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0,
+    "Current number of pv entry chunks allocated");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0,
+    "Current number of pv entry chunks frees");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail, 0,
+    "Number of times tried to get a chunk page but failed.");
+
+static long pv_entry_frees, pv_entry_allocs;
+static int pv_entry_spare;
+
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0,
+    "Current number of pv entry frees");
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs, 0,
+    "Current number of pv entry allocs");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0,
+    "Current number of spare pv entries");
+#endif
+
+/*
+ * We are in a serious low memory condition.  Resort to
+ * drastic measures to free some pages so we can allocate
+ * another pv entry chunk.
+ */
+static vm_page_t
+pmap_pv_reclaim(pmap_t locked_pmap)
+{
+	struct pch newtail;
+	struct pv_chunk *pc;
+	pd_entry_t *pde;
+	pmap_t pmap;
+	pt_entry_t *pte, oldpte;
+	pv_entry_t pv;
+	vm_offset_t va;
+	vm_page_t m, m_pc;
+	u_long inuse;
+	int bit, field, freed, idx;
+
+	PMAP_LOCK_ASSERT(locked_pmap, MA_OWNED);
+	pmap = NULL;
+	m_pc = NULL;
+	TAILQ_INIT(&newtail);
+	while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL) {
+		TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
+		if (pmap != pc->pc_pmap) {
+			if (pmap != NULL) {
+				pmap_invalidate_all(pmap);
+				if (pmap != locked_pmap)
+					PMAP_UNLOCK(pmap);
+			}
+			pmap = pc->pc_pmap;
+			/* Avoid deadlock and lock recursion. */
+			if (pmap > locked_pmap)
+				PMAP_LOCK(pmap);
+			else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap)) {
+				pmap = NULL;
+				TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
+				continue;
+			}
+		}
+
+		/*
+		 * Destroy every non-wired, 4 KB page mapping in the chunk.
+		 */
+		freed = 0;
+		for (field = 0; field < _NPCM; field++) {
+			for (inuse = ~pc->pc_map[field] & pc_freemask[field];
+			    inuse != 0; inuse &= ~(1UL << bit)) {
+				bit = ffsl(inuse) - 1;
+				idx = field * sizeof(inuse) * NBBY + bit;
+				pv = &pc->pc_pventry[idx];
+				va = pv->pv_va;
+				pde = pmap_pde(pmap, va);
+				KASSERT(pde != NULL && *pde != 0,
+				    ("pmap_pv_reclaim: pde"));
+				pte = pmap_pde_to_pte(pde, va);
+				oldpte = *pte;
+				KASSERT(!pte_test(&oldpte, PTE_W),
+				    ("wired pte for unwired page"));
+				if (is_kernel_pmap(pmap))
+					*pte = PTE_G;
+				else
+					*pte = 0;
+				pmap_invalidate_page(pmap, va);
+				m = PHYS_TO_VM_PAGE(TLBLO_PTE_TO_PA(oldpte));
+				if (pte_test(&oldpte, PTE_D))
+					vm_page_dirty(m);
+				if (m->md.pv_flags & PV_TABLE_REF)
+					vm_page_aflag_set(m, PGA_REFERENCED);
+				TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+				if (TAILQ_EMPTY(&m->md.pv_list)) {
+					vm_page_aflag_clear(m, PGA_WRITEABLE);
+					m->md.pv_flags &= ~(PV_TABLE_REF |
+					    PV_TABLE_MOD);
+				}
+				pc->pc_map[field] |= 1UL << bit;
+				pmap_unuse_pt(pmap, va, *pde);
+				freed++;
+			}
+		}
+		if (freed == 0) {
+			TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
+			continue;
+		}
+		/* Every freed mapping is for a 4 KB page. */
+		pmap->pm_stats.resident_count -= freed;
+		PV_STAT(pv_entry_frees += freed);
+		PV_STAT(pv_entry_spare += freed);
+		pv_entry_count -= freed;
+		TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+		for (field = 0; field < _NPCM; field++)
+			if (pc->pc_map[field] != pc_freemask[field]) {
+				TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc,
+				    pc_list);
+				TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
+
+				/*
+				 * One freed pv entry in locked_pmap is
+				 * sufficient.
+				 */
+				if (pmap == locked_pmap)
+					goto out;
+				break;
+			}
+		if (field == _NPCM) {
+			PV_STAT(pv_entry_spare -= _NPCPV);
+			PV_STAT(pc_chunk_count--);
+			PV_STAT(pc_chunk_frees++);
+			/* Entire chunk is free; return it. */
+			m_pc = PHYS_TO_VM_PAGE(MIPS_DIRECT_TO_PHYS(
+			    (vm_offset_t)pc));
+			break;
+		}
+	}
+out:
+	TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru);
+	if (pmap != NULL) {
+		pmap_invalidate_all(pmap);
+		if (pmap != locked_pmap)
+			PMAP_UNLOCK(pmap);
+	}
+	return (m_pc);
+}
+
 /*
  * free the pv_entry back to the free list
  */
-static PMAP_INLINE void
-free_pv_entry(pv_entry_t pv)
+static void
+free_pv_entry(pmap_t pmap, pv_entry_t pv)
 {
-
+	struct pv_chunk *pc;
+	int bit, field, idx;
+
+	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+	PV_STAT(pv_entry_frees++);
+	PV_STAT(pv_entry_spare++);
 	pv_entry_count--;
-	uma_zfree(pvzone, pv);
+	pc = pv_to_chunk(pv);
+	idx = pv - &pc->pc_pventry[0];
+	field = idx / (sizeof(u_long) * NBBY);
+	bit = idx % (sizeof(u_long) * NBBY);
+	pc->pc_map[field] |= 1ul << bit;
+	for (idx = 0; idx < _NPCM; idx++)
+		if (pc->pc_map[idx] != pc_freemask[idx]) {
+			/*
+			 * 98% of the time, pc is already at the head of the
+			 * list.  If it isn't already, move it to the head.
+			 */
+			if (__predict_false(TAILQ_FIRST(&pmap->pm_pvchunk) !=
+			    pc)) {
+				TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+				TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc,
+				    pc_list);
+			}
+			return;
+		}
+	TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+	free_pv_chunk(pc);
+}
+
+static void
+free_pv_chunk(struct pv_chunk *pc)
+{
+	vm_page_t m;
+
+ 	TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
+	PV_STAT(pv_entry_spare -= _NPCPV);
+	PV_STAT(pc_chunk_count--);
+	PV_STAT(pc_chunk_frees++);
+	/* entire chunk is free, return it */
+	m = PHYS_TO_VM_PAGE(MIPS_DIRECT_TO_PHYS((vm_offset_t)pc));
+	vm_page_unwire(m, 0);
+	vm_page_free(m);
 }
 
 /*
  * get a new pv_entry, allocating a block from the system
  * when needed.
- * the memory allocation is performed bypassing the malloc code
- * because of the possibility of allocations at interrupt time.
  */
 static pv_entry_t
-get_pv_entry(pmap_t locked_pmap)
+get_pv_entry(pmap_t pmap, boolean_t try)
 {
-	static const struct timeval printinterval = { 60, 0 };
-	static struct timeval lastprint;
-	struct vpgqueues *vpq;
-	pd_entry_t *pde;
-	pt_entry_t *pte, oldpte;
-	pmap_t pmap;
-	pv_entry_t allocated_pv, next_pv, pv;
-	vm_offset_t va;
+	struct pv_chunk *pc;
+	pv_entry_t pv;
 	vm_page_t m;
-
-	PMAP_LOCK_ASSERT(locked_pmap, MA_OWNED);
+	int bit, field, idx;
+
 	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
-	allocated_pv = uma_zalloc(pvzone, M_NOWAIT);
-	if (allocated_pv != NULL) {
-		pv_entry_count++;
-		if (pv_entry_count > pv_entry_high_water)
-			pagedaemon_wakeup();
-		else
-			return (allocated_pv);
-	}
-	/*
-	 * Reclaim pv entries: At first, destroy mappings to inactive
-	 * pages.  After that, if a pv entry is still needed, destroy
-	 * mappings to active pages.
-	 */
-	if (ratecheck(&lastprint, &printinterval))
-		printf("Approaching the limit on PV entries, "
-		    "increase the vm.pmap.shpgperproc tunable.\n");
-	vpq = &vm_page_queues[PQ_INACTIVE];
+	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+	PV_STAT(pv_entry_allocs++);
+	pv_entry_count++;
 retry:
-	TAILQ_FOREACH(m, &vpq->pl, pageq) {
-		if ((m->flags & PG_MARKER) != 0 || m->hold_count || m->busy)
-			continue;
-		TAILQ_FOREACH_SAFE(pv, &m->md.pv_list, pv_list, next_pv) {
-			va = pv->pv_va;
-			pmap = pv->pv_pmap;
-			/* Avoid deadlock and lock recursion. */
-			if (pmap > locked_pmap)
-				PMAP_LOCK(pmap);
-			else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap))
-				continue;
-			pmap->pm_stats.resident_count--;
-			pde = pmap_pde(pmap, va);
-			KASSERT(pde != NULL && *pde != 0,
-			    ("get_pv_entry: pde"));
-			pte = pmap_pde_to_pte(pde, va);
-			oldpte = *pte;
-			if (is_kernel_pmap(pmap))
-				*pte = PTE_G;
-			else
-				*pte = 0;
-			KASSERT(!pte_test(&oldpte, PTE_W),
-			    ("wired pte for unwired page"));
-			if (m->md.pv_flags & PV_TABLE_REF)
-				vm_page_aflag_set(m, PGA_REFERENCED);
-			if (pte_test(&oldpte, PTE_D))
-				vm_page_dirty(m);
-			pmap_invalidate_page(pmap, va);
-			TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
-			m->md.pv_list_count--;
-			TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
-			pmap_unuse_pt(pmap, va, *pde);
-			if (pmap != locked_pmap)
-				PMAP_UNLOCK(pmap);
-			if (allocated_pv == NULL)
-				allocated_pv = pv;
-			else
-				free_pv_entry(pv);
+	pc = TAILQ_FIRST(&pmap->pm_pvchunk);
+	if (pc != NULL) {
+		for (field = 0; field < _NPCM; field++) {
+			if (pc->pc_map[field]) {
+				bit = ffsl(pc->pc_map[field]) - 1;
+				break;
+			}
 		}
-		if (TAILQ_EMPTY(&m->md.pv_list)) {
-			vm_page_aflag_clear(m, PGA_WRITEABLE);
-			m->md.pv_flags &= ~(PV_TABLE_REF | PV_TABLE_MOD);
+		if (field < _NPCM) {
+			idx = field * sizeof(pc->pc_map[field]) * NBBY + bit;
+			pv = &pc->pc_pventry[idx];
+			pc->pc_map[field] &= ~(1ul << bit);
+			/* If this was the last item, move it to tail */
+			for (field = 0; field < _NPCM; field++)
+				if (pc->pc_map[field] != 0) {
+					PV_STAT(pv_entry_spare--);
+					return (pv);	/* not full, return */
+				}
+			TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+			TAILQ_INSERT_TAIL(&pmap->pm_pvchunk, pc, pc_list);
+			PV_STAT(pv_entry_spare--);
+			return (pv);
 		}
 	}
-	if (allocated_pv == NULL) {
-		if (vpq == &vm_page_queues[PQ_INACTIVE]) {
-			vpq = &vm_page_queues[PQ_ACTIVE];
+	/* No free items, allocate another chunk */
+	m = vm_page_alloc_freelist(VM_FREELIST_DIRECT, VM_ALLOC_NORMAL |
+	    VM_ALLOC_WIRED);
+	if (m == NULL) {
+		if (try) {
+			pv_entry_count--;
+			PV_STAT(pc_chunk_tryfail++);
+			return (NULL);
+		}
+		m = pmap_pv_reclaim(pmap);
+		if (m == NULL)
 			goto retry;
-		}
-		panic("get_pv_entry: increase the vm.pmap.shpgperproc tunable");
 	}
-	return (allocated_pv);
+	PV_STAT(pc_chunk_count++);
+	PV_STAT(pc_chunk_allocs++);
+	pc = (struct pv_chunk *)MIPS_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(m));
+	pc->pc_pmap = pmap;
+	pc->pc_map[0] = pc_freemask[0] & ~1ul;	/* preallocated bit 0 */
+	for (field = 1; field < _NPCM; field++)
+		pc->pc_map[field] = pc_freemask[field];
+	TAILQ_INSERT_TAIL(&pv_chunks, pc, pc_lru);
+	pv = &pc->pc_pventry[0];
+	TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
+	PV_STAT(pv_entry_spare += _NPCPV - 1);
+	return (pv);
 }
 
 /*
- *  Revision 1.370
- *
- *  Move pmap_collect() out of the machine-dependent code, rename it
- *  to reflect its new location, and add page queue and flag locking.
- *
- *  Notes: (1) alpha, i386, and ia64 had identical implementations
- *  of pmap_collect() in terms of machine-independent interfaces;
- *  (2) sparc64 doesn't require it; (3) powerpc had it as a TODO.
- *
- *  MIPS implementation was identical to alpha [Junos 8.2]
- */
-
-/*
  * If it is the first entry on the list, it is actually
  * in the header and we must copy the following entry up
  * to the header.  Otherwise we must search the list for
@@ -1428,23 +1616,12 @@
 {
 	pv_entry_t pv;
 
-	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
 	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
-	if (pvh->pv_list_count < pmap->pm_stats.resident_count) {
-		TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
-			if (pmap == pv->pv_pmap && va == pv->pv_va)
-				break;
+	TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
+		if (pmap == PV_PMAP(pv) && va == pv->pv_va) {
+			TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
+			break;
 		}
-	} else {
-		TAILQ_FOREACH(pv, &pmap->pm_pvlist, pv_plist) {
-			if (va == pv->pv_va)
-				break;
-		}
-	}
-	if (pv != NULL) {
-		TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
-		pvh->pv_list_count--;
-		TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
 	}
 	return (pv);
 }
@@ -1458,7 +1635,7 @@
 	KASSERT(pv != NULL, ("pmap_pvh_free: pv not found, pa %lx va %lx",
 	     (u_long)VM_PAGE_TO_PHYS(member2struct(vm_page, md, pvh)),
 	     (u_long)va));
-	free_pv_entry(pv);
+	free_pv_entry(pmap, pv);
 }
 
 static void
@@ -1482,14 +1659,9 @@
 
 	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
 	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
-	if (pv_entry_count < pv_entry_high_water && 
-	    (pv = uma_zalloc(pvzone, M_NOWAIT)) != NULL) {
-		pv_entry_count++;
+	if ((pv = get_pv_entry(pmap, TRUE)) != NULL) {
 		pv->pv_va = va;
-		pv->pv_pmap = pmap;
-		TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist);
 		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
-		m->md.pv_list_count++;
 		return (TRUE);
 	} else
 		return (FALSE);
@@ -1648,6 +1820,7 @@
 pmap_remove_all(vm_page_t m)
 {
 	pv_entry_t pv;
+	pmap_t pmap;
 	pd_entry_t *pde;
 	pt_entry_t *pte, tpte;
 
@@ -1659,29 +1832,30 @@
 		vm_page_aflag_set(m, PGA_REFERENCED);
 
 	while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
-		PMAP_LOCK(pv->pv_pmap);
+		pmap = PV_PMAP(pv);
+		PMAP_LOCK(pmap);
 
 		/*
 		 * If it's last mapping writeback all caches from 
 		 * the page being destroyed
 	 	 */
-		if (m->md.pv_list_count == 1) 
+		if (TAILQ_NEXT(pv, pv_list) == NULL)
 			mips_dcache_wbinv_range_index(pv->pv_va, PAGE_SIZE);
 
-		pv->pv_pmap->pm_stats.resident_count--;
-
-		pde = pmap_pde(pv->pv_pmap, pv->pv_va);
+		pmap->pm_stats.resident_count--;
+
+		pde = pmap_pde(pmap, pv->pv_va);
 		KASSERT(pde != NULL && *pde != 0, ("pmap_remove_all: pde"));
 		pte = pmap_pde_to_pte(pde, pv->pv_va);
 
 		tpte = *pte;
-		if (is_kernel_pmap(pv->pv_pmap))
+		if (is_kernel_pmap(pmap))
 			*pte = PTE_G;
 		else
 			*pte = 0;
 
 		if (pte_test(&tpte, PTE_W))
-			pv->pv_pmap->pm_stats.wired_count--;
+			pmap->pm_stats.wired_count--;
 
 		/*
 		 * Update the vm_page_t clean and reference bits.
@@ -1692,14 +1866,12 @@
 			    __func__, (void *)pv->pv_va, (uintmax_t)tpte));
 			vm_page_dirty(m);
 		}
-		pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
-
-		TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist);
+		pmap_invalidate_page(pmap, pv->pv_va);
+
 		TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
-		m->md.pv_list_count--;
-		pmap_unuse_pt(pv->pv_pmap, pv->pv_va, *pde);
-		PMAP_UNLOCK(pv->pv_pmap);
-		free_pv_entry(pv);
+		pmap_unuse_pt(pmap, pv->pv_va, *pde);
+		free_pv_entry(pmap, pv);
+		PMAP_UNLOCK(pmap);
 	}
 
 	vm_page_aflag_clear(m, PGA_WRITEABLE);
@@ -1894,14 +2066,11 @@
 		KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
 		    ("pmap_enter: managed mapping within the clean submap"));
 		if (pv == NULL)
-			pv = get_pv_entry(pmap);
+			pv = get_pv_entry(pmap, FALSE);
 		pv->pv_va = va;
-		pv->pv_pmap = pmap;
-		TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist);
 		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
-		m->md.pv_list_count++;
 	} else if (pv != NULL)
-		free_pv_entry(pv);
+		free_pv_entry(pmap, pv);
 
 	/*
 	 * Increment counters
@@ -2397,7 +2566,7 @@
 	rv = FALSE;
 	vm_page_lock_queues();
 	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
-		if (pv->pv_pmap == pmap) {
+		if (PV_PMAP(pv) == pmap) {
 			rv = TRUE;
 			break;
 		}
@@ -2422,8 +2591,11 @@
 {
 	pd_entry_t *pde;
 	pt_entry_t *pte, tpte;
-	pv_entry_t pv, npv;
+	pv_entry_t pv;
 	vm_page_t m;
+	struct pv_chunk *pc, *npc;
+	u_long inuse, bitmask;
+	int allfree, bit, field, idx;
 
 	if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) {
 		printf("warning: pmap_remove_pages called with non-current pmap\n");
@@ -2431,46 +2603,61 @@
 	}
 	vm_page_lock_queues();
 	PMAP_LOCK(pmap);
-	for (pv = TAILQ_FIRST(&pmap->pm_pvlist); pv != NULL; pv = npv) {
-
-		pde = pmap_pde(pmap, pv->pv_va);
-		KASSERT(pde != NULL && *pde != 0, ("pmap_remove_pages: pde"));
-		pte = pmap_pde_to_pte(pde, pv->pv_va);
-		if (!pte_test(pte, PTE_V))
-			panic("pmap_remove_pages: page on pm_pvlist has no pte");
-		tpte = *pte;
+	TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) {
+		allfree = 1;
+		for (field = 0; field < _NPCM; field++) {
+			inuse = ~pc->pc_map[field] & pc_freemask[field];
+			while (inuse != 0) {
+				bit = ffsl(inuse) - 1;
+				bitmask = 1UL << bit;
+				idx = field * sizeof(inuse) * NBBY + bit;
+				pv = &pc->pc_pventry[idx];
+				inuse &= ~bitmask;
+
+				pde = pmap_pde(pmap, pv->pv_va);
+				KASSERT(pde != NULL && *pde != 0,
+				    ("pmap_remove_pages: pde"));
+				pte = pmap_pde_to_pte(pde, pv->pv_va);
+				if (!pte_test(pte, PTE_V))
+					panic("pmap_remove_pages: bad pte");
+				tpte = *pte;
 
 /*
  * We cannot remove wired pages from a process' mapping at this time
  */
-		if (pte_test(&tpte, PTE_W)) {
-			npv = TAILQ_NEXT(pv, pv_plist);
-			continue;
+				if (pte_test(&tpte, PTE_W)) {
+					allfree = 0;
+					continue;
+				}
+				*pte = is_kernel_pmap(pmap) ? PTE_G : 0;
+
+				m = PHYS_TO_VM_PAGE(TLBLO_PTE_TO_PA(tpte));
+				KASSERT(m != NULL,
+				    ("pmap_remove_pages: bad tpte %#jx",
+				    (uintmax_t)tpte));
+
+				/*
+				 * Update the vm_page_t clean and reference bits.
+				 */
+				if (pte_test(&tpte, PTE_D))
+					vm_page_dirty(m);
+
+				/* Mark free */
+				PV_STAT(pv_entry_frees++);
+				PV_STAT(pv_entry_spare++);
+				pv_entry_count--;
+				pc->pc_map[field] |= bitmask;
+				pmap->pm_stats.resident_count--;
+				TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+				if (TAILQ_EMPTY(&m->md.pv_list))
+					vm_page_aflag_clear(m, PGA_WRITEABLE);
+				pmap_unuse_pt(pmap, pv->pv_va, *pde);
+			}
 		}
-		*pte = is_kernel_pmap(pmap) ? PTE_G : 0;
-
-		m = PHYS_TO_VM_PAGE(TLBLO_PTE_TO_PA(tpte));
-		KASSERT(m != NULL,
-		    ("pmap_remove_pages: bad tpte %#jx", (uintmax_t)tpte));
-
-		pmap->pm_stats.resident_count--;
-
-		/*
-		 * Update the vm_page_t clean and reference bits.
-		 */
-		if (pte_test(&tpte, PTE_D)) {
-			vm_page_dirty(m);
+		if (allfree) {
+			TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+			free_pv_chunk(pc);
 		}
-		npv = TAILQ_NEXT(pv, pv_plist);
-		TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
-
-		m->md.pv_list_count--;
-		TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
-		if (TAILQ_FIRST(&m->md.pv_list) == NULL) {
-			vm_page_aflag_clear(m, PGA_WRITEABLE);
-		}
-		pmap_unuse_pt(pmap, pv->pv_va, *pde);
-		free_pv_entry(pv);
 	}
 	pmap_invalidate_all(pmap);
 	PMAP_UNLOCK(pmap);
@@ -2486,21 +2673,20 @@
 pmap_testbit(vm_page_t m, int bit)
 {
 	pv_entry_t pv;
+	pmap_t pmap;
 	pt_entry_t *pte;
 	boolean_t rv = FALSE;
 
 	if (m->oflags & VPO_UNMANAGED)
 		return (rv);
 
-	if (TAILQ_FIRST(&m->md.pv_list) == NULL)
-		return (rv);
-
 	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
 	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
-		PMAP_LOCK(pv->pv_pmap);
-		pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+		pmap = PV_PMAP(pv);
+		PMAP_LOCK(pmap);
+		pte = pmap_pte(pmap, pv->pv_va);
 		rv = pte_test(pte, bit);
-		PMAP_UNLOCK(pv->pv_pmap);
+		PMAP_UNLOCK(pmap);
 		if (rv)
 			break;
 	}
@@ -2514,6 +2700,7 @@
 pmap_changebit(vm_page_t m, int bit, boolean_t setem)
 {
 	pv_entry_t pv;
+	pmap_t pmap;
 	pt_entry_t *pte;
 
 	if (m->oflags & VPO_UNMANAGED)
@@ -2525,11 +2712,12 @@
 	 * setting RO do we need to clear the VAC?
 	 */
 	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
-		PMAP_LOCK(pv->pv_pmap);
-		pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+		pmap = PV_PMAP(pv);
+		PMAP_LOCK(pmap);
+		pte = pmap_pte(pmap, pv->pv_va);
 		if (setem) {
 			*pte |= bit;
-			pmap_update_page(pv->pv_pmap, pv->pv_va, *pte);
+			pmap_update_page(pmap, pv->pv_va, *pte);
 		} else {
 			pt_entry_t pbits = *pte;
 
@@ -2541,10 +2729,10 @@
 				} else {
 					*pte = pbits & ~bit;
 				}
-				pmap_update_page(pv->pv_pmap, pv->pv_va, *pte);
+				pmap_update_page(pmap, pv->pv_va, *pte);
 			}
 		}
-		PMAP_UNLOCK(pv->pv_pmap);
+		PMAP_UNLOCK(pmap);
 	}
 	if (!setem && bit == PTE_D)
 		vm_page_aflag_clear(m, PGA_WRITEABLE);
@@ -2569,7 +2757,7 @@
 		return (count);
 	vm_page_lock_queues();
 	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
-		pmap = pv->pv_pmap;
+		pmap = PV_PMAP(pv);
 		PMAP_LOCK(pmap);
 		pte = pmap_pte(pmap, pv->pv_va);
 		if (pte_test(pte, PTE_W))
@@ -2586,9 +2774,9 @@
 void
 pmap_remove_write(vm_page_t m)
 {
-	pv_entry_t pv, npv;
-	vm_offset_t va;
-	pt_entry_t *pte;
+	pmap_t pmap;
+	pt_entry_t pbits, *pte;
+	pv_entry_t pv;
 
 	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 	    ("pmap_remove_write: page %p is not managed", m));
@@ -2602,20 +2790,25 @@
 	if ((m->oflags & VPO_BUSY) == 0 &&
 	    (m->aflags & PGA_WRITEABLE) == 0)
 		return;
-
-	/*
-	 * Loop over all current mappings setting/clearing as appropos.
-	 */
 	vm_page_lock_queues();
-	for (pv = TAILQ_FIRST(&m->md.pv_list); pv; pv = npv) {
-		npv = TAILQ_NEXT(pv, pv_plist);
-		pte = pmap_pte(pv->pv_pmap, pv->pv_va);
-		if (pte == NULL || !pte_test(pte, PTE_V))
-			panic("page on pm_pvlist has no pte");
-
-		va = pv->pv_va;
-		pmap_protect(pv->pv_pmap, va, va + PAGE_SIZE,
-		    VM_PROT_READ | VM_PROT_EXECUTE);
+	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+		pmap = PV_PMAP(pv);
+		PMAP_LOCK(pmap);
+		pte = pmap_pte(pmap, pv->pv_va);
+		KASSERT(pte != NULL && pte_test(pte, PTE_V),
+		    ("page on pv_list has no pte"));
+		pbits = *pte;
+		if (pte_test(&pbits, PTE_D)) {
+			pte_clear(&pbits, PTE_D);
+			vm_page_dirty(m);
+			m->md.pv_flags &= ~PV_TABLE_MOD;
+		}
+		pte_set(&pbits, PTE_RO);
+		if (pbits != *pte) {
+			*pte = pbits;
+			pmap_update_page(pmap, pv->pv_va, pbits);
+		}
+		PMAP_UNLOCK(pmap);
 	}
 	vm_page_aflag_clear(m, PGA_WRITEABLE);
 	vm_page_unlock_queues();
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/rt305x/rt305x_gpio.c
--- a/head/sys/mips/rt305x/rt305x_gpio.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/rt305x/rt305x_gpio.c	Wed Aug 15 11:46:11 2012 +0300
@@ -141,7 +141,6 @@
 		}
 	}
 
-
 	if (flags & GPIO_PIN_REPORT) {
 		pin->gp_flags |= GPIO_PIN_REPORT;
 		GPIO_BIT_SET(sc, pin->gp_pin, RENA);
@@ -574,7 +573,7 @@
 	    rt305x_gpio_register_irq_handler),
 	DEVMETHOD(gpio_unregister_irq_handler,
 	    rt305x_gpio_unregister_irq_handler),
-	{0, 0},
+	DEVMETHOD_END
 };
 
 static driver_t rt305x_gpio_driver = {
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/Makefile
--- a/head/sys/modules/Makefile	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/modules/Makefile	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/modules/Makefile 238026 2012-07-02 20:36:26Z marcel $
+# $FreeBSD: head/sys/modules/Makefile 239281 2012-08-15 06:31:32Z gonzo $
 
 .include <bsd.own.mk>
 
@@ -72,6 +72,7 @@
 	${_coff} \
 	${_coretemp} \
 	${_cp} \
+	${_cpsw} \
 	${_cpuctl} \
 	${_cpufreq} \
 	${_crypto} \
@@ -743,6 +744,7 @@
 
 .if ${MACHINE_CPUARCH} == "arm"
 _cfi=		cfi
+_cpsw=		cpsw
 .endif
 
 .if ${MACHINE_CPUARCH} == "ia64"
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/cpsw/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/modules/cpsw/Makefile	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,8 @@
+# $FreeBSD: head/sys/modules/cpsw/Makefile 239281 2012-08-15 06:31:32Z gonzo $
+
+.PATH: ${.CURDIR}/../../arm/ti/cpsw
+
+KMOD=   if_cpsw
+SRCS=   if_cpsw.c device_if.h bus_if.h ofw_bus_if.h miibus_if.h
+
+.include <bsd.kmod.mk>
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/cxgbe/if_cxgbe/Makefile
--- a/head/sys/modules/cxgbe/if_cxgbe/Makefile	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/modules/cxgbe/if_cxgbe/Makefile	Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,9 @@
 #
-# $FreeBSD: head/sys/modules/cxgbe/if_cxgbe/Makefile 237819 2012-06-29 19:51:06Z np $
+# $FreeBSD: head/sys/modules/cxgbe/if_cxgbe/Makefile 239264 2012-08-14 23:08:49Z np $
 #
 
+.include <bsd.own.mk>
+
 CXGBE = ${.CURDIR}/../../../dev/cxgbe
 .PATH: ${CXGBE} ${CXGBE}/common
 
@@ -17,4 +19,17 @@
 # Provide the timestamp of a packet in its header mbuf.
 #CFLAGS+= -DT4_PKT_TIMESTAMP
 
+.if !defined(KERNBUILDDIR)
+.if ${MK_INET_SUPPORT} != "no"
+opt_inet.h:
+	@echo "#define INET 1" > ${.TARGET}
+	@echo "#define TCP_OFFLOAD 1" >> ${.TARGET}
+.endif
+
+.if ${MK_INET6_SUPPORT} != "no"
+opt_inet6.h:
+	@echo "#define INET6 1" > ${.TARGET}
+.endif
+.endif
+
 .include <bsd.kmod.mk>
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/cxgbe/tom/Makefile
--- a/head/sys/modules/cxgbe/tom/Makefile	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/modules/cxgbe/tom/Makefile	Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,9 @@
 #
-# $FreeBSD: head/sys/modules/cxgbe/tom/Makefile 237263 2012-06-19 07:34:13Z np $
+# $FreeBSD: head/sys/modules/cxgbe/tom/Makefile 239264 2012-08-14 23:08:49Z np $
 #
 
+.include <bsd.own.mk>
+
 CXGBE = ${.CURDIR}/../../../dev/cxgbe
 .PATH: ${CXGBE}/tom
 
@@ -12,4 +14,12 @@
 
 CFLAGS+= -I${CXGBE}
 
+.if !defined(KERNBUILDDIR)
+.if ${MK_INET_SUPPORT} != "no"
+opt_inet.h:
+	echo "#define INET 1" > ${.TARGET}
+	echo "#define TCP_OFFLOAD 1" >> ${.TARGET}
+.endif
+.endif
+
 .include <bsd.kmod.mk>
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/mii/Makefile
--- a/head/sys/modules/mii/Makefile	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/modules/mii/Makefile	Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/modules/mii/Makefile 232016 2012-02-23 01:22:40Z yongari $
+# $FreeBSD: head/sys/modules/mii/Makefile 239275 2012-08-15 04:03:55Z gonzo $
 
 .PATH: ${.CURDIR}/../../dev/mii
 
@@ -8,7 +8,8 @@
 SRCS+=	e1000phy.c gentbi.c icsphy.c ip1000phy.c jmphy.c lxtphy.c
 SRCS+=	miibus_if.c miibus_if.h mii.c miidevs.h mii_bitbang.c mii_physubr.c
 SRCS+=	mlphy.c nsgphy.c nsphy.c nsphyter.c pci_if.h pnaphy.c qsphy.c
-SRCS+=	rdcphy.c rgephy.c rlphy.c smcphy.c tdkphy.c tlphy.c truephy.c
+SRCS+=	rdcphy.c rgephy.c rlphy.c smcphy.c
+SRCS+=	smscphy.c tdkphy.c tlphy.c truephy.c
 SRCS+=	ukphy.c ukphy_subr.c
 SRCS+=	xmphy.c
 
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/usb/smsc/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/modules/usb/smsc/Makefile	Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,37 @@
+#
+# $FreeBSD: head/sys/modules/usb/smsc/Makefile 239275 2012-08-15 04:03:55Z gonzo $
+#
+# Copyright (c) 2011 Ben Gray. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+S=     ${.CURDIR}/../../..
+
+.PATH: $S/dev/usb/net
+
+KMOD=	if_smsc
+SRCS=	opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \
+	miibus_if.h opt_inet.h \
+	if_smsc.c
+
+.include <bsd.kmod.mk>
diff -r a301a330526b -r 49889ad5ef1f head/sys/nfsclient/nfs_bio.c
--- a/head/sys/nfsclient/nfs_bio.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/nfsclient/nfs_bio.c	Wed Aug 15 11:46:11 2012 +0300
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_bio.c 239065 2012-08-05 14:11:42Z kib $");
+__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_bio.c 239246 2012-08-14 11:45:47Z kib $");
 
 #include "opt_kdtrace.h"
 
@@ -212,14 +212,18 @@
 			    ("nfs_getpages: page %p is dirty", m));
 		} else {
 			/*
-			 * Read operation was short.  If no error occured
-			 * we may have hit a zero-fill section.   We simply
-			 * leave valid set to 0.
+			 * Read operation was short.  If no error
+			 * occured we may have hit a zero-fill
+			 * section.  We leave valid set to 0, and page
+			 * is freed by vm_page_readahead_finish() if
+			 * its index is not equal to requested, or
+			 * page is zeroed and set valid by
+			 * vm_pager_get_pages() for requested page.
 			 */
 			;
 		}
 		if (i != ap->a_reqpage)
-			vm_page_readahead_finish(m, error);
+			vm_page_readahead_finish(m);
 	}
 	VM_OBJECT_UNLOCK(object);
 	return (0);
diff -r a301a330526b -r 49889ad5ef1f head/sys/sys/bus.h
--- a/head/sys/sys/bus.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/sys/bus.h	Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/sys/bus.h 239046 2012-08-05 06:15:12Z andreast $
+ * $FreeBSD: head/sys/sys/bus.h 239178 2012-08-10 15:02:49Z hselasky $
  */
 
 #ifndef _SYS_BUS_H_
@@ -492,6 +492,7 @@
 int	device_shutdown(device_t dev);
 void	device_unbusy(device_t dev);
 void	device_verbose(device_t dev);
+void	device_free_softc(device_t dev, void *softc);
 
 /*
  * Access functions for devclass.
diff -r a301a330526b -r 49889ad5ef1f head/sys/sys/param.h
--- a/head/sys/sys/param.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/sys/param.h	Wed Aug 15 11:46:11 2012 +0300
@@ -32,7 +32,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)param.h	8.3 (Berkeley) 4/4/95
- * $FreeBSD: head/sys/sys/param.h 238405 2012-07-12 19:30:53Z jkim $
+ * $FreeBSD: head/sys/sys/param.h 239214 2012-08-12 17:53:06Z hselasky $
  */
 
 #ifndef _SYS_PARAM_H_
@@ -58,7 +58,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1000015	/* Master, propagated to newvers */
+#define __FreeBSD_version 1000017	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff -r a301a330526b -r 49889ad5ef1f head/sys/vm/vm_mmap.c
--- a/head/sys/vm/vm_mmap.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/vm/vm_mmap.c	Wed Aug 15 11:46:11 2012 +0300
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vm_mmap.c 234556 2012-04-21 18:36:53Z kib $");
+__FBSDID("$FreeBSD: head/sys/vm/vm_mmap.c 239250 2012-08-14 12:11:48Z kib $");
 
 #include "opt_compat.h"
 #include "opt_hwpmc_hooks.h"
@@ -207,11 +207,23 @@
 
 	fp = NULL;
 
-	/* Make sure mapping fits into numeric range, etc. */
-	if ((uap->len == 0 && !SV_CURPROC_FLAG(SV_AOUT) &&
-	     curproc->p_osrel >= P_OSREL_MAP_ANON) ||
-	    ((flags & MAP_ANON) && (uap->fd != -1 || pos != 0)))
-		return (EINVAL);
+	/*
+	 * Enforce the constraints.
+	 * Mapping of length 0 is only allowed for old binaries.
+	 * Anonymous mapping shall specify -1 as filedescriptor and
+	 * zero position for new code. Be nice to ancient a.out
+	 * binaries and correct pos for anonymous mapping, since old
+	 * ld.so sometimes issues anonymous map requests with non-zero
+	 * pos.
+	 */
+	if (!SV_CURPROC_FLAG(SV_AOUT)) {
+		if ((uap->len == 0 && curproc->p_osrel >= P_OSREL_MAP_ANON) ||
+		    ((flags & MAP_ANON) != 0 && (uap->fd != -1 || pos != 0)))
+			return (EINVAL);
+	} else {
+		if ((flags & MAP_ANON) != 0)
+			pos = 0;
+	}
 
 	if (flags & MAP_STACK) {
 		if ((uap->fd != -1) ||
@@ -441,6 +453,13 @@
 	nargs.addr = uap->addr;
 	nargs.len = uap->len;
 	nargs.prot = cvtbsdprot[uap->prot & 0x7];
+#ifdef COMPAT_FREEBSD32
+#if defined(__amd64__) || defined(__ia64__)
+	if (i386_read_exec && SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
+	    nargs.prot != 0)
+		nargs.prot |= PROT_EXEC;
+#endif
+#endif
 	nargs.flags = 0;
 	if (uap->flags & OMAP_ANON)
 		nargs.flags |= MAP_ANON;
diff -r a301a330526b -r 49889ad5ef1f head/sys/vm/vm_page.c
--- a/head/sys/vm/vm_page.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/vm/vm_page.c	Wed Aug 15 11:46:11 2012 +0300
@@ -77,7 +77,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vm_page.c 239040 2012-08-04 18:16:43Z kib $");
+__FBSDID("$FreeBSD: head/sys/vm/vm_page.c 239246 2012-08-14 11:45:47Z kib $");
 
 #include "opt_vm.h"
 
@@ -699,10 +699,10 @@
  * array which is not the request page.
  */
 void
-vm_page_readahead_finish(vm_page_t m, int error)
+vm_page_readahead_finish(vm_page_t m)
 {
 
-	if (error == 0) {
+	if (m->valid != 0) {
 		/*
 		 * Since the page is not the requested page, whether
 		 * it should be activated or deactivated is not
@@ -721,6 +721,12 @@
 		}
 		vm_page_wakeup(m);
 	} else {
+		/*
+		 * Free the completely invalid page.  Such page state
+		 * occurs due to the short read operation which did
+		 * not covered our page at all, or in case when a read
+		 * error happens.
+		 */
 		vm_page_lock(m);
 		vm_page_free(m);
 		vm_page_unlock(m);
diff -r a301a330526b -r 49889ad5ef1f head/sys/vm/vm_page.h
--- a/head/sys/vm/vm_page.h	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/vm/vm_page.h	Wed Aug 15 11:46:11 2012 +0300
@@ -57,7 +57,7 @@
  * any improvements or extensions that they make and grant Carnegie the
  * rights to redistribute these changes.
  *
- * $FreeBSD: head/sys/vm/vm_page.h 239065 2012-08-05 14:11:42Z kib $
+ * $FreeBSD: head/sys/vm/vm_page.h 239246 2012-08-14 11:45:47Z kib $
  */
 
 /*
@@ -388,7 +388,7 @@
 int vm_page_pa_tryrelock(pmap_t, vm_paddr_t, vm_paddr_t *);
 vm_page_t vm_page_prev(vm_page_t m);
 void vm_page_putfake(vm_page_t m);
-void vm_page_readahead_finish(vm_page_t m, int error);
+void vm_page_readahead_finish(vm_page_t m);
 void vm_page_reference(vm_page_t m);
 void vm_page_remove (vm_page_t);
 void vm_page_rename (vm_page_t, vm_object_t, vm_pindex_t);
diff -r a301a330526b -r 49889ad5ef1f head/sys/vm/vnode_pager.c
--- a/head/sys/vm/vnode_pager.c	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/vm/vnode_pager.c	Wed Aug 15 11:46:11 2012 +0300
@@ -51,7 +51,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vnode_pager.c 239065 2012-08-05 14:11:42Z kib $");
+__FBSDID("$FreeBSD: head/sys/vm/vnode_pager.c 239246 2012-08-14 11:45:47Z kib $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -987,7 +987,7 @@
 		}
 		
 		if (i != reqpage)
-			vm_page_readahead_finish(mt, error);
+			vm_page_readahead_finish(mt);
 	}
 	VM_OBJECT_UNLOCK(object);
 	if (error) {
diff -r a301a330526b -r 49889ad5ef1f head/usr.bin/xlint/Makefile.inc
--- a/head/usr.bin/xlint/Makefile.inc	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/usr.bin/xlint/Makefile.inc	Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
 #	$NetBSD: Makefile.inc,v 1.8 2002/02/04 00:18:32 thorpej Exp $
-# $FreeBSD: head/usr.bin/xlint/Makefile.inc 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/usr.bin/xlint/Makefile.inc 239272 2012-08-15 03:21:56Z gonzo $
 
 WARNS?=		0
 
@@ -8,7 +8,7 @@
 # These assignments duplicate much of the functionality of
 # MACHINE_CPUARCH, but there's no easy way to export make functions...
 .if defined(TARGET_ARCH)
-TARGET_CPUARCH=	${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/}
+TARGET_CPUARCH=	${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/}
 .else
 TARGET_CPUARCH=	${MACHINE_CPUARCH}
 TARGET_ARCH=	${MACHINE_ARCH}
diff -r a301a330526b -r 49889ad5ef1f head/usr.sbin/lpr/lpd/lpd.8
--- a/head/usr.sbin/lpr/lpd/lpd.8	Wed Aug 15 11:16:36 2012 +0300
+++ b/head/usr.sbin/lpr/lpd/lpd.8	Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)lpd.8	8.3 (Berkeley) 4/19/94
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/lpr/lpd/lpd.8 239233 2012-08-13 15:16:25Z wblock $
 .\"
 .Dd June 6, 2001
 .Dt LPD 8
@@ -152,7 +152,7 @@
 .Pp
 The file
 .Em minfree
-in each spool directory contains the number of disk blocks to leave free
+in each spool directory contains the number of kilobytes to leave free
 so that the line printer queue will not completely fill the disk.
 The
 .Em minfree



More information about the Zrouter-src-freebsd mailing list