diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 9bed51f280b..9e2d734db39 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -14,6 +14,15 @@ # The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last. # +# 20090904: remove lukemftpd +OLD_FILES+=usr/libexec/lukemftpd +OLD_FILES+=usr/share/man/man5/ftpd.conf.5.gz +OLD_FILES+=usr/share/man/man5/ftpusers.5.gz +OLD_FILES+=usr/share/man/man8/lukemftpd.8.gz +# 20090902: BSD.{x11,x11-4}.dist are dead and BSD.local.dist lives in ports/ +OLD_FILES+=etc/mtree/BSD.local.dist +OLD_FILES+=etc/mtree/BSD.x11.dist +OLD_FILES+=etc/mtree/BSD.x11-4.dist # 20090801: vimage.h removed in favour of vnet.h OLD_FILES+=usr/include/sys/vimage.h # 20090719: library version bump for 8.0 @@ -803,8 +812,6 @@ OLD_FILES+=rescue/bsdlabel OLD_FILES+=rescue/fdisk OLD_FILES+=rescue/gpt .endif -# 20071026: kthread(9)/kproc(9) API changes -OLD_FILES+=usr/share/man/man9/kthread_create.9.gz # 20071025: rc.d/nfslocking superceeded by rc.d/lockd and rc.d/statd OLD_FILES+=etc/rc.d/nfslocking # 20070930: rename of cached to nscd diff --git a/UPDATING b/UPDATING index add10f3a78b..ab922195f6b 100644 --- a/UPDATING +++ b/UPDATING @@ -1,45 +1,60 @@ Updating Information for FreeBSD current users -This file is maintained and copyrighted by M. Warner Losh -. See end of file for further details. For commonly -done items, please see the COMMON ITEMS: section later in the file. +This file is maintained and copyrighted by M. Warner Losh . +See end of file for further details. For commonly done items, please see the +COMMON ITEMS: section later in the file. These instructions assume that you +basically know what you are doing. If not, then please consult the FreeBSD +handbook. Items affecting the ports and packages system can be found in -/usr/ports/UPDATING. Please read that file before running -portupgrade. +/usr/ports/UPDATING. Please read that file before running portupgrade. -NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW: - FreeBSD 8.x has many debugging features turned on, in - both the kernel and userland. These features attempt to detect - incorrect use of system primitives, and encourage loud failure - through extra sanity checking and fail stop semantics. They - also substantially impact system performance. If you want to - do performance measurement, benchmarking, and optimization, - you'll want to turn them off. This includes various WITNESS- - related kernel options, INVARIANTS, malloc debugging flags - in userland, and various verbose features in the kernel. Many - developers choose to disable these features on build machines - to maximize performance. (To disable malloc debugging, run +NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW: + FreeBSD 9.x has many debugging features turned on, in both the kernel + and userland. These features attempt to detect incorrect use of + system primitives, and encourage loud failure through extra sanity + checking and fail stop semantics. They also substantially impact + system performance. If you want to do performance measurement, + benchmarking, and optimization, you'll want to turn them off. This + includes various WITNESS- related kernel options, INVARIANTS, malloc + debugging flags in userland, and various verbose features in the + kernel. Many developers choose to disable these features on build + machines to maximize performance. (To disable malloc debugging, run ln -s aj /etc/malloc.conf.) +20090825: + The old tunable hw.bus.devctl_disable has been superseded by + hw.bus.devctl_queue. hw.bus.devctl_disable=1 in loader.conf should be + replaced by hw.bus.devctl_queue=0. The default for this new tunable + is 1000. + +20090813: + Remove the option STOP_NMI. The default action is now to use NMI only + for KDB via the newly introduced function stop_cpus_hard() and + maintain stop_cpus() to just use a normal IPI_STOP on ia32 and amd64. + +20090803: + The stable/8 branch created in subversion. This corresponds to the + RELENG_8 branch in CVS. + 20090719: - Bump the shared library version numbers for all libraries that - do not use symbol versioning as part of the 8.0-RELEASE cycle. - Bump __FreeBSD_version to 800105. + Bump the shared library version numbers for all libraries that do not + use symbol versioning as part of the 8.0-RELEASE cycle. Bump + __FreeBSD_version to 800105. 20090714: - Due to changes in the implementation of virtual network stack - support, all network-related kernel modules must be recompiled. - As this change breaks the ABI, bump __FreeBSD_version to 800104. + Due to changes in the implementation of virtual network stack support, + all network-related kernel modules must be recompiled. As this change + breaks the ABI, bump __FreeBSD_version to 800104. 20090713: - The TOE interface to the TCP syncache has been modified to remove struct - tcpopt () from the ABI of the network stack. The - cxgb driver is the only TOE consumer affected by this change, and needs - to be recompiled along with the kernel. As this change breaks the ABI, - bump __FreeBSD_version to 800103. + The TOE interface to the TCP syncache has been modified to remove + struct tcpopt () from the ABI of the network stack. + The cxgb driver is the only TOE consumer affected by this change, and + needs to be recompiled along with the kernel. As this change breaks + the ABI, bump __FreeBSD_version to 800103. -20090712: +20090712: Padding has been added to struct tcpcb, sackhint and tcpstat in to facilitate future MFCs and bug fixes whilst maintainig the ABI. However, this change breaks the ABI, so bump @@ -47,79 +62,75 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW: any of these structs (e.g. sockstat) need to be recompiled. 20090630: - The NFS_LEGACYRPC option has been removed along with the old - kernel RPC implementation that this option selected. Kernel - configurations may need to be adjusted. + The NFS_LEGACYRPC option has been removed along with the old kernel + RPC implementation that this option selected. Kernel configurations + may need to be adjusted. 20090629: - The network interface device nodes at /dev/net/ have - been removed. All ioctl operations can be performed the normal - way using routing sockets. The kqueue functionality can - generally be replaced with routing sockets. + The network interface device nodes at /dev/net/ have been + removed. All ioctl operations can be performed the normal way using + routing sockets. The kqueue functionality can generally be replaced + with routing sockets. 20090628: - The documentation from the FreeBSD Documentation Project - (Handbook, FAQ, etc.) is now installed via packages by - sysinstall(8) and under the /usr/local/share/doc/freebsd - directory instead of /usr/share/doc. + The documentation from the FreeBSD Documentation Project (Handbook, + FAQ, etc.) is now installed via packages by sysinstall(8) and under + the /usr/local/share/doc/freebsd directory instead of /usr/share/doc. 20090624: - The ABI of various structures related to the SYSV IPC API have - been changed. As a result, the COMPAT_FREEBSD[456] and COMPAT_43 - kernel options now all require COMPAT_FREEBSD7. - Bump __FreeBSD_version to 800100. + The ABI of various structures related to the SYSV IPC API have been + changed. As a result, the COMPAT_FREEBSD[456] and COMPAT_43 kernel + options now all require COMPAT_FREEBSD7. Bump __FreeBSD_version to + 800100. 20090622: - Layout of struct vnet has changed as routing related variables - were moved to their own Vimage module. Modules need to be - recompiled. Bump __FreeBSD_version to 800099. + Layout of struct vnet has changed as routing related variables were + moved to their own Vimage module. Modules need to be recompiled. Bump + __FreeBSD_version to 800099. 20090619: - NGROUPS_MAX and NGROUPS have been increased from 16 to 1023 - and 1024 respectively. As long as no more than 16 groups per - process are used, no changes should be visible. When more - than 16 groups are used, old binaries may fail if they call - getgroups() or getgrouplist() with statically sized storage. - Recompiling will work around this, but applications should be - modified to use dynamically allocated storage for group arrays - as POSIX.1-2008 does not cap an implementation's number of - supported groups at NGROUPS_MAX+1 as previous versions did. + NGROUPS_MAX and NGROUPS have been increased from 16 to 1023 and 1024 + respectively. As long as no more than 16 groups per process are used, + no changes should be visible. When more than 16 groups are used, old + binaries may fail if they call getgroups() or getgrouplist() with + statically sized storage. Recompiling will work around this, but + applications should be modified to use dynamically allocated storage + for group arrays as POSIX.1-2008 does not cap an implementation's + number of supported groups at NGROUPS_MAX+1 as previous versions did. - NFS and portalfs mounts may also be affected as the list of - groups is truncated to 16. Users of NFS who use more than 16 - groups, should take care that negative group permissions are not - used on the exported file systems as they will not be reliable - unless a GSSAPI based authentication method is used. + NFS and portalfs mounts may also be affected as the list of groups is + truncated to 16. Users of NFS who use more than 16 groups, should + take care that negative group permissions are not used on the exported + file systems as they will not be reliable unless a GSSAPI based + authentication method is used. -20090616: - The compiling option ADAPTIVE_LOCKMGRS has been introduced. - This option compiles in the support for adaptive spinning for lockmgrs - which want to enable it. The lockinit() function now accepts the - flag LK_ADAPTIVE in order to make the lock object subject to - adaptive spinning when both held in write and read mode. +20090616: + The compiling option ADAPTIVE_LOCKMGRS has been introduced. This + option compiles in the support for adaptive spinning for lockmgrs + which want to enable it. The lockinit() function now accepts the flag + LK_ADAPTIVE in order to make the lock object subject to adaptive + spinning when both held in write and read mode. 20090613: - The layout of the structure returned by IEEE80211_IOC_STA_INFO - has changed. User applications that use this ioctl need to be - rebuilt. + The layout of the structure returned by IEEE80211_IOC_STA_INFO has + changed. User applications that use this ioctl need to be rebuilt. 20090611: - The layout of struct thread has changed. Kernel and modules - need to be rebuilt. + The layout of struct thread has changed. Kernel and modules need to + be rebuilt. 20090608: - The layout of structs ifnet, domain, protosw and vnet_net has - changed. Kernel modules need to be rebuilt. - Bump __FreeBSD_version to 800097. + The layout of structs ifnet, domain, protosw and vnet_net has changed. + Kernel modules need to be rebuilt. Bump __FreeBSD_version to 800097. 20090602: window(1) has been removed from the base system. It can now be installed from ports. The port is called misc/window. 20090601: - The way we are storing and accessing `routing table' entries - has changed. Programs reading the FIB, like netstat, need to - be re-compiled. + The way we are storing and accessing `routing table' entries has + changed. Programs reading the FIB, like netstat, need to be + re-compiled. 20090601: A new netisr implementation has been added for FreeBSD 8. Network @@ -128,24 +139,24 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW: Bump __FreeBSD_version to 800096. 20090530: - Remove the tunable/sysctl debug.mpsafevfs as its initial purpose - is no more valid. + Remove the tunable/sysctl debug.mpsafevfs as its initial purpose is no + more valid. 20090530: Add VOP_ACCESSX(9). File system modules need to be rebuilt. Bump __FreeBSD_version to 800094. 20090529: - Add mnt_xflag field to 'struct mount'. File system modules - need to be rebuilt. + Add mnt_xflag field to 'struct mount'. File system modules need to be + rebuilt. Bump __FreeBSD_version to 800093. 20090528: The compiling option ADAPTIVE_SX has been retired while it has been introduced the option NO_ADAPTIVE_SX which handles the reversed logic. The KPI for sx_init_flags() changes as accepting flags: - SX_ADAPTIVESPIN flag has been retired while the SX_NOADAPTIVE flag - has been introduced in order to handle the reversed logic. + SX_ADAPTIVESPIN flag has been retired while the SX_NOADAPTIVE flag has + been introduced in order to handle the reversed logic. Bump __FreeBSD_version to 800092. 20090527: @@ -158,20 +169,18 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW: Bump __FreeBSD_version to 800090. 20090523: - The newly imported zic(8) produces a new format in the - output. Please run tzsetup(8) to install the newly created - data to /etc/localtime. + The newly imported zic(8) produces a new format in the output. Please + run tzsetup(8) to install the newly created data to /etc/localtime. 20090520: The sysctl tree for the usb stack has renamed from hw.usb2.* to hw.usb.* and is now consistent again with previous releases. 20090520: - 802.11 monitor mode support was revised and driver api's - were changed. Drivers dependent on net80211 now support - DLT_IEEE802_11_RADIO instead of DLT_IEEE802_11. No - user-visible data structures were changed but applications - that use DLT_IEEE802_11 may require changes. + 802.11 monitor mode support was revised and driver api's were changed. + Drivers dependent on net80211 now support DLT_IEEE802_11_RADIO instead + of DLT_IEEE802_11. No user-visible data structures were changed but + applications that use DLT_IEEE802_11 may require changes. Bump __FreeBSD_version to 800088. 20090430: @@ -762,730 +771,29 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW: 20071010: RELENG_7 branched. -20071009: - Setting WITHOUT_LIBPTHREAD now means WITHOUT_LIBKSE and - WITHOUT_LIBTHR are set. - -20070930: - The PCI code has been made aware of PCI domains. This means that - the location strings as used by pciconf(8) etc are now in the - following format: pci::[:]. It - also means that consumers of potentially need to - be recompiled; this includes the hal and xorg-server ports. - -20070928: - The caching daemon (cached) was renamed to nscd. nscd.conf - configuration file should be used instead of cached.conf and - nscd_enable, nscd_pidfile and nscd_flags options should be used - instead of cached_enable, cached_pidfile and cached_flags in - rc.conf. - -20070921: - The getfacl(1) utility now prints owning user and group name - instead of owning uid and gid in the three line comment header. - This is the same behavior as getfacl(1) on Solaris and Linux. - -20070704: - The new IPsec code is now compiled in using the IPSEC option. The - IPSEC option now requires "device crypto" be defined in your kernel - configuration. The FAST_IPSEC kernel option is now deprecated. - -20070702: - The packet filter (pf) code has been updated to OpenBSD 4.1 Please - note the changed syntax - keep state is now on by default. Also - note the fact that ftp-proxy(8) has been changed from bottom up and - has been moved from libexec to usr/sbin. Changes in the ALTQ - handling also affect users of IPFW's ALTQ capabilities. - -20070701: - Remove KAME IPsec in favor of FAST_IPSEC, which is now the - only IPsec supported by FreeBSD. The new IPsec stack - supports both IPv4 and IPv6. The kernel option will change - after the code changes have settled in. For now the kernel - option IPSEC is deprecated and FAST_IPSEC is the only option, that - will change after some settling time. - -20070701: - The wicontrol(8) utility has been removed from the base system. wi(4) - cards should be configured using ifconfig(8), see the man page for more - information. - -20070612: - The i386/amd64 GENERIC kernel now defaults to the nfe(4) driver - instead of the nve(4) driver. Please update your configuration - accordingly. - -20070612: - By default, /etc/rc.d/sendmail no longer rebuilds the aliases - database if it is missing or older than the aliases file. If - desired, set the new rc.conf option sendmail_rebuild_aliases - to "YES" to restore that functionality. - -20070612: - The IPv4 multicast socket code has been considerably modified, and - moved to the file sys/netinet/in_mcast.c. Initial support for the - RFC 3678 Source-Specific Multicast Socket API has been added to - the IPv4 network stack. - - Strict multicast and broadcast reception is now the default for - UDP/IPv4 sockets; the net.inet.udp.strict_mcast_mship sysctl variable - has now been removed. - - The RFC 1724 hack for interface selection has been removed; the use - of the Linux-derived ip_mreqn structure with IP_MULTICAST_IF has - been added to replace it. Consumers such as routed will soon be - updated to reflect this. - - These changes affect users who are running routed(8) or rdisc(8) - from the FreeBSD base system on point-to-point or unnumbered - interfaces. - -20070610: - The net80211 layer has changed significantly and all wireless - drivers that depend on it need to be recompiled. Further these - changes require that any program that interacts with the wireless - support in the kernel be recompiled; this includes: ifconfig, - wpa_supplicant, hostapd, and wlanstats. Users must also, for - the moment, kldload the wlan_scan_sta and/or wlan_scan_ap modules - if they use modules for wireless support. These modules implement - scanning support for station and ap modes, respectively. Failure - to load the appropriate module before marking a wireless interface - up will result in a message to the console and the device not - operating properly. - -20070610: - The pam_nologin(8) module ceases to provide an authentication - function and starts providing an account management function. - Consequent changes to /etc/pam.d should be brought in using - mergemaster(8). Third-party files in /usr/local/etc/pam.d may - need manual editing as follows. Locate this line (or similar): - - auth required pam_nologin.so no_warn - - and change it according to this example: - - account required pam_nologin.so no_warn - - That is, the first word needs to be changed from "auth" to - "account". The new line can be moved to the account section - within the file for clarity. Not updating pam.conf(5) files - will result in nologin(5) ignored by the respective services. - -20070529: - The ether_ioctl() function has been synchronized with ioctl(2) - and ifnet.if_ioctl. Due to that, the size of one of its arguments - has changed on 64-bit architectures. All kernel modules using - ether_ioctl() need to be rebuilt on such architectures. - -20070516: - Improved INCLUDE_CONFIG_FILE support has been introduced to the - config(8) utility. In order to take advantage of this new - functionality, you are expected to recompile and install - src/usr.sbin/config. If you don't rebuild config(8), and your - kernel configuration depends on INCLUDE_CONFIG_FILE, the kernel - build will be broken because of a missing "kernconfstring" - symbol. - -20070513: - Symbol versioning is enabled by default. To disable it, use - option WITHOUT_SYMVER. It is not advisable to attempt to - disable symbol versioning once it is enabled; your installworld - will break because a symbol version-less libc will get installed - before the install tools. As a result, the old install tools, - which previously had symbol dependencies to FBSD_1.0, will fail - because the freshly installed libc will not have them. - - The default threading library (providing "libpthread") has been - changed to libthr. If you wish to have libkse as your default, - use option DEFAULT_THREAD_LIB=libkse for the buildworld. - -20070423: - The ABI breakage in sendmail(8)'s libmilter has been repaired - so it is no longer necessary to recompile mail filters (aka, - milters). If you recompiled mail filters after the 20070408 - note, it is not necessary to recompile them again. - -20070417: - The new trunk(4) driver has been renamed to lagg(4) as it better - reflects its purpose. ifconfig will need to be recompiled. - -20070408: - sendmail(8) has been updated to version 8.14.1. Mail filters - (aka, milters) compiled against the libmilter included in the - base operating system should be recompiled. - -20070302: - Firmwares for ipw(4) and iwi(4) are now included in the base tree. - In order to use them one must agree to the respective LICENSE in - share/doc/legal and define legal.intel_.license_ack=1 via - loader.conf(5) or kenv(1). Make sure to deinstall the now - deprecated modules from the respective firmware ports. - -20070228: - The name resolution/mapping functions addr2ascii(3) and ascii2addr(3) - were removed from FreeBSD's libc. These originally came from INRIA - IPv6. Nothing in FreeBSD ever used them. They may be regarded as - deprecated in previous releases. - The AF_LINK support for getnameinfo(3) was merged from NetBSD to - replace it as a more portable (and re-entrant) API. - -20070224: - To support interrupt filtering a modification to the newbus API - has occurred, ABI was broken and __FreeBSD_version was bumped - to 700031. Please make sure that your kernel and modules are in - sync. For more info: - http://docs.freebsd.org/cgi/mid.cgi?20070221233124.GA13941 - -20070224: - The IPv6 multicast forwarding code may now be loaded into GENERIC - kernels by loading the ip_mroute.ko module. This is built into the - module unless WITHOUT_INET6 or WITHOUT_INET6_SUPPORT options are - set; see src.conf(5) for more information. - -20070214: - The output of netstat -r has changed. Without -n, we now only - print a "network name" without the prefix length if the network - address and mask exactly match a Class A/B/C network, and an entry - exists in the nsswitch "networks" map. - With -n, we print the full unabbreviated CIDR network prefix in - the form "a.b.c.d/p". 0.0.0.0/0 is always printed as "default". - This change is in preparation for changes such as equal-cost - multipath, and to more generally assist operational deployment - of FreeBSD as a modern IPv4 router. - -20070210: - PIM has been turned on by default in the IPv4 multicast - routing code. The kernel option 'PIM' has now been removed. - PIM is now built by default if option 'MROUTING' is specified. - It may now be loaded into GENERIC kernels by loading the - ip_mroute.ko module. - -20070207: - Support for IPIP tunnels (VIFF_TUNNEL) in IPv4 multicast routing - has been removed. Its functionality may be achieved by explicitly - configuring gif(4) interfaces and using the 'phyint' keyword in - mrouted.conf. - XORP does not support source-routed IPv4 multicast tunnels nor the - integrated IPIP tunneling, therefore it is not affected by this - change. The __FreeBSD_version macro has been bumped to 700030. - -20061221: - Support for PCI Message Signalled Interrupts has been - re-enabled in the bge driver, only for those chips which are - believed to support it properly. If there are any problems, - MSI can be disabled completely by setting the - 'hw.pci.enable_msi' and 'hw.pci.enable_msix' tunables to 0 - in the loader. - -20061214: - Support for PCI Message Signalled Interrupts has been - disabled again in the bge driver. Many revisions of the - hardware fail to support it properly. Support can be - re-enabled by removing the #define of BGE_DISABLE_MSI in - "src/sys/dev/bge/if_bge.c". - -20061214: - Support for PCI Message Signalled Interrupts has been added - to the bge driver. If there are any problems, MSI can be - disabled completely by setting the 'hw.pci.enable_msi' and - 'hw.pci.enable_msix' tunables to 0 in the loader. - -20061205: - The removal of several facets of the experimental Threading - system from the kernel means that the proc and thread structures - have changed quite a bit. I suggest all kernel modules that might - reference these structures be recompiled.. Especially the - linux module. - -20061126: - Sound infrastructure has been updated with various fixes and - improvements. Most of the changes are pretty much transparent, - with exceptions of followings: - 1) All sound driver specific sysctls (hw.snd.pcm%d.*) have been - moved to their own dev sysctl nodes, for example: - hw.snd.pcm0.vchans -> dev.pcm.0.vchans - 2) /dev/dspr%d.%d has been deprecated. Each channel now has its - own chardev in the form of "dsp%d.%d", where - is p = playback, r = record and v = virtual, respectively. Users - are encouraged to use these devs instead of (old) "/dev/dsp%d.%d". - This does not affect those who are using "/dev/dsp". - -20061122: - geom(4)'s gmirror(8) class metadata structure has been - rev'd from v3 to v4. If you update across this point and - your metadata is converted for you, you will not be easily - able to downgrade since the /boot/kernel.old/geom_mirror.ko - kernel module will be unable to read the v4 metadata. You - can resolve this by doing from the loader(8) prompt: - - set vfs.root.mountfrom="ufs:/dev/XXX" - - where XXX is the root slice of one of the disks that composed - the mirror (i.e.: /dev/ad0s1a). You can then rebuild - the array the same way you built it originally. - -20061122: - The following binaries have been disconnected from the build: - mount_devfs, mount_ext2fs, mount_fdescfs, mount_procfs, mount_linprocfs, - and mount_std. The functionality of these programs has been - moved into the mount program. For example, to mount a devfs - filesystem, instead of using mount_devfs, use: "mount -t devfs". - This does not affect entries in /etc/fstab, since entries in - /etc/fstab are always processed with "mount -t fstype". - -20061113: - Support for PCI Message Signalled Interrupts on i386 and amd64 - has been added to the kernel and various drivers will soon be - updated to use MSI when it is available. If there are any problems, - MSI can be disabled completely by setting the 'hw.pci.enable_msi' - and 'hw.pci.enable_msix' tunables to 0 in the loader. - -20061110: - The MUTEX_PROFILING option has been renamed to LOCK_PROFILING. - The lockmgr object layout has been changed as a result of having - a lock_object embedded in it. As a consequence all file system - kernel modules must be re-compiled. The mutex profiling man page - has not yet been updated to reflect this change. - -20061026: - KSE in the kernel has now been made optional and turned on by - default. Use 'nooption KSE' in your kernel config to turn it - off. All kernel modules *must* be recompiled after this change. - There-after, modules from a KSE kernel should be compatible with - modules from a NOKSE kernel due to the temporary padding fields - added to 'struct proc'. - -20060929: - mrouted and its utilities have been removed from the base system. - -20060927: - Some ioctl(2) command codes have changed. Full backward ABI - compatibility is provided if the "options COMPAT_FREEBSD6" is - present in the kernel configuration file. Make sure to add - this option to your kernel config file, or recompile X.Org - and the rest of ports; otherwise they may refuse to work. - -20060924: - tcpslice has been removed from the base system. - -20060913: - The sizes of struct tcpcb (and struct xtcpcb) have changed due to - the rewrite of TCP syncookies. Tools like netstat, sockstat, and - systat needs to be rebuilt. - -20060903: - libpcap updated to v0.9.4 and tcpdump to v3.9.4 - -20060816: - The IPFIREWALL_FORWARD_EXTENDED option is gone and the behaviour - for IPFIREWALL_FORWARD is now as it was before when it was first - committed and for years after. The behaviour is now ON. - -20060725: - enigma(1)/crypt(1) utility has been changed on 64 bit architectures. - Now it can decrypt files created from different architectures. - Unfortunately, it is no longer able to decrypt a cipher text - generated with an older version on 64 bit architectures. - If you have such a file, you need old utility to decrypt it. - -20060709: - The interface version of the i4b kernel part has changed. So - after updating the kernel sources and compiling a new kernel, - the i4b user space tools in "/usr/src/usr.sbin/i4b" must also - be rebuilt, and vice versa. - -20060627: - The XBOX kernel now defaults to the nfe(4) driver instead of - the nve(4) driver. Please update your configuration - accordingly. - -20060514: - The i386-only lnc(4) driver for the AMD Am7900 LANCE and Am79C9xx - PCnet family of NICs has been removed. The new le(4) driver serves - as an equivalent but cross-platform replacement with the pcn(4) - driver still providing performance-optimized support for the subset - of AMD Am79C971 PCnet-FAST and greater chips as before. - -20060511: - The machdep.* sysctls and the adjkerntz utility have been - modified a bit. The new adjkerntz utility uses the new - sysctl names and sysctlbyname() calls, so it may be impossible - to run an old /sbin/adjkerntz utility in single-user mode - with a new kernel. Replace the `adjkerntz -i' step before - `make installworld' with: - - /usr/obj/usr/src/sbin/adjkerntz/adjkerntz -i - - and proceed as usual with the rest of the installworld-stage - steps. Otherwise, you risk installing binaries with their - timestamp set several hours in the future, especially if - you are running with local time set to GMT+X hours. - -20060412: - The ip6fw utility has been removed. The behavior provided by - ip6fw has been in ipfw2 for a good while and the rc.d scripts - have been updated to deal with it. There are some rules that - might not migrate cleanly. Use rc.firewall6 as a template to - rewrite rules. - -20060428: - The puc(4) driver has been overhauled. The ebus(4) and sbus(4) - attachments have been removed. Make sure to configure scc(4) - on sparc64. Note also that by default puc(4) will use uart(4) - and not sio(4) for serial ports because interrupt handling has - been optimized for multi-port serial cards and only uart(4) - implements the interface to support it. - -20060330: - The scc(4) driver replaces puc(4) for Serial Communications - Controllers (SCCs) like the Siemens SAB82532 and the Zilog - Z8530. On sparc64, it is advised to add scc(4) to the kernel - configuration to make sure that the serial ports remain - functional. - -20060317: - Most world/kernel related NO_* build options changed names. - New knobs have common prefixes WITHOUT_*/WITH_* (modelled - after FreeBSD ports) and should be set in /etc/src.conf - (the src.conf(5) manpage is provided). Full backwards - compatibility is maintained for the time being though it's - highly recommended to start moving old options out of the - system-wide /etc/make.conf file into the new /etc/src.conf - while also properly renaming them. More conversions will - likely follow. Posting to current@: - - http://lists.freebsd.org/pipermail/freebsd-current/2006-March/061725.html - -20060305: - The NETSMBCRYPTO kernel option has been retired because its - functionality is always included in NETSMB and smbfs.ko now. - -20060303: - The TDFX_LINUX kernel option was retired and replaced by the - tdfx_linux device. The latter can be loaded as the 3dfx_linux.ko - kernel module. Loading it alone should suffice to get 3dfx support - for Linux apps because it will pull in 3dfx.ko and linux.ko through - its dependencies. - -20060204: - The 'audit' group was added to support the new auditing functionality - in the base system. Be sure to follow the directions for updating, - including the requirement to run mergemaster -p. - -20060201: - The kernel ABI to file system modules was changed on i386. - Please make sure that your kernel and modules are in sync. - -20060118: - This actually occured some time ago, but installing the kernel - now also installs a bunch of symbol files for the kernel modules. - This increases the size of /boot/kernel to about 67Mbytes. You - will need twice this if you will eventually back this up to kernel.old - on your next install. - If you have a shortage of room in your root partition, you should add - -DINSTALL_NODEBUG to your make arguments or add INSTALL_NODEBUG="yes" - to your /etc/make.conf. - -20060113: - libc's malloc implementation has been replaced. This change has the - potential to uncover application bugs that previously went unnoticed. - See the malloc(3) manual page for more details. - -20060112: - The generic netgraph(4) cookie has been changed. If you upgrade - kernel passing this point, you also need to upgrade userland - and netgraph(4) utilities like ports/net/mpd or ports/net/mpd4. - -20060106: - si(4)'s device files now contain the unit number. - Uses of {cua,tty}A[0-9a-f] should be replaced by {cua,tty}A0[0-9a-f]. - -20060106: - The kernel ABI was mostly destroyed due to a change in the size - of struct lock_object which is nested in other structures such - as mutexes which are nested in all sorts of other structures. - Make sure your kernel and modules are in sync. - -20051231: - The page coloring algorithm in the VM subsystem was converted - from tuning with kernel options to autotuning. Please remove - any PQ_* option except PQ_NOOPT from your kernel config. - -20051211: - The net80211-related tools in the tools/tools/ath directory - have been moved to tools/tools/net80211 and renamed with a - "wlan" prefix. Scripts that use them should be adjusted - accordingly. - -20051202: - Scripts in the local_startup directories (as defined in - /etc/defaults/rc.conf) that have the new rc.d semantics will - now be run as part of the base system rcorder. If there are - errors or problems with one of these local scripts, it could - cause boot problems. If you encounter such problems, boot in - single user mode, remove that script from the */rc.d directory. - Please report the problem to the port's maintainer, and the - freebsd-ports@freebsd.org mailing list. - -20051129: - The nodev mount option was deprecated in RELENG_6 (where it - was a no-op), and is now unsupported. If you have nodev or dev listed - in /etc/fstab, remove it, otherwise it will result in a mount error. - -20051129: - ABI between ipfw(4) and ipfw(8) has been changed. You need - to rebuild ipfw(8) when rebuilding kernel. - -20051108: - rp(4)'s device files now contain the unit number. - Uses of {cua,tty}R[0-9a-f] should be replaced by {cua,tty}R0[0-9a-f]. - -20051029: - /etc/rc.d/ppp-user has been renamed to /etc/rc.d/ppp. - Its /etc/rc.conf.d configuration file has been `ppp' from - the beginning, and hence there is no need to touch it. - -20051014: - Now most modules get their build-time options from the kernel - configuration file. A few modules still have fixed options - due to their non-conformant implementation, but they will be - corrected eventually. You may need to review the options of - the modules in use, explicitly specify the non-default options - in the kernel configuration file, and rebuild the kernel and - modules afterwards. - -20051001: - kern.polling.enable sysctl MIB is now deprecated. Use ifconfig(8) - to turn polling(4) on your interfaces. - -20050927: - The old bridge(4) implementation was retired. The new - if_bridge(4) serves as a full functional replacement. - -20050722: - The ai_addrlen of a struct addrinfo was changed to a socklen_t - to conform to POSIX-2001. This change broke an ABI - compatibility on 64 bit architecture. You have to recompile - userland programs that use getaddrinfo(3) on 64 bit - architecture. - -20050711: - RELENG_6 branched here. - -20050629: - The pccard_ifconfig rc.conf variable has been removed and a new - variable, ifconfig_DEFAULT has been introduced. Unlike - pccard_ifconfig, ifconfig_DEFAULT applies to ALL interfaces that - do not have ifconfig_ifn entries rather than just those in - removable_interfaces. - -20050616: - Some previous versions of PAM have permitted the use of - non-absolute paths in /etc/pam.conf or /etc/pam.d/* when referring - to third party PAM modules in /usr/local/lib. A change has been - made to require the use of absolute paths in order to avoid - ambiguity and dependence on library path configuration, which may - affect existing configurations. - -20050610: - Major changes to network interface API. All drivers must be - recompiled. Drivers not in the base system will need to be - updated to the new APIs. - -20050609: - Changes were made to kinfo_proc in sys/user.h. Please recompile - userland, or commands like `fstat', `pkill', `ps', `top' and `w' - will not behave correctly. - - The API and ABI for hwpmc(4) have changed with the addition - of sampling support. Please recompile lib/libpmc(3) and - usr.sbin/{pmcstat,pmccontrol}. - -20050606: - The OpenBSD dhclient was imported in place of the ISC dhclient - and the network interface configuration scripts were updated - accordingly. If you use DHCP to configure your interfaces, you - must now run devd. Also, DNS updating was lost so you will need - to find a workaround if you use this feature. - - The '_dhcp' user was added to support the OpenBSD dhclient. Be - sure to run mergemaster -p (like you are supposed to do every time - anyway). - -20050605: - if_bridge was added to the tree. This has changed struct ifnet. - Please recompile userland and all network related modules. - -20050603: - The n_net of a struct netent was changed to an uint32_t, and - 1st argument of getnetbyaddr() was changed to an uint32_t, to - conform to POSIX-2001. These changes broke an ABI - compatibility on 64 bit architecture. With these changes, - shlib major of libpcap was bumped. You have to recompile - userland programs that use getnetbyaddr(3), getnetbyname(3), - getnetent(3) and/or libpcap on 64 bit architecture. - -20050528: - Kernel parsing of extra options on '#!' first lines of shell - scripts has changed. Lines with multiple options likely will - fail after this date. For full details, please see - http://people.freebsd.org/~gad/Updating-20050528.txt - -20050503: - The packet filter (pf) code has been updated to OpenBSD 3.7 - Please note the changed anchor syntax and the fact that - authpf(8) now needs a mounted fdescfs(5) to function. - -20050415: - The NO_MIXED_MODE kernel option has been removed from the i386 - amd64 platforms as its use has been superceded by the new local - APIC timer code. Any kernel config files containing this option - should be updated. - -20050227: - The on-disk format of LC_CTYPE files was changed to be machine - independent. Please make sure NOT to use NO_CLEAN buildworld - when crossing this point. Crossing this point also requires - recompile or reinstall of all locale depended packages. - -20050225: - The ifi_epoch member of struct if_data has been changed to - contain the uptime at which the interface was created or the - statistics zeroed rather then the wall clock time because - wallclock time may go backwards. This should have no impact - unless an snmp implementation is using this value (I know of - none at this point.) - -20050224: - The acpi_perf and acpi_throttle drivers are now part of the - acpi(4) main module. They are no longer built separately. - -20050223: - The layout of struct image_params has changed. You have to - recompile all compatibility modules (linux, svr4, etc) for use - with the new kernel. - -20050223: - The p4tcc driver has been merged into cpufreq(4). This makes - "options CPU_ENABLE_TCC" obsolete. Please load cpufreq.ko or - compile in "device cpufreq" to restore this functionality. - -20050220: - The responsibility of recomputing the file system summary of - a SoftUpdates-enabled dirty volume has been transferred to the - background fsck. A rebuild of fsck(8) utility is recommended - if you have updated the kernel. - - To get the old behavior (recompute file system summary at mount - time), you can set vfs.ffs.compute_summary_at_mount=1 before - mounting the new volume. - -20050206: - The cpufreq import is complete. As part of this, the sysctls for - acpi(4) throttling have been removed. The power_profile script - has been updated, so you can use performance/economy_cpu_freq in - rc.conf(5) to set AC on/offline cpu frequencies. - -20050206: - NG_VERSION has been increased. Recompiling kernel (or ng_socket.ko) - requires recompiling libnetgraph and userland netgraph utilities. - -20050114: - Support for abbreviated forms of a number of ipfw options is - now deprecated. Warnings are printed to stderr indicating the - correct full form when a match occurs. Some abbreviations may - be supported at a later date based on user feedback. To be - considered for support, abbreviations must be in use prior to - this commit and unlikely to be confused with current key words. - -20041221: - By a popular demand, a lot of NOFOO options were renamed - to NO_FOO (see bsd.compat.mk for a full list). The old - spellings are still supported, but will cause annoying - warnings on stderr. Make sure you upgrade properly (see - the COMMON ITEMS: section later in this file). - -20041219: - Auto-loading of ancillary wlan modules such as wlan_wep has - been temporarily disabled; you need to statically configure - the modules you need into your kernel or explicitly load them - prior to use. Specifically, if you intend to use WEP encryption - with an 802.11 device load/configure wlan_wep; if you want to - use WPA with the ath driver load/configure wlan_tkip, wlan_ccmp, - and wlan_xauth as required. - -20041213: - The behaviour of ppp(8) has changed slightly. If lqr is enabled - (``enable lqr''), older versions would revert to LCP ECHO mode on - negotiation failure. Now, ``enable echo'' is required for this - behaviour. The ppp version number has been bumped to 3.4.2 to - reflect the change. - -20041201: - The wlan support has been updated to split the crypto support - into separate modules. For static WEP you must configure the - wlan_wep module in your system or build and install the module - in place where it can be loaded (the kernel will auto-load - the module when a wep key is configured). - -20041201: - The ath driver has been updated to split the tx rate control - algorithm into a separate module. You need to include either - ath_rate_onoe or ath_rate_amrr when configuring the kernel. - -20041116: - Support for systems with an 80386 CPU has been removed. Please - use FreeBSD 5.x or earlier on systems with an 80386. - -20041110: - We have had a hack which would mount the root filesystem - R/W if the device were named 'md*'. As part of the vnode - work I'm doing I have had to remove this hack. People - building systems which use preloaded MD root filesystems - may need to insert a "/sbin/mount -u -o rw /dev/md0 /" in - their /etc/rc scripts. - -20041104: - FreeBSD 5.3 shipped here. - -20041102: - The size of struct tcpcb has changed again due to the removal - of RFC1644 T/TCP. You have to recompile userland programs that - read kmem for tcp sockets directly (netstat, sockstat, etc.) - -20041022: - The size of struct tcpcb has changed. You have to recompile - userland programs that read kmem for tcp sockets directly - (netstat, sockstat, etc.) - -20041016: - RELENG_5 branched here. For older entries, please see updating - in the RELENG_5 branch. - COMMON ITEMS: General Notes ------------- - Avoid using make -j when upgrading. From time to time in the - past there have been problems using -j with buildworld and/or - installworld. This is especially true when upgrading between - "distant" versions (eg one that cross a major release boundary - or several minor releases, or when several months have passed - on the -current branch). + Avoid using make -j when upgrading. While generally safe, there are + sometimes problems using -j to upgrade. If your upgrade fails with + -j, please try again wtihout -j. From time to time in the past there + have been problems using -j with buildworld and/or installworld. This + is especially true when upgrading between "distant" versions (eg one + that cross a major release boundary or several minor releases, or when + several months have passed on the -current branch). Sometimes, obscure build problems are the result of environment poisoning. This can happen because the make utility reads its - environment when searching for values for global variables. - To run your build attempts in an "environmental clean room", - prefix all make commands with 'env -i '. See the env(1) manual - page for more details. + environment when searching for values for global variables. To run + your build attempts in an "environmental clean room", prefix all make + commands with 'env -i '. See the env(1) manual page for more details. - When upgrading from one major version to another it is generally - best to upgrade to the latest code in the currently installed branch - first, then do an upgrade to the new branch. This is the best-tested - upgrade path, and has the highest probability of being successful. - Please try this approach before reporting problems with a major - version upgrade. + When upgrading from one major version to another it is generally best + to upgrade to the latest code in the currently installed branch first, + then do an upgrade to the new branch. This is the best-tested upgrade + path, and has the highest probability of being successful. Please try + this approach before reporting problems with a major version upgrade. To build a kernel ----------------- @@ -1507,9 +815,9 @@ COMMON ITEMS: To just build a kernel when you know that it won't mess you up -------------------------------------------------------------- - This assumes you are already running a 5.X system. Replace + This assumes you are already running a CURRENT system. Replace ${arch} with the architecture of your machine (e.g. "i386", - "alpha", "amd64", "ia64", "pc98", "sparc64", etc). + "arm", "amd64", "ia64", "pc98", "sparc64", "powerpc", "mips", etc). cd src/sys/${arch}/conf config KERNEL_NAME_HERE @@ -1561,7 +869,7 @@ COMMON ITEMS: - To upgrade in-place from 5.x-stable to current + To upgrade in-place from 8.x-stable to current ---------------------------------------------- make buildworld [9] @@ -1613,11 +921,12 @@ COMMON ITEMS: install) after the buildworld before this step if you last updated from current before 20020224 or from -stable before 20020408. - [8] In order to have a kernel that can run the 4.x binaries - needed to do an installworld, you must include the COMPAT_FREEBSD4 - option in your kernel. Failure to do so may leave you with a system - that is hard to boot to recover. A similar kernel option COMPAT_FREEBSD5 - is required to run the 5.x binaries on more recent kernels. + [8] In order to have a kernel that can run the 4.x binaries needed to + do an installworld, you must include the COMPAT_FREEBSD4 option in + your kernel. Failure to do so may leave you with a system that is + hard to boot to recover. A similar kernel option COMPAT_FREEBSD5 is + required to run the 5.x binaries on more recent kernels. And so on + for COMPAT_FREEBSD6 and COMPAT_FREEBSD7. Make sure that you merge any new devices from GENERIC since the last time you updated your kernel config file. @@ -1641,7 +950,7 @@ previous releases if your system is older than this. Copyright information: -Copyright 1998-2005 M. Warner Losh. All Rights Reserved. +Copyright 1998-2009 M. Warner Losh. All Rights Reserved. Redistribution, publication, translation and use, with or without modification, in full or in part, in any form or format of this @@ -1659,9 +968,6 @@ 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. -If you find this document useful, and you want to, you may buy the -author a beer. - Contact Warner Losh if you have any questions about your use of this document. diff --git a/bin/chmod/chmod.c b/bin/chmod/chmod.c index d003b5fbc86..dc51faa39b0 100644 --- a/bin/chmod/chmod.c +++ b/bin/chmod/chmod.c @@ -41,7 +41,7 @@ static char sccsid[] = "@(#)chmod.c 8.8 (Berkeley) 4/1/94"; #include __FBSDID("$FreeBSD$"); -#include +#include #include #include @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); #include static void usage(void); -static int may_have_nfs4acl(const FTSENT *ent); +static int may_have_nfs4acl(const FTSENT *ent, int hflag); int main(int argc, char *argv[]) @@ -62,11 +62,10 @@ main(int argc, char *argv[]) FTS *ftsp; FTSENT *p; mode_t *set; - int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval; + int Hflag, Lflag, Rflag, ch, error, fflag, fts_options, hflag, rval; int vflag; char *mode; mode_t newmode; - int (*change_mode)(const char *, mode_t); set = NULL; Hflag = Lflag = Rflag = fflag = hflag = vflag = 0; @@ -140,11 +139,6 @@ done: argv += optind; } else fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL; - if (hflag) - change_mode = lchmod; - else - change_mode = chmod; - mode = *argv; if ((set = setmode(mode)) == NULL) errx(1, "invalid file mode: %s", mode); @@ -175,7 +169,6 @@ done: argv += optind; */ if (!hflag) continue; - /* else */ /* FALLTHROUGH */ default: break; @@ -186,12 +179,18 @@ done: argv += optind; * identical to the one computed from an ACL will change * that ACL. */ - if (may_have_nfs4acl(p) == 0 && + if (may_have_nfs4acl(p, hflag) == 0 && (newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS)) continue; - if ((*change_mode)(p->fts_accpath, newmode) && !fflag) { - warn("%s", p->fts_path); - rval = 1; + if (hflag) + error = lchmod(p->fts_accpath, newmode); + else + error = chmod(p->fts_accpath, newmode); + if (error) { + if (!fflag) { + warn("%s", p->fts_path); + rval = 1; + } } else { if (vflag) { (void)printf("%s", p->fts_path); @@ -202,7 +201,6 @@ done: argv += optind; strmode(p->fts_statp->st_mode, m1); strmode((p->fts_statp->st_mode & S_IFMT) | newmode, m2); - (void)printf(": 0%o [%s] -> 0%o [%s]", p->fts_statp->st_mode, m1, (p->fts_statp->st_mode & S_IFMT) | @@ -210,12 +208,10 @@ done: argv += optind; } (void)printf("\n"); } - } } if (errno) err(1, "fts_read"); - free(set); exit(rval); } @@ -228,17 +224,20 @@ usage(void) } static int -may_have_nfs4acl(const FTSENT *ent) +may_have_nfs4acl(const FTSENT *ent, int hflag) { int ret; - static dev_t previous_dev = (dev_t)-1; + static dev_t previous_dev = NODEV; static int supports_acls = -1; if (previous_dev != ent->fts_statp->st_dev) { previous_dev = ent->fts_statp->st_dev; supports_acls = 0; - ret = pathconf(ent->fts_accpath, _PC_ACL_NFS4); + if (hflag) + ret = lpathconf(ent->fts_accpath, _PC_ACL_NFS4); + else + ret = pathconf(ent->fts_accpath, _PC_ACL_NFS4); if (ret > 0) supports_acls = 1; else if (ret < 0 && errno != EINVAL) diff --git a/bin/cp/utils.c b/bin/cp/utils.c index c27c788a358..63eba422f3d 100644 --- a/bin/cp/utils.c +++ b/bin/cp/utils.c @@ -377,24 +377,52 @@ setfile(struct stat *fs, int fd) int preserve_fd_acls(int source_fd, int dest_fd) { - struct acl *aclp; acl_t acl; + acl_type_t acl_type; + int acl_supported = 0, ret, trivial; - if (fpathconf(source_fd, _PC_ACL_EXTENDED) != 1 || - fpathconf(dest_fd, _PC_ACL_EXTENDED) != 1) + ret = fpathconf(source_fd, _PC_ACL_NFS4); + if (ret > 0 ) { + acl_supported = 1; + acl_type = ACL_TYPE_NFS4; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", to.p_path); + return (1); + } + if (acl_supported == 0) { + ret = fpathconf(source_fd, _PC_ACL_EXTENDED); + if (ret > 0 ) { + acl_supported = 1; + acl_type = ACL_TYPE_ACCESS; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s", + to.p_path); + return (1); + } + } + if (acl_supported == 0) return (0); - acl = acl_get_fd(source_fd); + + acl = acl_get_fd_np(source_fd, acl_type); if (acl == NULL) { warn("failed to get acl entries while setting %s", to.p_path); return (1); } - aclp = &acl->ats_acl; - if (aclp->acl_cnt == 3) - return (0); - if (acl_set_fd(dest_fd, acl) < 0) { - warn("failed to set acl entries for %s", to.p_path); + if (acl_is_trivial_np(acl, &trivial)) { + warn("acl_is_trivial() failed for %s", to.p_path); + acl_free(acl); return (1); } + if (trivial) { + acl_free(acl); + return (0); + } + if (acl_set_fd_np(dest_fd, acl, acl_type) < 0) { + warn("failed to set acl entries for %s", to.p_path); + acl_free(acl); + return (1); + } + acl_free(acl); return (0); } @@ -405,10 +433,31 @@ preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir) int (*aclsetf)(const char *, acl_type_t, acl_t); struct acl *aclp; acl_t acl; + acl_type_t acl_type; + int acl_supported = 0, ret, trivial; - if (pathconf(source_dir, _PC_ACL_EXTENDED) != 1 || - pathconf(dest_dir, _PC_ACL_EXTENDED) != 1) + ret = pathconf(source_dir, _PC_ACL_NFS4); + if (ret > 0) { + acl_supported = 1; + acl_type = ACL_TYPE_NFS4; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", source_dir); + return (1); + } + if (acl_supported == 0) { + ret = pathconf(source_dir, _PC_ACL_EXTENDED); + if (ret > 0) { + acl_supported = 1; + acl_type = ACL_TYPE_ACCESS; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s", + source_dir); + return (1); + } + } + if (acl_supported == 0) return (0); + /* * If the file is a link we will not follow it */ @@ -419,34 +468,48 @@ preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir) aclgetf = acl_get_file; aclsetf = acl_set_file; } - /* - * Even if there is no ACL_TYPE_DEFAULT entry here, a zero - * size ACL will be returned. So it is not safe to simply - * check the pointer to see if the default ACL is present. - */ - acl = aclgetf(source_dir, ACL_TYPE_DEFAULT); - if (acl == NULL) { - warn("failed to get default acl entries on %s", - source_dir); - return (1); + if (acl_type == ACL_TYPE_ACCESS) { + /* + * Even if there is no ACL_TYPE_DEFAULT entry here, a zero + * size ACL will be returned. So it is not safe to simply + * check the pointer to see if the default ACL is present. + */ + acl = aclgetf(source_dir, ACL_TYPE_DEFAULT); + if (acl == NULL) { + warn("failed to get default acl entries on %s", + source_dir); + return (1); + } + aclp = &acl->ats_acl; + if (aclp->acl_cnt != 0 && aclsetf(dest_dir, + ACL_TYPE_DEFAULT, acl) < 0) { + warn("failed to set default acl entries on %s", + dest_dir); + acl_free(acl); + return (1); + } + acl_free(acl); } - aclp = &acl->ats_acl; - if (aclp->acl_cnt != 0 && aclsetf(dest_dir, - ACL_TYPE_DEFAULT, acl) < 0) { - warn("failed to set default acl entries on %s", - dest_dir); - return (1); - } - acl = aclgetf(source_dir, ACL_TYPE_ACCESS); + acl = aclgetf(source_dir, acl_type); if (acl == NULL) { warn("failed to get acl entries on %s", source_dir); return (1); } - aclp = &acl->ats_acl; - if (aclsetf(dest_dir, ACL_TYPE_ACCESS, acl) < 0) { - warn("failed to set acl entries on %s", dest_dir); + if (acl_is_trivial_np(acl, &trivial)) { + warn("acl_is_trivial() failed on %s", source_dir); + acl_free(acl); return (1); } + if (trivial) { + acl_free(acl); + return (0); + } + if (aclsetf(dest_dir, acl_type, acl) < 0) { + warn("failed to set acl entries on %s", dest_dir); + acl_free(acl); + return (1); + } + acl_free(acl); return (0); } diff --git a/bin/getfacl/getfacl.1 b/bin/getfacl/getfacl.1 index 913530935a3..58202299f65 100644 --- a/bin/getfacl/getfacl.1 +++ b/bin/getfacl/getfacl.1 @@ -30,7 +30,7 @@ .\" Developed by the TrustedBSD Project. .\" Support for POSIX.1e access control lists. .\" -.Dd March 13, 2006 +.Dd September 04, 2009 .Dt GETFACL 1 .Os .Sh NAME @@ -38,7 +38,7 @@ .Nd get ACL information .Sh SYNOPSIS .Nm -.Op Fl dhq +.Op Fl dhinqv .Op Ar .Sh DESCRIPTION The @@ -61,13 +61,25 @@ The operation applies to the default ACL of a directory instead of the access ACL. An error is generated if a default ACL cannot be associated with .Ar file . +This option is not valid for NFSv4 ACLs. .It Fl h If the target of the operation is a symbolic link, return the ACL from the symbolic link itself rather than following the link. +.It Fl i +For NFSv4 ACLs, append numerical ID at the end of each entry containing +user or group name. +Ignored for POSIX.1e ACLs. +.It Fl n +Display user and group IDs numerically rather than converting to +a user or group name. +Ignored for POSIX.1e ACLs. .It Fl q Do not write commented information about file name and ownership. This is useful when dealing with filenames with unprintable characters. +.It Fl v +For NFSv4 ACLs, display access mask and flags in a verbose form. +Ignored for POSIX.1e ACLs. .El .Pp The following operand is available: diff --git a/bin/getfacl/getfacl.c b/bin/getfacl/getfacl.c index 1ab86cde273..ea376c78f0e 100644 --- a/bin/getfacl/getfacl.c +++ b/bin/getfacl/getfacl.c @@ -54,7 +54,7 @@ static void usage(void) { - fprintf(stderr, "getfacl [-dhq] [file ...]\n"); + fprintf(stderr, "getfacl [-dhnqv] [file ...]\n"); } static char * @@ -175,22 +175,39 @@ acl_from_stat(struct stat sb) } static int -print_acl(char *path, acl_type_t type, int hflag, int qflag) +print_acl(char *path, acl_type_t type, int hflag, int iflag, int nflag, + int qflag, int vflag) { struct stat sb; acl_t acl; char *acl_text; - int error; + int error, flags = 0, ret; if (hflag) error = lstat(path, &sb); else error = stat(path, &sb); if (error == -1) { - warn("%s", path); + warn("%s: stat() failed", path); return(-1); } + if (hflag) + ret = lpathconf(path, _PC_ACL_NFS4); + else + ret = pathconf(path, _PC_ACL_NFS4); + if (ret > 0) { + if (type == ACL_TYPE_DEFAULT) { + warnx("%s: there are no default entries in NFSv4 ACLs", + path); + return (-1); + } + type = ACL_TYPE_NFS4; + } else if (ret < 0 && errno != EINVAL) { + warn("%s: pathconf(..., _PC_ACL_NFS4) failed", path); + return (-1); + } + if (more_than_one) printf("\n"); else @@ -210,18 +227,27 @@ print_acl(char *path, acl_type_t type, int hflag, int qflag) return(-1); } errno = 0; - if (type != ACL_TYPE_ACCESS) + if (type == ACL_TYPE_DEFAULT) return(0); acl = acl_from_stat(sb); if (!acl) { - warn("acl_from_stat()"); + warn("%s: acl_from_stat() failed", path); return(-1); } } - acl_text = acl_to_text(acl, 0); + if (iflag) + flags |= ACL_TEXT_APPEND_ID; + + if (nflag) + flags |= ACL_TEXT_NUMERIC_IDS; + + if (vflag) + flags |= ACL_TEXT_VERBOSE; + + acl_text = acl_to_text_np(acl, 0, flags); if (!acl_text) { - warn("%s", path); + warn("%s: acl_to_text_np() failed", path); return(-1); } @@ -234,7 +260,8 @@ print_acl(char *path, acl_type_t type, int hflag, int qflag) } static int -print_acl_from_stdin(acl_type_t type, int hflag, int qflag) +print_acl_from_stdin(acl_type_t type, int hflag, int iflag, int nflag, + int qflag, int vflag) { char *p, pathname[PATH_MAX]; int carried_error = 0; @@ -242,7 +269,8 @@ print_acl_from_stdin(acl_type_t type, int hflag, int qflag) while (fgets(pathname, (int)sizeof(pathname), stdin)) { if ((p = strchr(pathname, '\n')) != NULL) *p = '\0'; - if (print_acl(pathname, type, hflag, qflag) == -1) { + if (print_acl(pathname, type, hflag, iflag, nflag, + qflag, vflag) == -1) { carried_error = -1; } } @@ -256,11 +284,14 @@ main(int argc, char *argv[]) acl_type_t type = ACL_TYPE_ACCESS; int carried_error = 0; int ch, error, i; - int hflag, qflag; + int hflag, iflag, qflag, nflag, vflag; hflag = 0; + iflag = 0; qflag = 0; - while ((ch = getopt(argc, argv, "dhq")) != -1) + nflag = 0; + vflag = 0; + while ((ch = getopt(argc, argv, "dhinqv")) != -1) switch(ch) { case 'd': type = ACL_TYPE_DEFAULT; @@ -268,9 +299,18 @@ main(int argc, char *argv[]) case 'h': hflag = 1; break; + case 'i': + iflag = 1; + break; + case 'n': + nflag = 1; + break; case 'q': qflag = 1; break; + case 'v': + vflag = 1; + break; default: usage(); return(-1); @@ -279,17 +319,20 @@ main(int argc, char *argv[]) argv += optind; if (argc == 0) { - error = print_acl_from_stdin(type, hflag, qflag); + error = print_acl_from_stdin(type, hflag, iflag, nflag, + qflag, vflag); return(error ? 1 : 0); } for (i = 0; i < argc; i++) { if (!strcmp(argv[i], "-")) { - error = print_acl_from_stdin(type, hflag, qflag); + error = print_acl_from_stdin(type, hflag, iflag, nflag, + qflag, vflag); if (error == -1) carried_error = -1; } else { - error = print_acl(argv[i], type, hflag, qflag); + error = print_acl(argv[i], type, hflag, iflag, nflag, + qflag, vflag); if (error == -1) carried_error = -1; } diff --git a/bin/ls/print.c b/bin/ls/print.c index 4825d2e1052..3b80d93aefe 100644 --- a/bin/ls/print.c +++ b/bin/ls/print.c @@ -70,7 +70,7 @@ static void printsize(size_t, off_t); static void endcolor(int); static int colortype(mode_t); #endif -static void aclmode(char *, const FTSENT *, int *); +static void aclmode(char *, const FTSENT *); #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) @@ -139,16 +139,12 @@ printlong(const DISPLAY *dp) #ifdef COLORLS int color_printed = 0; #endif - int haveacls; - dev_t prevdev; if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && (f_longform || f_size)) { (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); } - haveacls = 1; - prevdev = (dev_t)-1; for (p = dp->list; p; p = p->fts_link) { if (IS_NOPRINT(p)) continue; @@ -159,14 +155,7 @@ printlong(const DISPLAY *dp) (void)printf("%*jd ", dp->s_block, howmany(sp->st_blocks, blocksize)); strmode(sp->st_mode, buf); - /* - * Cache whether or not the filesystem supports ACL's to - * avoid expensive syscalls. Try again when we change devices. - */ - if (haveacls || sp->st_dev != prevdev) { - aclmode(buf, p, &haveacls); - prevdev = sp->st_dev; - } + aclmode(buf, p); np = p->fts_pointer; (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, sp->st_nlink, dp->s_user, np->user, dp->s_group, @@ -612,56 +601,73 @@ printsize(size_t width, off_t bytes) (void)printf("%*jd ", (u_int)width, bytes); } +/* + * Add a + after the standard rwxrwxrwx mode if the file has an + * ACL. strmode() reserves space at the end of the string. + */ static void -aclmode(char *buf, const FTSENT *p, int *haveacls) +aclmode(char *buf, const FTSENT *p) { char name[MAXPATHLEN + 1]; - int entries, ret; + int ret, trivial; + static dev_t previous_dev = NODEV; + static int supports_acls = -1; + static int type = ACL_TYPE_ACCESS; acl_t facl; - acl_entry_t ae; /* - * Add a + after the standard rwxrwxrwx mode if the file has an - * extended ACL. strmode() reserves space at the end of the string. + * XXX: ACLs are not supported on whiteouts and device files + * residing on UFS. */ + if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) || + S_ISWHT(p->fts_statp->st_mode)) + return; + + if (previous_dev == p->fts_statp->st_dev && supports_acls == 0) + return; + if (p->fts_level == FTS_ROOTLEVEL) snprintf(name, sizeof(name), "%s", p->fts_name); else snprintf(name, sizeof(name), "%s/%s", p->fts_parent->fts_accpath, p->fts_name); - /* - * We have no way to tell whether a symbolic link has an ACL since - * pathconf() and acl_get_file() both follow them. They also don't - * support whiteouts. - */ - if (S_ISLNK(p->fts_statp->st_mode) || S_ISWHT(p->fts_statp->st_mode)) { - *haveacls = 1; - return; - } - if ((ret = pathconf(name, _PC_ACL_EXTENDED)) <= 0) { - if (ret < 0 && errno != EINVAL) + + if (previous_dev != p->fts_statp->st_dev) { + previous_dev = p->fts_statp->st_dev; + supports_acls = 0; + + ret = lpathconf(name, _PC_ACL_NFS4); + if (ret > 0) { + type = ACL_TYPE_NFS4; + supports_acls = 1; + } else if (ret < 0 && errno != EINVAL) { warn("%s", name); - else - *haveacls = 0; + return; + } + if (supports_acls == 0) { + ret = lpathconf(name, _PC_ACL_EXTENDED); + if (ret > 0) { + type = ACL_TYPE_ACCESS; + supports_acls = 1; + } else if (ret < 0 && errno != EINVAL) { + warn("%s", name); + return; + } + } + } + if (supports_acls == 0) + return; + facl = acl_get_link_np(name, type); + if (facl == NULL) { + warn("%s", name); return; } - *haveacls = 1; - if ((facl = acl_get_file(name, ACL_TYPE_ACCESS)) != NULL) { - if (acl_get_entry(facl, ACL_FIRST_ENTRY, &ae) == 1) { - entries = 1; - while (acl_get_entry(facl, ACL_NEXT_ENTRY, &ae) == 1) - if (++entries > 3) - break; - /* - * POSIX.1e requires that ACLs of type ACL_TYPE_ACCESS - * must have at least three entries (owner, group, - * and other). So anything with more than 3 ACLs looks - * interesting to us. - */ - if (entries > 3) - buf[10] = '+'; - } + if (acl_is_trivial_np(facl, &trivial)) { acl_free(facl); - } else warn("%s", name); + return; + } + if (!trivial) + buf[10] = '+'; + acl_free(facl); } diff --git a/bin/mv/mv.c b/bin/mv/mv.c index 22bdec19a45..1f98f94657f 100644 --- a/bin/mv/mv.c +++ b/bin/mv/mv.c @@ -74,6 +74,8 @@ static int copy(const char *, const char *); static int do_move(const char *, const char *); static int fastcopy(const char *, const char *, struct stat *); static void usage(void); +static void preserve_fd_acls(int source_fd, int dest_fd, const char *source_path, + const char *dest_path); int main(int argc, char *argv[]) @@ -260,7 +262,6 @@ fastcopy(const char *from, const char *to, struct stat *sbp) struct timeval tval[2]; static u_int blen; static char *bp; - acl_t acl; mode_t oldmode; int nread, from_fd, to_fd; @@ -311,23 +312,15 @@ err: if (unlink(to)) sbp->st_mode &= ~(S_ISUID | S_ISGID); } } + if (fchmod(to_fd, sbp->st_mode)) + warn("%s: set mode (was: 0%03o)", to, oldmode); /* * POSIX 1003.2c states that if _POSIX_ACL_EXTENDED is in effect * for dest_file, then its ACLs shall reflect the ACLs of the * source_file. */ - if (fpathconf(to_fd, _PC_ACL_EXTENDED) == 1 && - fpathconf(from_fd, _PC_ACL_EXTENDED) == 1) { - acl = acl_get_fd(from_fd); - if (acl == NULL) - warn("failed to get acl entries while setting %s", - from); - else if (acl_set_fd(to_fd, acl) < 0) - warn("failed to set acl entries for %s", to); - } + preserve_fd_acls(from_fd, to_fd, from, to); (void)close(from_fd); - if (fchmod(to_fd, sbp->st_mode)) - warn("%s: set mode (was: 0%03o)", to, oldmode); /* * XXX * NFS doesn't support chflags; ignore errors unless there's reason @@ -438,6 +431,59 @@ copy(const char *from, const char *to) return (0); } +static void +preserve_fd_acls(int source_fd, int dest_fd, const char *source_path, + const char *dest_path) +{ + acl_t acl; + acl_type_t acl_type; + int acl_supported = 0, ret, trivial; + + ret = fpathconf(source_fd, _PC_ACL_NFS4); + if (ret > 0 ) { + acl_supported = 1; + acl_type = ACL_TYPE_NFS4; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", + source_path); + return; + } + if (acl_supported == 0) { + ret = fpathconf(source_fd, _PC_ACL_EXTENDED); + if (ret > 0 ) { + acl_supported = 1; + acl_type = ACL_TYPE_ACCESS; + } else if (ret < 0 && errno != EINVAL) { + warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s", + source_path); + return; + } + } + if (acl_supported == 0) + return; + + acl = acl_get_fd_np(source_fd, acl_type); + if (acl == NULL) { + warn("failed to get acl entries for %s", source_path); + return; + } + if (acl_is_trivial_np(acl, &trivial)) { + warn("acl_is_trivial() failed for %s", source_path); + acl_free(acl); + return; + } + if (trivial) { + acl_free(acl); + return; + } + if (acl_set_fd_np(dest_fd, acl, acl_type) < 0) { + warn("failed to set acl entries for %s", dest_path); + acl_free(acl); + return; + } + acl_free(acl); +} + static void usage(void) { diff --git a/bin/setfacl/mask.c b/bin/setfacl/mask.c index b275893b1f5..547830279cc 100644 --- a/bin/setfacl/mask.c +++ b/bin/setfacl/mask.c @@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$"); /* set the appropriate mask the given ACL's */ int -set_acl_mask(acl_t *prev_acl) +set_acl_mask(acl_t *prev_acl, const char *filename) { acl_entry_t entry; acl_t acl; @@ -59,7 +59,7 @@ set_acl_mask(acl_t *prev_acl) acl = acl_dup(*prev_acl); if (acl == NULL) - err(1, "acl_dup() failed"); + err(1, "%s: acl_dup() failed", filename); if (n_flag == 0) { /* @@ -70,7 +70,7 @@ set_acl_mask(acl_t *prev_acl) * class in the resulting ACL */ if (acl_calc_mask(&acl)) { - warn("acl_calc_mask() failed"); + warn("%s: acl_calc_mask() failed", filename); acl_free(acl); return (-1); } @@ -86,7 +86,8 @@ set_acl_mask(acl_t *prev_acl) while (acl_get_entry(acl, entry_id, &entry) == 1) { entry_id = ACL_NEXT_ENTRY; if (acl_get_tag_type(entry, &tag) == -1) - err(1, "acl_get_tag_type() failed"); + err(1, "%s: acl_get_tag_type() failed", + filename); if (tag == ACL_MASK) { acl_free(acl); @@ -100,7 +101,7 @@ set_acl_mask(acl_t *prev_acl) * file, then write an error message to standard error and * continue with the next file. */ - warnx("warning: no mask entry"); + warnx("%s: warning: no mask entry", filename); acl_free(acl); return (0); } diff --git a/bin/setfacl/merge.c b/bin/setfacl/merge.c index 9f1b5dd48f4..495e66c45a2 100644 --- a/bin/setfacl/merge.c +++ b/bin/setfacl/merge.c @@ -36,12 +36,15 @@ __FBSDID("$FreeBSD$"); #include "setfacl.h" -static int merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new); +static int merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new, + int acl_brand); static int -merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new) +merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new, int acl_brand) { acl_permset_t permset; + acl_entry_type_t entry_type; + acl_flagset_t flagset; int have_entry; uid_t *id, *id_new; @@ -59,6 +62,18 @@ merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new) err(1, "acl_get_permset() failed"); if (acl_set_permset(*entry_new, permset) == -1) err(1, "acl_set_permset() failed"); + + if (acl_brand == ACL_BRAND_NFS4) { + if (acl_get_entry_type_np(*entry, &entry_type)) + err(1, "acl_get_entry_type_np() failed"); + if (acl_set_entry_type_np(*entry_new, entry_type)) + err(1, "acl_set_entry_type_np() failed"); + if (acl_get_flagset_np(*entry, &flagset)) + err(1, "acl_get_flagset_np() failed"); + if (acl_set_flagset_np(*entry_new, flagset)) + err(1, "acl_set_flagset_np() failed"); + } + have_entry = 1; } acl_free(id); @@ -71,20 +86,31 @@ merge_user_group(acl_entry_t *entry, acl_entry_t *entry_new) * merge an ACL into existing file's ACL */ int -merge_acl(acl_t acl, acl_t *prev_acl) +merge_acl(acl_t acl, acl_t *prev_acl, const char *filename) { acl_entry_t entry, entry_new; acl_permset_t permset; acl_t acl_new; acl_tag_t tag, tag_new; - int entry_id, entry_id_new, have_entry; + acl_entry_type_t entry_type, entry_type_new; + acl_flagset_t flagset; + int entry_id, entry_id_new, have_entry, entry_number = 0; + int acl_brand, prev_acl_brand; - if (acl_type == ACL_TYPE_ACCESS) - acl_new = acl_dup(prev_acl[ACCESS_ACL]); - else - acl_new = acl_dup(prev_acl[DEFAULT_ACL]); + acl_get_brand_np(acl, &acl_brand); + acl_get_brand_np(*prev_acl, &prev_acl_brand); + + if (acl_brand != prev_acl_brand) { + warnx("%s: branding mismatch; existing ACL is %s, " + "entry to be merged is %s", filename, + prev_acl_brand == ACL_BRAND_NFS4 ? "NFSv4" : "POSIX.1e", + acl_brand == ACL_BRAND_NFS4 ? "NFSv4" : "POSIX.1e"); + return (-1); + } + + acl_new = acl_dup(*prev_acl); if (acl_new == NULL) - err(1, "acl_dup() failed"); + err(1, "%s: acl_dup() failed", filename); entry_id = ACL_FIRST_ENTRY; @@ -94,28 +120,45 @@ merge_acl(acl_t acl, acl_t *prev_acl) /* keep track of existing ACL_MASK entries */ if (acl_get_tag_type(entry, &tag) == -1) - err(1, "acl_get_tag_type() failed - invalid ACL entry"); + err(1, "%s: acl_get_tag_type() failed - " + "invalid ACL entry", filename); if (tag == ACL_MASK) have_mask = 1; /* check against the existing ACL entries */ entry_id_new = ACL_FIRST_ENTRY; - while (have_entry == 0 && - acl_get_entry(acl_new, entry_id_new, &entry_new) == 1) { + while (acl_get_entry(acl_new, entry_id_new, &entry_new) == 1) { entry_id_new = ACL_NEXT_ENTRY; if (acl_get_tag_type(entry, &tag) == -1) - err(1, "acl_get_tag_type() failed"); + err(1, "%s: acl_get_tag_type() failed", + filename); if (acl_get_tag_type(entry_new, &tag_new) == -1) - err(1, "acl_get_tag_type() failed"); + err(1, "%s: acl_get_tag_type() failed", + filename); if (tag != tag_new) continue; + /* + * For NFSv4, in addition to "tag" and "id" we also + * compare "entry_type". + */ + if (acl_brand == ACL_BRAND_NFS4) { + if (acl_get_entry_type_np(entry, &entry_type)) + err(1, "%s: acl_get_entry_type_np() " + "failed", filename); + if (acl_get_entry_type_np(entry_new, &entry_type_new)) + err(1, "%s: acl_get_entry_type_np() " + "failed", filename); + if (entry_type != entry_type_new) + continue; + } + switch(tag) { case ACL_USER: case ACL_GROUP: have_entry = merge_user_group(&entry, - &entry_new); + &entry_new, acl_brand); if (have_entry == 0) break; /* FALLTHROUGH */ @@ -123,37 +166,127 @@ merge_acl(acl_t acl, acl_t *prev_acl) case ACL_GROUP_OBJ: case ACL_OTHER: case ACL_MASK: + case ACL_EVERYONE: if (acl_get_permset(entry, &permset) == -1) - err(1, "acl_get_permset() failed"); + err(1, "%s: acl_get_permset() failed", + filename); if (acl_set_permset(entry_new, permset) == -1) - err(1, "acl_set_permset() failed"); + err(1, "%s: acl_set_permset() failed", + filename); + + if (acl_brand == ACL_BRAND_NFS4) { + if (acl_get_entry_type_np(entry, &entry_type)) + err(1, "%s: acl_get_entry_type_np() failed", + filename); + if (acl_set_entry_type_np(entry_new, entry_type)) + err(1, "%s: acl_set_entry_type_np() failed", + filename); + if (acl_get_flagset_np(entry, &flagset)) + err(1, "%s: acl_get_flagset_np() failed", + filename); + if (acl_set_flagset_np(entry_new, flagset)) + err(1, "%s: acl_set_flagset_np() failed", + filename); + } have_entry = 1; break; default: /* should never be here */ - errx(1, "Invalid tag type: %i", tag); + errx(1, "%s: invalid tag type: %i", filename, tag); break; } } /* if this entry has not been found, it must be new */ if (have_entry == 0) { - if (acl_create_entry(&acl_new, &entry_new) == -1) { - acl_free(acl_new); - return (-1); + + /* + * NFSv4 ACL entries must be prepended to the ACL. + * Appending them at the end makes no sense, since + * in most cases they wouldn't even get evaluated. + */ + if (acl_brand == ACL_BRAND_NFS4) { + if (acl_create_entry_np(&acl_new, &entry_new, entry_number) == -1) { + warn("%s: acl_create_entry_np() failed", filename); + acl_free(acl_new); + return (-1); + } + /* + * Without this increment, adding several + * entries at once, for example + * "setfacl -m user:1:r:allow,user:2:r:allow", + * would make them appear in reverse order. + */ + entry_number++; + } else { + if (acl_create_entry(&acl_new, &entry_new) == -1) { + warn("%s: acl_create_entry() failed", filename); + acl_free(acl_new); + return (-1); + } } if (acl_copy_entry(entry_new, entry) == -1) - err(1, "acl_copy_entry() failed"); + err(1, "%s: acl_copy_entry() failed", filename); } } - if (acl_type == ACL_TYPE_ACCESS) { - acl_free(prev_acl[ACCESS_ACL]); - prev_acl[ACCESS_ACL] = acl_new; - } else { - acl_free(prev_acl[DEFAULT_ACL]); - prev_acl[DEFAULT_ACL] = acl_new; - } + acl_free(*prev_acl); + *prev_acl = acl_new; + + return (0); +} + +int +add_acl(acl_t acl, uint entry_number, acl_t *prev_acl, const char *filename) +{ + acl_entry_t entry, entry_new; + acl_t acl_new; + int entry_id, acl_brand, prev_acl_brand; + + acl_get_brand_np(acl, &acl_brand); + acl_get_brand_np(*prev_acl, &prev_acl_brand); + + if (prev_acl_brand != ACL_BRAND_NFS4) { + warnx("%s: the '-a' option is only applicable to NFSv4 ACLs", + filename); + return (-1); + } + + if (acl_brand != ACL_BRAND_NFS4) { + warnx("%s: branding mismatch; existing ACL is NFSv4, " + "entry to be added is POSIX.1e", filename); + return (-1); + } + + acl_new = acl_dup(*prev_acl); + if (acl_new == NULL) + err(1, "%s: acl_dup() failed", filename); + + entry_id = ACL_FIRST_ENTRY; + + while (acl_get_entry(acl, entry_id, &entry) == 1) { + entry_id = ACL_NEXT_ENTRY; + + if (acl_create_entry_np(&acl_new, &entry_new, entry_number) == -1) { + warn("%s: acl_create_entry_np() failed", filename); + acl_free(acl_new); + return (-1); + } + + /* + * Without this increment, adding several + * entries at once, for example + * "setfacl -m user:1:r:allow,user:2:r:allow", + * would make them appear in reverse order. + */ + entry_number++; + + if (acl_copy_entry(entry_new, entry) == -1) + err(1, "%s: acl_copy_entry() failed", filename); + } + + acl_free(*prev_acl); + *prev_acl = acl_new; return (0); } diff --git a/bin/setfacl/remove.c b/bin/setfacl/remove.c index 23240554a34..6cd82b36d9e 100644 --- a/bin/setfacl/remove.c +++ b/bin/setfacl/remove.c @@ -41,21 +41,31 @@ __FBSDID("$FreeBSD$"); * remove ACL entries from an ACL */ int -remove_acl(acl_t acl, acl_t *prev_acl) +remove_acl(acl_t acl, acl_t *prev_acl, const char *filename) { acl_entry_t entry; acl_t acl_new; acl_tag_t tag; - int carried_error, entry_id; + int carried_error, entry_id, acl_brand, prev_acl_brand; carried_error = 0; - if (acl_type == ACL_TYPE_ACCESS) - acl_new = acl_dup(prev_acl[ACCESS_ACL]); - else - acl_new = acl_dup(prev_acl[DEFAULT_ACL]); + acl_get_brand_np(acl, &acl_brand); + acl_get_brand_np(*prev_acl, &prev_acl_brand); + + if (acl_brand != prev_acl_brand) { + warnx("%s: branding mismatch; existing ACL is %s, " + "entry to be removed is %s", filename, + prev_acl_brand == ACL_BRAND_NFS4 ? "NFSv4" : "POSIX.1e", + acl_brand == ACL_BRAND_NFS4 ? "NFSv4" : "POSIX.1e"); + return (-1); + } + + carried_error = 0; + + acl_new = acl_dup(*prev_acl); if (acl_new == NULL) - err(1, "acl_dup() failed"); + err(1, "%s: acl_dup() failed", filename); tag = ACL_UNDEFINED_TAG; @@ -64,23 +74,68 @@ remove_acl(acl_t acl, acl_t *prev_acl) while (acl_get_entry(acl, entry_id, &entry) == 1) { entry_id = ACL_NEXT_ENTRY; if (acl_get_tag_type(entry, &tag) == -1) - err(1, "acl_get_tag_type() failed"); + err(1, "%s: acl_get_tag_type() failed", filename); if (tag == ACL_MASK) have_mask++; if (acl_delete_entry(acl_new, entry) == -1) { carried_error++; - warnx("cannot remove non-existent acl entry"); + warnx("%s: cannot remove non-existent ACL entry", + filename); } } - if (acl_type == ACL_TYPE_ACCESS) { - acl_free(prev_acl[ACCESS_ACL]); - prev_acl[ACCESS_ACL] = acl_new; - } else { - acl_free(prev_acl[DEFAULT_ACL]); - prev_acl[DEFAULT_ACL] = acl_new; + acl_free(*prev_acl); + *prev_acl = acl_new; + + if (carried_error) + return (-1); + + return (0); +} + +int +remove_by_number(uint entry_number, acl_t *prev_acl, const char *filename) +{ + acl_entry_t entry; + acl_t acl_new; + acl_tag_t tag; + int carried_error, entry_id; + uint i; + + carried_error = 0; + + acl_new = acl_dup(*prev_acl); + if (acl_new == NULL) + err(1, "%s: acl_dup() failed", filename); + + tag = ACL_UNDEFINED_TAG; + + /* + * Find out whether we're removing the mask entry, + * to behave the same as the routine above. + * + * XXX: Is this loop actually needed? + */ + entry_id = ACL_FIRST_ENTRY; + i = 0; + while (acl_get_entry(acl_new, entry_id, &entry) == 1) { + entry_id = ACL_NEXT_ENTRY; + if (i != entry_number) + continue; + if (acl_get_tag_type(entry, &tag) == -1) + err(1, "%s: acl_get_tag_type() failed", filename); + if (tag == ACL_MASK) + have_mask++; } + if (acl_delete_entry_np(acl_new, entry_number) == -1) { + carried_error++; + warn("%s: acl_delete_entry_np() failed", filename); + } + + acl_free(*prev_acl); + *prev_acl = acl_new; + if (carried_error) return (-1); @@ -91,18 +146,14 @@ remove_acl(acl_t acl, acl_t *prev_acl) * remove default entries */ int -remove_default(acl_t *prev_acl) +remove_default(acl_t *prev_acl, const char *filename) { - if (prev_acl[1]) { - acl_free(prev_acl[1]); - prev_acl[1] = acl_init(ACL_MAX_ENTRIES); - if (prev_acl[1] == NULL) - err(1, "acl_init() failed"); - } else { - warn("cannot remove default ACL"); - return (-1); - } + acl_free(*prev_acl); + *prev_acl = acl_init(ACL_MAX_ENTRIES); + if (*prev_acl == NULL) + err(1, "%s: acl_init() failed", filename); + return (0); } @@ -110,71 +161,14 @@ remove_default(acl_t *prev_acl) * remove extended entries */ void -remove_ext(acl_t *prev_acl) +remove_ext(acl_t *prev_acl, const char *filename) { - acl_t acl_new, acl_old; - acl_entry_t entry, entry_new; - acl_permset_t perm; - acl_tag_t tag; - int entry_id, have_mask_entry; + acl_t acl_new; - if (acl_type == ACL_TYPE_ACCESS) - acl_old = acl_dup(prev_acl[ACCESS_ACL]); - else - acl_old = acl_dup(prev_acl[DEFAULT_ACL]); - if (acl_old == NULL) - err(1, "acl_dup() failed"); - - have_mask_entry = 0; - acl_new = acl_init(ACL_MAX_ENTRIES); + acl_new = acl_strip_np(*prev_acl, !n_flag); if (acl_new == NULL) - err(1, "acl_init() failed"); - tag = ACL_UNDEFINED_TAG; + err(1, "%s: acl_strip_np() failed", filename); - /* only save the default user/group/other entries */ - entry_id = ACL_FIRST_ENTRY; - while (acl_get_entry(acl_old, entry_id, &entry) == 1) { - entry_id = ACL_NEXT_ENTRY; - - if (acl_get_tag_type(entry, &tag) == -1) - err(1, "acl_get_tag_type() failed"); - - switch(tag) { - case ACL_USER_OBJ: - case ACL_GROUP_OBJ: - case ACL_OTHER: - if (acl_get_tag_type(entry, &tag) == -1) - err(1, "acl_get_tag_type() failed"); - if (acl_get_permset(entry, &perm) == -1) - err(1, "acl_get_permset() failed"); - if (acl_create_entry(&acl_new, &entry_new) == -1) - err(1, "acl_create_entry() failed"); - if (acl_set_tag_type(entry_new, tag) == -1) - err(1, "acl_set_tag_type() failed"); - if (acl_set_permset(entry_new, perm) == -1) - err(1, "acl_get_permset() failed"); - if (acl_copy_entry(entry_new, entry) == -1) - err(1, "acl_copy_entry() failed"); - break; - case ACL_MASK: - have_mask_entry = 1; - break; - default: - break; - } - } - if (have_mask_entry && n_flag == 0) { - if (acl_calc_mask(&acl_new) == -1) - err(1, "acl_calc_mask() failed"); - } else { - have_mask = 1; - } - - if (acl_type == ACL_TYPE_ACCESS) { - acl_free(prev_acl[ACCESS_ACL]); - prev_acl[ACCESS_ACL] = acl_new; - } else { - acl_free(prev_acl[DEFAULT_ACL]); - prev_acl[DEFAULT_ACL] = acl_new; - } + acl_free(*prev_acl); + *prev_acl = acl_new; } diff --git a/bin/setfacl/setfacl.1 b/bin/setfacl/setfacl.1 index e49d18a185a..f527bbbfb3d 100644 --- a/bin/setfacl/setfacl.1 +++ b/bin/setfacl/setfacl.1 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 7, 2001 +.Dd September 5, 2009 .Dt SETFACL 1 .Os .Sh NAME @@ -34,9 +34,10 @@ .Sh SYNOPSIS .Nm .Op Fl bdhkn +.Op Fl a Ar position entries .Op Fl m Ar entries .Op Fl M Ar file -.Op Fl x Ar entries +.Op Fl x Ar entries | position .Op Fl X Ar file .Op Ar .Sh DESCRIPTION @@ -50,9 +51,19 @@ the file names are taken from the standard input. .Pp The following options are available: .Bl -tag -width indent +.It Fl a Ar position entries +Modify the ACL on the specified files by inserting new +ACL entries +specified in +.Ar entries , +starting at position +.Ar position , +counting from zero. +This option is only applicable to NFSv4 ACLs. .It Fl b -Remove all ACL entries except for the three required entries. -If the ACL contains a +Remove all ACL entries except for the three required entries +(POSIX.1e ACLs) or six "canonical" entries (NFSv4 ACLs). +If the POSIX.1e ACL contains a .Dq Li mask entry, the permissions of the .Dq Li group @@ -66,7 +77,7 @@ entries of the current ACL. The operations apply to the default ACL entries instead of access ACL entries. Currently only directories may have -default ACL's. +default ACL's. This option is not applicable to NFSv4 ACLs. .It Fl h If the target of the operation is a symbolic link, perform the operation on the symbolic link itself, rather than following the link. @@ -77,7 +88,7 @@ is not considered an error if the specified files do not have any default ACL entries. An error will be reported if any of the specified files cannot have a default entry (i.e.\& -non-directories). +non-directories). This option is not applicable to NFSv4 ACLs. .It Fl m Ar entries Modify the ACL entries on the specified files by adding new entries and modifying existing ACL entries with the ACL entries @@ -95,11 +106,15 @@ is the input is taken from stdin. .It Fl n Do not recalculate the permissions associated with the ACL -mask entry. -.It Fl x Ar entries -Remove the ACL entries specified in +mask entry. This option is not applicable to NFSv4 ACLs. +.It Fl x Ar entries | position +If .Ar entries +is specified, remove the ACL entries specified there from the access or default ACL of the specified files. +Otherwise, remove entry at index +.Ar position , +counting from zero. .It Fl X Ar file Remove the ACL entries specified in the file .Ar file @@ -108,8 +123,8 @@ from the access or default ACL of the specified files. .Pp The above options are evaluated in the order specified on the command-line. -.Sh ACL ENTRIES -An ACL entry contains three colon-separated fields: +.Sh POSIX.1e ACL ENTRIES +A POSIX.1E ACL entry contains three colon-separated fields: an ACL tag, an ACL qualifier, and discretionary access permissions: .Bl -tag -width indent @@ -223,7 +238,7 @@ previously specified; whitespace is ignored; any text after a .Ql # is ignored (comments). .Pp -When ACL entries are evaluated, the access check algorithm checks +When POSIX.1e ACL entries are evaluated, the access check algorithm checks the ACL entries in the following order: file owner, .Dq Li user ACL entries, file owning group, @@ -243,13 +258,135 @@ ACL entries for user, group, other and mask must be set. For more details see the examples below. Default ACLs can be created by using .Fl d . +.Sh NFSv4 ACL ENTRIES +An NFSv4 ACL entry contains four or five colon-separated fields: an ACL tag, +an ACL qualifier (only for +.Dq Li user +and +.Dq Li group +tags), discretionary access permissions, ACL inheritance flags, and ACL type: +.Bl -tag -width indent +.It Ar "ACL tag" +The ACL tag specifies the ACL entry type and consists of +one of the following: +.Dq Li user +or +.Ql u +specifying the access +granted to the specified user; +.Dq Li group +or +.Ql g +specifying the access granted to the specified group; +.Dq Li owner@ +specifying the access granted to the owner of the file; +.Dq Li group@ +specifying the access granted to the file owning group; +.Dq Li everyone@ +specifying everyone. Note that +.Dq Li everyone@ +is not the same as traditional Unix +.Dq Li other +- it means, +literally, everyone, including file owner and owning group. +.It Ar "ACL qualifier" +The ACL qualifier field describes the user or group associated with +the ACL entry. +It may consist of one of the following: uid or +user name, or gid or group name. In entries whose tag type is +one of +.Dq Li owner@ , +.Dq Li group@ , +or +.Dq Li everyone@ , +this field is ommited altogether, including the trailing comma. +.It Ar "access permissions" +Access permissions may be specified in either short or long form. +Short and long forms may not be mixed. +Permissions in long form are separated by the +.Ql / +character; in short form, they are concatenated together. +Valid permissions are: +.Bl -tag -width ".Dv short" +.It Short +Long +.It r +read_data +.It w +write_data +.It x +execute +.It p +append_data +.It d +delete_child +.It D +delete +.It a +read_attributes +.It A +write_attributes +.It R +read_xattr +.It W +write_xattr +.It c +read_acl +.It C +write_acl +.It o +write_owner +.It S +synchronize +.El +.It Ar "ACL inheritance flags" +Inheritance flags may be specified in either short or long form. +Short and long forms may not be mixed. +Access flags in long form are separated by the +.Ql / +character; in short form, they are concatenated together. +Valid inheritance flags are: +.Bl -tag -width ".Dv short" +.It Short +Long +.It f +file_inherit +.It d +dir_inherit +.It i +inherit_only +.It n +no_propagate +.El +.Pp +Inheritance flags may be only set on directories. +.It Ar "ACL type" +The ACL type field is either +.Dq Li allow +or +.Dq Li deny . +.El +.Pp +ACL entries applied from a file using the +.Fl M +or +.Fl X +options shall be of the following form: one ACL entry per line, as +previously specified; whitespace is ignored; any text after a +.Ql # +is ignored (comments). +.Pp +NFSv4 ACL entries are evaluated in their visible order. +.Pp +Multiple ACL entries specified on the command line are +separated by commas. .Sh EXIT STATUS .Ex -std .Sh EXAMPLES .Dl setfacl -d -m u::rwx,g::rx,o::rx,mask::rwx dir .Dl setfacl -d -m g:admins:rwx dir .Pp -The first command sets the mandatory elements of the default ACL. +The first command sets the mandatory elements of the POSIX.1e default ACL. The second command specifies that users in group admins can have read, write, and execute permissions for directory named "dir". It should be noted that any files or directories created underneath "dir" will @@ -259,9 +396,13 @@ inherit these default ACLs upon creation. .Pp Sets read, write, and execute permissions for the .Pa file -owner's ACL entry and read and write permissions for group mail on +owner's POSIX.1e ACL entry and read and write permissions for group mail on .Pa file . .Pp +.Dl setfacl -m owner@:rwxp::allow,g:mail:rwp::allow file +.Pp +Semantically equal to the example above, but for NFSv4 ACL. +.Pp .Dl setfacl -M file1 file2 .Pp Sets/updates the ACL entries contained in @@ -271,10 +412,15 @@ on .Pp .Dl setfacl -x g:mail:rw file .Pp -Remove the group mail ACL entry containing read/write permissions +Remove the group mail POSIX.1e ACL entry containing read/write permissions from .Pa file . .Pp +.Dl setfacl -x0 file +.Pp +Remove the first entry from the NFSv4 ACL from +.Pa file . +.Pp .Dl setfacl -bn file .Pp Remove all diff --git a/bin/setfacl/setfacl.c b/bin/setfacl/setfacl.c index 2286efb244a..2835ba894c4 100644 --- a/bin/setfacl/setfacl.c +++ b/bin/setfacl/setfacl.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -41,9 +42,8 @@ __FBSDID("$FreeBSD$"); #include "setfacl.h" -static void add_filename(const char *filename); -static acl_t *get_file_acls(const char *filename); -static void usage(void); +static void add_filename(const char *filename); +static void usage(void); static void add_filename(const char *filename) @@ -59,57 +59,28 @@ add_filename(const char *filename) TAILQ_INSERT_TAIL(&filelist, file, next); } -static acl_t * -get_file_acls(const char *filename) -{ - acl_t *acl; - struct stat sb; - - if (stat(filename, &sb) == -1) { - warn("stat() of %s failed", filename); - return (NULL); - } - - acl = zmalloc(sizeof(acl_t) * 2); - if (h_flag) - acl[ACCESS_ACL] = acl_get_link_np(filename, ACL_TYPE_ACCESS); - else - acl[ACCESS_ACL] = acl_get_file(filename, ACL_TYPE_ACCESS); - if (acl[ACCESS_ACL] == NULL) - err(1, "acl_get_file() failed"); - if (S_ISDIR(sb.st_mode)) { - if (h_flag) - acl[DEFAULT_ACL] = acl_get_link_np(filename, - ACL_TYPE_DEFAULT); - else - acl[DEFAULT_ACL] = acl_get_file(filename, - ACL_TYPE_DEFAULT); - if (acl[DEFAULT_ACL] == NULL) - err(1, "acl_get_file() failed"); - } else - acl[DEFAULT_ACL] = NULL; - - return (acl); -} - static void usage(void) { - fprintf(stderr, "usage: setfacl [-bdhkn] [-m entries] [-M file] " - "[-x entries] [-X file] [file ...]\n"); + fprintf(stderr, "usage: setfacl [-bdhkn] [-a position entries] " + "[-m entries] [-M file] [-x entries] [-X file] [file ...]\n"); exit(1); } int main(int argc, char *argv[]) { - acl_t *acl, final_acl; + acl_t acl; + acl_type_t acl_type; char filename[PATH_MAX]; - int local_error, carried_error, ch, i; + int local_error, carried_error, ch, i, entry_number, ret; + int h_flag; struct sf_file *file; struct sf_entry *entry; const char *fn_dup; + char *end; + struct stat sb; acl_type = ACL_TYPE_ACCESS; carried_error = local_error = 0; @@ -118,13 +89,13 @@ main(int argc, char *argv[]) TAILQ_INIT(&entrylist); TAILQ_INIT(&filelist); - while ((ch = getopt(argc, argv, "M:X:bdhkm:nx:")) != -1) + while ((ch = getopt(argc, argv, "M:X:a:bdhkm:nx:")) != -1) switch(ch) { case 'M': entry = zmalloc(sizeof(struct sf_entry)); entry->acl = get_acl_from_file(optarg); if (entry->acl == NULL) - err(1, "get_acl_from_file() failed"); + err(1, "%s: get_acl_from_file() failed", optarg); entry->op = OP_MERGE_ACL; TAILQ_INSERT_TAIL(&entrylist, entry, next); break; @@ -134,6 +105,25 @@ main(int argc, char *argv[]) entry->op = OP_REMOVE_ACL; TAILQ_INSERT_TAIL(&entrylist, entry, next); break; + case 'a': + entry = zmalloc(sizeof(struct sf_entry)); + + entry_number = strtol(optarg, &end, 10); + if (end - optarg != (int)strlen(optarg)) + errx(1, "%s: invalid entry number", optarg); + if (entry_number < 0) + errx(1, "%s: entry number cannot be less than zero", optarg); + entry->entry_number = entry_number; + + if (argv[optind] == NULL) + errx(1, "missing ACL"); + entry->acl = acl_from_text(argv[optind]); + if (entry->acl == NULL) + err(1, "%s", argv[optind]); + optind++; + entry->op = OP_ADD_ACL; + TAILQ_INSERT_TAIL(&entrylist, entry, next); + break; case 'b': entry = zmalloc(sizeof(struct sf_entry)); entry->op = OP_REMOVE_EXT; @@ -163,10 +153,18 @@ main(int argc, char *argv[]) break; case 'x': entry = zmalloc(sizeof(struct sf_entry)); - entry->acl = acl_from_text(optarg); - if (entry->acl == NULL) - err(1, "%s", optarg); - entry->op = OP_REMOVE_ACL; + entry_number = strtol(optarg, &end, 10); + if (end - optarg == (int)strlen(optarg)) { + if (entry_number < 0) + errx(1, "%s: entry number cannot be less than zero", optarg); + entry->entry_number = entry_number; + entry->op = OP_REMOVE_BY_NUMBER; + } else { + entry->acl = acl_from_text(optarg); + if (entry->acl == NULL) + err(1, "%s", optarg); + entry->op = OP_REMOVE_ACL; + } TAILQ_INSERT_TAIL(&entrylist, entry, next); break; default: @@ -199,16 +197,51 @@ main(int argc, char *argv[]) /* cycle through each file */ TAILQ_FOREACH(file, &filelist, next) { - /* get our initial access and default ACL's */ - acl = get_file_acls(file->filename); - if (acl == NULL) - continue; - if ((acl_type == ACL_TYPE_DEFAULT) && !acl[1]) { - warnx("Default ACL not valid for %s", file->filename); + local_error = 0; + + if (stat(file->filename, &sb) == -1) { + warn("%s: stat() failed", file->filename); continue; } - local_error = 0; + if (acl_type == ACL_TYPE_DEFAULT && S_ISDIR(sb.st_mode) == 0) { + warnx("%s: default ACL may only be set on a directory", + file->filename); + continue; + } + + if (h_flag) + ret = lpathconf(file->filename, _PC_ACL_NFS4); + else + ret = pathconf(file->filename, _PC_ACL_NFS4); + if (ret > 0) { + if (acl_type == ACL_TYPE_DEFAULT) { + warnx("%s: there are no default entries " + "in NFSv4 ACLs", file->filename); + continue; + } + acl_type = ACL_TYPE_NFS4; + } else if (ret == 0) { + if (acl_type == ACL_TYPE_NFS4) + acl_type = ACL_TYPE_ACCESS; + } else if (ret < 0 && errno != EINVAL) { + warn("%s: pathconf(..., _PC_ACL_NFS4) failed", + file->filename); + } + + if (h_flag) + acl = acl_get_link_np(file->filename, acl_type); + else + acl = acl_get_file(file->filename, acl_type); + if (acl == NULL) { + if (h_flag) + warn("%s: acl_get_link_np() failed", + file->filename); + else + warn("%s: acl_get_file() failed", + file->filename); + continue; + } /* cycle through each option */ TAILQ_FOREACH(entry, &entrylist, next) { @@ -216,24 +249,44 @@ main(int argc, char *argv[]) continue; switch(entry->op) { + case OP_ADD_ACL: + local_error += add_acl(entry->acl, + entry->entry_number, &acl, file->filename); + break; case OP_MERGE_ACL: - local_error += merge_acl(entry->acl, acl); + local_error += merge_acl(entry->acl, &acl, + file->filename); need_mask = 1; break; case OP_REMOVE_EXT: - remove_ext(acl); + remove_ext(&acl, file->filename); need_mask = 0; break; case OP_REMOVE_DEF: + if (acl_type == ACL_TYPE_NFS4) { + warnx("%s: there are no default entries in NFSv4 ACLs; " + "cannot remove", file->filename); + local_error++; + break; + } if (acl_delete_def_file(file->filename) == -1) { - warn("acl_delete_def_file() failed"); + warn("%s: acl_delete_def_file() failed", + file->filename); local_error++; } - local_error += remove_default(acl); + if (acl_type == ACL_TYPE_DEFAULT) + local_error += remove_default(&acl, + file->filename); need_mask = 0; break; case OP_REMOVE_ACL: - local_error += remove_acl(entry->acl, acl); + local_error += remove_acl(entry->acl, &acl, + file->filename); + need_mask = 1; + break; + case OP_REMOVE_BY_NUMBER: + local_error += remove_by_number(entry->entry_number, + &acl, file->filename); need_mask = 1; break; } @@ -245,35 +298,27 @@ main(int argc, char *argv[]) continue; } - if (acl_type == ACL_TYPE_ACCESS) { - final_acl = acl[ACCESS_ACL]; - acl_free(acl[DEFAULT_ACL]); - } else { - final_acl = acl[DEFAULT_ACL]; - acl_free(acl[ACCESS_ACL]); - } - - if (need_mask && (set_acl_mask(&final_acl) == -1)) { - warnx("failed to set ACL mask on %s", file->filename); + if (acl_type != ACL_TYPE_NFS4 && need_mask && + set_acl_mask(&acl, file->filename) == -1) { + warnx("%s: failed to set ACL mask", file->filename); carried_error++; } else if (h_flag) { if (acl_set_link_np(file->filename, acl_type, - final_acl) == -1) { + acl) == -1) { carried_error++; - warn("acl_set_link_np() failed for %s", + warn("%s: acl_set_link_np() failed", file->filename); } } else { if (acl_set_file(file->filename, acl_type, - final_acl) == -1) { + acl) == -1) { carried_error++; - warn("acl_set_file() failed for %s", + warn("%s: acl_set_file() failed", file->filename); } } - acl_free(final_acl); - free(acl); + acl_free(acl); } return (carried_error); diff --git a/bin/setfacl/setfacl.h b/bin/setfacl/setfacl.h index bdf052ba0a8..7c11b3a14f7 100644 --- a/bin/setfacl/setfacl.h +++ b/bin/setfacl/setfacl.h @@ -38,15 +38,14 @@ #define OP_REMOVE_DEF 0x01 /* remove default acl's (-k) */ #define OP_REMOVE_EXT 0x02 /* remove extended acl's (-b) */ #define OP_REMOVE_ACL 0x03 /* remove acl's (-xX) */ - -/* ACL types for the acl array */ -#define ACCESS_ACL 0 -#define DEFAULT_ACL 1 +#define OP_REMOVE_BY_NUMBER 0x04 /* remove acl's (-xX) by acl entry number */ +#define OP_ADD_ACL 0x05 /* add acls entries at a given position */ /* TAILQ entry for acl operations */ struct sf_entry { uint op; acl_t acl; + uint entry_number; TAILQ_ENTRY(sf_entry) next; }; TAILQ_HEAD(, sf_entry) entrylist; @@ -61,21 +60,21 @@ TAILQ_HEAD(, sf_file) filelist; /* files.c */ acl_t get_acl_from_file(const char *filename); /* merge.c */ -int merge_acl(acl_t acl, acl_t *prev_acl); +int merge_acl(acl_t acl, acl_t *prev_acl, const char *filename); +int add_acl(acl_t acl, uint entry_number, acl_t *prev_acl, const char *filename); /* remove.c */ -int remove_acl(acl_t acl, acl_t *prev_acl); -int remove_default(acl_t *prev_acl); -void remove_ext(acl_t *prev_acl); +int remove_acl(acl_t acl, acl_t *prev_acl, const char *filename); +int remove_by_number(uint entry_number, acl_t *prev_acl, const char *filename); +int remove_default(acl_t *prev_acl, const char *filename); +void remove_ext(acl_t *prev_acl, const char *filename); /* mask.c */ -int set_acl_mask(acl_t *prev_acl); +int set_acl_mask(acl_t *prev_acl, const char *filename); /* util.c */ void *zmalloc(size_t size); -acl_type_t acl_type; uint have_mask; uint need_mask; uint have_stdin; -uint h_flag; uint n_flag; #endif /* _SETFACL_H */ diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 39e16602abf..7978b84f051 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -785,6 +785,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) INTOFF; savelocalvars = localvars; localvars = NULL; + reffunc(cmdentry.u.func); INTON; savehandler = handler; if (setjmp(jmploc.loc)) { @@ -794,6 +795,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) freeparam(&shellparam); shellparam = saveparam; } + unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; handler = savehandler; @@ -805,11 +807,12 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) funcnest++; exitstatus = oexitstatus; if (flags & EV_TESTED) - evaltree(cmdentry.u.func, EV_TESTED); + evaltree(getfuncnode(cmdentry.u.func), EV_TESTED); else - evaltree(cmdentry.u.func, 0); + evaltree(getfuncnode(cmdentry.u.func), 0); funcnest--; INTOFF; + unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; freeparam(&shellparam); diff --git a/bin/sh/exec.c b/bin/sh/exec.c index 3dc88954243..810782166a9 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -286,7 +286,7 @@ printentry(struct tblentry *cmdp, int verbose) out1fmt("function %s", cmdp->cmdname); if (verbose) { INTOFF; - name = commandtext(cmdp->param.func); + name = commandtext(getfuncnode(cmdp->param.func)); out1c(' '); out1str(name); ckfree(name); @@ -583,7 +583,7 @@ deletefuncs(void) while ((cmdp = *pp) != NULL) { if (cmdp->cmdtype == CMDFUNCTION) { *pp = cmdp->next; - freefunc(cmdp->param.func); + unreffunc(cmdp->param.func); ckfree(cmdp); } else { pp = &cmdp->next; @@ -670,7 +670,7 @@ addcmdentry(char *name, struct cmdentry *entry) INTOFF; cmdp = cmdlookup(name, 1); if (cmdp->cmdtype == CMDFUNCTION) { - freefunc(cmdp->param.func); + unreffunc(cmdp->param.func); } cmdp->cmdtype = entry->cmdtype; cmdp->param = entry->u; @@ -705,7 +705,7 @@ unsetfunc(char *name) struct tblentry *cmdp; if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) { - freefunc(cmdp->param.func); + unreffunc(cmdp->param.func); delete_cmd_entry(); return (0); } diff --git a/bin/sh/exec.h b/bin/sh/exec.h index 9f81a6a43df..e3b9acdd84d 100644 --- a/bin/sh/exec.h +++ b/bin/sh/exec.h @@ -46,11 +46,12 @@ enum { TYPECMD_TYPE /* type */ }; +union node; struct cmdentry { int cmdtype; union param { int index; - union node *func; + struct funcdef *func; } u; int special; }; diff --git a/bin/sh/mknodes.c b/bin/sh/mknodes.c index f0afca6800c..1a177f89531 100644 --- a/bin/sh/mknodes.c +++ b/bin/sh/mknodes.c @@ -248,8 +248,11 @@ output(char *file) fputs("\tstruct nodelist *next;\n", hfile); fputs("\tunion node *n;\n", hfile); fputs("};\n\n\n", hfile); - fputs("union node *copyfunc(union node *);\n", hfile); - fputs("void freefunc(union node *);\n", hfile); + fputs("struct funcdef;\n", hfile); + fputs("struct funcdef *copyfunc(union node *);\n", hfile); + fputs("union node *getfuncnode(struct funcdef *);\n", hfile); + fputs("void reffunc(struct funcdef *);\n", hfile); + fputs("void unreffunc(struct funcdef *);\n", hfile); fputs(writer, cfile); while (fgets(line, sizeof line, patfile) != NULL) { diff --git a/bin/sh/nodes.c.pat b/bin/sh/nodes.c.pat index 10dab26d2ac..1f5adbbae4a 100644 --- a/bin/sh/nodes.c.pat +++ b/bin/sh/nodes.c.pat @@ -35,6 +35,7 @@ #include #include +#include /* * Routine for dealing with parsed shell commands. */ @@ -60,25 +61,40 @@ STATIC struct nodelist *copynodelist(struct nodelist *); STATIC char *nodesavestr(char *); +struct funcdef { + unsigned int refcount; + union node n; +}; /* * Make a copy of a parse tree. */ -union node * +struct funcdef * copyfunc(union node *n) { + struct funcdef *fn; + if (n == NULL) return NULL; - funcblocksize = 0; + funcblocksize = offsetof(struct funcdef, n); funcstringsize = 0; calcsize(n); - funcblock = ckmalloc(funcblocksize + funcstringsize); - funcstring = (char *)funcblock + funcblocksize; - return copynode(n); + fn = ckmalloc(funcblocksize + funcstringsize); + fn->refcount = 1; + funcblock = (char *)fn + offsetof(struct funcdef, n); + funcstring = (char *)fn + funcblocksize; + copynode(n); + return fn; } +union node * +getfuncnode(struct funcdef *fn) +{ + return fn == NULL ? NULL : &fn->n; +} + STATIC void calcsize(union node *n) @@ -144,14 +160,26 @@ nodesavestr(char *s) } +void +reffunc(struct funcdef *fn) +{ + if (fn) + fn->refcount++; +} + /* - * Free a parse tree. + * Decrement the reference count of a function definition, freeing it + * if it falls to 0. */ void -freefunc(union node *n) +unreffunc(struct funcdef *fn) { - if (n) - ckfree(n); + if (fn) { + fn->refcount--; + if (fn->refcount > 0) + return; + ckfree(fn); + } } diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c index 16b2787704a..9e1e1063544 100644 --- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c +++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c @@ -1322,6 +1322,14 @@ dump_label(const char *dev) exit(1); } + if (S_ISCHR(statbuf.st_mode)) { + if (ioctl(fd, DIOCGMEDIASIZE, &statbuf.st_size) == -1) { + (void) printf("failed to get size of '%s': %s\n", dev, + strerror(errno)); + exit(1); + } + } + psize = statbuf.st_size; psize = P2ALIGN(psize, (uint64_t)sizeof (vdev_label_t)); diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_mount.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_mount.c index 84a8a576f99..76ab7ac0d35 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_mount.c +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_mount.c @@ -172,6 +172,7 @@ is_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto) *tab = '\0'; if (strcmp(buf, mountpoint) == 0) { +#if defined(sun) /* * the protocol field is the third field * skip over second field @@ -194,6 +195,10 @@ is_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto) return (0); } } +#else + if (proto == PROTO_NFS) + return (SHARED_NFS); +#endif } } diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c index 110fa889dab..5ee17fb8508 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c @@ -1126,7 +1126,7 @@ again: uint64_t originguid = 0; uint64_t stream_originguid = 0; uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid; - char *fsname, *stream_fsname; + char *fsname, *stream_fsname, *p1, *p2; nextfselem = nvlist_next_nvpair(local_nv, fselem); @@ -1295,10 +1295,11 @@ again: "parentfromsnap", &stream_parent_fromsnap_guid)); /* check for rename */ + p1 = strrchr(fsname, '/'); + p2 = strrchr(stream_fsname, '/'); if ((stream_parent_fromsnap_guid != 0 && stream_parent_fromsnap_guid != parent_fromsnap_guid) || - strcmp(strrchr(fsname, '/'), - strrchr(stream_fsname, '/')) != 0) { + (p1 != NULL && p2 != NULL && strcmp (p1, p2) != 0)) { nvlist_t *parent; char tryname[ZFS_MAXNAMELEN]; @@ -1317,7 +1318,7 @@ again: VERIFY(0 == nvlist_lookup_string(parent, "name", &pname)); (void) snprintf(tryname, sizeof (tryname), - "%s%s", pname, strrchr(stream_fsname, '/')); + "%s%s", pname, p2 != NULL ? p2 : ""); } else { tryname[0] = '\0'; if (flags.verbose) { diff --git a/cddl/lib/libnvpair/Makefile b/cddl/lib/libnvpair/Makefile index 120339002ce..7bf500193dc 100644 --- a/cddl/lib/libnvpair/Makefile +++ b/cddl/lib/libnvpair/Makefile @@ -13,5 +13,6 @@ SRCS= libnvpair.c \ CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common +CFLAGS+= -I${.CURDIR}/../../../sys .include diff --git a/contrib/bzip2/FREEBSD-vendor b/contrib/bzip2/FREEBSD-vendor index 72eb8776ccb..6847c8b9a49 100644 --- a/contrib/bzip2/FREEBSD-vendor +++ b/contrib/bzip2/FREEBSD-vendor @@ -2,6 +2,4 @@ Project: bzip2 ProjectURL: http://www.bzip.org/ Version: 1.0.5 -VendorTag: BZIP2 -VersionTag: v1_0_5 License: BSD diff --git a/contrib/ee/ee.c b/contrib/ee/ee.c index 070bb9781fe..a603756fb51 100755 --- a/contrib/ee/ee.c +++ b/contrib/ee/ee.c @@ -72,10 +72,7 @@ char *version = "@(#) ee, version " EE_VERSION " $Revision: 1.102 $"; #include #endif -#ifdef HAS_CTYPE #include -#endif - #include #include #include @@ -83,6 +80,7 @@ char *version = "@(#) ee, version " EE_VERSION " $Revision: 1.102 $"; #include #include #include +#include #ifdef HAS_SYS_WAIT #include @@ -100,9 +98,7 @@ char *version = "@(#) ee, version " EE_VERSION " $Revision: 1.102 $"; #include #endif - #ifndef NO_CATGETS -#include #include nl_catd catalog; @@ -726,7 +722,7 @@ int character; /* new character */ } *point = character; /* insert new character */ wclrtoeol(text_win); - if (((character >= 0) && (character < ' ')) || (character >= 127)) /* check for TAB character*/ + if (!isprint((unsigned char)character)) /* check for TAB character*/ { scr_pos = scr_horz += out_char(text_win, character, scr_horz); point++; @@ -734,7 +730,7 @@ int character; /* new character */ } else { - waddch(text_win, character); + waddch(text_win, (unsigned char)character); scr_pos = ++scr_horz; point++; position ++; @@ -969,17 +965,17 @@ int column; } else { - waddch(window, (char)character ); + waddch(window, (unsigned char)character ); return(1); } } else { - waddch(window, (char)character); + waddch(window, (unsigned char)character); return(1); } for (i2 = 0; (string[i2] != '\0') && (((column+i2+1)-horiz_offset) < last_col); i2++) - waddch(window, string[i2]); + waddch(window, (unsigned char)string[i2]); return(strlen(string)); } @@ -1044,7 +1040,7 @@ int length; /* length (in bytes) of line */ wclrtoeol(text_win); while ((posit < length) && (column <= last_col)) { - if ((*temp < 32) || (*temp >= 127)) + if (!isprint(*temp)) { column += len_char(*temp, abs_column); abs_column += out_char(text_win, *temp, abs_column); @@ -1923,13 +1919,13 @@ int advance; /* if true, skip leading spaces and tabs */ } *nam_str = in; g_pos++; - if (((in < ' ') || (in > 126)) && (g_horz < (last_col - 1))) + if (!isprint((unsigned char)in) && (g_horz < (last_col - 1))) g_horz += out_char(com_win, in, g_horz); else { g_horz++; if (g_horz < (last_col - 1)) - waddch(com_win, in); + waddch(com_win, (unsigned char)in); } nam_str++; } @@ -1974,7 +1970,7 @@ int sensitive; } else { - if (toupper(*strng1) != toupper(*strng2)) + if (toupper((unsigned char)*strng1) != toupper((unsigned char)*strng2)) equal = FALSE; } strng1++; @@ -2446,7 +2442,7 @@ int noverify; if ((text_changes) && (!noverify)) { ans = get_string(changes_made_prompt, TRUE); - if (toupper(*ans) == toupper(*yes_char)) + if (toupper((unsigned char)*ans) == toupper((unsigned char)*yes_char)) text_changes = FALSE; else return(0); @@ -2523,7 +2519,7 @@ int warn_if_exists; if ((temp_fp = fopen(file_name, "r"))) { tmp_point = get_string(file_exists_prompt, TRUE); - if (toupper(*tmp_point) == toupper(*yes_char)) + if (toupper((unsigned char)*tmp_point) == toupper((unsigned char)*yes_char)) write_flag = TRUE; else write_flag = FALSE; @@ -3438,14 +3434,13 @@ struct menu_entries menu_list[]; if (input == -1) exit(0); - if (((tolower(input) >= 'a') && (tolower(input) <= 'z')) || - ((input >= '0') && (input <= '9'))) + if (isascii(input) && isalnum(input)) { - if ((tolower(input) >= 'a') && (tolower(input) <= 'z')) + if (isalpha(input)) { temp = 1 + tolower(input) - 'a'; } - else if ((input >= '0') && (input <= '9')) + else if (isdigit(input)) { temp = (2 + 'z' - 'a') + (input - '0'); } @@ -5085,8 +5080,8 @@ strings_init() { int counter; -#ifndef NO_CATGETS setlocale(LC_ALL, ""); +#ifndef NO_CATGETS catalog = catopen("ee", NL_CAT_LOCALE); #endif /* NO_CATGETS */ diff --git a/contrib/gdtoa/gdtoaimp.h b/contrib/gdtoa/gdtoaimp.h index c550ada8775..9991ffac6e9 100644 --- a/contrib/gdtoa/gdtoaimp.h +++ b/contrib/gdtoa/gdtoaimp.h @@ -485,7 +485,7 @@ extern pthread_mutex_t __gdtoa_locks[2]; _pthread_mutex_unlock(&__gdtoa_locks[n]); \ } while(0) -#define Kmax 15 +#define Kmax 9 struct Bigint { diff --git a/contrib/gdtoa/misc.c b/contrib/gdtoa/misc.c index b3ce7c9b8a4..8d2888e249f 100644 --- a/contrib/gdtoa/misc.c +++ b/contrib/gdtoa/misc.c @@ -55,7 +55,9 @@ Balloc #endif ACQUIRE_DTOA_LOCK(0); - if ( (rv = freelist[k]) !=0) { + /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */ + /* but this case seems very unlikely. */ + if (k <= Kmax && (rv = freelist[k]) !=0) { freelist[k] = rv->next; } else { @@ -65,7 +67,7 @@ Balloc #else len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) /sizeof(double); - if (pmem_next - private_mem + len <= PRIVATE_mem) { + if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { rv = (Bigint*)pmem_next; pmem_next += len; } @@ -89,10 +91,14 @@ Bfree #endif { if (v) { - ACQUIRE_DTOA_LOCK(0); - v->next = freelist[v->k]; - freelist[v->k] = v; - FREE_DTOA_LOCK(0); + if (v->k > Kmax) + free((void*)v); + else { + ACQUIRE_DTOA_LOCK(0); + v->next = freelist[v->k]; + freelist[v->k] = v; + FREE_DTOA_LOCK(0); + } } } diff --git a/contrib/netcat/FREEBSD-vendor b/contrib/netcat/FREEBSD-vendor index 6e31d26c32e..1009e388e2e 100644 --- a/contrib/netcat/FREEBSD-vendor +++ b/contrib/netcat/FREEBSD-vendor @@ -2,6 +2,4 @@ Project: netcat (aka src/usr.bin/nc in OpenBSD) ProjectURL: http://www.openbsd.org/ Version: 4.4 -VendorTag: OPENBSD -VersionTag: OPENBSD_4_4 License: BSD diff --git a/contrib/openpam/FREEBSD-vendor b/contrib/openpam/FREEBSD-vendor index 69a0ade0ef5..51a8bbfa480 100644 --- a/contrib/openpam/FREEBSD-vendor +++ b/contrib/openpam/FREEBSD-vendor @@ -2,7 +2,5 @@ Project: OpenPAM ProjectURL: http://www.openpam.org/ Version: Hydrangea (20071221) -VendorTag: OPENPAM -VersionTag: OPENPAM_HYDRANGEA License: BSD Maintainer: des diff --git a/contrib/top/display.c b/contrib/top/display.c index 0b1226ce03d..3fca57b5fdc 100644 --- a/contrib/top/display.c +++ b/contrib/top/display.c @@ -452,6 +452,7 @@ for (cpu = 0; cpu < num_cpus; cpu++) { lastline++; /* now walk thru the names and print the line */ + Move_to(cpustates_column, y_cpustates + cpu); while ((thisname = *names++) != NULL) { if (*thisname != '\0') @@ -543,6 +544,7 @@ for (cpu = 0; cpu < num_cpus; cpu++) { printf("\nCPU %d: ", cpu); lastline++; + Move_to(cpustates_column, y_cpustates + cpu); while ((thisname = *names++) != NULL) { if (*thisname != '\0') diff --git a/contrib/traceroute/as.c b/contrib/traceroute/as.c index abb6c710805..689848a89cf 100644 --- a/contrib/traceroute/as.c +++ b/contrib/traceroute/as.c @@ -63,55 +63,42 @@ struct aslookup { }; void * -as_setup(server) - char *server; +as_setup(char *server) { struct aslookup *asn; - struct hostent *he = NULL; - struct servent *se; - struct sockaddr_in in; + struct addrinfo hints, *res0, *res; FILE *f; - int s; + int s, error; + if (server == NULL) + server = getenv("RA_SERVER"); if (server == NULL) server = DEFAULT_AS_SERVER; - (void)memset(&in, 0, sizeof(in)); - in.sin_family = AF_INET; - in.sin_len = sizeof(in); - if ((se = getservbyname("whois", "tcp")) == NULL) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(server, "whois", &hints, &res0); + if (error == EAI_SERVICE) { warnx("warning: whois/tcp service not found"); - in.sin_port = ntohs(43); - } else - in.sin_port = se->s_port; - - if (inet_aton(server, &in.sin_addr) == 0 && - ((he = gethostbyname(server)) == NULL || - he->h_addr == NULL)) { - warnx("%s: %s", server, hstrerror(h_errno)); + error = getaddrinfo(server, "43", &hints, &res0); + } + if (error != 0) { + warnx("%s: %s", server, gai_strerror(error)); return (NULL); } - if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) { - warn("socket"); - return (NULL); + for (res = res0; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s < 0) + continue; + if (connect(s, res->ai_addr, res->ai_addrlen) >= 0) + break; + close(s); + s = -1; } - - do { - if (he != NULL) { - memcpy(&in.sin_addr, he->h_addr, he->h_length); - he->h_addr_list++; - } - if (connect(s, (struct sockaddr *)&in, sizeof(in)) == 0) - break; - if (he == NULL || he->h_addr == NULL) { - close(s); - s = -1; - break; - } - } while (1); - - if (s == -1) { + freeaddrinfo(res0); + if (s < 0) { warn("connect"); return (NULL); } @@ -137,23 +124,23 @@ as_setup(server) return (asn); } -int -as_lookup(_asn, addr) - void *_asn; - struct in_addr *addr; +unsigned int +as_lookup(void *_asn, char *addr, sa_family_t family) { struct aslookup *asn = _asn; char buf[1024]; - int as, rc, dlen; + unsigned int as; + int rc, dlen, plen; - as = rc = dlen = 0; - (void)fprintf(asn->as_f, "!r%s/32,l\n", inet_ntoa(*addr)); + as = 0; + rc = dlen = 0; + plen = (family == AF_INET6) ? 128 : 32; + (void)fprintf(asn->as_f, "!r%s/%d,l\n", addr, plen); (void)fflush(asn->as_f); #ifdef AS_DEBUG_FILE if (asn->as_debug) { - (void)fprintf(asn->as_debug, ">> !r%s/32,l\n", - inet_ntoa(*addr)); + (void)fprintf(asn->as_debug, ">> !r%s/%d,l\n", addr, plen); (void)fflush(asn->as_debug); } #endif /* AS_DEBUG_FILE */ @@ -182,7 +169,7 @@ as_lookup(_asn, addr) } #endif /* AS_DEBUG_FILE */ break; - case 'C': + case 'C': case 'D': case 'E': case 'F': @@ -209,7 +196,7 @@ as_lookup(_asn, addr) /* origin line is the interesting bit */ if (as == 0 && strncasecmp(buf, "origin:", 7) == 0) { - sscanf(buf + 7, " AS%d", &as); + sscanf(buf + 7, " AS%u", &as); #ifdef AS_DEBUG_FILE if (asn->as_debug) { (void)fprintf(asn->as_debug, "as: %d\n", as); @@ -223,8 +210,7 @@ as_lookup(_asn, addr) } void -as_shutdown(_asn) - void *_asn; +as_shutdown(void *_asn) { struct aslookup *asn = _asn; diff --git a/contrib/traceroute/as.h b/contrib/traceroute/as.h index 5ed563ded75..3b7d3a660a5 100644 --- a/contrib/traceroute/as.h +++ b/contrib/traceroute/as.h @@ -37,6 +37,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -void *as_setup __P((char *)); -int as_lookup __P((void *, struct in_addr *)); -void as_shutdown __P((void *)); +void *as_setup(char *); +unsigned int as_lookup(void *, char *, sa_family_t); +void as_shutdown(void *); diff --git a/contrib/traceroute/traceroute.c b/contrib/traceroute/traceroute.c index a4bce610145..120d1cd9e57 100644 --- a/contrib/traceroute/traceroute.c +++ b/contrib/traceroute/traceroute.c @@ -1477,19 +1477,21 @@ print(register u_char *buf, register int cc, register struct sockaddr_in *from) { register struct ip *ip; register int hlen; + char addr[INET_ADDRSTRLEN]; ip = (struct ip *) buf; hlen = ip->ip_hl << 2; cc -= hlen; + strlcpy(addr, inet_ntoa(from->sin_addr), sizeof(addr)); + if (as_path) - Printf(" [AS%d]", as_lookup(asn, &from->sin_addr)); + Printf(" [AS%u]", as_lookup(asn, addr, AF_INET)); if (nflag) - Printf(" %s", inet_ntoa(from->sin_addr)); + Printf(" %s", addr); else - Printf(" %s (%s)", inetname(from->sin_addr), - inet_ntoa(from->sin_addr)); + Printf(" %s (%s)", inetname(from->sin_addr), addr); if (verbose) Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); diff --git a/crypto/openssh/FREEBSD-vendor b/crypto/openssh/FREEBSD-vendor index 6329f5abf05..0fa56d03f5d 100644 --- a/crypto/openssh/FREEBSD-vendor +++ b/crypto/openssh/FREEBSD-vendor @@ -1,8 +1,6 @@ # $FreeBSD$ Project: Portable OpenSSH ProjectURL: http://www.openssh.com/portable.html -Version: 5.1p1 -VendorTag: OPENSSH -VersionTag: OpenSSH_5_1p1 +Version: 5.2p1 License: BSD Maintainer: des diff --git a/crypto/openssl/apps/md4.c b/crypto/openssl/apps/md4.c deleted file mode 120000 index 7f457b2ab1e..00000000000 --- a/crypto/openssl/apps/md4.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/md4/md4.c \ No newline at end of file diff --git a/crypto/openssl/crypto/pqueue/pqueue.c b/crypto/openssl/crypto/pqueue/pqueue.c index 5cc18527f8d..6c89f06fb10 100644 --- a/crypto/openssl/crypto/pqueue/pqueue.c +++ b/crypto/openssl/crypto/pqueue/pqueue.c @@ -234,3 +234,17 @@ pqueue_next(pitem **item) return ret; } + +int +pqueue_size(pqueue_s *pq) +{ + pitem *item = pq->items; + int count = 0; + + while(item != NULL) + { + count++; + item = item->next; + } + return count; +} diff --git a/crypto/openssl/crypto/pqueue/pqueue.h b/crypto/openssl/crypto/pqueue/pqueue.h index 02386d130e9..16c4072681c 100644 --- a/crypto/openssl/crypto/pqueue/pqueue.h +++ b/crypto/openssl/crypto/pqueue/pqueue.h @@ -91,5 +91,6 @@ pitem *pqueue_iterator(pqueue pq); pitem *pqueue_next(piterator *iter); void pqueue_print(pqueue pq); +int pqueue_size(pqueue pq); #endif /* ! HEADER_PQUEUE_H */ diff --git a/crypto/openssl/ssl/d1_both.c b/crypto/openssl/ssl/d1_both.c index 15a201a25cf..01771921061 100644 --- a/crypto/openssl/ssl/d1_both.c +++ b/crypto/openssl/ssl/d1_both.c @@ -519,6 +519,7 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) if ( s->d1->handshake_read_seq == frag->msg_header.seq) { + unsigned long frag_len = frag->msg_header.frag_len; pqueue_pop(s->d1->buffered_messages); al=dtls1_preprocess_fragment(s,&frag->msg_header,max); @@ -536,7 +537,7 @@ dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) if (al==0) { *ok = 1; - return frag->msg_header.frag_len; + return frag_len; } ssl3_send_alert(s,SSL3_AL_FATAL,al); @@ -561,7 +562,16 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len) goto err; - if (msg_hdr->seq <= s->d1->handshake_read_seq) + /* Try to find item in queue, to prevent duplicate entries */ + pq_64bit_init(&seq64); + pq_64bit_assign_word(&seq64, msg_hdr->seq); + item = pqueue_find(s->d1->buffered_messages, seq64); + pq_64bit_free(&seq64); + + /* Discard the message if sequence number was already there, is + * too far in the future or the fragment is already in the queue */ + if (msg_hdr->seq <= s->d1->handshake_read_seq || + msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL) { unsigned char devnull [256]; @@ -575,30 +585,31 @@ dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) } } - frag = dtls1_hm_fragment_new(frag_len); - if ( frag == NULL) - goto err; - - memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); - if (frag_len) - { - /* read the body of the fragment (header has already been read */ + { + frag = dtls1_hm_fragment_new(frag_len); + if ( frag == NULL) + goto err; + + memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); + + /* read the body of the fragment (header has already been read) */ i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, frag->fragment,frag_len,0); if (i<=0 || (unsigned long)i!=frag_len) goto err; - } - pq_64bit_init(&seq64); - pq_64bit_assign_word(&seq64, msg_hdr->seq); + pq_64bit_init(&seq64); + pq_64bit_assign_word(&seq64, msg_hdr->seq); - item = pitem_new(seq64, frag); - pq_64bit_free(&seq64); - if ( item == NULL) - goto err; + item = pitem_new(seq64, frag); + pq_64bit_free(&seq64); + if ( item == NULL) + goto err; + + pqueue_insert(s->d1->buffered_messages, item); + } - pqueue_insert(s->d1->buffered_messages, item); return DTLS1_HM_FRAGMENT_RETRY; err: diff --git a/crypto/openssl/ssl/d1_pkt.c b/crypto/openssl/ssl/d1_pkt.c index eb56cf987ba..4ae9be54ae6 100644 --- a/crypto/openssl/ssl/d1_pkt.c +++ b/crypto/openssl/ssl/d1_pkt.c @@ -167,6 +167,10 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, PQ_64BIT priority) DTLS1_RECORD_DATA *rdata; pitem *item; + /* Limit the size of the queue to prevent DOS attacks */ + if (pqueue_size(queue->q) >= 100) + return 0; + rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA)); item = pitem_new(priority, rdata); if (rdata == NULL || item == NULL) diff --git a/crypto/openssl/test/bftest.c b/crypto/openssl/test/bftest.c deleted file mode 120000 index 78b1749a4d1..00000000000 --- a/crypto/openssl/test/bftest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/bf/bftest.c \ No newline at end of file diff --git a/crypto/openssl/test/bntest.c b/crypto/openssl/test/bntest.c deleted file mode 120000 index 03f54a238ef..00000000000 --- a/crypto/openssl/test/bntest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/bn/bntest.c \ No newline at end of file diff --git a/crypto/openssl/test/casttest.c b/crypto/openssl/test/casttest.c deleted file mode 120000 index ac7ede8d795..00000000000 --- a/crypto/openssl/test/casttest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/cast/casttest.c \ No newline at end of file diff --git a/crypto/openssl/test/destest.c b/crypto/openssl/test/destest.c deleted file mode 120000 index 5988c7303a3..00000000000 --- a/crypto/openssl/test/destest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/des/destest.c \ No newline at end of file diff --git a/crypto/openssl/test/dhtest.c b/crypto/openssl/test/dhtest.c deleted file mode 120000 index 9a67f916288..00000000000 --- a/crypto/openssl/test/dhtest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/dh/dhtest.c \ No newline at end of file diff --git a/crypto/openssl/test/dsatest.c b/crypto/openssl/test/dsatest.c deleted file mode 120000 index 16a1b5a349f..00000000000 --- a/crypto/openssl/test/dsatest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/dsa/dsatest.c \ No newline at end of file diff --git a/crypto/openssl/test/ecdhtest.c b/crypto/openssl/test/ecdhtest.c deleted file mode 120000 index 206d98686d7..00000000000 --- a/crypto/openssl/test/ecdhtest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/ecdh/ecdhtest.c \ No newline at end of file diff --git a/crypto/openssl/test/ecdsatest.c b/crypto/openssl/test/ecdsatest.c deleted file mode 120000 index 441082ba243..00000000000 --- a/crypto/openssl/test/ecdsatest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/ecdsa/ecdsatest.c \ No newline at end of file diff --git a/crypto/openssl/test/ectest.c b/crypto/openssl/test/ectest.c deleted file mode 120000 index df1831f812c..00000000000 --- a/crypto/openssl/test/ectest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/ec/ectest.c \ No newline at end of file diff --git a/crypto/openssl/test/enginetest.c b/crypto/openssl/test/enginetest.c deleted file mode 120000 index 5c74a6f4189..00000000000 --- a/crypto/openssl/test/enginetest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/engine/enginetest.c \ No newline at end of file diff --git a/crypto/openssl/test/evp_test.c b/crypto/openssl/test/evp_test.c deleted file mode 120000 index 074162812a3..00000000000 --- a/crypto/openssl/test/evp_test.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/evp/evp_test.c \ No newline at end of file diff --git a/crypto/openssl/test/exptest.c b/crypto/openssl/test/exptest.c deleted file mode 120000 index 50ccf71cbb7..00000000000 --- a/crypto/openssl/test/exptest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/bn/exptest.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_aesavs.c b/crypto/openssl/test/fips_aesavs.c deleted file mode 120000 index 7d9da0e8856..00000000000 --- a/crypto/openssl/test/fips_aesavs.c +++ /dev/null @@ -1 +0,0 @@ -../fips/aes/fips_aesavs.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_desmovs.c b/crypto/openssl/test/fips_desmovs.c deleted file mode 120000 index dd74966b06b..00000000000 --- a/crypto/openssl/test/fips_desmovs.c +++ /dev/null @@ -1 +0,0 @@ -../fips/des/fips_desmovs.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_dsatest.c b/crypto/openssl/test/fips_dsatest.c deleted file mode 120000 index e43b79b16dc..00000000000 --- a/crypto/openssl/test/fips_dsatest.c +++ /dev/null @@ -1 +0,0 @@ -../fips/dsa/fips_dsatest.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_dssvs.c b/crypto/openssl/test/fips_dssvs.c deleted file mode 120000 index 93e05e687fd..00000000000 --- a/crypto/openssl/test/fips_dssvs.c +++ /dev/null @@ -1 +0,0 @@ -../fips/dsa/fips_dssvs.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_hmactest.c b/crypto/openssl/test/fips_hmactest.c deleted file mode 120000 index b674d16df59..00000000000 --- a/crypto/openssl/test/fips_hmactest.c +++ /dev/null @@ -1 +0,0 @@ -../fips/hmac/fips_hmactest.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_randtest.c b/crypto/openssl/test/fips_randtest.c deleted file mode 120000 index 8b8f4863bf0..00000000000 --- a/crypto/openssl/test/fips_randtest.c +++ /dev/null @@ -1 +0,0 @@ -../fips/rand/fips_randtest.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_rngvs.c b/crypto/openssl/test/fips_rngvs.c deleted file mode 120000 index 0d6c9be190a..00000000000 --- a/crypto/openssl/test/fips_rngvs.c +++ /dev/null @@ -1 +0,0 @@ -../fips/rand/fips_rngvs.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_rsagtest.c b/crypto/openssl/test/fips_rsagtest.c deleted file mode 120000 index 3ed6b5186ba..00000000000 --- a/crypto/openssl/test/fips_rsagtest.c +++ /dev/null @@ -1 +0,0 @@ -../fips/rsa/fips_rsagtest.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_rsastest.c b/crypto/openssl/test/fips_rsastest.c deleted file mode 120000 index 2a5f8b0280d..00000000000 --- a/crypto/openssl/test/fips_rsastest.c +++ /dev/null @@ -1 +0,0 @@ -../fips/rsa/fips_rsastest.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_rsavtest.c b/crypto/openssl/test/fips_rsavtest.c deleted file mode 120000 index f45aa58a8b7..00000000000 --- a/crypto/openssl/test/fips_rsavtest.c +++ /dev/null @@ -1 +0,0 @@ -../fips/rsa/fips_rsavtest.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_shatest.c b/crypto/openssl/test/fips_shatest.c deleted file mode 120000 index 67c47caba4b..00000000000 --- a/crypto/openssl/test/fips_shatest.c +++ /dev/null @@ -1 +0,0 @@ -../fips/sha/fips_shatest.c \ No newline at end of file diff --git a/crypto/openssl/test/fips_test_suite.c b/crypto/openssl/test/fips_test_suite.c deleted file mode 120000 index b538efa4281..00000000000 --- a/crypto/openssl/test/fips_test_suite.c +++ /dev/null @@ -1 +0,0 @@ -../fips/fips_test_suite.c \ No newline at end of file diff --git a/crypto/openssl/test/hmactest.c b/crypto/openssl/test/hmactest.c deleted file mode 120000 index 353ee2c7f98..00000000000 --- a/crypto/openssl/test/hmactest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/hmac/hmactest.c \ No newline at end of file diff --git a/crypto/openssl/test/ideatest.c b/crypto/openssl/test/ideatest.c deleted file mode 120000 index a9bfb3d4804..00000000000 --- a/crypto/openssl/test/ideatest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/idea/ideatest.c \ No newline at end of file diff --git a/crypto/openssl/test/jpaketest.c b/crypto/openssl/test/jpaketest.c deleted file mode 120000 index 49f44f8b69e..00000000000 --- a/crypto/openssl/test/jpaketest.c +++ /dev/null @@ -1 +0,0 @@ -dummytest.c \ No newline at end of file diff --git a/crypto/openssl/test/md2test.c b/crypto/openssl/test/md2test.c deleted file mode 120000 index b0c6e6f8091..00000000000 --- a/crypto/openssl/test/md2test.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/md2/md2test.c \ No newline at end of file diff --git a/crypto/openssl/test/md4test.c b/crypto/openssl/test/md4test.c deleted file mode 120000 index 1509be911da..00000000000 --- a/crypto/openssl/test/md4test.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/md4/md4test.c \ No newline at end of file diff --git a/crypto/openssl/test/md5test.c b/crypto/openssl/test/md5test.c deleted file mode 120000 index 20f4aaf0a4e..00000000000 --- a/crypto/openssl/test/md5test.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/md5/md5test.c \ No newline at end of file diff --git a/crypto/openssl/test/mdc2test.c b/crypto/openssl/test/mdc2test.c deleted file mode 120000 index 49f44f8b69e..00000000000 --- a/crypto/openssl/test/mdc2test.c +++ /dev/null @@ -1 +0,0 @@ -dummytest.c \ No newline at end of file diff --git a/crypto/openssl/test/randtest.c b/crypto/openssl/test/randtest.c deleted file mode 120000 index a2b107a2b0e..00000000000 --- a/crypto/openssl/test/randtest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/rand/randtest.c \ No newline at end of file diff --git a/crypto/openssl/test/rc2test.c b/crypto/openssl/test/rc2test.c deleted file mode 120000 index 5c53ad984a4..00000000000 --- a/crypto/openssl/test/rc2test.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/rc2/rc2test.c \ No newline at end of file diff --git a/crypto/openssl/test/rc4test.c b/crypto/openssl/test/rc4test.c deleted file mode 120000 index 061ac377344..00000000000 --- a/crypto/openssl/test/rc4test.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/rc4/rc4test.c \ No newline at end of file diff --git a/crypto/openssl/test/rc5test.c b/crypto/openssl/test/rc5test.c deleted file mode 120000 index 49f44f8b69e..00000000000 --- a/crypto/openssl/test/rc5test.c +++ /dev/null @@ -1 +0,0 @@ -dummytest.c \ No newline at end of file diff --git a/crypto/openssl/test/rmdtest.c b/crypto/openssl/test/rmdtest.c deleted file mode 120000 index ce66460654d..00000000000 --- a/crypto/openssl/test/rmdtest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/ripemd/rmdtest.c \ No newline at end of file diff --git a/crypto/openssl/test/rsa_test.c b/crypto/openssl/test/rsa_test.c deleted file mode 120000 index aaea20d98ba..00000000000 --- a/crypto/openssl/test/rsa_test.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/rsa/rsa_test.c \ No newline at end of file diff --git a/crypto/openssl/test/sha1test.c b/crypto/openssl/test/sha1test.c deleted file mode 120000 index 8d66e9ee4c2..00000000000 --- a/crypto/openssl/test/sha1test.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/sha/sha1test.c \ No newline at end of file diff --git a/crypto/openssl/test/sha256t.c b/crypto/openssl/test/sha256t.c deleted file mode 120000 index 952a5086766..00000000000 --- a/crypto/openssl/test/sha256t.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/sha/sha256t.c \ No newline at end of file diff --git a/crypto/openssl/test/sha512t.c b/crypto/openssl/test/sha512t.c deleted file mode 120000 index c80d152f1ba..00000000000 --- a/crypto/openssl/test/sha512t.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/sha/sha512t.c \ No newline at end of file diff --git a/crypto/openssl/test/shatest.c b/crypto/openssl/test/shatest.c deleted file mode 120000 index 43cfda78fbf..00000000000 --- a/crypto/openssl/test/shatest.c +++ /dev/null @@ -1 +0,0 @@ -../crypto/sha/shatest.c \ No newline at end of file diff --git a/crypto/openssl/test/ssltest.c b/crypto/openssl/test/ssltest.c deleted file mode 120000 index 40191f0da24..00000000000 --- a/crypto/openssl/test/ssltest.c +++ /dev/null @@ -1 +0,0 @@ -../ssl/ssltest.c \ No newline at end of file diff --git a/etc/Makefile b/etc/Makefile index e68df034bb5..1181104a3a4 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -99,8 +99,7 @@ BIN1+= regdomain.xml # -rwxr-xr-x root:wheel, for the new cron root:wheel BIN2= netstart pccard_ether rc.suspend rc.resume -MTREE= BSD.include.dist BSD.local.dist BSD.root.dist BSD.usr.dist \ - BSD.var.dist BSD.x11.dist BSD.x11-4.dist +MTREE= BSD.include.dist BSD.root.dist BSD.usr.dist BSD.var.dist .if ${MK_SENDMAIL} != "no" MTREE+= BSD.sendmail.dist .endif diff --git a/etc/defaults/periodic.conf b/etc/defaults/periodic.conf index c79e956cf99..b45483894af 100644 --- a/etc/defaults/periodic.conf +++ b/etc/defaults/periodic.conf @@ -224,7 +224,7 @@ weekly_noid_dirs="/" # Look here # 400.status-pkg weekly_status_pkg_enable="NO" # Find out-of-date pkgs pkg_version=pkg_version # Use this program -pkg_version_index=/usr/ports/INDEX-8 # Use this index file +pkg_version_index=/usr/ports/INDEX-9 # Use this index file # 999.local weekly_local="/etc/weekly.local" # Local scripts diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index edeedaeaca7..afb7e74ddce 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -357,6 +357,7 @@ bsnmpd_flags="" # Flags for bsnmpd. ### Network routing options: ### defaultrouter="NO" # Set to default gateway (or NO). +static_arp_pairs="" # Set to static ARP list (or leave empty). static_routes="" # Set to static route list (or leave empty). natm_static_routes="" # Set to static route list for NATM (or leave empty). gateway_enable="NO" # Set to YES if this host will be a gateway. diff --git a/etc/freebsd-update.conf b/etc/freebsd-update.conf index af53be4cb62..44109034b00 100644 --- a/etc/freebsd-update.conf +++ b/etc/freebsd-update.conf @@ -63,3 +63,14 @@ MergeChanges /etc/ /var/named/etc/ /boot/device.hints # which *might* be installed of which FreeBSD Update should figure out # which actually are installed and upgrade those (StrictComponents no)? # StrictComponents no + +# When installing a new kernel perform a backup of the old one first +# so it is possible to boot the old kernel in case of problems. +# BackupKernel yes + +# If BackupKernel is enabled, the backup kernel is saved to this +# directory. +# BackupKernelDir /boot/kernel.old + +# When backing up a kernel also back up debug symbol files? +# BackupKernelSymbolFiles no diff --git a/etc/inetd.conf b/etc/inetd.conf index 6f2e234b257..bbc21dfca60 100644 --- a/etc/inetd.conf +++ b/etc/inetd.conf @@ -8,8 +8,6 @@ # #ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l #ftp stream tcp6 nowait root /usr/libexec/ftpd ftpd -l -#ftp stream tcp nowait root /usr/libexec/lukemftpd ftpd -l -r -#ftp stream tcp6 nowait root /usr/libexec/lukemftpd ftpd -l -r #ssh stream tcp nowait root /usr/sbin/sshd sshd -i -4 #ssh stream tcp6 nowait root /usr/sbin/sshd sshd -i -6 #telnet stream tcp nowait root /usr/libexec/telnetd telnetd diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 97d70c1d81e..50fec7a7962 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -104,6 +104,8 @@ .. lmc .. + mfi + .. mpt mpilib .. diff --git a/etc/mtree/BSD.local.dist b/etc/mtree/BSD.local.dist deleted file mode 100644 index e78641453d4..00000000000 --- a/etc/mtree/BSD.local.dist +++ /dev/null @@ -1,850 +0,0 @@ -# $FreeBSD$ -# -# Please see the file src/etc/mtree/README before making changes to this file. -# - -/set type=dir uname=root gname=wheel mode=0755 -. - bin - .. - etc - pam.d - .. - rc.d - .. - .. - include - .. - info - .. - lib - .. - libdata - ldconfig - .. - ldconfig32 - .. - pkgconfig - .. - .. - libexec - .. - man -/set uname=man - cat1 - .. - cat2 - .. - cat3 - .. - cat4 - .. - cat5 - .. - cat6 - .. - cat7 - .. - cat8 - .. - cat9 - .. - catl - .. - catn - .. - de.ISO8859-1 uname=root - cat1 - .. - cat2 - .. - cat3 - .. - cat4 - .. - cat5 - .. - cat6 - .. - cat7 - .. - cat8 - .. - cat9 - .. - catl - .. - catn - .. -/set uname=root - man1 - .. - man2 - .. - man3 - .. - man4 - .. - man5 - .. - man6 - .. - man7 - .. - man8 - .. - man9 - .. - manl - .. - mann - .. - .. - en.ISO8859-1 -/set uname=man - cat1 - .. - cat1aout - .. - cat2 - .. - cat3 - .. - cat4 - i386 - .. - .. - cat5 - .. - cat6 - .. - cat7 - .. - cat8 - i386 - .. - .. - cat9 - i386 - .. - .. - catn - .. - .. - ja uname=root - cat1 - .. - cat2 - .. - cat3 - .. - cat4 - .. - cat5 - .. - cat6 - .. - cat7 - .. - cat8 - .. - cat9 - .. - catl - .. - catn - .. -/set uname=root - man1 - .. - man2 - .. - man3 - .. - man4 - .. - man5 - .. - man6 - .. - man7 - .. - man8 - .. - man9 - .. - manl - .. - mann - .. - .. - man1 - .. - man2 - .. - man3 - .. - man4 - .. - man5 - .. - man6 - .. - man7 - .. - man8 - .. - man9 - .. - manl - .. - mann - .. - ru.KOI8-R -/set uname=man - cat1 - .. - cat2 - .. - cat3 - .. - cat4 - .. - cat5 - .. - cat6 - .. - cat7 - .. - cat8 - .. - cat9 - .. - catl - .. - catn - .. -/set uname=root - man1 - .. - man2 - .. - man3 - .. - man4 - .. - man5 - .. - man6 - .. - man7 - .. - man8 - .. - man9 - .. - manl - .. - mann - .. - .. - .. - sbin - .. - share - aclocal - .. - dict - .. - doc - ja - .. - .. - emacs - site-lisp - .. - .. - examples - .. - java - classes - .. - .. - locale - af - LC_MESSAGES - .. - .. - am - LC_MESSAGES - .. - .. - ar - LC_MESSAGES - .. - .. - az - LC_MESSAGES - .. - .. - bg - LC_MESSAGES - .. - .. - bn - LC_MESSAGES - .. - .. - br - LC_MESSAGES - .. - .. - bs - LC_MESSAGES - .. - .. - cy - LC_MESSAGES - .. - .. - da - LC_MESSAGES - .. - .. - de - LC_MESSAGES - .. - .. - dk - LC_MESSAGES - .. - .. - ee - LC_MESSAGES - .. - .. - en - LC_MESSAGES - .. - .. - en_CA - LC_MESSAGES - .. - .. - en_GB - LC_MESSAGES - .. - .. - eo - LC_MESSAGES - .. - .. - es - LC_MESSAGES - .. - .. - es_ES - LC_MESSAGES - .. - .. - es_MX - LC_MESSAGES - .. - .. - et - LC_MESSAGES - .. - .. - eu - LC_MESSAGES - .. - .. - fa - LC_MESSAGES - .. - .. - fr - LC_MESSAGES - .. - .. - ga - LC_MESSAGES - .. - .. - gu - LC_MESSAGES - .. - .. - he - LC_MESSAGES - .. - .. - hi - LC_MESSAGES - .. - .. - hr - LC_MESSAGES - .. - .. - hu - LC_MESSAGES - .. - .. - id - LC_MESSAGES - .. - .. - is - LC_MESSAGES - .. - .. - it - LC_MESSAGES - .. - .. - ja - LC_MESSAGES - .. - .. - ka - LC_MESSAGES - .. - .. - kn - LC_MESSAGES - .. - .. - lt - LC_MESSAGES - .. - .. - lv - LC_MESSAGES - .. - .. - mk - LC_MESSAGES - .. - .. - ml - LC_MESSAGES - .. - .. - mn - LC_MESSAGES - .. - .. - ms - LC_MESSAGES - .. - .. - mt - LC_MESSAGES - .. - .. - nb - LC_MESSAGES - .. - .. - nl - LC_MESSAGES - .. - .. - or - LC_MESSAGES - .. - .. - pa - LC_MESSAGES - .. - .. - pt_BR - LC_MESSAGES - .. - .. - pt_PT - LC_MESSAGES - .. - .. - ru - LC_MESSAGES - .. - .. - sq - LC_MESSAGES - .. - .. - sr@Latn - LC_MESSAGES - .. - .. - sv - LC_MESSAGES - .. - .. - ta - LC_MESSAGES - .. - .. - th - LC_MESSAGES - .. - .. - tr - LC_MESSAGES - .. - .. - vi - LC_MESSAGES - .. - .. - wa - LC_MESSAGES - .. - .. - zh - LC_MESSAGES - .. - .. - zh_CN.GB2312 - LC_MESSAGES - .. - .. - zh_TW.Big5 - LC_MESSAGES - .. - .. - .. - misc - .. - nls - C - .. - af_ZA.ISO8859-1 - .. - af_ZA.ISO8859-15 - .. - af_ZA.UTF-8 - .. - am_ET.UTF-8 - .. - be_BY.CP1131 - .. - be_BY.CP1251 - .. - be_BY.ISO8859-5 - .. - be_BY.UTF-8 - .. - bg_BG.CP1251 - .. - bg_BG.UTF-8 - .. - ca_AD.ISO8859-1 - .. - ca_ES.ISO8859-1 - .. - ca_FR.ISO8859-1 - .. - ca_IT.ISO8859-1 - .. - ca_AD.ISO8859-15 - .. - ca_ES.ISO8859-15 - .. - ca_FR.ISO8859-15 - .. - ca_IT.ISO8859-15 - .. - ca_AD.UTF-8 - .. - ca_ES.UTF-8 - .. - ca_FR.UTF-8 - .. - ca_IT.UTF-8 - .. - cs_CZ.ISO8859-2 - .. - cs_CZ.UTF-8 - .. - da_DK.ISO8859-1 - .. - da_DK.ISO8859-15 - .. - da_DK.UTF-8 - .. - de_AT.ISO8859-1 - .. - de_AT.ISO8859-15 - .. - de_AT.UTF-8 - .. - de_CH.ISO8859-1 - .. - de_CH.ISO8859-15 - .. - de_CH.UTF-8 - .. - de_DE.ISO8859-1 - .. - de_DE.ISO8859-15 - .. - de_DE.UTF-8 - .. - el_GR.ISO8859-7 - .. - el_GR.UTF-8 - .. - en_AU.ISO8859-1 - .. - en_AU.ISO8859-15 - .. - en_AU.US-ASCII - .. - en_AU.UTF-8 - .. - en_CA.ISO8859-1 - .. - en_CA.ISO8859-15 - .. - en_CA.US-ASCII - .. - en_CA.UTF-8 - .. - en_GB.ISO8859-1 - .. - en_GB.ISO8859-15 - .. - en_GB.US-ASCII - .. - en_GB.UTF-8 - .. - en_IE.UTF-8 - .. - en_NZ.ISO8859-1 - .. - en_NZ.ISO8859-15 - .. - en_NZ.US-ASCII - .. - en_NZ.UTF-8 - .. - en_US.ISO8859-1 - .. - en_US.ISO8859-15 - .. - en_US.UTF-8 - .. - es_ES.ISO8859-1 - .. - es_ES.ISO8859-15 - .. - es_ES.UTF-8 - .. - et_EE.ISO8859-15 - .. - et_EE.UTF-8 - .. - fi_FI.ISO8859-1 - .. - fi_FI.ISO8859-15 - .. - fi_FI.UTF-8 - .. - fr_BE.ISO8859-1 - .. - fr_BE.ISO8859-15 - .. - fr_BE.UTF-8 - .. - fr_CA.ISO8859-1 - .. - fr_CA.ISO8859-15 - .. - fr_CA.UTF-8 - .. - fr_CH.ISO8859-1 - .. - fr_CH.ISO8859-15 - .. - fr_CH.UTF-8 - .. - fr_FR.ISO8859-1 - .. - fr_FR.ISO8859-15 - .. - fr_FR.UTF-8 - .. - he_IL.UTF-8 - .. - hi_IN.ISCII-DEV - .. - hr_HR.ISO8859-2 - .. - hr_HR.UTF-8 - .. - hu_HU.ISO8859-2 - .. - hu_HU.UTF-8 - .. - hy_AM.ARMSCII-8 - .. - hy_AM.UTF-8 - .. - is_IS.ISO8859-1 - .. - is_IS.ISO8859-15 - .. - is_IS.UTF-8 - .. - it_CH.ISO8859-1 - .. - it_CH.ISO8859-15 - .. - it_CH.UTF-8 - .. - it_IT.ISO8859-1 - .. - it_IT.ISO8859-15 - .. - it_IT.UTF-8 - .. - ja_JP.SJIS - .. - ja_JP.UTF-8 - .. - ja_JP.eucJP - .. - kk_KZ.PT154 - .. - kk_KZ.UTF-8 - .. - ko_KR.CP949 - .. - ko_KR.UTF-8 - .. - ko_KR.eucKR - .. - la_LN.ISO8859-1 - .. - la_LN.ISO8859-15 - .. - la_LN.ISO8859-2 - .. - la_LN.ISO8859-4 - .. - la_LN.US-ASCII - .. - lt_LT.ISO8859-13 - .. - lt_LT.ISO8859-4 - .. - lt_LT.UTF-8 - .. - nl_BE.ISO8859-1 - .. - nl_BE.ISO8859-15 - .. - nl_BE.UTF-8 - .. - nl_NL.ISO8859-1 - .. - nl_NL.ISO8859-15 - .. - nl_NL.UTF-8 - .. - no_NO.ISO8859-1 - .. - no_NO.ISO8859-15 - .. - no_NO.UTF-8 - .. - pl_PL.ISO8859-2 - .. - pl_PL.UTF-8 - .. - pt_BR.ISO8859-1 - .. - pt_BR.UTF-8 - .. - pt_PT.ISO8859-1 - .. - pt_PT.ISO8859-15 - .. - pt_PT.UTF-8 - .. - ro_RO.ISO8859-2 - .. - ro_RO.UTF-8 - .. - ru_RU.CP1251 - .. - ru_RU.CP866 - .. - ru_RU.ISO8859-5 - .. - ru_RU.KOI8-R - .. - ru_RU.UTF-8 - .. - sk_SK.ISO8859-2 - .. - sk_SK.UTF-8 - .. - sl_SI.ISO8859-2 - .. - sl_SI.UTF-8 - .. - sr_YU.ISO8859-2 - .. - sr_YU.ISO8859-5 - .. - sr_YU.UTF-8 - .. - sv_SE.ISO8859-1 - .. - sv_SE.ISO8859-15 - .. - sv_SE.UTF-8 - .. - tr_TR.ISO8859-9 - .. - tr_TR.UTF-8 - .. - uk_UA.ISO8859-5 - .. - uk_UA.KOI8-U - .. - uk_UA.UTF-8 - .. - zh_CN.GB18030 - .. - zh_CN.GB2312 - .. - zh_CN.GBK - .. - zh_CN.UTF-8 - .. - zh_CN.eucCN - .. - zh_HK.Big5HKSCS - .. - zh_HK.UTF-8 - .. - zh_TW.Big5 - .. - zh_TW.UTF-8 - .. - .. - sgml - .. - skel - .. - xml - .. - .. - www - .. -.. diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index 054ba9ceb22..d4d60534e8a 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -553,6 +553,8 @@ .. la_LN.ISO8859-1 .. + la_LN.ISO8859-13 + .. la_LN.ISO8859-15 .. la_LN.ISO8859-2 @@ -567,6 +569,10 @@ .. lt_LT.UTF-8 .. + lv_LV.ISO8859-13 + .. + lv_LV.UTF-8 + .. mn_MN.UTF-8 .. nb_NO.ISO8859-1 @@ -1077,6 +1083,8 @@ .. la_LN.ISO8859-1 .. + la_LN.ISO8859-13 + .. la_LN.ISO8859-15 .. la_LN.ISO8859-2 @@ -1091,6 +1099,10 @@ .. lt_LT.UTF-8 .. + lv_LV.ISO8859-13 + .. + lv_LV.UTF-8 + .. mn_MN.UTF-8 .. nl_BE.ISO8859-1 diff --git a/etc/mtree/BSD.x11-4.dist b/etc/mtree/BSD.x11-4.dist deleted file mode 100644 index c3a233c39a7..00000000000 --- a/etc/mtree/BSD.x11-4.dist +++ /dev/null @@ -1,488 +0,0 @@ -# $FreeBSD$ -# -# Please see the file src/etc/mtree/README before making changes to this file. -# - -/set type=dir uname=root gname=wheel mode=0755 -. - bin - .. - etc - rc.d - .. - .. - include - X11 - .. - .. - info - .. - lib - X11 - app-defaults - .. - fonts - local - .. - .. - .. - .. - libdata - ldconfig - .. - ldconfig32 - .. - pkgconfig - .. - .. - libexec - .. - man -/set uname=man - cat1 - .. - cat2 - .. - cat3 - .. - cat4 - .. - cat5 - .. - cat6 - .. - cat7 - .. - cat8 - .. - cat9 - .. - catl - .. - catn - .. - ja uname=root - cat1 - .. - cat2 - .. - cat3 - .. - cat4 - .. - cat5 - .. - cat6 - .. - cat7 - .. - cat8 - .. - cat9 - .. - catl - .. - catn - .. -/set uname=root - man1 - .. - man2 - .. - man3 - .. - man4 - .. - man5 - .. - man6 - .. - man7 - .. - man8 - .. - man9 - .. - manl - .. - mann - .. - .. - man1 - .. - man2 - .. - man3 - .. - man4 - .. - man5 - .. - man6 - .. - man7 - .. - man8 - .. - man9 - .. - manl - .. - mann - .. - .. - share - aclocal - .. - doc - ja - .. - .. - examples - .. - locale - af - LC_MESSAGES - .. - .. - am - LC_MESSAGES - .. - .. - ar - LC_MESSAGES - .. - .. - az - LC_MESSAGES - .. - .. - be - LC_MESSAGES - .. - .. - bg - LC_MESSAGES - .. - .. - bn - LC_MESSAGES - .. - .. - bs - LC_MESSAGES - .. - .. - ca - LC_MESSAGES - .. - .. - cs - LC_MESSAGES - .. - .. - cy - LC_MESSAGES - .. - .. - da - LC_MESSAGES - .. - .. - de - LC_MESSAGES - .. - .. - de_AT - LC_MESSAGES - .. - .. - el - LC_MESSAGES - .. - .. - en - LC_MESSAGES - .. - .. - en_AU - LC_MESSAGES - .. - .. - en_CA - LC_MESSAGES - .. - .. - en_GB - LC_MESSAGES - .. - .. - eo - LC_MESSAGES - .. - .. - es - LC_MESSAGES - .. - .. - es_ES - LC_MESSAGES - .. - .. - es_MX - LC_MESSAGES - .. - .. - et - LC_MESSAGES - .. - .. - eu - LC_MESSAGES - .. - .. - fa - LC_MESSAGES - .. - .. - fa_IR - LC_MESSAGES - .. - .. - fi - LC_MESSAGES - .. - .. - fr - LC_MESSAGES - .. - .. - fr_FR - LC_MESSAGES - .. - .. - ga - LC_MESSAGES - .. - .. - gl - LC_MESSAGES - .. - .. - gu - LC_MESSAGES - .. - .. - he - LC_MESSAGES - .. - .. - hi - LC_MESSAGES - .. - .. - hr - LC_MESSAGES - .. - .. - hu - LC_MESSAGES - .. - .. - id - LC_MESSAGES - .. - .. - is - LC_MESSAGES - .. - .. - it - LC_MESSAGES - .. - .. - ja - LC_MESSAGES - .. - .. - ka - LC_MESSAGES - .. - .. - kn - LC_MESSAGES - .. - .. - ko - LC_MESSAGES - .. - .. - li - LC_MESSAGES - .. - .. - lt - LC_MESSAGES - .. - .. - lv - LC_MESSAGES - .. - .. - mk - LC_MESSAGES - .. - .. - ml - LC_MESSAGES - .. - .. - mn - LC_MESSAGES - .. - .. - ms - LC_MESSAGES - .. - .. - mt - LC_MESSAGES - .. - .. - nb - LC_MESSAGES - .. - .. - ne - LC_MESSAGES - .. - .. - nl - LC_MESSAGES - .. - .. - nn - LC_MESSAGES - .. - .. - no - LC_MESSAGES - .. - .. - or - LC_MESSAGES - .. - .. - pa - LC_MESSAGES - .. - .. - pl - LC_MESSAGES - .. - .. - pt - LC_MESSAGES - .. - .. - pt_BR - LC_MESSAGES - .. - .. - pt_PT - LC_MESSAGES - .. - .. - ro - LC_MESSAGES - .. - .. - ru - LC_MESSAGES - .. - .. - sk - LC_MESSAGES - .. - .. - sl - LC_MESSAGES - .. - .. - sq - LC_MESSAGES - .. - .. - sr - LC_MESSAGES - .. - .. - sr@Latn - LC_MESSAGES - .. - .. - sv - LC_MESSAGES - .. - .. - ta - LC_MESSAGES - .. - .. - tg - LC_MESSAGES - .. - .. - th - LC_MESSAGES - .. - .. - tk - LC_MESSAGES - .. - .. - tr - LC_MESSAGES - .. - .. - uk - LC_MESSAGES - .. - .. - uz - LC_MESSAGES - .. - .. - vi - LC_MESSAGES - .. - .. - wa - LC_MESSAGES - .. - .. - zh - LC_MESSAGES - .. - .. - zh_CN - LC_MESSAGES - .. - .. - zh_CN.GB2312 - LC_MESSAGES - .. - .. - zh_TW - LC_MESSAGES - .. - .. - zh_TW.Big5 - LC_MESSAGES - .. - .. - .. - pixmaps - .. - .. -.. diff --git a/etc/mtree/BSD.x11.dist b/etc/mtree/BSD.x11.dist deleted file mode 100644 index 122cdd5d60e..00000000000 --- a/etc/mtree/BSD.x11.dist +++ /dev/null @@ -1,306 +0,0 @@ -# $FreeBSD$ -# -# Please see the file src/etc/mtree/README before making changes to this file. -# - -/set type=dir uname=root gname=wheel mode=0755 -. - bin - .. - etc - rc.d - .. - .. - include - X11 - ICE - .. - PEX5 - .. - PM - .. - SM - .. - Xaw - .. - Xmu - .. - bitmaps - .. - extensions - .. - fonts - .. - pixmaps - .. - .. - .. - info - .. - lib - X11 - XF86Setup - pics - .. - scripts - .. - tcllib - .. - .. - app-defaults - .. - config - .. - doc - .. - etc - .. - fonts - 100dpi - .. - 75dpi - .. - PEX - .. - Speedo - .. - Type1 - .. - cyrillic - .. - local - .. - misc - .. - .. - fs - .. - lbxproxy - .. - locale - C - .. - en_US.utf - .. - iso8859-1 - .. - iso8859-2 - .. - iso8859-3 - .. - iso8859-4 - .. - iso8859-5 - .. - iso8859-6 - .. - iso8859-7 - .. - iso8859-8 - .. - iso8859-9 - .. - ja - .. - ja.JIS - .. - ja.SJIS - .. - ko - .. - koi8-r - .. - tbl_data - .. - th_TH.TACTIS - .. - zh - .. - zh_TW - .. - zh_TW.Big5 - .. - .. - proxymngr - .. - rstart - commands - x11r6 - .. - .. - contexts - .. - .. - twm - .. - x11perfcomp - .. - xdm - .. - xinit - .. - xkb - compat - .. - compiled - .. - geometry - digital - .. - sgi - .. - .. - keycodes - digital - .. - sgi - .. - .. - keymap - digital - .. - sgi - .. - sun - .. - .. - rules - .. - semantics - .. - symbols - digital - .. - fujitsu - .. - nec - .. - sony - .. - sun - .. - .. - .. - xserver - .. - xsm - .. - .. - aout - .. - modules - .. - .. - libdata - ldconfig - .. - ldconfig32 - .. - .. - libexec - .. - man -/set uname=man - cat1 - .. - cat2 - .. - cat3 - .. - cat4 - .. - cat5 - .. - cat6 - .. - cat7 - .. - cat8 - .. - cat9 - .. - catl - .. - catn - .. - ja uname=root - cat1 - .. - cat2 - .. - cat3 - .. - cat4 - .. - cat5 - .. - cat6 - .. - cat7 - .. - cat8 - .. - cat9 - .. - catl - .. - catn - .. -/set uname=root - man1 - .. - man2 - .. - man3 - .. - man4 - .. - man5 - .. - man6 - .. - man7 - .. - man8 - .. - man9 - .. - manl - .. - mann - .. - .. - man1 - .. - man2 - .. - man3 - .. - man4 - .. - man5 - .. - man6 - .. - man7 - .. - man8 - .. - man9 - .. - manl - .. - mann - .. - .. - share - aclocal - .. - doc - ja - .. - .. - examples - .. - .. -.. diff --git a/etc/mtree/Makefile b/etc/mtree/Makefile index de69da92fc5..3090ffb2adf 100644 --- a/etc/mtree/Makefile +++ b/etc/mtree/Makefile @@ -5,12 +5,10 @@ FILES= ${_BIND.chroot.dist} \ ${_BIND.include.dist} \ BSD.include.dist \ - BSD.local.dist \ BSD.root.dist \ + ${_BSD.sendmail.dist} \ BSD.usr.dist \ - BSD.var.dist \ - BSD.x11-4.dist \ - BSD.x11.dist + BSD.var.dist .if ${MK_BIND} != "no" _BIND.chroot.dist= BIND.chroot.dist @@ -18,6 +16,9 @@ _BIND.chroot.dist= BIND.chroot.dist _BIND.include.dist= BIND.include.dist .endif .endif +.if ${MK_SENDMAIL} != "no" +_BSD.sendmail.dist= BSD.sendmail.dist +.endif NO_OBJ= FILESDIR= /etc/mtree diff --git a/etc/network.subr b/etc/network.subr index 22bfc7dc8b9..e794faba2d7 100644 --- a/etc/network.subr +++ b/etc/network.subr @@ -727,6 +727,13 @@ list_net_interfaces() ;; *) _tmplist="${network_interfaces} ${cloned_interfaces}" + + # lo0 is effectively mandatory, so help prevent foot-shooting + # + case "$_tmplist" in + lo0|'lo0 '*|*' lo0'|*' lo0 '*) ;; # This is fine, do nothing + *) _tmplist="lo0 ${_tmplist}" ;; + esac ;; esac @@ -816,6 +823,17 @@ hexprint() echo ${str} } +is_wired_interface() +{ + local media + + case `ifconfig $1 2>/dev/null` in + *media:?Ethernet*) media=Ethernet ;; + esac + + test "$media" = "Ethernet" +} + # Setup the interfaces for IPv6 network6_interface_setup() { @@ -858,14 +876,19 @@ network6_interface_setup() ifconfig $i inet6 ${ipv6_ifconfig} alias fi + # Wireless NIC cards are virtualized through the wlan interface + if ! is_wired_interface ${i}; then + case "${i}" in + wlan*) rtsol_interface=yes ;; + *) rtsol_interface=no ;; + esac + fi + if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ] then case ${i} in lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*|pflog[0-9]*|pfsync[0-9]*) ;; - # Wireless NIC cards are virtualized through the wlan interface - an[0-9]*|ath[0-9]*|ipw[0-9]*|iwi[0-9]*|iwn[0-9]*|ral[0-9]*|wi[0-9]*|wl[0-9]*|wpi[0-9]*) - ;; *) rtsol_interfaces="${rtsol_interfaces} ${i}" ;; diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 24ae3ae5ec2..110f3d783a2 100755 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -32,7 +32,7 @@ FILES= DAEMON FILESYSTEMS LOGIN NETWORKING SERVERS \ random rarpd resolv rfcomm_pppd_server root \ route6d routed routing rpcbind rtadvd rwho \ savecore sdpd securelevel sendmail \ - serial sppp statd swap1 \ + serial sppp statd static_arp swap1 \ syscons sysctl syslogd \ timed tmp \ ugidfw \ diff --git a/etc/rc.d/ipsec b/etc/rc.d/ipsec index 2bb3cf5d63c..0ad54908a14 100755 --- a/etc/rc.d/ipsec +++ b/etc/rc.d/ipsec @@ -41,9 +41,9 @@ ipsec_stop() { echo "Clearing ipsec manual keys/policies." - # still not 100% sure if we would like to do this. - # it is very questionable to do this during shutdown session, since - # it can hang any of remaining IPv4/v6 session. + # Still not 100% sure if we would like to do this. + # It is very questionable to do this during shutdown session + # since it can hang any of the remaining IPv4/v6 sessions. # ${ipsec_program} -F ${ipsec_program} -FP diff --git a/etc/rc.d/wpa_supplicant b/etc/rc.d/wpa_supplicant index 192ca966aa9..8514efcbbc1 100755 --- a/etc/rc.d/wpa_supplicant +++ b/etc/rc.d/wpa_supplicant @@ -18,18 +18,6 @@ if [ -z "$ifn" ]; then return 1 fi -is_wired_interface() -{ - media=`ifconfig $1 2>/dev/null | while read line; do - case "$line" in - *media:?Ethernet*) - echo Ethernet - ;; - esac - done` - test "$media" = "Ethernet" -} - is_ndis_interface() { case `sysctl -n net.wlan.${1#wlan}.%parent 2>/dev/null` in diff --git a/gnu/usr.bin/groff/tmac/mdoc.local b/gnu/usr.bin/groff/tmac/mdoc.local index a963b7e7770..daf54b85a57 100644 --- a/gnu/usr.bin/groff/tmac/mdoc.local +++ b/gnu/usr.bin/groff/tmac/mdoc.local @@ -66,13 +66,14 @@ .ds doc-volume-as-arm arm . .\" Default .Os value -.ds doc-default-operating-system FreeBSD\~8.0 +.ds doc-default-operating-system FreeBSD\~9.0 . .\" FreeBSD releases not found in doc-common .ds doc-operating-system-FreeBSD-6.3 6.3 .ds doc-operating-system-FreeBSD-6.4 6.4 .ds doc-operating-system-FreeBSD-7.1 7.1 .ds doc-operating-system-FreeBSD-8.0 8.0 +.ds doc-operating-system-FreeBSD-9.0 9.0 . .\" Definitions not (yet) in doc-syms .ds doc-str-St--p1003.1-2008 \*[doc-Tn-font-size]\%IEEE\*[doc-str-St] Std 1003.1-2008 diff --git a/gnu/usr.bin/patch/pch.c b/gnu/usr.bin/patch/pch.c index 1638241151a..d72f84f3069 100644 --- a/gnu/usr.bin/patch/pch.c +++ b/gnu/usr.bin/patch/pch.c @@ -211,6 +211,25 @@ there_is_another_patch(void) return TRUE; } +static char * +p4_savestr(char *str) +{ + char *t, *h; + + /* Leading whitespace. */ + while (isspace((unsigned char)*str)) + str++; + + /* Remove the file revision number. */ + for (t = str, h = NULL; *t != '\0' && !isspace((unsigned char)*t); t++) + if (*t == '#') + h = t; + if (h != NULL) + *h = '\0'; + + return savestr(str); +} + /* * Determine what kind of diff is in the remaining part of the patch file. */ @@ -298,6 +317,11 @@ intuit_diff_type(void) free(revision); revision = Nullch; } + } else if (strnEQ(s, "==== ", 5)) { + /* Perforce-style diffs. */ + if ((t = strstr(s + 5, " - ")) != NULL) + newtmp = p4_savestr(t + 3); + oldtmp = p4_savestr(s + 5); } if ((!diff_type || diff_type == ED_DIFF) && first_command_line >= 0L && diff --git a/include/Makefile b/include/Makefile index 72d7e728593..08ef6a5c768 100644 --- a/include/Makefile +++ b/include/Makefile @@ -40,7 +40,7 @@ LDIRS= bsm cam geom net net80211 netatalk netgraph netinet netinet6 \ LSUBDIRS= cam/ata cam/scsi \ dev/acpica dev/an dev/bktr dev/firewire dev/hwpmc \ - dev/ic dev/iicbus ${_dev_ieee488} dev/lmc dev/ofw \ + dev/ic dev/iicbus ${_dev_ieee488} dev/lmc dev/mfi dev/ofw \ dev/pbio ${_dev_powermac_nvram} dev/ppbus dev/smbus \ dev/speaker dev/usb dev/utopia dev/vkbd dev/wi \ fs/devfs fs/fdescfs fs/fifofs fs/msdosfs fs/nfs fs/ntfs fs/nullfs \ diff --git a/lib/libarchive/archive_read.c b/lib/libarchive/archive_read.c index 9274d661cc4..fd4f888867b 100644 --- a/lib/libarchive/archive_read.c +++ b/lib/libarchive/archive_read.c @@ -928,9 +928,12 @@ __archive_read_filter_ahead(struct archive_read_filter *filter, for (;;) { /* - * If we can satisfy from the copy buffer, we're done. + * If we can satisfy from the copy buffer (and the + * copy buffer isn't empty), we're done. In particular, + * note that min == 0 is a perfectly well-defined + * request. */ - if (filter->avail >= min) { + if (filter->avail >= min && filter->avail > 0) { if (avail != NULL) *avail = filter->avail; return (filter->next); diff --git a/lib/libarchive/archive_read_support_format_iso9660.c b/lib/libarchive/archive_read_support_format_iso9660.c index eaa0f897c7b..efc39b46e47 100644 --- a/lib/libarchive/archive_read_support_format_iso9660.c +++ b/lib/libarchive/archive_read_support_format_iso9660.c @@ -571,9 +571,13 @@ archive_read_format_iso9660_read_header(struct archive_read *a, if (file->symlink.s != NULL) archive_entry_copy_symlink(entry, file->symlink.s); - /* If this entry points to the same data as the previous - * entry, convert this into a hardlink to that entry. - * But don't bother for zero-length files. */ + /* Note: If the input isn't seekable, we can't rewind to + * return the same body again, so if the next entry refers to + * the same data, we have to return it as a hardlink to the + * original entry. */ + /* TODO: We have enough information here to compute an + * accurate value for nlinks. We should do so and ignore + * nlinks from the RR extensions. */ if (file->offset == iso9660->previous_offset && file->size == iso9660->previous_size && file->size > 0) { @@ -586,8 +590,21 @@ archive_read_format_iso9660_read_header(struct archive_read *a, return (ARCHIVE_OK); } - /* If the offset is before our current position, we can't - * seek backwards to extract it, so issue a warning. */ + /* Except for the hardlink case above, if the offset of the + * next entry is before our current position, we can't seek + * backwards to extract it, so issue a warning. Note that + * this can only happen if this entry was added to the heap + * after we passed this offset, that is, only if the directory + * mentioning this entry is later than the body of the entry. + * Such layouts are very unusual; most ISO9660 writers lay out + * and record all directory information first, then store + * all file bodies. */ + /* TODO: Someday, libarchive's I/O core will support optional + * seeking. When that day comes, this code should attempt to + * seek and only return the error if the seek fails. That + * will give us support for whacky ISO images that require + * seeking while retaining the ability to read almost all ISO + * images in a streaming fashion. */ if (file->offset < iso9660->current_position) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Ignoring out-of-order file @%x (%s) %jd < %jd", @@ -628,7 +645,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a, struct file_info *child; /* N.B.: these special directory identifiers - * are 8 bit "values" even on a + * are 8 bit "values" even on a * Joliet CD with UCS-2 (16bit) encoding. */ diff --git a/lib/libarchive/test/test_compat_zip.c b/lib/libarchive/test/test_compat_zip.c index f60bc4f817a..fefc6fefabd 100644 --- a/lib/libarchive/test/test_compat_zip.c +++ b/lib/libarchive/test/test_compat_zip.c @@ -36,7 +36,7 @@ test_compat_zip_1(void) assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); extract_reference_file(name); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); diff --git a/lib/libarchive/test/test_read_format_isojoliet_bz2.c b/lib/libarchive/test/test_read_format_isojoliet_bz2.c index 7b11bbbfcee..9ee87c91cba 100644 --- a/lib/libarchive/test/test_read_format_isojoliet_bz2.c +++ b/lib/libarchive/test/test_read_format_isojoliet_bz2.c @@ -107,14 +107,12 @@ joliettest(int withrr) assertEqualInt(2, archive_entry_gid(ae)); } - /* A hardlink to the regular file. */ + /* A regular file with two names ("hardlink" gets returned + * first, so it's not marked as a hardlink). */ assertEqualInt(0, archive_read_next_header(a, &ae)); assertEqualString("hardlink", archive_entry_pathname(ae)); assert(S_ISREG(archive_entry_stat(ae)->st_mode)); - if (withrr) { - assertEqualString("long-joliet-file-name.textfile", - archive_entry_hardlink(ae)); - } + assert(archive_entry_hardlink(ae) == NULL); assertEqualInt(6, archive_entry_size(ae)); assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset)); assertEqualInt(6, (int)size); @@ -123,20 +121,27 @@ joliettest(int withrr) if (withrr) { assertEqualInt(86401, archive_entry_mtime(ae)); assertEqualInt(86401, archive_entry_atime(ae)); - assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + /* TODO: Actually, libarchive should be able to + * compute nlinks correctly even without RR + * extensions. See comments in libarchive source. */ + assertEqualInt(2, archive_entry_nlink(ae)); assertEqualInt(1, archive_entry_uid(ae)); assertEqualInt(2, archive_entry_gid(ae)); } - /* A regular file. */ + /* Second name for the same regular file (this happens to be + * returned second, so does get marked as a hardlink). */ assertEqualInt(0, archive_read_next_header(a, &ae)); - assertEqualString("long-joliet-file-name.textfile", archive_entry_pathname(ae)); + assertEqualString("long-joliet-file-name.textfile", + archive_entry_pathname(ae)); assert(S_ISREG(archive_entry_stat(ae)->st_mode)); - assertEqualInt(6, archive_entry_size(ae)); + assertEqualString("hardlink", archive_entry_hardlink(ae)); + assert(!archive_entry_size_is_set(ae)); if (withrr) { assertEqualInt(86401, archive_entry_mtime(ae)); assertEqualInt(86401, archive_entry_atime(ae)); - assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + /* TODO: See above. */ + assertEqualInt(2, archive_entry_nlink(ae)); assertEqualInt(1, archive_entry_uid(ae)); assertEqualInt(2, archive_entry_gid(ae)); } @@ -153,7 +158,7 @@ joliettest(int withrr) assertEqualInt(172802, archive_entry_mtime(ae)); assertEqualInt(172802, archive_entry_atime(ae)); if (withrr) { - assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_nlink(ae)); assertEqualInt(1, archive_entry_uid(ae)); assertEqualInt(2, archive_entry_gid(ae)); } diff --git a/lib/libarchive/test/test_read_format_isorr_bz2.c b/lib/libarchive/test/test_read_format_isorr_bz2.c index cd53c7c7aa1..250019f8156 100644 --- a/lib/libarchive/test/test_read_format_isorr_bz2.c +++ b/lib/libarchive/test/test_read_format_isorr_bz2.c @@ -111,7 +111,7 @@ DEFINE_TEST(test_read_format_isorr_bz2) assertEqualString("hardlink", archive_entry_pathname(ae)); assert(S_ISREG(archive_entry_stat(ae)->st_mode)); assertEqualString("file", archive_entry_hardlink(ae)); - assertEqualInt(12345684, archive_entry_size(ae)); + assert(!archive_entry_size_is_set(ae)); assertEqualInt(86401, archive_entry_mtime(ae)); assertEqualInt(86401, archive_entry_atime(ae)); assertEqualInt(2, archive_entry_stat(ae)->st_nlink); diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c index b58b36f1fc3..83d26577740 100644 --- a/lib/libc/db/hash/hash.c +++ b/lib/libc/db/hash/hash.c @@ -711,7 +711,7 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag) hashp->cndx = 1; hashp->cpage = NULL; } - next_bucket: +next_bucket: for (bp = NULL; !bp || !bp[0]; ) { if (!(bufp = hashp->cpage)) { for (bucket = hashp->cbucket; @@ -732,7 +732,7 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag) } } else { bp = (u_int16_t *)hashp->cpage->page; - if (flag == R_NEXT) { + if (flag == R_NEXT || flag == 0) { hashp->cndx += 2; if (hashp->cndx > bp[0]) { hashp->cpage = NULL; diff --git a/lib/libc/net/getifaddrs.c b/lib/libc/net/getifaddrs.c index 41ef3f464ab..acca5de96a0 100644 --- a/lib/libc/net/getifaddrs.c +++ b/lib/libc/net/getifaddrs.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" +#include #include #include #include diff --git a/lib/libc/posix1e/Makefile.inc b/lib/libc/posix1e/Makefile.inc index de0302bfb52..c9e78bda89d 100644 --- a/lib/libc/posix1e/Makefile.inc +++ b/lib/libc/posix1e/Makefile.inc @@ -106,14 +106,16 @@ MLINKS+=acl_create_entry.3 acl_create_entry_np.3\ mac_get.3 mac_get_fd.3 \ mac_get.3 mac_get_file.3 \ mac_get.3 mac_get_link.3 \ + mac_get.3 mac_get_peer.3 \ mac_get.3 mac_get_pid.3 \ mac_get.3 mac_get_proc.3 \ mac_prepare.3 mac_prepare_file_label.3 \ mac_prepare.3 mac_prepare_ifnet_label.3 \ mac_prepare.3 mac_prepare_process_label.3 \ - mac_set.3 mac_set_link.3 \ + mac_prepare.3 mac_prepare_type.3 \ mac_set.3 mac_set_fd.3 \ mac_set.3 mac_set_file.3 \ + mac_set.3 mac_set_link.3 \ mac_set.3 mac_set_proc.3 \ mac_text.3 mac_from_text.3 \ mac_text.3 mac_to_text.3 diff --git a/lib/libc/posix1e/acl_calc_mask.c b/lib/libc/posix1e/acl_calc_mask.c index 95fd26055fa..a2d15276bf3 100644 --- a/lib/libc/posix1e/acl_calc_mask.c +++ b/lib/libc/posix1e/acl_calc_mask.c @@ -50,12 +50,6 @@ acl_calc_mask(acl_t *acl_p) acl_t acl_new; int i, mask_mode, mask_num; - if (!_acl_brand_may_be(*acl_p, ACL_BRAND_POSIX)) { - errno = EINVAL; - return (-1); - } - _acl_brand_as(*acl_p, ACL_BRAND_POSIX); - /* * (23.4.2.4) requires acl_p to point to a pointer to a valid ACL. * Since one of the primary reasons to use this function would be @@ -67,6 +61,13 @@ acl_calc_mask(acl_t *acl_p) errno = EINVAL; return (-1); } + + if (!_acl_brand_may_be(*acl_p, ACL_BRAND_POSIX)) { + errno = EINVAL; + return (-1); + } + _acl_brand_as(*acl_p, ACL_BRAND_POSIX); + acl_int = &(*acl_p)->ats_acl; if ((acl_int->acl_cnt < 3) || (acl_int->acl_cnt > ACL_MAX_ENTRIES)) { errno = EINVAL; diff --git a/lib/libc/posix1e/acl_support.c b/lib/libc/posix1e/acl_support.c index 1907286e315..680debc000c 100644 --- a/lib/libc/posix1e/acl_support.c +++ b/lib/libc/posix1e/acl_support.c @@ -80,7 +80,7 @@ _acl_differs(const acl_t a, const acl_t b) return (0); } - + /* * _posix1e_acl_entry_compare -- compare two acl_entry structures to * determine the order they should appear in. Used by _posix1e_acl_sort to @@ -164,7 +164,7 @@ _posix1e_acl(acl_t acl, acl_type_t type) * from code in sys/kern/kern_acl.c, and if changes are made in one, they * should be made in the other also. This copy of acl_check is made * available * in userland for the benefit of processes wanting to check ACLs - * for validity before submitting them to the kernel, or for performing + * for validity before submitting them to the kernel, or for performing * in userland file system checking. Needless to say, the kernel makes * the real checks on calls to get/setacl. * @@ -203,7 +203,7 @@ _posix1e_acl_check(acl_t acl) stage = ACL_USER; count_user_obj++; break; - + case ACL_USER: /* printf("_posix1e_acl_check: %d: ACL_USER\n", i); */ if (stage > ACL_USER) @@ -213,8 +213,8 @@ _posix1e_acl_check(acl_t acl) return (EINVAL); highest_uid = entry->ae_id; count_user++; - break; - + break; + case ACL_GROUP_OBJ: /* printf("_posix1e_acl_check: %d: ACL_GROUP_OBJ\n", i); */ @@ -223,7 +223,7 @@ _posix1e_acl_check(acl_t acl) stage = ACL_GROUP; count_group_obj++; break; - + case ACL_GROUP: /* printf("_posix1e_acl_check: %d: ACL_GROUP\n", i); */ if (stage > ACL_GROUP) @@ -234,7 +234,7 @@ _posix1e_acl_check(acl_t acl) highest_gid = entry->ae_id; count_group++; break; - + case ACL_MASK: /* printf("_posix1e_acl_check: %d: ACL_MASK\n", i); */ if (stage > ACL_MASK) @@ -242,7 +242,7 @@ _posix1e_acl_check(acl_t acl) stage = ACL_MASK; count_mask++; break; - + case ACL_OTHER: /* printf("_posix1e_acl_check: %d: ACL_OTHER\n", i); */ if (stage > ACL_OTHER) @@ -250,7 +250,7 @@ _posix1e_acl_check(acl_t acl) stage = ACL_OTHER; count_other++; break; - + default: /* printf("_posix1e_acl_check: %d: INVALID\n", i); */ return (EINVAL); @@ -260,7 +260,7 @@ _posix1e_acl_check(acl_t acl) if (count_user_obj != 1) return (EINVAL); - + if (count_group_obj != 1) return (EINVAL); @@ -312,7 +312,7 @@ _posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, char *buf, g = NULL; else g = getgrgid(id); - if (g == NULL) + if (g == NULL) i = snprintf(buf, buf_len, "%d", id); else i = snprintf(buf, buf_len, "%s", g->gr_name); diff --git a/lib/libc/posix1e/acl_to_text.c b/lib/libc/posix1e/acl_to_text.c index 3485b1e7777..79a950a543c 100644 --- a/lib/libc/posix1e/acl_to_text.c +++ b/lib/libc/posix1e/acl_to_text.c @@ -70,11 +70,6 @@ _posix1e_acl_to_text(acl_t acl, ssize_t *len_p, int flags) if (buf == NULL) return(NULL); - if (acl == NULL) { - errno = EINVAL; - return(NULL); - } - acl_int = &acl->ats_acl; mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */ @@ -243,6 +238,11 @@ char * acl_to_text_np(acl_t acl, ssize_t *len_p, int flags) { + if (acl == NULL) { + errno = EINVAL; + return(NULL); + } + switch (_acl_brand(acl)) { case ACL_BRAND_POSIX: return (_posix1e_acl_to_text(acl, len_p, flags)); diff --git a/lib/libc/posix1e/mac.3 b/lib/libc/posix1e/mac.3 index ac6affd52e5..c570998ba7a 100644 --- a/lib/libc/posix1e/mac.3 +++ b/lib/libc/posix1e/mac.3 @@ -1,4 +1,5 @@ .\" Copyright (c) 2001, 2003 Networks Associates Technology, Inc. +.\" Copyright (c) 2009 Robert N. M. Watson .\" All rights reserved. .\" .\" This software was developed for the FreeBSD Project by Chris @@ -30,7 +31,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 19, 2003 +.Dd August 7, 2009 .Dt MAC 3 .Os .Sh NAME @@ -44,81 +45,82 @@ In the kernel configuration file: .Cd "options MAC" .Sh DESCRIPTION -.Fx -permits administrators to define Mandatory Access Control labels -defining levels for the privacy and integrity of data, -overriding discretionary policies -for those objects. -Not all objects currently provide support for MAC labels, -and MAC support must be explicitly enabled by the administrator. -The library calls include routines to retrieve, duplicate, -and set MAC labels associated with files and processes. +Mandatory Access Control labels describe confidentiality, integrity, and +other security attributes of operating system objects, overriding +discretionary access control. +Not all system objects support MAC labeling, and MAC policies must be +explicitly enabled by the administrator. +This API, based on POSIX.1e, includes routines to retrieve, manipulate, set, +and convert to and from text the MAC labels on files and processes. .Pp -POSIX.1e describes a set of MAC manipulation routines -to manage the contents of MAC labels, -as well as their relationships with -files and processes; -almost all of these support routines -are implemented in -.Fx . +MAC labels consist of a set of (name, value) tuples, representing security +attributes from MAC policies. +For example, this label contains security labels defined by two policies, +.Xr mac_biba 4 +and +.Xr mac_mls 4 : +.Bd -literal -offset indent +biba/low,mls/low +.Ed .Pp -Available functions, sorted by behavior, include: -.Bl -tag -width indent -.It Fn mac_get_fd -This function is described in -.Xr mac_get 3 , -and may be used to retrieve the -MAC label associated with -a specific file descriptor. -.It Fn mac_get_file -This function is described in -.Xr mac_get 3 , -and may be used to retrieve the -MAC label associated with -a named file. -.It Fn mac_get_proc -This function is described in -.Xr mac_get 3 , -and may be used to retrieve the -MAC label associated with -the calling process. -.It Fn mac_set_fd -This function is described in -.Xr mac_set 3 , -and may be used to set the -MAC label associated with -a specific file descriptor. -.It Fn mac_set_file -This function is described in -.Xr mac_set 3 , -and may be used to set the -MAC label associated with -a named file. -.It Fn mac_set_proc -This function is described in -.Xr mac_set 3 , -and may be used to set the -MAC label associated with -the calling process. -.It Fn mac_free -This function is described in -.Xr mac_free 3 , -and may be used to free -userland working MAC label storage. -.It Fn mac_from_text -This function is described in -.Xr mac_text 3 , -and may be used to convert -a text-form MAC label -into a working -.Vt mac_t . -.It Fn mac_prepare -.It Fn mac_prepare_file_label -.It Fn mac_prepare_ifnet_label -.It Fn mac_prepare_process_label -These functions are described in +Further syntax and semantics of MAC labels may be found in +.Xr maclabel 7 . +.Pp +Applications operate on labels stored in +.Vt mac_t , +but can convert between this internal format and a text format for the +purposes of presentation to uses or external storage. +When querying a label on an object, a +.Vt mac_t +must first be prepared using the interfaces described in .Xr mac_prepare 3 , -and may be used to preallocate storage for MAC label retrieval. +allowing the application to declare which policies it wishes to interogate. +The application writer can also rely on default label names declared in +.Xr mac.conf 5 . +.Pp +When finished with a +.Vt mac_t , +the application must call +.Xr mac_free 3 +to release its storage. +.Pp +The following functions are defined: +.Bl -tag -width indent +.It Fn mac_is_present +This function, described in +.Xr mac_is_present 3 , +allows applications to test whether MAC is configured, as well as whether +specific policies are configured. +.It Fn mac_get_fd , Fn mac_get_file , Fn mac_get_link , Fn mac_get_peer +These functions, described in +.Xr mac_get 3 , +retrieve the MAC labels associated with file descriptors, files, and socket +peers. +.It Fn mac_get_pid , Fn mac_get_proc +These functions, described in +.Xr mac_get 3 , +retrieve the MAC labels associated with processes. +.It Fn mac_set_fd , Fn mac_set_file , Fn mac_set_link +These functions, described in +.Xr mac_set 3 , +set the MAC labels associated with file descriptors and files. +.It Fn mac_set_proc +This function, described in +.Xr mac_set 3 , +sets the MAC label associated with the current process. +.It Fn mac_free +This function, desribed in +.Xr mac_free 3 , +frees working MAC label storage. +.It Fn mac_from_text +This function, described in +.Xr mac_text 3 , +converts a text-form MAC label into working MAC label storage, +.Vt mac_t . +.It Fn mac_prepare , Fn mac_prepare_file_label , Fn mac_prepare_ifnet_label , Fn mac_prepare_process_label , Fn mac_prepare_type +These functions, described in +.Xr mac_prepare 3 , +allocate working storage for MAC label operations. .Xr mac_prepare 3 prepares a label based on caller-specified label names; the other calls rely on the default configuration specified in @@ -130,15 +132,6 @@ and may be used to convert a .Vt mac_t into a text-form MAC label. .El -The behavior of some of these calls is influenced by the configuration -settings found in -.Xr mac.conf 5 , -the MAC library run-time configuration file. -.Sh IMPLEMENTATION NOTES -.Fx Ns 's -support for POSIX.1e interfaces and features -is -.Ud . .Sh FILES .Bl -tag -width ".Pa /etc/mac.conf" -compact .It Pa /etc/mac.conf @@ -150,24 +143,20 @@ system objects, but without policy-specific knowledge. .Sh SEE ALSO .Xr mac_free 3 , .Xr mac_get 3 , +.Xr mac_is_present 3 , .Xr mac_prepare 3 , .Xr mac_set 3 , .Xr mac_text 3 , +.Xr posix1e 3 , .Xr mac 4 , .Xr mac.conf 5 , .Xr mac 9 .Sh STANDARDS -These APIs are loosely based on the APIs described in POSIX.1e. -POSIX.1e is described in IEEE POSIX.1e draft 17. -Discussion of the draft -continues on the cross-platform POSIX.1e implementation mailing list. -To join this list, see the -.Fx -POSIX.1e implementation page -for more information. -However, the resemblance of these APIs to the POSIX APIs is only loose, -as the POSIX APIs were unable to express many notions required for -flexible and extensible access control. +These APIs are loosely based on the APIs described in POSIX.1e, as described +in IEEE POSIX.1e draft 17. +However, the resemblence of these APIS to the POSIX APIs is loose, as the +PSOXI APIS were unable to express some notinos required for flexible and +extensible access control. .Sh HISTORY Support for Mandatory Access Control was introduced in .Fx 5.0 diff --git a/lib/libc/posix1e/mac_free.3 b/lib/libc/posix1e/mac_free.3 index 33ef9ec785a..78118a1efa5 100644 --- a/lib/libc/posix1e/mac_free.3 +++ b/lib/libc/posix1e/mac_free.3 @@ -64,6 +64,7 @@ function. .Xr mac_prepare 3 , .Xr mac_set 3 , .Xr mac_text 3 , +.Xr posix1e 3 , .Xr mac 4 , .Xr mac 9 .Sh STANDARDS @@ -91,8 +92,8 @@ is a complex structure in the .Tn TrustedBSD implementation, .Fn mac_free -is specific to that type, and must not be used to free the character -strings returned from +is specific to +.Vt mac_3 , +and must not be used to free the character strings returned from .Fn mac_to_text . -Doing so may result in undefined behavior, -including application failure. +Doing so may result in undefined behavior. diff --git a/lib/libc/posix1e/mac_get.3 b/lib/libc/posix1e/mac_get.3 index cd498d0e4e7..35fa72b0824 100644 --- a/lib/libc/posix1e/mac_get.3 +++ b/lib/libc/posix1e/mac_get.3 @@ -133,6 +133,7 @@ is not a directory. .Xr mac_prepare 3 , .Xr mac_set 3 , .Xr mac_text 3 , +.Xr posix1e 3 , .Xr mac 4 , .Xr mac 9 .Sh STANDARDS diff --git a/lib/libc/posix1e/mac_set.3 b/lib/libc/posix1e/mac_set.3 index 84a1800412d..0b245a00027 100644 --- a/lib/libc/posix1e/mac_set.3 +++ b/lib/libc/posix1e/mac_set.3 @@ -138,6 +138,7 @@ is not a directory. .Xr mac_is_present 3 , .Xr mac_prepare 3 , .Xr mac_text 3 , +.Xr posix1e 3 , .Xr mac 4 , .Xr mac 9 .Sh HISTORY diff --git a/lib/libc/posix1e/mac_text.3 b/lib/libc/posix1e/mac_text.3 index 66c1e211394..dde6ccf5e23 100644 --- a/lib/libc/posix1e/mac_text.3 +++ b/lib/libc/posix1e/mac_text.3 @@ -98,6 +98,7 @@ to allocate internal storage. .Xr mac_is_present 3 , .Xr mac_prepare 3 , .Xr mac_set 3 , +.Xr posix1e 3 , .Xr mac 4 , .Xr maclabel 7 .Sh STANDARDS diff --git a/lib/libc/posix1e/posix1e.3 b/lib/libc/posix1e/posix1e.3 index 2065523bad9..84ce2ec80d1 100644 --- a/lib/libc/posix1e/posix1e.3 +++ b/lib/libc/posix1e/posix1e.3 @@ -1,5 +1,5 @@ .\"- -.\" Copyright (c) 2000 Robert N. M. Watson +.\" Copyright (c) 2000, 2009 Robert N. M. Watson .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 20, 2009 +.Dd August 7, 2009 .Dt POSIX1E 3 .Os .Sh NAME @@ -36,99 +36,77 @@ .Sh SYNOPSIS .In sys/types.h .In sys/acl.h -.\" .In sys/capability.h .In sys/mac.h .Sh DESCRIPTION -The IEEE POSIX.1e specification never left draft form, but the interfaces -it describes are now widely used despite inherent limitations. -Currently, only a few of the interfaces and features are implemented in -.Fx , -although efforts are underway to complete the integration at this time. +POSIX.1e describes five security extensions to the POSIX.1 API: Access +Control Lists (ACLs), Auditing, Capabilities, Mandatory Access Control, and +Information Flow Labels. +While IEEE POSIX.1e D17 specification has not been standardized, several of +its interfaces are widely used. .Pp -POSIX.1e describes five security extensions to the base POSIX.1 API: -Access Control Lists (ACLs), Auditing, Capabilities, Mandatory Access -Control, and Information Flow Labels. .Fx -supports POSIX.1e ACL interfaces, as well as POSIX.1e-like MAC -interfaces. -The TrustedBSD Project has produced but not integrated an implementation -of POSIX.1e Capabilities. +implements POSIX.1e interface for access control lists, described in +.Xr acl 3 , +and supports ACLs on the +.Xr ffs 7 +file system; ACLs must be administratively enabled using +.Xr tunefs 8 . .Pp -POSIX.1e defines both syntax and semantics for these features, but fairly -substantial changes are required to implement these features in the -operating system. +.Fx +implements a POSIX.1e-like mandatory access control interface, described in +.Xr mac 3 , +although with a number of extensions and important semantic differences. .Pp -As shipped, -.Fx 4.0 -provides API and VFS support for ACLs, but not an implementation on any -native file system. -.Fx 5.0 -includes support for ACLs as part of UFS1 and UFS2, as well as necessary -VFS support for additional file systems to export ACLs as appropriate. -Available API calls relating to ACLs are described in detail in -.Xr acl 3 . -.Pp -As shipped, -.Fx 5.0 -includes support for Mandatory Access Control as well as POSIX.1e-like -APIs for label management. -More information on API calls relating to MAC is available in -.Xr mac 3 . -.Pp -Additional patches supporting POSIX.1e features are provided by the -TrustedBSD project: -.Pp -http://www.TrustedBSD.org/ -.Sh IMPLEMENTATION NOTES -.Fx Ns 's -support for POSIX.1e interfaces and features is still under -development at this time, and many of these features are considered new -or experimental. +.Fx +does not implement the POSIX.1e audit, privilege (capability), or information +flow label APIs. +However, +.Fx +does implement the +.Xr libbsm +audit API. .Sh ENVIRONMENT -POSIX.1e assigns security labels to all objects, extending the security +POSIX.1e assigns security attributes to all objects, extending the security functionality described in POSIX.1. -These additional labels provide -fine-grained discretionary access control, fine-grained capabilities, -and labels necessary for mandatory access control. -POSIX.2c describes -a set of userland utilities for manipulating these labels. +These additional attributes store fine-grained discretionary access control +information and mandatory access control labels; for files, they are stored +in extended attributes, described in +.Xr extattr 3 . .Pp -Many of these services are supported by extended attributes, documented -in -.Xr extattr 2 +POSIX.2c describes +a set of userland utilities for manipulating these attributes, including +.Xr getfacl 1 and -.Xr extattr 9 . -While these APIs are not documented in POSIX.1e, they are similar in -structure. +.Xr setfacl 1 +for access control lists, and +.Xr getfmac 8 +and +.Xr setfmac 8 +for mandatory access control labels. .Sh SEE ALSO +.Xr getfacl 1 , +.Xr setfacl 1 , .Xr extattr 2 , .Xr acl 3 , +.Xr extattr 3 , .Xr libbsm 3 , .Xr mac 3 , +.Xr ffs 7 , +.Xr getfmac 8 , +.Xr setfmac 8 , +.Xr tunefs 8 , .Xr acl 9 , .Xr extattr 9 , .Xr mac 9 .Sh STANDARDS POSIX.1e is described in IEEE POSIX.1e draft 17. -Discussion of the draft continues -on the cross-platform POSIX.1e implementation -mailing list. -To join this list, see the -.Fx -POSIX.1e implementation -page for more information. .Sh HISTORY POSIX.1e support was introduced in .Fx 4.0 ; -most of the features are available as of +most features were available as of .Fx 5.0 . -Development continues. .Sh AUTHORS .An Robert N M Watson .An Chris D. Faulhaber .An Thomas Moestl .An Ilmar S Habibulin -.Sh BUGS -Many of these features are considered new or experimental in -.Fx 5.0 -and should be deployed with appropriate caution. diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index 270d64198fc..b56b0030bed 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -5320,6 +5320,15 @@ posix_memalign(void **memptr, size_t alignment, size_t size) goto RETURN; } + if (size == 0) { + if (opt_sysv == false) + size = 1; + else { + result = NULL; + ret = 0; + goto RETURN; + } + } result = ipalloc(alignment, size); } diff --git a/lib/libc/stdlib/ptsname.3 b/lib/libc/stdlib/ptsname.3 index bfa36473ce2..f674a54bd90 100644 --- a/lib/libc/stdlib/ptsname.3 +++ b/lib/libc/stdlib/ptsname.3 @@ -134,14 +134,22 @@ The slave pseudo-terminal device could not be accessed. The .Fn ptsname function conforms to -.St -p1003.1-2001 . +.St -p1003.1-2008 . .Pp This implementation of .Fn grantpt and .Fn unlockpt -does not comply with any standard, because these functions assume the -pseudo-terminal has the correct attributes upon creation. +does not conform to +.St -p1003.1-2008 , +because it depends on +.Xr posix_openpt 2 +to create the pseudo-terminal device with proper permissions in place. +It only validates whether +.Fa fildes +is a valid pseudo-terminal master device. +Future revisions of the specification will likely allow this behaviour, +as stated by the Austin Group. .Sh HISTORY The .Fn grantpt , @@ -150,15 +158,3 @@ and .Fn unlockpt functions appeared in .Fx 5.0 . -.Sh NOTES -The purpose of the -.Fn grantpt -and -.Fn unlockpt -functions has no meaning in -.Fx , -because pseudo-terminals obtained by -.Xr posix_openpt 2 -are created on demand. -Because these devices are created with proper permissions in place, they -are guaranteed to be unused by unprivileged processes. diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c index c7de35c0d68..51d41ed6b9b 100644 --- a/lib/libc/stdtime/strptime.c +++ b/lib/libc/stdtime/strptime.c @@ -529,7 +529,7 @@ label: buf++; i = 0; for (len = 4; len > 0; len--) { - if (isdigit((int)*buf)) { + if (isdigit((unsigned char)*buf)) { i *= 10; i += *buf - '0'; buf++; diff --git a/lib/libc/sys/intro.2 b/lib/libc/sys/intro.2 index 7338f8b0f52..1c01c3937e7 100644 --- a/lib/libc/sys/intro.2 +++ b/lib/libc/sys/intro.2 @@ -302,7 +302,7 @@ Internet protocols. .It Er 48 EADDRINUSE Em "Address already in use" . Only one usage of each address is normally permitted. .Pp -.It Er 49 EADDRNOTAVAIL Em "Cannot assign requested address" . +.It Er 49 EADDRNOTAVAIL Em "Can't assign requested address" . Normally results from an attempt to create a socket with an address not on this machine. .It Er 50 ENETDOWN Em "Network is down" . @@ -335,7 +335,7 @@ when already connected. An request to send or receive data was disallowed because the socket was not connected and (when sending on a datagram socket) no address was supplied. -.It Er 58 ESHUTDOWN Em "Cannot send after socket shutdown" . +.It Er 58 ESHUTDOWN Em "Can't send after socket shutdown" . A request to send data was disallowed because the socket had already been shut down with a previous .Xr shutdown 2 diff --git a/lib/libkvm/kvm_vnet.c b/lib/libkvm/kvm_vnet.c index 1a02cad68d3..d192c67ced0 100644 --- a/lib/libkvm/kvm_vnet.c +++ b/lib/libkvm/kvm_vnet.c @@ -195,7 +195,7 @@ _kvm_vnet_selectpid(kvm_t *kd, pid_t pid) kd->vnet_start = nl[NLIST_START_VNET].n_value; kd->vnet_stop = nl[NLIST_STOP_VNET].n_value; kd->vnet_current = (uintptr_t)prison.pr_vnet; - kd->vnet_base = (uintptr_t)vnet.vnet_data_mem - kd->vnet_start; + kd->vnet_base = vnet.vnet_data_base; return (0); } diff --git a/lib/libpam/modules/pam_lastlog/pam_lastlog.c b/lib/libpam/modules/pam_lastlog/pam_lastlog.c index 817d1f3ba79..9899f8d16fa 100644 --- a/lib/libpam/modules/pam_lastlog/pam_lastlog.c +++ b/lib/libpam/modules/pam_lastlog/pam_lastlog.c @@ -183,6 +183,11 @@ pam_sm_close_session(pam_handle_t *pamh __unused, int flags __unused, pam_err = pam_get_item(pamh, PAM_TTY, (const void **)&tty); if (pam_err != PAM_SUCCESS) goto err; + if (tty == NULL) { + PAM_LOG("No PAM_TTY"); + pam_err = PAM_SERVICE_ERR; + goto err; + } if (strncmp(tty, _PATH_DEV, strlen(_PATH_DEV)) == 0) tty = (const char *)tty + strlen(_PATH_DEV); if (*(const char *)tty == '\0') diff --git a/lib/libpmc/pmc.3 b/lib/libpmc/pmc.3 index af96fc09caf..f48fe7985e9 100644 --- a/lib/libpmc/pmc.3 +++ b/lib/libpmc/pmc.3 @@ -120,7 +120,7 @@ Process scope sampling PMCs. Process scope counting PMCs that have been configured to report PMC readings on process context switches or process exits. .El -Upto one log file may be configured per owner process. +Up to one log file may be configured per owner process. Events logged to a log file may be subsequently analyzed using the .Xr pmclog 3 family of functions. @@ -187,7 +187,7 @@ enumeration. Supported PMC kinds include: .Bl -tag -width "Li PMC_CLASS_IAF" -compact .It Li PMC_CLASS_IAF -Fixed function hardwre counters presents in CPUs conforming to the +Fixed function hardware counters presents in CPUs conforming to the .Tn Intel performance measurement architecture version 2 and later. .It Li PMC_CLASS_IAP @@ -262,7 +262,7 @@ CPU is running unprivileged code. The ability to write to performance counters. .El .Ss CPU Naming Conventions -CPUs are named using small integers from zero uptil, but +CPUs are named using small integers from zero up to, but excluding, the value returned by function .Fn pmc_ncpu . On platforms supporting sparsely numbered CPUs not all the numbers in @@ -423,7 +423,7 @@ The PMCs would then be started using function .Fn pmc_start . .It Once started, the values of counting PMCs may be read using function -.Fn pmc_start . +.Fn pmc_read . For PMCs that write events to the log file, this logged data would be read and parsed using the .Xr pmclog 3 diff --git a/lib/libpmc/pmc.atom.3 b/lib/libpmc/pmc.atom.3 index 934d22201f1..bd081f9d27a 100644 --- a/lib/libpmc/pmc.atom.3 +++ b/lib/libpmc/pmc.atom.3 @@ -93,13 +93,13 @@ Configure the PMC to increment only if the number of configured events measured in a cycle is greater than or equal to .Ar value . .It Li edge -Configure the PMC to count the number of deasserted to asserted +Configure the PMC to count the number of de-asserted to asserted transitions of the conditions expressed by the other qualifiers. If specified, the counter will increment only once whenever a condition becomes true, irrespective of the number of clocks during which the condition remains true. .It Li inv -Invert the sense of comparision when the +Invert the sense of comparison when the .Dq Li cmask qualifier is present, making the counter increment when the number of events per cycle is less than the value specified by the @@ -170,7 +170,7 @@ The default is .Dq Li both . .Pp Events that require a cache coherence qualifier to be specified use an -additional qualifer +additional qualifier .Dq Li cachestate= Ns Ar state , where argument .Ar state @@ -222,7 +222,7 @@ Measure CMP2S snoops. .Pp The default is to measure both snoops. .Ss Event Specifiers (Programmable PMCs) -Core2 programmable PMCs support the following events: +Atom programmable PMCs support the following events: .Bl -tag -width indent .It Li BACLEARS .Pq Event E6H , Umask 01H @@ -371,7 +371,7 @@ This event is thread independent. .Xc .Pq Event 60H The number of pending full cache line read transactions on the bus -occuring in each cycle. +occurring in each cycle. This event is thread independent. .It Li BUS_TRANS_P Xo .Op ,agent= Ns Ar agent @@ -432,7 +432,7 @@ The number of burst read transactions. .Op ,core= Ns Ar core .Xc .Pq Event 6CH -The number of completed I/O bus transaactions due to +The number of completed I/O bus transactions due to .Li IN and .Li OUT @@ -448,7 +448,7 @@ The number of Read For Ownership bus transactions. .Op ,core= Ns Ar core .Xc .Pq Event 67H -The number explicit writeback bus transactions due to dirty line +The number explicit write-back bus transactions due to dirty line evictions. .It Li CMP_SNOOP Xo .Op ,core= Ns Ar core @@ -576,7 +576,7 @@ The number of transitions from floating point instructions to MMX instructions. .It Li HW_INT_RCV .Pq Event C8H , Umask 00H -The number of hardware interrupts recieved. +The number of hardware interrupts received. .It Li ICACHE.ACCESSES .Pq Event 80H , Umask 03H The number of instruction fetches. @@ -693,7 +693,7 @@ fetch unit. .It Li L2_LD Xo .Op ,cachestate= Ns Ar state .Op ,core= Ns Ar core -.Op ,prefech= Ns Ar prefetch +.Op ,prefetch= Ns Ar prefetch .Xc .Pq Event 29H The number of L2 cache read requests from L1 cache and L2 @@ -778,7 +778,7 @@ The number of loads blocked by preceding stores to the same address whose data value is not known. .It Li LOAD_BLOCK.UNTIL_RETIRE .Pq Event 03H , Umask 10H -The numer of load operations that were blocked until retirement. +The number of load operations that were blocked until retirement. .It Li LOAD_HIT_PRE .Pq Event 4CH , Umask 00H The number of load operations that conflicted with an prefetch to the diff --git a/lib/libpmc/pmc.core.3 b/lib/libpmc/pmc.core.3 index ce085caf520..3c97e092594 100644 --- a/lib/libpmc/pmc.core.3 +++ b/lib/libpmc/pmc.core.3 @@ -85,13 +85,13 @@ Configure the PMC to increment only if the number of configured events measured in a cycle is greater than or equal to .Ar value . .It Li edge -Configure the PMC to count the number of deasserted to asserted +Configure the PMC to count the number of de-asserted to asserted transitions of the conditions expressed by the other qualifiers. If specified, the counter will increment only once whenever a condition becomes true, irrespective of the number of clocks during which the condition remains true. .It Li inv -Invert the sense of comparision when the +Invert the sense of comparison when the .Dq Li cmask qualifier is present, making the counter increment when the number of events per cycle is less than the value specified by the @@ -159,7 +159,7 @@ The default is .Dq Li both . .Pp Events that require a cache coherence qualifier to be specified use an -additional qualifer +additional qualifier .Dq Li cachestate= Ns Ar value , where argument .Ar value @@ -348,8 +348,8 @@ The number of completed partial write transactions. The number of completed read-for-ownership transactions. .It Li Bus_Trans_WB Op ,agent= Ns Ar agent .Pq Event 67H -The number of completed writeback transactions from the data cache -unit, excluding L2 writebacks. +The number of completed write-back transactions from the data cache +unit, excluding L2 write-backs. .It Li Cycles_Div_Busy .Pq Event 14H , Umask 00H The number of cycles the divider is busy. @@ -393,13 +393,13 @@ The number of cacheable read and write operations to L1 data cache. .It Li Data_Mem_Ref .Pq Event 43H , Umask 01H The number of L1 data reads and writes, both cacheable and -uncacheable. +un-cacheable. .It Li Dbus_Busy Op ,core= Ns Ar core .Pq Event 22H The number of core cycles during which the data bus was busy. .It Li Dbus_Busy_Rd Op ,core= Ns Ar core .Pq Event 23H -The nunber of cycles during which the data bus was busy transferring +The number of cycles during which the data bus was busy transferring data to a core. .It Li Div .Pq Event 13H , Umask 00H @@ -460,7 +460,7 @@ streaming buffers. .It Li ICache_Reads .Pq Event 80H , Umask 00H The number of instruction fetches from the the instruction cache and -streaming buffers counting both cacheable and uncacheable fetches. +streaming buffers counting both cacheable and un-cacheable fetches. .It Li IFU_Mem_Stall .Pq Event 86H , Umask 00H The number of cycles the instruction fetch unit was stalled while @@ -754,7 +754,7 @@ Performance monitoring events for retired floating point operations .It AE29 DR3 address match on MOVD/MOVQ/MOVNTQ memory store instruction may incorrectly increment performance monitoring count -for saturating simd instructions retired (Event CFH). +for saturating SIMD instructions retired (Event CFH). .It AE33 Hardware prefetch performance monitoring events may be counted inaccurately. diff --git a/lib/libpmc/pmc.core2.3 b/lib/libpmc/pmc.core2.3 index 6d86c304276..41c16750d62 100644 --- a/lib/libpmc/pmc.core2.3 +++ b/lib/libpmc/pmc.core2.3 @@ -42,7 +42,7 @@ family CPUs CPUs contain PMCs conforming to version 2 of the .Tn Intel performance measurement architecture. -These CPUs may contain upto two classes of PMCs: +These CPUs may contain up to two classes of PMCs: .Bl -tag -width "Li PMC_CLASS_IAP" .It Li PMC_CLASS_IAF Fixed-function counters that count only one hardware event per counter. @@ -92,13 +92,13 @@ Configure the PMC to increment only if the number of configured events measured in a cycle is greater than or equal to .Ar value . .It Li edge -Configure the PMC to count the number of deasserted to asserted +Configure the PMC to count the number of de-asserted to asserted transitions of the conditions expressed by the other qualifiers. If specified, the counter will increment only once whenever a condition becomes true, irrespective of the number of clocks during which the condition remains true. .It Li inv -Invert the sense of comparision when the +Invert the sense of comparison when the .Dq Li cmask qualifier is present, making the counter increment when the number of events per cycle is less than the value specified by the @@ -169,7 +169,7 @@ The default is .Dq Li both . .Pp Events that require a cache coherence qualifier to be specified use an -additional qualifer +additional qualifier .Dq Li cachestate= Ns Ar state , where argument .Ar state @@ -361,7 +361,7 @@ signal was asserted on the bus. .Xc .Pq Event 60H The number of pending full cache line read transactions on the bus -occuring in each cycle. +occurring in each cycle. .It Li BUS_TRANS_P Xo .Op ,agent= Ns Ar agent .Op ,core= Ns Ar core @@ -421,7 +421,7 @@ The number of burst read transactions. .Op ,core= Ns Ar core .Xc .Pq Event 6CH -The number of completed I/O bus transaactions due to +The number of completed I/O bus transactions due to .Li IN and .Li OUT @@ -437,7 +437,7 @@ The number of Read For Ownership bus transactions. .Op ,core= Ns Ar core .Xc .Pq Event 67H -The number explicit writeback bus transactions due to dirty line +The number explicit write-back bus transactions due to dirty line evictions. .It Li CMP_SNOOP Xo .Op ,core= Ns Ar core @@ -544,7 +544,7 @@ The number of transitions from floating point instructions to MMX instructions. .It Li HW_INT_RCV .Pq Event C8H , Umask 00H -The number of hardware interrupts recieved. +The number of hardware interrupts received. .It Li IDLE_DURING_DIV .Pq Event 18H , Umask 00H The number of cycles the divider is busy and no other execution unit @@ -661,7 +661,7 @@ fetch unit. .It Li L2_LD Xo .Op ,cachestate= Ns Ar state .Op ,core= Ns Ar core -.Op ,prefech= Ns Ar prefetch +.Op ,prefetch= Ns Ar prefetch .Xc .Pq Event 29H The number of L2 cache read requests from L1 cache and L2 @@ -747,7 +747,7 @@ The number of loads blocked by preceding stores to the same address whose data value is not known. .It Li LOAD_BLOCK.UNTIL_RETIRE .Pq Event 03H , Umask 10H -The numer of load operations that were blocked until retirement. +The number of load operations that were blocked until retirement. .It Li LOAD_HIT_PRE .Pq Event 4CH , Umask 00H The number of load operations that conflicted with an prefetch to the diff --git a/lib/libpmc/pmc.iaf.3 b/lib/libpmc/pmc.iaf.3 index 76e0cc89c03..c6d01eaaa72 100644 --- a/lib/libpmc/pmc.iaf.3 +++ b/lib/libpmc/pmc.iaf.3 @@ -73,7 +73,7 @@ Fixed-function PMCs support the following capabilities: .It PMC_CAP_WRITE Ta Yes .El .Ss Class Name Prefix -These pmcs are named using a class name prefix of +These PMCs are named using a class name prefix of .Dq Li iaf- . .Ss Event Qualifiers (Fixed Function PMCs) These PMCs support the following modifiers: diff --git a/lib/libpmc/pmc.k7.3 b/lib/libpmc/pmc.k7.3 index b9068a22ef5..8db9020dead 100644 --- a/lib/libpmc/pmc.k7.3 +++ b/lib/libpmc/pmc.k7.3 @@ -79,7 +79,7 @@ In other words, the counter will increment only once whenever a given condition becomes true, irrespective of the number of clocks during which the condition remains true. .It Li inv -Invert the sense of comparision when the +Invert the sense of comparison when the .Dq Li count qualifier is present, making the counter to increment when the number of events per cycle is less than the value specified by @@ -205,7 +205,7 @@ Count all retired branches (conditional, unconditional, exceptions and interrupts). .It Li k7-retired-branches-mispredicted .Pq Event C3H -Count all misprediced retired branches. +Count all mispredicted retired branches. .It Li k7-retired-far-control-transfers .Pq Event C6H Count retired far control transfers. diff --git a/lib/libpmc/pmc.k8.3 b/lib/libpmc/pmc.k8.3 index c8fea11f76f..3e4afb1ff5b 100644 --- a/lib/libpmc/pmc.k8.3 +++ b/lib/libpmc/pmc.k8.3 @@ -82,7 +82,7 @@ In other words, the counter will increment only once whenever a given condition becomes true, irrespective of the number of clocks during which the condition remains true. .It Li inv -Invert the sense of comparision when the +Invert the sense of comparison when the .Dq Li count qualifier is present, making the counter to increment when the number of events per cycle is less than the value specified by @@ -173,7 +173,7 @@ Count TLB reloads. The default is to count all types of requests. .It Li k8-dc-access .Pq Event 40H -Count data cache accesses including microcode scratchpad accesses. +Count data cache accesses including microcode scratch pad accesses. .It Li k8-dc-copyback Op Li ,mask= Ns Ar qualifier .Pq Event 44H Count data cache copyback operations. diff --git a/lib/libpmc/pmc.p4.3 b/lib/libpmc/pmc.p4.3 index d3c7665879c..ecfc6287db8 100644 --- a/lib/libpmc/pmc.p4.3 +++ b/lib/libpmc/pmc.p4.3 @@ -121,7 +121,7 @@ See below for more information. .It Li edge Configure the counter to count false to true transitions of the threshold -comparision output. +comparison output. This qualifier only takes effect if a threshold qualifier has also been specified. .It Li complement @@ -547,7 +547,7 @@ Count cycles when the processor is active. .It Li p4-instr-retired Op Li ,mask= Ns Ar flags .Pq "TS event" Count instructions retired during a clock cycle. -Qualifer +Qualifier .Ar flags comprises of the following strings separated by .Ql + @@ -589,7 +589,7 @@ Count read entries. .It Li all-write Count write entries. .It Li mem-uc -Count entries accessing uncacheable memory. +Count entries accessing un-cacheable memory. .It Li mem-wc Count entries accessing write-combining memory. .It Li mem-wt @@ -620,7 +620,7 @@ The default is 0. The .Dq Li edge qualifier should not be used when counting cycles with this event. -The exact behaviour of this event depends on the processor revision. +The exact behavior of this event depends on the processor revision. .It Li p4-ioq-allocation Xo .Op Li ,mask= Ns Ar qualifier .Op Li ,busreqtype= Ns Ar req-type @@ -644,7 +644,7 @@ Count read entries. .It Li all-write Count write entries. .It Li mem-uc -Count entries accessing uncacheable memory. +Count entries accessing un-cacheable memory. .It Li mem-wc Count entries accessing write-combining memory. .It Li mem-wt @@ -676,10 +676,10 @@ The .Dq Li edge qualifier is normally used with this event to prevent multiple counting. -The exact behaviour of this event depends on the processor revision. +The exact behavior of this event depends on the processor revision. .It Li p4-itlb-reference Op mask= Ns Ar qualifier .Pq "TS event" -Count translations using the intruction translation look-aside +Count translations using the instruction translation look-aside buffer. The .Ar qualifier @@ -693,7 +693,7 @@ Count ITLB hits. .It Li miss Count ITLB misses. .It Li hit-uc -Count uncacheable ITLB hits. +Count un-cacheable ITLB hits. .El .Pp If no @@ -730,7 +730,7 @@ Count non-bogus retired branch instructions. .It Li p4-machine-clear Op Li ,mask= Ns Ar flags .Pq "TS event" Count the number of pipeline clears seen by the processor. -Qualifer +Qualifier .Ar flags is a list of the following strings separated by .Ql + @@ -753,7 +753,7 @@ The default qualifier is .Dq Li clear . .It Li p4-memory-cancel Op Li ,mask= Ns Ar event-list .Pq "TS event" -Count the cancelling of various kinds of requests in the data cache +Count the canceling of various kinds of requests in the data cache address control unit of the CPU. The qualifier .Ar event-list @@ -773,8 +773,8 @@ If is not specified, then the default is to count both kinds of events. .It Li p4-memory-complete Op Li ,mask= Ns Ar event-list .Pq "TS event" -Count the completion of load split, store split, uncacheable split and -uncacheable load operations selected by qualifier +Count the completion of load split, store split, un-cacheable split and +un-cacheable load operations selected by qualifier .Ar event-list . The qualifier .Ar event-list @@ -784,7 +784,7 @@ separated list of the following flags: .Pp .Bl -tag -width indent -compact .It Li lsc -Count load splits completed, excluding loads from uncacheable or +Count load splits completed, excluding loads from un-cacheable or write-combining areas. .It Li ssc Count any split stores completed. @@ -1065,7 +1065,7 @@ The default qualifier counts all the above kinds of uops. .Pq "TS event" This event is used in conjunction with the front-end at-retirement mechanism to tag load and store uops. -Qualifer +Qualifier .Ar flags comprises the following strings separated by .Ql + @@ -1112,7 +1112,7 @@ WC buffer evictions due to any cause. WC buffer evictions due to no WC buffer being available. .El .Pp -The default qualifer counts both kinds of evictions. +The default qualifier counts both kinds of evictions. .It Li p4-x87-assist Op Li ,mask= Ns Ar flags .Pq "TS event" Count the retirement of x87 instructions that required special diff --git a/lib/libpmc/pmc.p5.3 b/lib/libpmc/pmc.p5.3 index 5e6af32f993..2930f16caac 100644 --- a/lib/libpmc/pmc.p5.3 +++ b/lib/libpmc/pmc.p5.3 @@ -156,14 +156,14 @@ This event is only allocated on counter 0. .It Li p5-code-cache-miss .Pq Event 0EH The number of instruction reads that miss the internal code cache. -Both cacheable and uncacheable misses are counted. +Both cacheable and un-cacheable misses are counted. .It Li p5-code-read .Pq Event 0CH -The number of instruction reads to both cacheable and uncacheable regions. +The number of instruction reads to both cacheable and un-cacheable regions. .It Li p5-code-tlb-miss .Pq Event 0DH The number of instruction reads that miss the instruction TLB. -Both cacheable and uncacheable unreads are counted. +Both cacheable and un-cacheable unreads are counted. .It Li p5-d1-starvation-and-fifo-is-empty .Pq Event 33H , Tn Pentium MMX The number of times the D1 stage cannot issue any instructions because @@ -193,13 +193,13 @@ Split cycle reads are counted individually. .It Li p5-data-read-miss .Pq Event 03H The number of memory read accesses that miss the data cache, counting -both cacheable and uncacheable accesses. +both cacheable and un-cacheable accesses. Data accesses that are part of TLB miss processing are not included. I/O accesses are not included. .It Li p5-data-read-miss-or-write-miss .Pq Event 29H The number of data reads and writes that miss the internal data cache, -counting uncacheable accesses. +counting un-cacheable accesses. Data accesses due to TLB miss processing are not counted. .It Li p5-data-read-or-write .Pq Event 28H @@ -208,7 +208,7 @@ and misses. Data reads due to TLB miss processing are not counted. .It Li p5-data-tlb-miss .Pq Event 02H -The number of misses to the data cache translation lookaside buffer. +The number of misses to the data cache translation look aside buffer. .It Li p5-data-write .Pq Event 01H The number of memory data writes, counting internal data cache hits @@ -217,7 +217,7 @@ I/O is not included and split cycle writes are counted individually. .It Li p5-data-write-miss .Pq Event 04H The number of memory write accesses that miss the data cache, counting -both cacheable and uncacheable accesses. +both cacheable and un-cacheable accesses. I/O accesses are not counted. .It Li p5-emms-instructions-executed .Pq Event 2DH , Tn Pentium MMX diff --git a/lib/libpmc/pmc.p6.3 b/lib/libpmc/pmc.p6.3 index b4de735f311..15a1101bf67 100644 --- a/lib/libpmc/pmc.p6.3 +++ b/lib/libpmc/pmc.p6.3 @@ -89,13 +89,13 @@ Configure the PMC to increment only if the number of configured events measured in a cycle is greater than or equal to .Ar value . .It Li edge -Configure the PMC to count the number of deasserted to asserted +Configure the PMC to count the number of de-asserted to asserted transitions of the conditions expressed by the other qualifiers. If specified, the counter will increment only once whenever a condition becomes true, irrespective of the number of clocks during which the condition remains true. .It Li inv -Invert the sense of comparision when the +Invert the sense of comparison when the .Dq Li cmask qualifier is present, making the counter increment when the number of events per cycle is less than the value specified by the @@ -584,7 +584,7 @@ Count SSE2 scalar-double instructions. .El .Pp The default is to count SSE packed-single instructions. -.It Li p6-emon-sse-sse2-inst-retired Op Li ,umask= Ns Ar qualifer +.It Li p6-emon-sse-sse2-inst-retired Op Li ,umask= Ns Ar qualifier .Pq Event D8H , Tn "Pentium M" Count the number of SSE instructions retired. An additional qualifier can be specified, and can be one of the diff --git a/lib/libpmc/pmc_capabilities.3 b/lib/libpmc/pmc_capabilities.3 index 9a7b6e9f0f6..0d1a99dd602 100644 --- a/lib/libpmc/pmc_capabilities.3 +++ b/lib/libpmc/pmc_capabilities.3 @@ -63,7 +63,7 @@ is a PMC handle obtained by a prior call to .Fn pmc_allocate . The function sets argument .Fa caps -to a bitmask of capabilities supported by the PMC denoted by +to a bit mask of capabilities supported by the PMC denoted by argument .Fa pmc . PMC capabilities are described in diff --git a/lib/libpmc/pmc_read.3 b/lib/libpmc/pmc_read.3 index 6056feac253..d9fa3ce8b9c 100644 --- a/lib/libpmc/pmc_read.3 +++ b/lib/libpmc/pmc_read.3 @@ -30,7 +30,7 @@ .Nm pmc_read , .Nm pmc_rw , .Nm pmc_write , -.Nd read and write hardware performace counters +.Nd read and write hardware performance counters .Sh LIBRARY .Lb libpmc .Sh SYNOPSIS @@ -62,7 +62,7 @@ Function .Fn pmc_rw combines a read and a write into a single atomic operation. .Pp -For write operations the PMC should be a quiesced state. +For write operations the PMC should be a quiescent state. .Sh RETURN VALUES .Rv -std .Sh ERRORS diff --git a/libexec/Makefile b/libexec/Makefile index 72ec91315af..26a8ff236a2 100644 --- a/libexec/Makefile +++ b/libexec/Makefile @@ -9,7 +9,6 @@ SUBDIR= ${_atrun} \ fingerd \ ftpd \ getty \ - lukemftpd \ ${_mail.local} \ ${_mknetid} \ ${_pppoed} \ diff --git a/release/Makefile b/release/Makefile index 22f250af064..e3a11715828 100644 --- a/release/Makefile +++ b/release/Makefile @@ -1,7 +1,8 @@ # $FreeBSD$ # # make release [BUILDNAME=somename] CHROOTDIR=/some/dir CVSROOT=/cvs/dir \ -# [RELEASETAG=tag] +# [RELEASETAG=tag] [SVNROOT=svn://svn.freebsd.org/base] \ +# [SVNBRANCH=some/branch] # # Where "/some/dir" is the pathname of a directory on a some filesystem with # at least 1000MB of free space, "somename" is what you want the release to @@ -9,6 +10,11 @@ # which CVS "tag" name should be used when checking out the sources to build # the release (default is HEAD). # +# Please note the support for building from SVN is preliminary and there +# are still questions about things like how to handle updates of +# /usr/src on production systems (csup(1) replacement). It is a work +# in progress and may change as the other issues get worked out. +# # Please note: the md(4) driver must be present in the kernel # (either by being compiled in or available as a kld(4) module), # otherwise the target 'release.8' and possibly others will fail. @@ -18,16 +24,16 @@ # Set these, release builder! # # Fixed version: -#BUILDNAME=8.0-CURRENT +#BUILDNAME=9.0-CURRENT # # Automatic SNAP versioning: DATE != date +%Y%m%d -BASE = 8.0 +BASE = 9.0 BUILDNAME?=${BASE}-${DATE}-SNAP # #CHROOTDIR=/junk/release # If this is a -stable snapshot, then set -#RELEASETAG=RELENG_7 +#RELEASETAG=RELENG_8 # # To test a release with a source tree containing patches and # other work. This tree will get copied instead of getting the @@ -49,12 +55,25 @@ BUILDNAME?=${BASE}-${DATE}-SNAP # To add other options to the CVS command, set #CVSARGS="-lfq" # -# To prefix the cvs command +# To prefix the CVS command #CVSPREFIX="/usr/bin/time" # # Where the CVS repository is #CVSROOT="/home/ncvs" # +# To add other options to the Subversion subcommands (co,up), set +#SVNCMDARGS="-r '{ 01/01/2002 00:00:00 UTC }'" +# +# To prefix the Subversion command +#SVNPREFIX="/usr/bin/time" +# +# Where the Subversion repository is +#SVNROOT=svn://svn.freebsd.org/base +# +# Subversion branch to build for src. If this is not set then it is +# automatically computed from RELEASETAG. +#SVNBRANCH=stable/8 +# # Non-zero if ${RELEASETAG} is in the form "RELENG_ver_RELEASE"; we # are building an official release. Otherwise, we are building for # a branch. @@ -68,6 +87,16 @@ PORTSRELEASETAG?= ${AUXRELEASETAG} .endif .endif +# Determine the Subversion source branch that corresponds to the requested +# RELEASETAG. +.if !defined(SVNBRANCH) +.if defined(RELEASETAG) +SVNBRANCH!= echo "${RELEASETAG}" | awk -f ${.CURDIR}/svnbranch.awk +.else +SVNBRANCH= head +.endif +.endif + # If you want to pass flags to the world build such as -j X, use # WORLD_FLAGS. Similarly, you can specify make flags for kernel # builds via KERNEL_FLAGS. @@ -341,8 +370,17 @@ CVS_PORTSARGS+= -r ${PORTSRELEASETAG} WORLDDIR?= ${.CURDIR}/.. release rerelease: -.if !defined(CHROOTDIR) || !defined(BUILDNAME) || !defined(CVSROOT) - @echo "To make a release you must set CHROOTDIR, BUILDNAME and CVSROOT" && false +.if !defined(CHROOTDIR) || !defined(BUILDNAME) + @echo "To make a release you must set CHROOTDIR and BUILDNAME" && false +.endif +.if !defined(NOPORTSATALL) && !defined(EXTPORTSDIR) && !defined(CVSROOT) + @echo "Building ports requires CVSROOT or EXTPORTSDIR" && false +.endif +.if !defined(NODOC) && !defined(EXTDOCDIR) && !defined(CVSROOT) + @echo "Building docs requires CVSROOT or EXTDOCDIR" && false +.endif +.if !defined(EXTSRCDIR) && !defined(CVSROOT) && !defined(SVNROOT) + @echo "The source tree requires SVNROOT, CVSROOT, or EXTSRCDIR" && false .endif .if defined(NOPORTSATALL) && !defined(NODOC) @echo "Ports are required for building the release docs. Either set NODOC or" @@ -387,6 +425,10 @@ release rerelease: .if defined(EXTSRCDIR) cd ${CHROOTDIR}/usr && \ cp -R -H ${EXTSRCDIR} src +.elif defined(SVNROOT) + cd ${CHROOTDIR}/usr && \ + ${SVNPREFIX} svn co ${SVNCMDARGS} ${SVNROOT}/${SVNBRANCH} \ + ${RELEASESRCMODULE} .else cd ${CHROOTDIR}/usr && \ ${CVSPREFIX} cvs -R ${CVSARGS} -d ${CVSROOT} \ @@ -432,7 +474,10 @@ release rerelease: .endif .if make(rerelease) .if !defined(RELEASENOUPDATE) && !defined(EXTSRCDIR) -.if !defined(RELEASETAG) +.if defined(SVNROOT) + cd ${CHROOTDIR}/usr/src && ${SVNPREFIX} svn switch ${SVNCMDARGS} \ + ${SVNROOT}/${SVNBRANCH} +.elif !defined(RELEASETAG) cd ${CHROOTDIR}/usr/src && ${CVSPREFIX} cvs -R ${CVSARGS} -q \ update ${CVSCMDARGS} -P -d -A .else @@ -601,6 +646,7 @@ release.2: cd ${.CURDIR}/.. && ${CROSSMAKE} distrib-dirs DESTDIR=${RD}/trees/base cd ${.CURDIR}/.. && ${CROSSMAKE} ${WORLD_FLAGS} distributeworld \ DISTDIR=${RD}/trees + sh ${.CURDIR}/scripts/mm-mtree.sh -F "${CROSSENV}" -D "${RD}/trees/base" touch ${.TARGET} # Make and install the generic kernel(s). @@ -651,7 +697,7 @@ release.5: # Remove all the directories we don't need. -cd ${RD}/trees && \ (find ${OTHER_DISTS} -path '*/var/empty' | xargs chflags noschg; \ - find ${OTHER_DISTS} -depth -type d -empty -print | xargs rmdir) + find ${OTHER_DISTS} -depth -type d -empty -delete) touch ${.TARGET} # @@ -1117,10 +1163,10 @@ iso.1: .endif # -# --==## Documentation Project files such as the Handbook and FAQ ##==-- +# --==## Documentation Project tools required to build the release notes ##==-- # doc.1: - @echo "Making docs..." + @echo "Making docproj tools..." @for i in ${DOCPORTS}; do \ cd /usr/ports/$$i && \ env -i FTP_PASSIVE_MODE=$${FTP_PASSIVE_MODE:-no} PATH=$${PATH} \ diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.sgml b/release/doc/en_US.ISO8859-1/relnotes/article.sgml index 46819186d9e..68db4f45e8a 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.sgml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.sgml @@ -411,6 +411,9 @@ &man.top.1; now supports a flag to provide per-CPU usage statistics. + &man.zdump.8; is now working properly on 64 bit architectures. + + &man.traceroute.8; now has the ability to print the AS number for each hop with the new switch; a new option allows selecting a particular @@ -468,8 +471,15 @@ 8.14.1 to 8.14.3. The timezone database has been updated from - the tzdata2008b release to - the tzdata2008h release. + the tzdata2008h release to + the tzdata2009j release. + + The stdtime part of libc, &man.zdump.8 and &man.zic.8 + have been updated from the tzcode2004a + release to the tzcode2009h release. + If you have upgraded from source or via the &man.freebsd-update.8, + then please run &man.tzsetup.8 to install a new /etc/localtime. + WPA Supplicant has been updated from 0.5.8 to 0.5.10. diff --git a/release/scripts/lib32-make.sh b/release/scripts/lib32-make.sh index 37e16d4c719..99bbee4172e 100644 --- a/release/scripts/lib32-make.sh +++ b/release/scripts/lib32-make.sh @@ -5,4 +5,4 @@ # Clean the dust. cd ${RD}/trees/lib32 && \ - find . ! -path '*/libexec/*' ! -path '*/usr/lib32/*' -delete + find . '(' -path '*/usr/share/*' -or -path '*/usr/lib/*' ')' -delete diff --git a/release/scripts/package-split.py b/release/scripts/package-split.py index 54fdde03abf..6d895297c16 100644 --- a/release/scripts/package-split.py +++ b/release/scripts/package-split.py @@ -23,71 +23,14 @@ if 'PKG_VERBOSE' in os.environ: else: verbose = 0 -# List of packages for disc1. This just includes packages sysinstall can -# install as a distribution +if 'PKG_DVD' in os.environ: + doing_dvd = 1 +else: + doing_dvd = 0 + +# List of packages for disc1. def disc1_packages(): - pkgs = ['lang/perl5.8'] - pkgs.extend(['x11/xorg', - 'devel/imake']) - if arch == 'i386': - pkgs.append('emulators/linux_base-fc4') - return pkgs - -# List of packages for disc2. This includes packages that the X desktop -# menu depends on (if it still exists) and other "nice to have" packages. -# For architectures that use a separate livefs, this is actually disc3. -def disc2_packages(): - # X Desktops - if arch == 'ia64': - pkgs = ['x11/gnome2-lite', - 'x11/kde-lite'] - else: - pkgs = ['x11/gnome2', - 'x11/kde3'] - pkgs.extend(['x11-wm/afterstep', - 'x11-wm/windowmaker', - 'x11-wm/fvwm2', - # "Nice to have" - 'archivers/unzip', - 'astro/xearth', - 'devel/gmake', - 'editors/emacs', - 'editors/vim-lite', - 'emulators/mtools', - 'graphics/png', - 'graphics/xv', - 'irc/xchat', - 'mail/exim', - 'mail/fetchmail', - 'mail/mutt', - 'mail/pine4', - 'mail/popd', - 'mail/xfmail', - 'mail/postfix', - 'net/cvsup-without-gui', - 'net/rsync', - 'net/samba3', - 'news/slrn', - 'news/tin', - 'ports-mgmt/portupgrade', - 'print/a2ps-letter', - 'print/apsfilter', - 'print/ghostscript-gnu-nox11', - 'print/gv', - 'print/psutils-letter', - 'shells/bash', - 'shells/pdksh', - 'shells/zsh', - 'security/sudo', - 'www/links', - 'www/lynx', - 'x11/rxvt', - # Formerly on disc3 - 'ports-mgmt/portaudit']) - return pkgs - -def docs_packages(): - pkgs = ['misc/freebsd-doc-bn', + pkgs = ['misc/freebsd-doc-bn', 'misc/freebsd-doc-da', 'misc/freebsd-doc-de', 'misc/freebsd-doc-el', @@ -106,14 +49,58 @@ def docs_packages(): 'misc/freebsd-doc-tr', 'misc/freebsd-doc-zh_cn', 'misc/freebsd-doc-zh_tw'] + + if doing_dvd: + pkgs.extend(['lang/perl5.8', + 'x11/xorg', + 'devel/imake', + 'emulators/linux_base-fc4', + 'x11/gnome2', + 'x11/kde4', + 'x11-wm/afterstep', + 'x11-wm/windowmaker', + 'x11-wm/fvwm2', + 'archivers/unzip', + 'astro/xearth', + 'devel/gmake', + 'editors/emacs', + 'editors/vim-lite', + 'emulators/mtools', + 'graphics/png', + 'graphics/xv', + 'irc/xchat', + 'mail/exim', + 'mail/fetchmail', + 'mail/mutt', + 'mail/alpine', + 'mail/popd', + 'mail/xfmail', + 'mail/postfix', + 'net/cvsup-without-gui', + 'net/rsync', + 'net/samba3', + 'news/slrn', + 'news/tin', + 'ports-mgmt/portupgrade', + 'print/a2ps-letter', + 'print/apsfilter', + 'print/ghostscript7-nox11', + 'print/gv', + 'print/psutils-letter', + 'shells/bash', + 'shells/pdksh', + 'shells/zsh', + 'security/sudo', + 'www/links', + 'www/lynx', + 'x11/rxvt', + 'ports-mgmt/portaudit']) return pkgs # The list of desired packages def desired_packages(): disc1 = disc1_packages() - disc2 = disc2_packages() - docs = docs_packages() - return [disc1, disc2, docs] + return [disc1] # Suck the entire INDEX file into a two different dictionaries. The first # dictionary maps port names (origins) to package names. The second diff --git a/sbin/bsdlabel/bsdlabel.c b/sbin/bsdlabel/bsdlabel.c index 1cb99950bbd..9a6027c7951 100644 --- a/sbin/bsdlabel/bsdlabel.c +++ b/sbin/bsdlabel/bsdlabel.c @@ -118,7 +118,7 @@ static int installboot; /* non-zero if we should install a boot program */ static int allfields; /* present all fields in edit */ static char const *xxboot; /* primary boot */ -static off_t mbroffset; +static uint32_t lba_offset; #ifndef LABELSECTOR #define LABELSECTOR -1 #endif @@ -403,7 +403,7 @@ writelabel(void) readboot(); for (i = 0; i < lab.d_npartitions; i++) if (lab.d_partitions[i].p_size) - lab.d_partitions[i].p_offset += mbroffset; + lab.d_partitions[i].p_offset += lba_offset; bsd_disklabel_le_enc(bootarea + labeloffset + labelsoffset * secsize, lp); if (alphacksum) { @@ -479,10 +479,9 @@ get_file_parms(int f) static int readlabel(int flag) { + uint32_t lba; int f, i; int error; - struct gctl_req *grq; - char const *errstr; f = open(specname, O_RDONLY); if (f < 0) @@ -510,22 +509,28 @@ readlabel(int flag) if (is_file) return(0); - grq = gctl_get_handle(); - gctl_ro_param(grq, "verb", -1, "read mbroffset"); - gctl_ro_param(grq, "class", -1, "BSD"); - gctl_ro_param(grq, "geom", -1, pname); - gctl_rw_param(grq, "mbroffset", sizeof(mbroffset), &mbroffset); - errstr = gctl_issue(grq); - if (errstr != NULL) { - mbroffset = 0; - gctl_free(grq); - return (error); + + /* + * Compensate for absolute block addressing by finding the + * smallest partition offset and if the offset of the 'c' + * partition is equal to that, subtract it from all offsets. + */ + lba = ~0; + for (i = 0; i < lab.d_npartitions; i++) { + if (lab.d_partitions[i].p_size) + lba = MIN(lba, lab.d_partitions[i].p_offset); } - mbroffset /= lab.d_secsize; - if (lab.d_partitions[RAW_PART].p_offset == mbroffset) - for (i = 0; i < lab.d_npartitions; i++) + if (lba != 0 && lab.d_partitions[RAW_PART].p_offset == lba) { + for (i = 0; i < lab.d_npartitions; i++) { if (lab.d_partitions[i].p_size) - lab.d_partitions[i].p_offset -= mbroffset; + lab.d_partitions[i].p_offset -= lba; + } + /* + * Save the offset so that we can write the label + * back with absolute block addresses. + */ + lba_offset = lba; + } return (error); } diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 index 0c994e6d538..b987cad2e07 100644 --- a/sbin/camcontrol/camcontrol.8 +++ b/sbin/camcontrol/camcontrol.8 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 29, 2009 +.Dd September 4, 2009 .Dt CAMCONTROL 8 .Os .Sh NAME @@ -120,10 +120,12 @@ .Ic cmd .Op device id .Op generic args +.Aq Fl a Ar cmd Op args .Aq Fl c Ar cmd Op args .Op Fl i Ar len Ar fmt .Bk -words .Op Fl o Ar len Ar fmt Op args +.Op Fl r Ar fmt .Ek .Nm .Ic debug @@ -486,12 +488,14 @@ Saved values .El .El .It Ic cmd -Allows the user to send an arbitrary SCSI CDB to any device. +Allows the user to send an arbitrary ATA or SCSI CDB to any device. The .Ic cmd function requires the .Fl c -argument to specify the CDB. +argument to specify SCSI CDB or the +.Fl a +argument to specify ATA Command Block registers values. Other arguments are optional, depending on the command type. The command and data specification syntax is documented @@ -503,9 +507,13 @@ SCSI device in question, you MUST specify either or .Fl o . .Bl -tag -width 17n +.It Fl a Ar cmd Op args +This specifies the content of 12 ATA Command Block registers (command, +features, lba_low, lba_mid, lba_high, device, lba_low_exp, lba_mid_exp. +lba_high_exp, features_exp, sector_count, sector_count_exp). .It Fl c Ar cmd Op args This specifies the SCSI CDB. -CDBs may be 6, 10, 12 or 16 bytes. +SCSI CDBs may be 6, 10, 12 or 16 bytes. .It Fl i Ar len Ar fmt This specifies the amount of data to read, and how it should be displayed. If the format is @@ -519,6 +527,13 @@ If the format is .Sq - , .Ar len bytes of data will be read from standard input and written to the device. +.It Fl r Ar fmt +This specifies that 11 result ATA Command Block registers should be displayed +(status, error, lba_low, lba_mid, lba_high, device, lba_low_exp, lba_mid_exp, +lba_high_exp, sector_count, sector_count_exp), and how. +If the format is +.Sq - , +11 result registers will be written to standard output in hex. .El .It Ic debug Turn on CAM debugging printfs in the kernel. diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index d7bf96a3dad..1bba49cfbcd 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -120,7 +120,7 @@ struct camcontrol_opts { }; #ifndef MINIMALISTIC -static const char scsicmd_opts[] = "c:i:o:"; +static const char scsicmd_opts[] = "a:c:i:o:r"; static const char readdefect_opts[] = "f:GP"; static const char negotiate_opts[] = "acD:O:qR:T:UW:"; #endif @@ -206,6 +206,7 @@ static void cts_print(struct cam_device *device, struct ccb_trans_settings *cts); static void cpi_print(struct ccb_pathinq *cpi); static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi); +static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd); static int get_print_cts(struct cam_device *device, int user_settings, int quiet, struct ccb_trans_settings *cts); static int ratecontrol(struct cam_device *device, int retry_count, @@ -1015,17 +1016,18 @@ atacapprint(struct ata_params *parm) ((u_int64_t)parm->lba_size48_4 << 48); printf("\n"); - printf("Protocol "); + printf("protocol "); + printf("ATA/ATAPI-%d", ata_version(parm->version_major)); if (parm->satacapabilities && parm->satacapabilities != 0xffff) { if (parm->satacapabilities & ATA_SATA_GEN2) - printf("SATA revision 2.x\n"); + printf(" SATA 2.x\n"); else if (parm->satacapabilities & ATA_SATA_GEN1) - printf("SATA revision 1.x\n"); + printf(" SATA 1.x\n"); else - printf("Unknown SATA revision\n"); + printf(" SATA x.x\n"); } else - printf("ATA/ATAPI revision %d\n", ata_version(parm->version_major)); + printf("\n"); printf("device model %.40s\n", parm->model); printf("serial number %.20s\n", parm->serial); printf("firmware revision %.8s\n", parm->revision); @@ -1038,22 +1040,74 @@ atacapprint(struct ata_params *parm) (parm->support.command2 & ATA_SUPPORT_CFA)) printf("CFA supported\n"); - printf("lba%ssupported ", + printf("LBA%ssupported ", parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not "); if (lbasize) printf("%d sectors\n", lbasize); else printf("\n"); - printf("lba48%ssupported ", + printf("LBA48%ssupported ", parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not "); if (lbasize48) printf("%ju sectors\n", (uintmax_t)lbasize48); else printf("\n"); - printf("dma%ssupported\n", + printf("PIO supported PIO"); + if (parm->atavalid & ATA_FLAG_64_70) { + if (parm->apiomodes & 0x02) + printf("4"); + else if (parm->apiomodes & 0x01) + printf("3"); + } else if (parm->mwdmamodes & 0x04) + printf("4"); + else if (parm->mwdmamodes & 0x02) + printf("3"); + else if (parm->mwdmamodes & 0x01) + printf("2"); + else if ((parm->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x200) + printf("2"); + else if ((parm->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x100) + printf("1"); + else + printf("0"); + printf("\n"); + + printf("DMA%ssupported ", parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not "); + if (parm->capabilities1 & ATA_SUPPORT_DMA) { + if (parm->mwdmamodes & 0xff) { + printf("WDMA"); + if (parm->mwdmamodes & 0x04) + printf("2"); + else if (parm->mwdmamodes & 0x02) + printf("1"); + else if (parm->mwdmamodes & 0x01) + printf("0"); + printf(" "); + } + if ((parm->atavalid & ATA_FLAG_88) && + (parm->udmamodes & 0xff)) { + printf("UDMA"); + if (parm->udmamodes & 0x40) + printf("6"); + else if (parm->udmamodes & 0x20) + printf("5"); + else if (parm->udmamodes & 0x10) + printf("4"); + else if (parm->udmamodes & 0x08) + printf("3"); + else if (parm->udmamodes & 0x04) + printf("2"); + else if (parm->udmamodes & 0x02) + printf("1"); + else if (parm->udmamodes & 0x01) + printf("0"); + printf(" "); + } + } + printf("\n"); printf("overlap%ssupported\n", parm->capabilities1 & ATA_SUPPORT_OVERLAP ? " " : " not "); @@ -1070,10 +1124,10 @@ atacapprint(struct ata_params *parm) parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no"); if (parm->satacapabilities && parm->satacapabilities != 0xffff) { - printf("Native Command Queuing (NCQ) %s %s" + printf("Native Command Queuing (NCQ) %s " " %d/0x%02X\n", parm->satacapabilities & ATA_SUPPORT_NCQ ? - "yes" : "no", " -", + "yes" : "no", (parm->satacapabilities & ATA_SUPPORT_NCQ) ? ATA_QUEUE_LEN(parm->queue) : 0, (parm->satacapabilities & ATA_SUPPORT_NCQ) ? @@ -1121,9 +1175,14 @@ ataidentify(struct cam_device *device, int retry_count, int timeout) { union ccb *ccb; struct ata_params *ident_buf; + struct ccb_getdev cgd; u_int i, error = 0; int16_t *ptr; - + + if (get_cgd(device, &cgd) != 0) { + warnx("couldn't get CGD"); + return(1); + } ccb = cam_getccb(device); if (ccb == NULL) { @@ -1152,10 +1211,10 @@ ataidentify(struct cam_device *device, int retry_count, int timeout) /*data_ptr*/(u_int8_t *)ptr, /*dxfer_len*/sizeof(struct ata_params), timeout ? timeout : 30 * 1000); -// if (periph->path->device->protocol == PROTO_ATA) - ata_36bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0); -// else -// ata_36bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); + if (cgd.protocol == PROTO_ATA) + ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0); + else + ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0); /* Disable freezing the device queue */ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; @@ -2019,12 +2078,15 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, u_int32_t flags = CAM_DIR_NONE; u_int8_t *data_ptr = NULL; u_int8_t cdb[20]; + u_int8_t atacmd[12]; struct get_hook hook; int c, data_bytes = 0; int cdb_len = 0; - char *datastr = NULL, *tstr; + int atacmd_len = 0; + int need_res = 0; + char *datastr = NULL, *tstr, *resstr = NULL; int error = 0; - int fd_data = 0; + int fd_data = 0, fd_res = 0; int retval; ccb = cam_getccb(device); @@ -2035,10 +2097,32 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, } bzero(&(&ccb->ccb_h)[1], - sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); + sizeof(union ccb) - sizeof(struct ccb_hdr)); while ((c = getopt(argc, argv, combinedopt)) != -1) { switch(c) { + case 'a': + tstr = optarg; + while (isspace(*tstr) && (*tstr != '\0')) + tstr++; + hook.argc = argc - optind; + hook.argv = argv + optind; + hook.got = 0; + atacmd_len = buff_encode_visit(atacmd, sizeof(atacmd), tstr, + iget, &hook); + /* + * Increment optind by the number of arguments the + * encoding routine processed. After each call to + * getopt(3), optind points to the argument that + * getopt should process _next_. In this case, + * that means it points to the first command string + * argument, if there is one. Once we increment + * this, it should point to either the next command + * line argument, or it should be past the end of + * the list. + */ + optind += hook.got; + break; case 'c': tstr = optarg; while (isspace(*tstr) && (*tstr != '\0')) @@ -2135,6 +2219,16 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, iget, &hook); optind += hook.got; break; + case 'r': + need_res = 1; + hook.argc = argc - optind; + hook.argv = argv + optind; + hook.got = 0; + resstr = cget(&hook, NULL); + if ((resstr != NULL) && (resstr[0] == '-')) + fd_res = 1; + optind += hook.got; + break; default: break; } @@ -2167,50 +2261,51 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, /* Disable freezing the device queue */ flags |= CAM_DEV_QFRZDIS; - /* - * This is taken from the SCSI-3 draft spec. - * (T10/1157D revision 0.3) - * The top 3 bits of an opcode are the group code. The next 5 bits - * are the command code. - * Group 0: six byte commands - * Group 1: ten byte commands - * Group 2: ten byte commands - * Group 3: reserved - * Group 4: sixteen byte commands - * Group 5: twelve byte commands - * Group 6: vendor specific - * Group 7: vendor specific - */ - switch((cdb[0] >> 5) & 0x7) { - case 0: - cdb_len = 6; - break; - case 1: - case 2: - cdb_len = 10; - break; - case 3: - case 6: - case 7: - /* computed by buff_encode_visit */ - break; - case 4: - cdb_len = 16; - break; - case 5: - cdb_len = 12; - break; - } + if (cdb_len) { + /* + * This is taken from the SCSI-3 draft spec. + * (T10/1157D revision 0.3) + * The top 3 bits of an opcode are the group code. + * The next 5 bits are the command code. + * Group 0: six byte commands + * Group 1: ten byte commands + * Group 2: ten byte commands + * Group 3: reserved + * Group 4: sixteen byte commands + * Group 5: twelve byte commands + * Group 6: vendor specific + * Group 7: vendor specific + */ + switch((cdb[0] >> 5) & 0x7) { + case 0: + cdb_len = 6; + break; + case 1: + case 2: + cdb_len = 10; + break; + case 3: + case 6: + case 7: + /* computed by buff_encode_visit */ + break; + case 4: + cdb_len = 16; + break; + case 5: + cdb_len = 12; + break; + } - /* - * We should probably use csio_build_visit or something like that - * here, but it's easier to encode arguments as you go. The - * alternative would be skipping the CDB argument and then encoding - * it here, since we've got the data buffer argument by now. - */ - bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len); + /* + * We should probably use csio_build_visit or something like that + * here, but it's easier to encode arguments as you go. The + * alternative would be skipping the CDB argument and then encoding + * it here, since we've got the data buffer argument by now. + */ + bcopy(cdb, &ccb->csio.cdb_io.cdb_bytes, cdb_len); - cam_fill_csio(&ccb->csio, + cam_fill_csio(&ccb->csio, /*retries*/ retry_count, /*cbfcnp*/ NULL, /*flags*/ flags, @@ -2220,6 +2315,21 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, /*sense_len*/ SSD_FULL_SIZE, /*cdb_len*/ cdb_len, /*timeout*/ timeout ? timeout : 5000); + } else { + atacmd_len = 12; + bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len); + if (need_res) + ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT; + + cam_fill_ataio(&ccb->ataio, + /*retries*/ retry_count, + /*cbfcnp*/ NULL, + /*flags*/ flags, + /*tag_action*/ 0, + /*data_ptr*/ data_ptr, + /*dxfer_len*/ data_bytes, + /*timeout*/ timeout ? timeout : 5000); + } if (((retval = cam_send_ccb(device, ccb)) < 0) || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { @@ -2237,6 +2347,28 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, goto scsicmd_bailout; } + if (atacmd_len && need_res) { + if (fd_res == 0) { + buff_decode_visit(&ccb->ataio.res.status, 11, resstr, + arg_put, NULL); + fprintf(stdout, "\n"); + } else { + fprintf(stdout, + "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + ccb->ataio.res.status, + ccb->ataio.res.error, + ccb->ataio.res.lba_low, + ccb->ataio.res.lba_mid, + ccb->ataio.res.lba_high, + ccb->ataio.res.device, + ccb->ataio.res.lba_low_exp, + ccb->ataio.res.lba_mid_exp, + ccb->ataio.res.lba_high_exp, + ccb->ataio.res.sector_count, + ccb->ataio.res.sector_count_exp); + fflush(stdout); + } + } if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) && (arglist & CAM_ARG_CMD_IN) @@ -2588,46 +2720,71 @@ get_cpi(struct cam_device *device, struct ccb_pathinq *cpi) int retval = 0; ccb = cam_getccb(device); - if (ccb == NULL) { warnx("get_cpi: couldn't allocate CCB"); return(1); } - bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr)); - ccb->ccb_h.func_code = XPT_PATH_INQ; - if (cam_send_ccb(device, ccb) < 0) { warn("get_cpi: error sending Path Inquiry CCB"); - if (arglist & CAM_ARG_VERBOSE) cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); - retval = 1; - goto get_cpi_bailout; } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - if (arglist & CAM_ARG_VERBOSE) cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); - retval = 1; - goto get_cpi_bailout; } - bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq)); get_cpi_bailout: - cam_freeccb(ccb); + return(retval); +} +/* + * Get a get device CCB for the specified device. + */ +static int +get_cgd(struct cam_device *device, struct ccb_getdev *cgd) +{ + union ccb *ccb; + int retval = 0; + + ccb = cam_getccb(device); + if (ccb == NULL) { + warnx("get_cgd: couldn't allocate CCB"); + return(1); + } + bzero(&(&ccb->ccb_h)[1], + sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr)); + ccb->ccb_h.func_code = XPT_GDEV_TYPE; + if (cam_send_ccb(device, ccb) < 0) { + warn("get_cgd: error sending Path Inquiry CCB"); + if (arglist & CAM_ARG_VERBOSE) + cam_error_print(device, ccb, CAM_ESF_ALL, + CAM_EPF_ALL, stderr); + retval = 1; + goto get_cgd_bailout; + } + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (arglist & CAM_ARG_VERBOSE) + cam_error_print(device, ccb, CAM_ESF_ALL, + CAM_EPF_ALL, stderr); + retval = 1; + goto get_cgd_bailout; + } + bcopy(&ccb->cgd, cgd, sizeof(struct ccb_getdev)); + +get_cgd_bailout: + cam_freeccb(ccb); return(retval); } @@ -2673,6 +2830,9 @@ cpi_print(struct ccb_pathinq *cpi) case PI_SOFT_RST: str = "soft reset alternative"; break; + case PI_SATAPM: + str = "SATA Port Multiplier"; + break; default: str = "unknown PI bit set"; break; @@ -2702,6 +2862,12 @@ cpi_print(struct ccb_pathinq *cpi) str = "user has disabled initial BUS RESET or" " controller is in target/mixed mode"; break; + case PIM_NO_6_BYTE: + str = "do not send 6-byte commands"; + break; + case PIM_SEQSCAN: + str = "scan bus sequentially"; + break; default: str = "unknown PIM bit set"; break; @@ -3936,8 +4102,9 @@ usage(int verbose) " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n" " camcontrol modepage [dev_id][generic args] <-m page | -l>\n" " [-P pagectl][-e | -b][-d]\n" -" camcontrol cmd [dev_id][generic args] <-c cmd [args]>\n" -" [-i len fmt|-o len fmt [args]]\n" +" camcontrol cmd [dev_id][generic args]\n" +" <-a cmd [args] | -c cmd [args]>\n" +" [-i len fmt|-o len fmt [args]] [-r fmt]\n" " camcontrol debug [-I][-P][-T][-S][-X][-c]\n" " \n" " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n" diff --git a/sbin/geom/class/label/glabel.8 b/sbin/geom/class/label/glabel.8 index 454cba0c7a6..fff92052339 100644 --- a/sbin/geom/class/label/glabel.8 +++ b/sbin/geom/class/label/glabel.8 @@ -1,5 +1,4 @@ .\" Copyright (c) 2004-2005 Pawel Jakub Dawidek -.\" Copyright (c) 2008-2009 Ivan Voras .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without diff --git a/sbin/geom/class/mirror/geom_mirror.c b/sbin/geom/class/mirror/geom_mirror.c index 38912a34958..6ac4fb9a775 100644 --- a/sbin/geom/class/mirror/geom_mirror.c +++ b/sbin/geom/class/mirror/geom_mirror.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004-2005 Pawel Jakub Dawidek + * Copyright (c) 2004-2009 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,13 +41,12 @@ __FBSDID("$FreeBSD$"); #include #include - uint32_t lib_version = G_LIB_VERSION; uint32_t version = G_MIRROR_VERSION; static char label_balance[] = "split", configure_balance[] = "none"; static intmax_t label_slice = 4096, configure_slice = -1; -static intmax_t insert_priority = 0; +static intmax_t insert_priority = 0, configure_priority = -1; static void mirror_main(struct gctl_req *req, unsigned flags); static void mirror_activate(struct gctl_req *req); @@ -71,10 +70,12 @@ struct g_command class_commands[] = { { 'F', "nofailsync", NULL, G_TYPE_BOOL }, { 'h', "hardcode", NULL, G_TYPE_BOOL }, { 'n', "noautosync", NULL, G_TYPE_BOOL }, + { 'p', "priority", &configure_priority, G_TYPE_NUMBER }, { 's', "slice", &configure_slice, G_TYPE_NUMBER }, G_OPT_SENTINEL }, - NULL, "[-adfFhnv] [-b balance] [-s slice] name" + NULL, "[-adfFhnv] [-b balance] [-s slice] name\n" + "[-v] -p priority name prov" }, { "deactivate", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, NULL, "[-v] name prov ..." diff --git a/sbin/geom/class/mirror/gmirror.8 b/sbin/geom/class/mirror/gmirror.8 index 185b3d3838c..78baf0b3592 100644 --- a/sbin/geom/class/mirror/gmirror.8 +++ b/sbin/geom/class/mirror/gmirror.8 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2004-2005 Pawel Jakub Dawidek +.\" Copyright (c) 2004-2009 Pawel Jakub Dawidek .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 1, 2006 +.Dd August 1, 2009 .Dt GMIRROR 8 .Os .Sh NAME @@ -49,6 +49,12 @@ .Op Fl s Ar slice .Ar name .Nm +.Cm configure +.Op Fl v +.Fl p Ar priority +.Ar name +.Ar prov +.Nm .Cm rebuild .Op Fl v .Ar name @@ -115,8 +121,8 @@ indicates an action to be performed: .It Cm label Create a mirror. The order of components is important, because a component's priority is based on its position -(starting from 0). -The component with the biggest priority is used by the +(starting from 0 to 255). +The component with the biggest priority (the lowest number) is used by the .Cm prefer balance algorithm and is also used as a master component when resynchronization is needed, @@ -159,7 +165,7 @@ Clear metadata on the given providers. Configure the given device. .Pp Additional options include: -.Bl -tag -width ".Fl b Ar balance" +.Bl -tag -width ".Fl p Ar priority" .It Fl a Turn on autosynchronization of stale components. .It Fl b Ar balance @@ -175,6 +181,9 @@ Assumes device is in consistent state. Hardcode providers' names in metadata. .It Fl n Turn off autosynchronization of stale components. +.It Fl p Ar priority +Specifies priority for the given component +.Ar prov . .It Fl s Ar slice Specifies slice size for .Cm split diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c index fc179a4cccc..db3c5e9515e 100644 --- a/sbin/geom/class/part/geom_part.c +++ b/sbin/geom/class/part/geom_part.c @@ -274,8 +274,18 @@ gpart_autofill(struct gctl_req *req) error = geom_gettree(&mesh); if (error) return (error); - cp = find_class(&mesh, gctl_get_ascii(req, "class")); - gp = find_geom(cp, gctl_get_ascii(req, "geom")); + s = gctl_get_ascii(req, "class"); + if (s == NULL) + abort(); + cp = find_class(&mesh, s); + if (cp == NULL) + errx(EXIT_FAILURE, "Class %s not found.", s); + s = gctl_get_ascii(req, "geom"); + if (s == NULL) + abort(); + gp = find_geom(cp, s); + if (gp == NULL) + errx(EXIT_FAILURE, "No such geom: %s.", s); first = atoll(find_geomcfg(gp, "first")); last = atoll(find_geomcfg(gp, "last")); grade = ~0ULL; @@ -536,6 +546,8 @@ gpart_write_partcode(struct gctl_req *req, int idx, void *code, ssize_t size) errx(EXIT_FAILURE, "Class %s not found.", s); } s = gctl_get_ascii(req, "geom"); + if (s == NULL) + abort(); gp = find_geom(classp, s); if (gp == NULL) errx(EXIT_FAILURE, "No such geom: %s.", s); diff --git a/sbin/geom/core/geom.c b/sbin/geom/core/geom.c index 8949b73f559..7f2a281be99 100644 --- a/sbin/geom/core/geom.c +++ b/sbin/geom/core/geom.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004-2005 Pawel Jakub Dawidek + * Copyright (c) 2004-2009 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -98,11 +98,21 @@ usage_command(struct g_command *cmd, const char *prefix) struct g_option *opt; unsigned i; - fprintf(stderr, "%s %s %s", prefix, comm, cmd->gc_name); if (cmd->gc_usage != NULL) { - fprintf(stderr, " %s\n", cmd->gc_usage); + char *pos, *ptr, *sptr; + + sptr = ptr = strdup(cmd->gc_usage); + while ((pos = strsep(&ptr, "\n")) != NULL) { + if (*pos == '\0') + continue; + fprintf(stderr, "%s %s %s %s\n", prefix, comm, + cmd->gc_name, pos); + } + free(sptr); return; } + + fprintf(stderr, "%s %s %s", prefix, comm, cmd->gc_name); if ((cmd->gc_flags & G_FLAG_VERBOSE) != 0) fprintf(stderr, " [-v]"); for (i = 0; ; i++) { diff --git a/sbin/ifconfig/ifgif.c b/sbin/ifconfig/ifgif.c index f9f3524e98e..f91508b53c7 100644 --- a/sbin/ifconfig/ifgif.c +++ b/sbin/ifconfig/ifgif.c @@ -51,36 +51,22 @@ static const char rcsid[] = #include "ifconfig.h" -static void gif_status(int); +#define GIFBITS "\020\1ACCEPT_REV_ETHIP_VER\5SEND_REV_ETHIP_VER" -static struct { - const char *label; - u_int mask; -} gif_opts[] = { - { "ACCEPT_REV_ETHIP_VER", GIF_ACCEPT_REVETHIP }, - { "SEND_REV_ETHIP_VER", GIF_SEND_REVETHIP }, -}; +static void gif_status(int); static void gif_status(int s) { int opts; - int nopts = 0; - size_t i; ifr.ifr_data = (caddr_t)&opts; if (ioctl(s, GIFGOPTS, &ifr) == -1) return; - - printf("\toptions=%d<", opts); - for (i=0; i < sizeof(gif_opts)/sizeof(gif_opts[0]); i++) { - if (opts & gif_opts[i].mask) { - if (nopts++) - printf(","); - printf("%s", gif_opts[i].label); - } - } - printf(">\n"); + if (opts == 0) + return; + printb("\toptions", opts, GIFBITS); + putchar('\n'); } static void diff --git a/sbin/route/route.8 b/sbin/route/route.8 index 65a1de16607..59567865ccf 100644 --- a/sbin/route/route.8 +++ b/sbin/route/route.8 @@ -279,7 +279,6 @@ when sending to destinations matched by the routes. These flags may be set (or sometimes cleared) by indicating the following corresponding modifiers: .Bd -literal --cloning RTF_CLONING - generates a new route on use -xresolve RTF_XRESOLVE - emit mesg on use (for external lookup) -iface ~RTF_GATEWAY - destination is directly reachable -static RTF_STATIC - manually added route @@ -288,7 +287,6 @@ by indicating the following corresponding modifiers: -blackhole RTF_BLACKHOLE - silently discard pkts (during updates) -proto1 RTF_PROTO1 - set protocol specific routing flag #1 -proto2 RTF_PROTO2 - set protocol specific routing flag #2 --llinfo RTF_LLINFO - validly translates proto addr to link addr .Ed .Pp The optional modifiers @@ -326,25 +324,6 @@ or .Fl ifa modifiers may be used to determine the interface or interface address. .Pp -The optional -.Fl proxy -modifier specifies that the -.Dv RTF_LLINFO -routing table entry is the -.Dq published (proxy-only) -.Tn ARP -entry, as reported by -.Xr arp 8 . -.Pp -The optional -.Fl genmask -modifier specifies that a cloning mask is present. -This specifies the mask applied when determining if a child route -should be created. -It is only applicable to network routes with the -.Dv RTF_CLONING -flag set. -.Pp All symbolic names specified for a .Ar destination or diff --git a/sbin/route/route.c b/sbin/route/route.c index e20cedbcee3..4380f42196a 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -37,10 +37,11 @@ static const char copyright[] = #if 0 static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95"; #endif -static const char rcsid[] = - "$FreeBSD$"; #endif /* not lint */ +#include +__FBSDID("$FreeBSD$"); + #include #include #include @@ -92,29 +93,44 @@ union sockunion { typedef union sockunion *sup; int pid, rtm_addrs; int s; -int forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword(); +int forcehost, forcenet, doflush, nflag, af, qflag, tflag; int iflag, verbose, aflen = sizeof (struct sockaddr_in); int locking, lockrest, debugonly; struct rt_metrics rt_metrics; u_long rtm_inits; uid_t uid; + int atalk_aton(const char *, struct at_addr *); char *atalk_ntoa(struct at_addr); -const char *routename(), *netname(); -void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf(); -void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr(); +void bprintf(FILE *, int, u_char *); +void flushroutes(int argc, char *argv[]); +int getaddr(int, char *, struct hostent **); +int keyword(char *); +void inet_makenetandmask(u_long, struct sockaddr_in *, u_long); #ifdef INET6 static int inet6_makenetandmask(struct sockaddr_in6 *, char *); #endif -int getaddr(), rtmsg(), x25_makemask(); -int prefixlen(); +void interfaces(void); +void mask_addr(void); +void monitor(void); +const char *netname(struct sockaddr *); +void newroute(int, char **); +void pmsg_addrs(char *, int); +void pmsg_common(struct rt_msghdr *); +int prefixlen(char *); +void print_getmsg(struct rt_msghdr *, int); +void print_rtmsg(struct rt_msghdr *, int); +const char *routename(struct sockaddr *); +int rtmsg(int, int); +void set_metric(char *, int); +void sockaddr(char *, struct sockaddr *); +void sodump(sup, char *); extern char *iso_ntoa(); void usage(const char *) __dead2; void -usage(cp) - const char *cp; +usage(const char *cp) { if (cp) warnx("bad keyword: %s", cp); @@ -125,9 +141,7 @@ usage(cp) } int -main(argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { int ch; @@ -198,9 +212,7 @@ main(argc, argv) * associated with network interfaces. */ void -flushroutes(argc, argv) - int argc; - char *argv[]; +flushroutes(int argc, char *argv[]) { size_t needed; int mib[6], rlen, seqno, count = 0; @@ -301,8 +313,7 @@ retry: } const char * -routename(sa) - struct sockaddr *sa; +routename(struct sockaddr *sa) { char *cp; static char line[MAXHOSTNAMELEN + 1]; @@ -410,8 +421,7 @@ routename(sa) * The address is assumed to be that of a net or subnet, not a host. */ const char * -netname(sa) - struct sockaddr *sa; +netname(struct sockaddr *sa) { char *cp = 0; static char line[MAXHOSTNAMELEN + 1]; @@ -532,9 +542,7 @@ netname(sa) } void -set_metric(value, key) - char *value; - int key; +set_metric(char *value, int key) { int flag = 0; u_long noval, *valp = &noval; @@ -560,11 +568,9 @@ set_metric(value, key) } void -newroute(argc, argv) - int argc; - char **argv; +newroute(int argc, char **argv) { - char *cmd, *dest = "", *gateway = "", *err; + char *cmd, *dest = "", *gateway = "", *errmsg; int ishost = 0, proxy = 0, ret, attempts, oerrno, flags = RTF_STATIC; int key; struct hostent *hp = 0; @@ -767,35 +773,33 @@ newroute(argc, argv) } else { switch (oerrno) { case ESRCH: - err = "not in table"; + errmsg = "not in table"; break; case EBUSY: - err = "entry in use"; + errmsg = "entry in use"; break; case ENOBUFS: - err = "not enough memory"; + errmsg = "not enough memory"; break; case EADDRINUSE: /* handle recursion avoidance in rt_setgate() */ - err = "gateway uses the same route"; + errmsg = "gateway uses the same route"; break; case EEXIST: - err = "route already in table"; + errmsg = "route already in table"; break; default: - err = strerror(oerrno); + errmsg = strerror(oerrno); break; } - (void) printf(": %s\n", err); + (void) printf(": %s\n", errmsg); } } exit(ret != 0); } void -inet_makenetandmask(net, sin, bits) - u_long net, bits; - struct sockaddr_in *sin; +inet_makenetandmask(u_long net, struct sockaddr_in *sin, u_long bits) { u_long addr, mask = 0; char *cp; @@ -847,9 +851,7 @@ inet_makenetandmask(net, sin, bits) * XXX the function may need more improvement... */ static int -inet6_makenetandmask(sin6, plen) - struct sockaddr_in6 *sin6; - char *plen; +inet6_makenetandmask(struct sockaddr_in6 *sin6, char *plen) { struct in6_addr in6; @@ -879,10 +881,7 @@ inet6_makenetandmask(sin6, plen) * returning 1 if a host address, 0 if a network address. */ int -getaddr(which, s, hpp) - int which; - char *s; - struct hostent **hpp; +getaddr(int which, char *s, struct hostent **hpp) { sup su; struct hostent *hp; @@ -1077,8 +1076,7 @@ netdone: } int -prefixlen(s) - char *s; +prefixlen(char *s) { int len = atoi(s), q, r; int max; @@ -1123,7 +1121,7 @@ prefixlen(s) } void -interfaces() +interfaces(void) { size_t needed; int mib[6]; @@ -1158,7 +1156,7 @@ retry2: } void -monitor() +monitor(void) { int n; char msg[2048]; @@ -1183,8 +1181,7 @@ struct { } m_rtmsg; int -rtmsg(cmd, flags) - int cmd, flags; +rtmsg(int cmd, int flags) { static int seq; int rlen; @@ -1254,7 +1251,7 @@ rtmsg(cmd, flags) } void -mask_addr() +mask_addr(void) { int olen = so_mask.sa.sa_len; char *cp1 = olen + (char *)&so_mask, *cp2; @@ -1322,9 +1319,7 @@ char addrnames[] = "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; void -print_rtmsg(rtm, msglen) - struct rt_msghdr *rtm; - int msglen; +print_rtmsg(struct rt_msghdr *rtm, int msglen) { struct if_msghdr *ifm; struct ifa_msghdr *ifam; @@ -1405,9 +1400,7 @@ print_rtmsg(rtm, msglen) } void -print_getmsg(rtm, msglen) - struct rt_msghdr *rtm; - int msglen; +print_getmsg(struct rt_msghdr *rtm, int msglen) { struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL; struct sockaddr_dl *ifp = NULL; @@ -1415,7 +1408,8 @@ print_getmsg(rtm, msglen) char *cp; int i; - (void) printf(" route to: %s\n", routename(&so_dst)); + (void) printf(" route to: %s\n", + routename((struct sockaddr *)&so_dst)); if (rtm->rtm_version != RTM_VERSION) { warnx("routing message version %d not understood", rtm->rtm_version); @@ -1500,8 +1494,7 @@ print_getmsg(rtm, msglen) } void -pmsg_common(rtm) - struct rt_msghdr *rtm; +pmsg_common(struct rt_msghdr *rtm) { (void) printf("\nlocks: "); bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); @@ -1511,9 +1504,7 @@ pmsg_common(rtm) } void -pmsg_addrs(cp, addrs) - char *cp; - int addrs; +pmsg_addrs(char *cp, int addrs) { struct sockaddr *sa; int i; @@ -1536,10 +1527,7 @@ pmsg_addrs(cp, addrs) } void -bprintf(fp, b, s) - FILE *fp; - int b; - u_char *s; +bprintf(FILE *fp, int b, u_char *s) { int i; int gotsome = 0; @@ -1565,8 +1553,7 @@ bprintf(fp, b, s) } int -keyword(cp) - char *cp; +keyword(char *cp) { struct keytab *kt = keywords; @@ -1576,9 +1563,7 @@ keyword(cp) } void -sodump(su, which) - sup su; - char *which; +sodump(sup su, char *which) { switch (su->sa.sa_family) { case AF_LINK: @@ -1607,9 +1592,7 @@ sodump(su, which) #define DELIM (4*2) void -sockaddr(addr, sa) - char *addr; - struct sockaddr *sa; +sockaddr(char *addr, struct sockaddr *sa) { char *cp = (char *)sa; int size = sa->sa_len; diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index 77636488e9e..c115c725f3e 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -97,6 +97,9 @@ static int nfound, nsaved, nerr; /* statistics */ extern FILE *zopen(const char *, const char *); +static sig_atomic_t got_siginfo; +static void infohandler(int); + static void printheader(FILE *f, const struct kerneldumpheader *h, const char *device, int bounds, const int status) @@ -231,9 +234,10 @@ DoRegularFile(int fd, off_t dumpsize, char *buf, const char *device, const char *filename, FILE *fp) { int he, hs, nr, nw, wl; - off_t dmpcnt; + off_t dmpcnt, origsize; dmpcnt = 0; + origsize = dumpsize; he = 0; while (dumpsize > 0) { wl = BUFFERSIZE; @@ -304,6 +308,11 @@ DoRegularFile(int fd, off_t dumpsize, char *buf, const char *device, fflush(stdout); } dumpsize -= wl; + if (got_siginfo) { + printf("%s %.1lf%%\n", filename, (100.0 - (100.0 * + (double)dumpsize / (double)origsize))); + got_siginfo = 0; + } } return (0); } @@ -648,6 +657,7 @@ main(int argc, char **argv) nfound = nsaved = nerr = 0; openlog("savecore", LOG_PERROR, LOG_DAEMON); + signal(SIGINFO, infohandler); while ((ch = getopt(argc, argv, "Ccfkvz")) != -1) switch(ch) { @@ -719,3 +729,9 @@ main(int argc, char **argv) return (0); } + +static void +infohandler(int sig __unused) +{ + got_siginfo = 1; +} diff --git a/sbin/umount/umount.8 b/sbin/umount/umount.8 index d19ea9ae7a4..42b55ee724f 100644 --- a/sbin/umount/umount.8 +++ b/sbin/umount/umount.8 @@ -57,7 +57,8 @@ device or remote node (rhost:path), the path to the mount point or by the file system ID .Ar fsid as reported by -.Dq mount -v . +.Dq mount -v +when run by root. .Pp The options are as follows: .Bl -tag -width indent diff --git a/share/colldef/Makefile b/share/colldef/Makefile index b29f774b34d..4b68f1e59a4 100644 --- a/share/colldef/Makefile +++ b/share/colldef/Makefile @@ -20,6 +20,7 @@ LOCALES= bg_BG.CP1251 \ is_IS.ISO8859-15 \ kk_KZ.PT154 \ la_LN.ISO8859-1 \ + la_LN.ISO8859-13 \ la_LN.ISO8859-15 \ la_LN.ISO8859-2 \ la_LN.ISO8859-4 \ @@ -27,7 +28,6 @@ LOCALES= bg_BG.CP1251 \ no_NO.ISO8859-1 \ no_NO.ISO8859-15 \ lt_LT.ISO8859-4 \ - lt_LT.ISO8859-13 \ pl_PL.ISO8859-2 \ ru_RU.CP1251 \ ru_RU.CP866 \ @@ -62,7 +62,7 @@ ${locale}.out: map.${locale:E} CLEANFILES= ${FILES} ENCODINGS= Big5 Big5HKSCS CP949 eucCN eucJP eucKR GB18030 GB2312 GBK \ - ISO8859-1 ISO8859-2 ISO8859-15 SJIS US-ASCII UTF-8 + ISO8859-1 ISO8859-2 ISO8859-13 ISO8859-15 SJIS US-ASCII UTF-8 ISO8859-1_Big5= is_IS:zh_TW ISO8859-1_ISO8859-1= ${ISO8859-15_ISO8859-15} pt_PT:pt_BR @@ -78,6 +78,9 @@ ISO8859-15_ISO8859-15= \ LATIN2LINKS= hu_HU ro_RO sr_YU ISO8859-2_ISO8859-2= ${LATIN2LINKS:C/^/la_LN:/} cs_CZ:sk_SK +LATIN13LINKS= lt_LT lv_LV +ISO8859-13_ISO8859-13= ${LATIN13LINKS:C/^/la_LN:/} + US-ASCII_Big5HKSCS= la_LN:zh_HK US-ASCII_CP949= la_LN:ko_KR US-ASCII_eucCN= la_LN:zh_CN @@ -95,7 +98,7 @@ UTF8LINKS= af_ZA am_ET be_BY bg_BG ca_AD ca_ES ca_FR ca_IT cs_CZ \ da_DK de_AT de_CH de_DE \ el_GR en_AU en_CA en_GB en_IE en_NZ en_US es_ES et_EE eu_ES \ fi_FI fr_BE fr_CA fr_CH fr_FR he_IL hr_HR hu_HU hy_AM \ - is_IS it_CH it_IT ja_JP kk_KZ ko_KR lt_LT mn_MN \ + is_IS it_CH it_IT ja_JP kk_KZ ko_KR lt_LT lv_LV mn_MN \ nb_NO nl_BE nl_NL nn_NO no_NO pl_PL pt_BR pt_PT \ ro_RO ru_RU sk_SK sl_SI sr_YU sv_SE tr_TR uk_UA zh_CN zh_HK \ zh_TW diff --git a/share/colldef/lt_LT.ISO8859-13.src b/share/colldef/lt_LT.ISO8859-13.src deleted file mode 100644 index 811db89f7c8..00000000000 --- a/share/colldef/lt_LT.ISO8859-13.src +++ /dev/null @@ -1,37 +0,0 @@ -# Lithuanian (backward compatible with ASCII) -# -# $FreeBSD$ -# -charmap map.ISO8859-13 -order \ -# controls - ;...;;;...;;\ -# - ;;!;\";<"">;;\ - ;;;;\ - %;&;';\(;\);*;+;<-:>;<*X>;<.M>;\,;<,,>;<``>;<-->;<+->;-;.;<'.>;/;\ -# digits - 0;...;9;\ -# - :;\;;\<;=;>;<<<>;/>>;?;;;;\ -# capital - (A,,,,,);\ - B;(C,,);D;(E,,,,);\ - F;(G,);H;(I,,);Y;\ - J;(K,);(L,,);M;(N,,);(O,,,,,);\ - P;Q;(R,);(S,,);T;\ - (U,,,);\ - V;W;X;(Z,,,);\ -# - [;\\;];^;_;`;\ -# small - (a,,,,,);\ - b;(c,,);d;(e,,,,);\ - f;(g,);h;(i,,);y;\ - j;(k,);(l,,);m;(n,,);(o,,,,,);\ - p;q;(r,);(s,,,);t;\ - (u,,,);\ - v;w;x;(z,,,);\ -# - \{;|;;\};~;;
;;;;;<1S>;<2S>;<3S>;\ - <14>;<12>;<34> diff --git a/share/examples/cvsup/stable-supfile b/share/examples/cvsup/stable-supfile index 3b0c8e96892..7f4f0e9c61c 100644 --- a/share/examples/cvsup/stable-supfile +++ b/share/examples/cvsup/stable-supfile @@ -66,10 +66,11 @@ *default host=CHANGE_THIS.FreeBSD.org *default base=/var/db *default prefix=/usr -# The following line is for 7-stable. If you want 6-stable, 5-stable, -# 4-stable, 3-stable, or 2.2-stable, change to "RELENG_6", "RELENG_5", -# "RELENG_4", "RELENG_3", or "RELENG_2_2" respectively. -*default release=cvs tag=RELENG_7 +# The following line is for 8-stable. If you want 7-stable, 6-stable, +# 5-stable, 4-stable, 3-stable, or 2.2-stable, change to "RELENG_7", +# "RELENG_6", "RELENG_5", "RELENG_4", "RELENG_3", or "RELENG_2_2" +# respectively. +*default release=cvs tag=RELENG_8 *default delete use-rel-suffix # If you seem to be limited by CPU rather than network or disk bandwidth, try diff --git a/share/examples/scsi_target/scsi_target.c b/share/examples/scsi_target/scsi_target.c index c9686f955db..1cf0bf5da1e 100644 --- a/share/examples/scsi_target/scsi_target.c +++ b/share/examples/scsi_target/scsi_target.c @@ -226,7 +226,7 @@ main(int argc, char *argv[]) /* Open backing store for IO */ file_fd = open(file_name, O_RDWR); if (file_fd < 0) - err(1, "open backing store file"); + errx(EX_NOINPUT, "open backing store file"); /* Check backing store size or use the size user gave us */ if (user_size == 0) { @@ -291,7 +291,9 @@ main(int argc, char *argv[]) } while (targ_fd < 0 && errno == EBUSY); if (targ_fd < 0) - err(1, "Tried to open %d devices, none available", unit); + errx(1, "Tried to open %d devices, none available", unit); + else + warnx("opened /dev/targ%d", unit); /* The first three are handled by kevent() later */ signal(SIGHUP, SIG_IGN); @@ -318,6 +320,7 @@ main(int argc, char *argv[]) /* Set up inquiry data according to what SIM supports */ if (get_sim_flags(&sim_flags) != CAM_REQ_CMP) errx(1, "get_sim_flags"); + if (tcmd_init(req_flags, sim_flags) != 0) errx(1, "Initializing tcmd subsystem failed"); @@ -327,6 +330,7 @@ main(int argc, char *argv[]) if (debug) warnx("main loop beginning"); + request_loop(); exit(0); diff --git a/share/examples/scsi_target/scsi_target.h b/share/examples/scsi_target/scsi_target.h index 3d94810d149..51af49225b6 100644 --- a/share/examples/scsi_target/scsi_target.h +++ b/share/examples/scsi_target/scsi_target.h @@ -35,7 +35,7 @@ * Maximum number of parallel commands to accept, * 1024 for Fibre Channel (SPI is 16). */ -#define MAX_INITIATORS 1024 +#define MAX_INITIATORS 8 #define SECTOR_SIZE 512 #define MAX_EVENTS (MAX_INITIATORS + 5) /* kqueue for AIO, signals */ diff --git a/share/man/man4/ahci.4 b/share/man/man4/ahci.4 index 0173e1e7bc0..46660d3a273 100644 --- a/share/man/man4/ahci.4 +++ b/share/man/man4/ahci.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 26, 2009 +.Dd August 24, 2009 .Dt AHCI 4 .Os .Sh NAME @@ -60,6 +60,13 @@ single MSI vector used, if supported (default); .It 2 multiple MSI vectors used, if supported; .El +.It Va hint.ahci.X.ccc +controls Command Completion Coalescing (CCC) usage by the specified controller. +Non-zero value enables CCC and defines maximum time (in ms), request can wait +for interrupt, if there are some more requests present on controller queue. +CCC reduces number of context switches on systems with many parallel requests, +but it can decrease disk performance on some workloads due to additional +command latency. .It Va hint.ahcich.X.pm_level controls SATA interface Power Management for specified channel, allowing some power to be saved at the cost of additional command @@ -74,7 +81,15 @@ device is allowed to initiate PM state change, host is passive; host initiates PARTIAL PM state transition every time port becomes idle; .It 3 host initiates SLUMBER PM state transition every time port becomes idle. +.It 4 +driver initiates PARTIAL PM state transition 1ms after port becomes idle; +.It 5 +driver initiates SLUMBER PM state transition 125ms after port becomes idle. .El +Some controllers, such as ICH8, do not implement modes 2 and 3 with NCQ used. +Because of artificial entering latency, performance degradation in modes +4 and 5 is much smaller then in modes 2 and 3. +.Pp Note that interface Power Management is not compatible with device presence detection. You will have to reset bus manually on device hot-plug. diff --git a/share/man/man4/ip6.4 b/share/man/man4/ip6.4 index 633537bb1ec..caf5ae5a404 100644 --- a/share/man/man4/ip6.4 +++ b/share/man/man4/ip6.4 @@ -692,7 +692,7 @@ An ancillary data object was improperly formed. Most of the socket options are defined in RFC 2292 or RFC 2553. The .Dv IPV6_V6ONLY -socket option is defined in RFC 3542. +socket option is defined in RFC 3493 Section 5.3. The .Dv IPV6_PORTRANGE socket option and the conflict resolution rule are not defined in the diff --git a/share/man/man4/ips.4 b/share/man/man4/ips.4 index 26fc261a02d..0a38d5b4471 100644 --- a/share/man/man4/ips.4 +++ b/share/man/man4/ips.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 4, 2006 +.Dd August 7, 2009 .Dt IPS 4 .Os .Sh NAME @@ -92,6 +92,12 @@ ServeRAID 6i/6M .It ServeRAID 7t/7k/7M .El +.Pp +Newer ServeRAID controllers are supported by the +.Xr aac 4 +or +.Xr mfi 4 +driver. .Sh DIAGNOSTICS Several error codes may be shown when the card initializes the .Tn IBM @@ -180,6 +186,8 @@ driver does not use the .Tn SCSI subsystem. .Sh SEE ALSO +.Xr aac 4 , +.Xr mfi 4 , .Xr ch 4 , .Xr da 4 , .Xr sysctl 8 diff --git a/share/man/man4/mfi.4 b/share/man/man4/mfi.4 index 2288ecbbe6e..8ab8d938100 100644 --- a/share/man/man4/mfi.4 +++ b/share/man/man4/mfi.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 17, 2008 +.Dd August 15, 2009 .Dt MFI 4 .Os .Sh NAME @@ -103,7 +103,8 @@ An attempt was made to remove a mounted volume. .El .Sh SEE ALSO .Xr amr 4 , -.Xr pci 4 +.Xr pci 4 , +.Xr mfiutil 8 .Sh HISTORY The .Nm diff --git a/share/man/man4/mpt.4 b/share/man/man4/mpt.4 index f9659fd2334..9a38f29e27e 100644 --- a/share/man/man4/mpt.4 +++ b/share/man/man4/mpt.4 @@ -35,7 +35,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 6, 2007 +.Dd August 15, 2009 .Dt MPT 4 .Os .Sh NAME @@ -155,6 +155,7 @@ can take on - no separate compilation is required. .Xr sa 4 , .Xr scsi 4 , .Xr targ 4 , +.Xr mptutil 8 , .Xr gmultipath 8 .Rs .%T "LSI Logic Website" diff --git a/share/man/man4/polling.4 b/share/man/man4/polling.4 index fea0bfb7988..2c711cc7d8d 100644 --- a/share/man/man4/polling.4 +++ b/share/man/man4/polling.4 @@ -87,6 +87,16 @@ feature. It is turned on and off with help of .Xr ifconfig 8 command. +.Pp +The historic +.Va kern.polling.enable , +which enabled polling for all interfaces, can be replaced with the following +code: +.Bd -literal +for i in `ifconfig -l` ; + do ifconfig $i polling; # use -polling to disable +done +.Ed .Ss MIB Variables The operation of .Nm @@ -156,15 +166,6 @@ Default is 20. How many active devices have registered for .Nm . .Pp -.It Va kern.polling.enable -Legacy MIB, that was used to enable or disable polling globally. -Currently if set to 1, -.Nm -is enabled on all capable interfaces. -If set to 0, -.Nm -is disabled on all interfaces. -.Pp .It Va kern.polling.short_ticks .It Va kern.polling.lost_polls .It Va kern.polling.pending_polls diff --git a/share/man/man4/pts.4 b/share/man/man4/pts.4 index dc13a90014f..d0e8832b959 100644 --- a/share/man/man4/pts.4 +++ b/share/man/man4/pts.4 @@ -147,15 +147,6 @@ The files used by this pseudo-terminals implementation are: .Pp .Bl -tag -width ".Pa /dev/pts/[num]" -.It Pa /dev/ptmx -Control device, returns a file descriptor to a new master -pseudo-terminal when opened. -This device should not be opened directly. -It's only available for binary compatibility. -New devices should only be allocated with -.Xr posix_openpt 2 -and -.Xr openpty 3 . .It Pa /dev/pts/[num] Pseudo-terminal slave devices. .El diff --git a/share/man/man4/pty.4 b/share/man/man4/pty.4 index 515f912363b..f72a8bee81c 100644 --- a/share/man/man4/pty.4 +++ b/share/man/man4/pty.4 @@ -32,7 +32,7 @@ .Os .Sh NAME .Nm pty -.Nd BSD-style compatibility pseudo-terminal driver +.Nd BSD-style and System V-style compatibility pseudo-terminal driver .Sh SYNOPSIS .Cd "device pty" .Sh DESCRIPTION @@ -48,6 +48,12 @@ driver. A device node for this terminal shall be created, which has the name .Pa /dev/ttyXX . .Pp +The +.Nm +driver also provides a cloning System V +.Pa /dev/ptmx +device. +.Pp New code should not try to allocate pseudo-terminals using this interface. It is only provided for compatibility with older C libraries @@ -63,6 +69,9 @@ device names: Pseudo-terminal master devices. .It Pa /dev/tty[l-sL-S][0-9a-v] Pseudo-terminal slave devices. +.It Pa /dev/ptmx +Control device, returns a file descriptor to a new master +pseudo-terminal when opened. .El .Sh DIAGNOSTICS None. @@ -75,7 +84,7 @@ A pseudo-terminal driver appeared in .Bx 4.2 . .Sh BUGS -Unlike previous implementations, the master slave device nodes are +Unlike previous implementations, the master and slave device nodes are destroyed when the PTY becomes unused. A call to .Xr stat 2 diff --git a/share/man/man5/freebsd-update.conf.5 b/share/man/man5/freebsd-update.conf.5 index 29775fdb276..d3721028e26 100644 --- a/share/man/man5/freebsd-update.conf.5 +++ b/share/man/man5/freebsd-update.conf.5 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 30, 2006 +.Dd August 19, 2009 .Dt FREEBSD-UPDATE.CONF 5 .Os FreeBSD .Sh NAME @@ -48,7 +48,7 @@ error. .Pp The possible options and their meanings are as follows: .Pp -.Bl -tag -width "KeepModifiedMetadata" +.Bl -tag -width ".Cm BackupKernelSymbolFiles" .It Cm KeyPrint The single parameter following this keyword is the SHA256 hash of the RSA key which will be trusted to sign updates. @@ -171,6 +171,54 @@ command is used ("yes"), or merely as a list of components which might be installed, of which .Cm freebsd-update should identify which in fact are present ("no"). +.It Cm BackupKernel +The single parameter following this keyword must be +.Dq yes +or +.Dq no +and specifies whether +.Cm freebsd-update +will create a backup of the old kernel before installing a new kernel. +This backup kernel can be used to recover a system where the newly +installed kernel somehow did not work. +Note that the backup kernel is not reverted to its original state by +the +.Cm freebsd-update +rollback command. +.It Cm BackupKernelDir +This keyword sets the directory which is used to store a backup +kernel, if the BackupKernel feature is enabled. +If the directory already exist, and it was not created by +.Cm freebsd-update , +the directory is skipped. +In the case of the primary directory name not being usable, a number +starting with +.Sq 1 +is appended to the directory name. +Like with the primary directory name, the constructed directory name is +only used if the path name does not exist, or if the directory was +previously created by +.Cm freebsd-update . +If the constructed directory still exist the appended number is +incremented with 1 and the directory search process restarted. +Should the number increment go above 9, +.Cm freebsd-update +will abort. +.It Cm BackupKernelSymbolFiles +The single parameter following this keyword must be +.Dq yes +or +.Dq no +and specifies whether +.Cm freebsd-update +will also backup kernel symbol files, if they exist. +The kernel symbol files takes up a lot of disk space and are not +needed for recovery purposes. +If the symbol files are needed, after recovering a system using the +backup kernel, the +.Cm freebsd-update +rollback command will recreate the symbol files along with the old +kernel. .El .Sh FILES .Bl -tag -width "/etc/freebsd-update.conf" diff --git a/share/man/man5/make.conf.5 b/share/man/man5/make.conf.5 index f8dbef491cf..a1428013e26 100644 --- a/share/man/man5/make.conf.5 +++ b/share/man/man5/make.conf.5 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 5, 2006 +.Dd September 1, 2009 .Dt MAKE.CONF 5 .Os .Sh NAME @@ -466,6 +466,12 @@ console driver to and allow access over FireWire(IEEE1394) using .Xr dconschat 8 . Currently, only i386 and amd64 are supported. +.It Va MALLOC_PRODUCTION +.Pq Vt bool +Set this to disable assertions and statistics gathering in +.Xr malloc 3 . +It also defaults the A and J runtime options to off. +Disabled by default on -CURRENT. .It Va MODULES_WITH_WORLD .Pq Vt bool Set to build modules with the system instead of the kernel. diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index 3075a4e7083..9d2ba4346c8 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 10, 2009 +.Dd August 25, 2009 .Dt RC.CONF 5 .Os .Sh NAME @@ -2227,6 +2227,22 @@ name server!). .Pq Vt str The IPv6 equivalent of .Va defaultrouter . +.It Va static_arp_pairs +.Pq Vt str +Set to the list of static ARP pairs that are to be added at system +boot time. +For each whitespace separated +.Ar element +in the value, a +.Va static_arp_ Ns Aq Ar element +variable is assumed to exist whose contents will later be passed to a +.Dq Nm arp Cm -S +operation. +For example +.Bd -literal +static_arp_pairs="gw" +static_arp_gw="192.168.1.1 00:01:02:03:04:05" +.Ed .It Va static_routes .Pq Vt str Set to the list of static routes that are to be added at system diff --git a/share/man/man5/tmpfs.5 b/share/man/man5/tmpfs.5 index ef21a8c7131..12f392a8fd1 100644 --- a/share/man/man5/tmpfs.5 +++ b/share/man/man5/tmpfs.5 @@ -70,6 +70,7 @@ permissions in octal format. maximum number of inodes. .It Cm size maximum size (in bytes) for the file system. +.El .Sh EXAMPLES To mount a .Nm diff --git a/share/man/man7/release.7 b/share/man/man7/release.7 index a026db51d3e..68c431cfded 100644 --- a/share/man/man7/release.7 +++ b/share/man/man7/release.7 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 12, 2006 +.Dd August 17, 2009 .Dt RELEASE 7 .Os .Sh NAME @@ -332,6 +332,10 @@ patch file. A script that will be run in the .Xr chroot 8 environment immediately after any local patches are applied. +.It Va MAKE_DVD +If defined, build a bootable ISO DVD image in the CD-ROM +stage directory. +This option may not be available for all architectures. .It Va MAKE_ISOS If defined, bootable ISO CD-ROM images will be created from the contents of the CD-ROM stage directory. @@ -390,6 +394,35 @@ of the CVS tree .It Va SEPARATE_LIVEFS Store the live file system on its own CD-ROM image rather than placing it on the first disc. +.It Va SVNCMDARGS +Additional arguments for svn +.Ic checkout +and +.Ic switch +commands. +.It Va SVNROOT +The location of the FreeBSD SVN source repository. +If this variable is set, +then the source tree will be extracted using Subversion rather than +CVS. +.It Va SVNBRANCH +The branch to check out from a SVN source repository. +It is specified as a path such as +.Pa head +or +.Pa stable/7 . +If this variable is not set, +then the branch that corresponds to the current value of +.Va RELEASETAG +will be used. +If neither +.Va SVNBRANCH +nor +.Va RELEASETAG +are set, +then the +.Pa head +branch will be used. .It Va TARGET_ARCH The target machine processor architecture. This is analogous to the @@ -474,6 +507,7 @@ make release CHROOTDIR=/local3/release BUILDNAME=6.0-CURRENT \\ .Xr install 1 , .Xr make 1 , .Xr patch 1 , +.Xr svn 1 Pq Pa ports/devel/subversion-freebsd , .Xr uname 1 , .Xr md 4 , .Xr make.conf 5 , @@ -511,7 +545,7 @@ effort was spent getting into a shape where it could at least automate most of the tediousness of building a release in a sterile environment. .Pp -With its almost 1000 revisions spread over multiple branches, the +At near 1000 revisions spread over multiple branches, the .Xr cvs 1 log of .Pa src/release/Makefile diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 844e117eddc..86b5838c112 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -121,13 +121,19 @@ MAN= accept_filter.9 \ hashinit.9 \ hexdump.9 \ ieee80211.9 \ + ieee80211_amrr.9 \ + ieee80211_beacon.9 \ + ieee80211_bmiss.9 \ ieee80211_crypto.9 \ + ieee80211_ddb.9 \ ieee80211_input.9 \ - ieee80211_ioctl.9 \ ieee80211_node.9 \ ieee80211_output.9 \ ieee80211_proto.9 \ ieee80211_radiotap.9 \ + ieee80211_regdomain.9 \ + ieee80211_scan.9 \ + ieee80211_vap.9 \ ifnet.9 \ inittodr.9 \ insmntque.9 \ @@ -627,52 +633,62 @@ MLINKS+=hash.9 hash32.9 \ MLINKS+=hashinit.9 hashdestroy.9 \ hashinit.9 hashinit_flags.9 \ hashinit.9 phashinit.9 -MLINKS+=ieee80211.9 ieee80211_attach.9 \ - ieee80211.9 ieee80211_chan2ieee.9 \ - ieee80211.9 ieee80211_chan2mode.9 \ - ieee80211.9 ieee80211_ieee2mhz.9 \ - ieee80211.9 ieee80211_ifattach.9 \ - ieee80211.9 ieee80211_ifdetach.9 \ - ieee80211.9 ieee80211_media2rate.9 \ - ieee80211.9 ieee80211_media_change.9 \ - ieee80211.9 ieee80211_media_init.9 \ - ieee80211.9 ieee80211_media_status.9 \ - ieee80211.9 ieee80211_mhz2ieee.9 \ - ieee80211.9 ieee80211_rate2media.9 \ - ieee80211.9 ieee80211_setmode.9 \ - ieee80211.9 ieee80211_watchdog.9 -MLINKS+=ieee80211_crypto.9 ieee80211_crypto_attach.9 \ - ieee80211_crypto.9 ieee80211_crypto_detach.9 \ - ieee80211_crypto.9 ieee80211_wep_crypt.9 -MLINKS+=ieee80211_input.9 ieee80211_decap.9 \ - ieee80211_input.9 ieee80211_recv_mgmt.9 -MLINKS+=ieee80211_ioctl.9 ieee80211_cfgget.9 \ - ieee80211_ioctl.9 ieee80211_cfgset.9 -MLINKS+=ieee80211_node.9 ieee80211_alloc_node.9 \ - ieee80211_node.9 ieee80211_begin_scan.9 \ - ieee80211_node.9 ieee80211_create_ibss.9 \ - ieee80211_node.9 ieee80211_dup_bss.9 \ - ieee80211_node.9 ieee80211_end_scan.9 \ - ieee80211_node.9 ieee80211_find_node.9 \ - ieee80211_node.9 ieee80211_free_allnodes.9 \ +MLINKS+=ieee80211.9 ieee80211_ifattach.9 \ + ieee80211.9 ieee80211_ifdetach.9 +MLINKS+=ieee80211_amrr.9 ieee80211_amrr_init.9 \ + ieee80211_amrr.9 ieee80211_amrr_cleanup.9 \ + ieee80211_amrr.9 ieee80211_amrr_setinterval.9 \ + ieee80211_amrr.9 ieee80211_amrr_node_init.9 \ + ieee80211_amrr.9 ieee80211_amrr_tx_complete.9 \ + ieee80211_amrr.9 ieee80211_amrr_tx_update.9 +MLINKS+=ieee80211_beacon.9 ieee80211_beacon_alloc.9 \ + ieee80211_beacon.9 ieee80211_beacon_update.9 \ + ieee80211_beacon.9 ieee80211_beacon_notify.9 +MLINKS+=ieee80211_bmiss.9 ieee80211_beacon_miss.9 +MLINKS+=ieee80211_crypto.9 ieee80211_key_update_begin.9 \ + ieee80211_crypto.9 ieee80211_key_update_end.9 \ + ieee80211_crypto.9 ieee80211_crypto_newkey.9 \ + ieee80211_crypto.9 ieee80211_crypto_setkey.9 \ + ieee80211_crypto.9 ieee80211_crypto_delglobalkeys.9 \ + ieee80211_crypto.9 ieee80211_crypto_reload_keys.9 \ + ieee80211_crypto.9 ieee80211_crypto_decap.9 \ + ieee80211_crypto.9 ieee80211_crypto_encap.9 \ + ieee80211_crypto.9 ieee80211_crypto_demic.9 \ + ieee80211_crypto.9 ieee80211_crypto_enmic.9 \ + ieee80211_crypto.9 ieee80211_notify_michael_failure.9 \ + ieee80211_crypto.9 ieee80211_notify_replay_failure.9 \ + ieee80211_crypto.9 ieee80211_crypto_register.9 \ + ieee80211_crypto.9 ieee80211_crypto_unregister.9 \ + ieee80211_crypto.9 ieee80211_crypto_available.9 +MLINKS+=ieee80211_input.9 ieee80211_input_all.9 +MLINKS+=ieee80211_node.9 ieee80211_find_rxnode.9 \ + ieee80211_node.9 ieee80211_find_rxnode_withkey.9 \ + ieee80211_node.9 ieee80211_ref_node.9 \ + ieee80211_node.9 ieee80211_unref_node.9 \ ieee80211_node.9 ieee80211_free_node.9 \ ieee80211_node.9 ieee80211_iterate_nodes.9 \ - ieee80211_node.9 ieee80211_lookup_node.9 \ - ieee80211_node.9 ieee80211_next_scan.9 \ - ieee80211_node.9 ieee80211_node_attach.9 \ - ieee80211_node.9 ieee80211_node_detach.9 \ - ieee80211_node.9 ieee80211_node_lateattach.9 \ - ieee80211_node.9 ieee80211_timeout_nodes.9 -MLINKS+=ieee80211_output.9 ieee80211_add_rates.9 \ - ieee80211_output.9 ieee80211_add_xrates.9 \ - ieee80211_output.9 ieee80211_encap.9 \ - ieee80211_output.9 ieee80211_send_mgmt.9 -MLINKS+=ieee80211_proto.9 ieee80211_dump_pkt.9 \ - ieee80211_proto.9 ieee80211_fix_rate.9 \ - ieee80211_proto.9 ieee80211_print_essid.9 \ - ieee80211_proto.9 ieee80211_proto_attach.9 \ - ieee80211_proto.9 ieee80211_proto_detach.9 -MLINKS+=ieee80211_radiotap.9 radiotap.9 + ieee80211_node.9 ieee80211_dump_node.9 \ + ieee80211_node.9 ieee80211_dump_nodes.9 +MLINKS+=ieee80211_output.9 M_WME_GETAC.9 \ + ieee80211_output.9 M_SEQNO_GET.9 \ + ieee80211_output.9 ieee80211_process_callback.9 +MLINKS+=ieee80211_proto.9 ieee80211_new_state.9 \ + ieee80211_proto.9 ieee80211_start_all.9 \ + ieee80211_proto.9 ieee80211_stop_all.9 \ + ieee80211_proto.9 ieee80211_suspend_all.9 \ + ieee80211_proto.9 ieee80211_resume_all.9 \ + ieee80211_proto.9 ieee80211_waitfor_parent.9 +MLINKS+=ieee80211_radiotap.9 radiotap.9 \ + ieee80211_radiotap.9 ieee80211_radiotap_attach.9 \ + ieee80211_radiotap.9 ieee80211_radiotap_active_vap.9 \ + ieee80211_radiotap.9 ieee80211_radiotap_active.9 \ + ieee80211_radiotap.9 ieee80211_radiotap_tx.9 +MLINKS+=ieee80211_regdomain.9 ieee80211_init_channels.9 \ + ieee80211_regdomain.9 ieee80211_sort_channels.9 \ + ieee80211_regdomain.9 ieee80211_alloc_countryie.9 +MLINKS+=ieee80211_vap.9 ieee80211_vap_setup.9 \ + ieee80211_vap.9 ieee80211_vap_attach.9 \ + ieee80211_vap.9 ieee80211_vap_detach.9 MLINKS+=ifnet.9 ifaddr.9 \ ifnet.9 if_data.9 \ ifnet.9 ifqueue.9 @@ -697,6 +713,7 @@ MLINKS+=kobj.9 DEFINE_CLASS.9 \ kobj.9 kobj_delete.9 \ kobj.9 kobj_init.9 MLINKS+=kproc.9 kproc_create.9 \ + kproc.9 kthread_create.9 \ kproc.9 kproc_exit.9 \ kproc.9 kproc_resume.9 \ kproc.9 kproc_shutdown.9 \ diff --git a/share/man/man9/ieee80211.9 b/share/man/man9/ieee80211.9 index 827daece94d..49fb3ce3487 100644 --- a/share/man/man9/ieee80211.9 +++ b/share/man/man9/ieee80211.9 @@ -1,6 +1,5 @@ .\" -.\" Copyright (c) 2004 Bruce M. Simpson -.\" Copyright (c) 2004 Darron Broad +.\" Copyright (c) 2009 Sam Leffler, Errno Consulting .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -25,236 +24,538 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.\" $Id: ieee80211.9,v 1.5 2004/03/04 12:33:27 bruce Exp $ .\" -.Dd March 2, 2004 -.Dt IEEE80211 9 +.Dd August 4, 2009 +.Dt NET80211 9 .Os .Sh NAME -.Nm ieee80211_ifattach , ieee80211_ifdetach , -.Nm ieee80211_mhz2ieee , ieee80211_chan2ieee , ieee80211_ieee2mhz , -.Nm ieee80211_media_init , ieee80211_media_change , ieee80211_media_status , -.Nm ieee80211_watchdog , -.Nm ieee80211_setmode , ieee80211_chan2mode , -.Nm ieee80211_rate2media , ieee80211_media2rate -.Nd core 802.11 network stack functions +.Nm net80211 +.Nd 802.11 network layer .Sh SYNOPSIS .In net80211/ieee80211_var.h -.In net80211/ieee80211_proto.h .Ft void -.Fn ieee80211_ifattach "struct ifnet *ifp" +.Fn ieee80211_ifattach "struct ieee80211com *ic" "const uint8_t macaddr[IEEE80211_ADDR_LEN]" .Ft void -.Fn ieee80211_ifdetach "struct ifnet *ifp" -.Ft u_int -.Fn ieee80211_mhz2ieee "u_int freq" "u_int flags" -.Ft u_int -.Fn ieee80211_chan2ieee "struct ieee80211com *ic" "struct ieee80211_channel *c" -.Ft u_int -.Fn ieee80211_ieee2mhz "u_int chan" "u_int flags" -.Ft void -.Fo ieee80211_media_init -.Fa "struct ifnet *ifp" "ifm_change_cb_t media_change" -.Fa "ifm_stat_cb_t media_stat" -.Fc -.Fa int -.Fn ieee80211_media_change "struct ifnet *ifp" -.Fa void -.Fn ieee80211_media_status "struct ifnet *ifp" "struct ifmediareq *imr" -.Ft void -.Fn ieee80211_watchdog "struct ifnet *ifp" -.Ft int -.Fn ieee80211_setmode "struct ieee80211com *ic" "enum ieee80211_phymode mode" -.Ft enum ieee80211_phymode -.Fo ieee80211_chan2mode -.Fa "struct ieee80211com *ic" "struct ieee80211_channel *chan" -.Fc -.Ft int -.Fo ieee80211_rate2media -.Fa "struct ieee80211com *ic" "int rate" "enum ieee80211_phymode mode" -.Fc -.Ft int -.Fn ieee80211_media2rate "int mword" +.Fn ieee80211_ifdetach "struct ieee80211com *ic" .Sh DESCRIPTION -The -.Nm ieee80211 -collection of functions are used to manage wireless network interfaces in the -system which use the system's software 802.11 network stack. -Most of these functions require that attachment to the stack is performed -before calling. -Several utility functions are also provided; these are safe to call from -any driver without prior initialization. +IEEE 802.11 device drivers are written to use the infrastructure provided +by the +.Nm +software layer. +This software provides a support framework for drivers that includes +ifnet cloning, state management, and a user management API by which +applications interact with 802.11 devices. +Most drivers depend on the +.Nm +layer for protocol services but devices that off-load functionality +may bypass the layer to connect directly to the device +(e.g. the +.Xr ndis 4 +emulation support does this). .Pp -.\" +A +.Nm +device driver implements a virtual radio API that is exported to +users through network interfaces (aka vaps) that are cloned from the +underlying device. +These interfaces have an operating mode +(station, adhoc, hostap, wds, monitor, etc.) +that is fixed for the lifetime of the interface. +Devices that can support multiple concurrent interfaces allow +multiple vaps to be cloned. +This enables construction of interesting applications such as +an AP vap and one or more WDS vaps +or multiple AP vaps, each with a different security model. The +.Nm +layer virtualizes most 802.11 state +and coordinates vap state changes including scheduling multiple vaps. +State that is not virtualized includes the current channel and +WME/WMM parameters. +Protocol processing is typically handled entirely in the +.Nm +layer with drivers responsible purely for moving data between the host +and device. +Similarly, +.Nm +handles most +.Xr ioctl 2 +requests without entering the driver; +instead drivers are notified of state changes that +require their involvement. +.Pp +The virtual radio interface defined by the +.Nm +layer means that drivers must be structured to follow specific rules. +Drivers that support only a single interface at any time must still +follow these rules. +.Sh DATA STRUCTURES +The virtual radio architecture splits state between a single per-device +.Vt ieee80211com +structure and one or more +.Vt ieee80211vap +structures. +Drivers are expected to setup various shared state in these structures +at device attach and during vap creation but otherwise should treat them +as read-only. +The +.Vt ieee80211com +structure is allocated by the +.Nm +layer as adjunct data to a device's +.Vt ifnet ; +it is accessed through the +.Vt if_l2com +structure member. +The +.Vt ieee80211vap +structure is allocated by the driver in the +.Dq vap create +method +and should be extended with any driver-private state. +This technique of giving the driver control to allocate data structures +is used for other +.Nm +data structures and should be exploited to maintain driver-private state +together with public +.Nm +state. +.Pp +The other main data structures are the station, or node, table +that tracks peers in the local BSS, and the channel table that defines +the current set of available radio channels. +Both tables are bound to the +.Vt ieee80211com +structure and shared by all vaps. +Long-lasting references to a node are counted to guard against +premature reclamation. +In particular every packet sent/received holds a node reference +(either explicitly for transmit or implicitly on receive). +.Pp +The +.Vt ieee80211com +and +.Vt ieee80211vap +structures also hold a collection of method pointers that drivers +fill-in and/or override to take control of certain operations. +These methods are the primary way drivers are bound to the +.Nm +layer and are described below. +.Sh DRIVER ATTACH/DETACH +Drivers attach to the +.Nm +layer with the .Fn ieee80211_ifattach -function attaches the network interface -.Fa ifp -to the 802.11 network stack layer. -This function must be called before using any of the -.Nm ieee80211 -functions which need to store driver state across invocations; +function. +The driver is expected to allocate and setup any device-private +data structures before passing control. The -.Vt struct ifnet -instance pointed to by -.Fa ifp -MUST be an instance of -.Vt struct ieee80211com , -with various fields initialized to tell -.Nm ieee80211 -about its capabilities. -This function performs Ethernet and BPF attachment (by calling -.Fn ether_ifattach -and -.Fn bpfattach2 ) -on behalf of the caller. -It also implements the -.Vt ifmedia -interface. +.Vt ieee80211com +structure must be pre-initialized with state required to setup the +.Nm +layer: +.Bl -tag -width ic_channels +.It Dv ic_ifp +Backpointer to the physical device's ifnet. +.It Dv ic_caps +Device/driver capabilities; see below for a complete description. +.It Dv ic_channels +Table of channels the device is capable of operating on. +This is initially provided by the driver but may be changed +through calls that change the regulatory state. +.It Dv ic_nchan +Number of entries in +.Dv ic_channels . +.El .Pp -.\" -The +On return from +.Fn ieee80211_ifattach +the driver is expected to override default callback functions in the +.Vt ieee80211com +structure to register it's private routines. +Methods marked with a +.Dq * +must be provided by the driver. +.Bl -tag -width ic_channels +.It Dv ic_vap_create* +Create a vap instance of the specified type (operating mode). +Any fixed BSSID and/or MAC address is provided. +Drivers that support multi-bssid operation may honor the requested BSSID +or assign their own. +.It Dv ic_vap_delete* +Destroy a vap instance created with +.Dv ic_vap_create . +.It Dv ic_getradiocaps +Return the list of calibrated channels for the radio. +The default method returns the current list of channels +(space permitting). +.It Dv ic_setregdomain +Process a request to change regulatory state. +The routine may reject a request or constrain changes (e.g. reduce +transmit power caps). +The default method accepts all proposed changes. +.It Dv ic_send_mgmt +Send an 802.11 management frame. +The default method fabricates the frame using +.Nm +state and passes it to the driver through the +.Dv ic_raw_xmit +method. +.It Dv ic_raw_xmit +Transmit a raw 802.11 frame. +The default method drops the frame and generates a message on the console. +.It Dv ic_updateslot +Update hardware state after an 802.11 IFS slot time change, +There is no default method; the pointer may be NULL in which case +it will not be used. +.It Dv ic_update_mcast +Update hardware for a change in the multicast packet filter, +The default method prints a console message. +.It Dv ic_update_promisc +Update hardware for a change in the promiscuous mode setting. +The default method prints a console message. +.It Dv ic_newassoc +Update driver/device state for association to a new AP (in station mode) +or when a new station associates (e.g. in AP mode). +There is no default method; the pointer may be NULL in which case +it will not be used. +.It Dv ic_node_alloc +Allocate and initialize a +.Vt ieee80211_node +structure. +This method cannot sleep. +The default method allocates zero'd memory using +.Xr malloc 9. +Drivers should override this method to allocate extended storage +for their own needs. +Memory allocated by the driver must be tagged with +.Dv M_80211_NODE +to balance the memory allocation statistics. +.It Dv ic_node_free +Reclaim storage of a node allocated by +.Dv ic_node_alloc . +Drivers are expected to +.Em interpose +their own method to cleanup private state but must call through +this method to allow +.Nm +to reclaim it's private state. +.It Dv ic_node_cleanup +Cleanup state in a +.Vt ieee80211_node +created by +.Dv ic_node_alloc . +This operation is distinguished from +.Dv ic_node_free +in that it may be called long before the node is actually reclaimed +to cleanup adjunct state. +This can happen, for example, when a node must not be reclaimed +due to references held by packets in the transmit queue. +Drivers typically interpose +.Dv ic_node_cleanup +instead of +.Dv ic_node_free . +.It Dv ic_node_age +Age, and potentially reclaim, resources associated with a node. +The default method ages frames on the power-save queue (in AP mode) +and pending frames in the receive reorder queues (for stations using A-MPDU). +.It Dv ic_node_drain +Reclaim all optional resources associated with a node. +This call is used to free up resources when they are in short supply, +.It Dv ic_node_getrssi +Return the Receive Signal Strength Indication (RSSI) in .5 dBm units for +the specified node. +This interface returns a subset of the information +returned by +.Dv ic_node_getsignal , +The default method calculates a filtered average over the last ten +samples passed in to +.Xr ieee80211_input 9 +or +.Xr ieee80211_input_all 9 . +.It Dv ic_node_getsignal +Return the RSSI and noise floor (in .5 dBm units) for a station. +The default method calculates RSSI as described above; +the noise floor returned is the last value supplied to +.Xr ieee80211_input 9 +or +.Xr ieee80211_input_all 9 . +.It Dv ic_node_getmimoinfo +Return MIMO radio state for a station in support of the +.Dv IEEE80211_IOC_STA_INFO +ioctl request. +The default method returns nothing. +.It Dv ic_scan_start* +Prepare driver/hardware state for scanning. +This callback is done in a sleepable context. +.It Dv ic_scan_end* +Restore driver/hardware state after scanning completes. +This callback is done in a sleepable context. +.It Dv ic_set_channel* +Set the current radio channel using +.Vt ic_curchan . +This callback is done in a sleepable context. +.It Dv ic_scan_curchan +Start scanning on a channel. +This method is called immediately after each channel change +and must initiate the work to scan a channel and schedule a timer +to advance to the next channel in the scan list. +This callback is done in a sleepable context. +The default method handles active scan work (e.g. sending ProbRequest +frames), and schedules a call to +.Xr ieee80211_scan_next 9 +according to the maximum dwell time for the channel. +Drivers that off-load scan work to firmware typically use this method +to trigger per-channel scan activity. +.It Dv ic_scan_mindwell +Handle reaching the minimum dwell time on a channel when scanning. +This event is triggered when one or more stations have been found on +a channel and the minimum dwell time has been reached. +This callback is done in a sleepable context. +The default method signals the scan machinery to advance +to the next channel as soon as possible. +Drivers can use this method to preempt further work (e.g. if scanning +is handled by firmware) or ignore the request to force maximum dwell time +on a channel. +.It Dv ic_recv_action +Process a received Action frame. +The default method points to +.Xr ieee80211_recv_action 9 +which provides a mechanism for setting up handlers for each Action frame class. +.It Dv ic_send_action +Transmit an Action frame. +The default method points to +.Xr ieee80211_send_action 9 +which provides a mechanism for setting up handlers for each Action frame class. +.It Dv ic_ampdu_enable +Check if transmit A-MPDU should be enabled for the specified station and AC. +The default method checks a per-AC traffic rate against a per-vap +threshold to decide if A-MPDU should be enabled. +This method also rate-limits ADDBA requests so that requests are not +made too frequently when a receiver has limited resources. +.It Dv ic_addba_request +Request A-MPDU transmit aggregation. +The default method sets up local state and issues an +ADDBA Request Action frame. +Drivers may interpose this method if they need to setup private state +for handling transmit A-MPDU. +.It Dv ic_addb_response +Process a received ADDBA Response Action frame and setup resources as +needed for doing transmit A-MPDU, +.It Dv ic_addb_stop +Shutdown an A-MPDU transmit stream for the specified station and AC. +The default method reclaims local state after sending a DelBA Action frame. +.It Dv ic_bar_response +Process a response to a transmitted BAR control frame. +.It Dv ic_ampdu_rx_start +Prepare to receive A-MPDU data from the specified station for the TID. +.It Dv ic_ampdu_rx_stop +Terminate receipt of A-MPDU data from the specified station for the TID. +.El +.Pp +Once the +.Nm +layer is attached to a driver there are two more steps typically done +to complete the work: +.Bl -enum +.It +Setup +.Dq radiotap support +for capturing raw 802.11 packets that pass through the device. +This is done with a call to +.Xr ieee80211_radiotap_attach 9 . +.It +Do any final device setup like enabling interrupts. +.El +.Pp +State is torn down and reclaimed with a call to +.Fn ieee80211_ifdetach . +Note this call may result in multiple callbacks into the driver +so it should be done before any critical driver state is reclaimed. +On return from .Fn ieee80211_ifdetach -function frees any -.Nm ieee80211 -structures associated with the driver, and performs Ethernet and BPF -detachment on behalf of the caller. -.Pp -.\" +all associated vaps and ifnet structures are reclaimed or inaccessible +to user applications so it is safe to teardown driver state without +worry about being re-entered. +The driver is responsible for calling +.Xr if_free 9 +on the ifnet it allocated for the physical device. +.Sh DRIVER CAPABILITIES +Driver/device capabilities are specified using several sets of flags +in the +.Vt ieee80211com +structure. +General capabilities are specified by +.Vt ic_caps . +Hardware cryptographic capabilities are specified by +.Vt ic_cryptocaps . +802.11n capabilities, if any, are specified by +.Vt ic_htcaps . The -.Fn ieee80211_mhz2ieee -utility function converts the frequency -.Fa freq -(specified in MHz) to an IEEE 802.11 channel number. -The -.Fa flags -argument is a hint which specifies whether the frequency is in -the 2GHz ISM band -.Pq Vt IEEE80211_CHAN_2GHZ -or the 5GHz band -.Pq Vt IEEE80211_CHAN_5GHZ ; -appropriate clipping of the result is then performed. -.Pp -.\" -The -.Fn ieee80211_chan2ieee -function converts the channel specified in -.Fa *c -to an IEEE channel number for the driver -.Fa ic . -If the conversion would be invalid, an error message is printed to the -system console. -This function REQUIRES that the driver is hooked up to the -.Nm ieee80211 -subsystem. -.Pp -.\" -The -.Fn ieee80211_ieee2mhz -utility function converts the IEEE channel number -.Ft chan -to a frequency (in MHz). -The -.Fa flags -argument is a hint which specifies whether the frequency is in -the 2GHz ISM band -.Pq Vt IEEE80211_CHAN_2GHZ -or the 5GHz band -.Pq Vt IEEE80211_CHAN_5GHZ ; -appropriate clipping of the result is then performed. -.Pp -.\" -The -.Fn ieee80211_media_init -function initializes media data structures used by the -.Vt ifmedia -interface, for the driver -.Fa ifp . -It must be called by the driver after calling -.Fn ieee80211_attach -and before calling most -.Nm ieee80211 -functions. -The -.Fa media_change +.Nm +layer propagates a subset of these capabilities to each vap through +the equivalent fields: +.Vt iv_caps , +.Vt iv_cryptocaps , and -.Fa media_stat -arguments specify helper functions which will be invoked by the -.Vt ifmedia -framework when the user changes or queries media options, -using a command such as -.Xr ifconfig 8 . +.Vt iv_htcaps . +The following general capabilities are defined: +.Bl -tag -width IEEE80211_C_8023ENCAP +.It Dv IEEE80211_C_STA +Device is capable of operating in station (aka Infrastructure) mode. +.It Dv IEEE80211_C_8023ENCAP +Device requires 802.3-encapsulated frames be passed for transmit. +By default +.Nm +will encapsulate all outbound frames as 802.11 frames (without a PLCP header). +.It Dv IEEE80211_C_FF +Device supports Atheros Fast-Frames. +.It Dv IEEE80211_C_TURBOP +Device supports Atheros Dynamic Turbo mode. +.It Dv IEEE80211_C_IBSS +Device is capable of operating in adhoc/IBSS mode. +.It Dv IEEE80211_C_PMGT +Device supports dynamic power-management (aka power save) in station mode. +.It Dv IEEE80211_C_HOSTAP +Device is capable of operating as an Access Point in Infrastructure mode. +.It Dv IEEE80211_C_AHDEMO +Device is capable of operating in Adhoc Demo mode. +In this mode the device is used purely to send/receive raw 802.11 frames. +.It Dv IEEE80211_C_SWRETRY +Device supports software retry of transmitted frames. +.It Dv IEEE80211_C_TXPMGT +Device support dynamic transmit power changes on transmitted frames; +also known as Transmit Power Control (TPC). +.It Dv IEEE80211_C_SHSLOT +Device supports short slot time operation (for 802.11g). +.It Dv IEEE80211_C_SHPREAMBLE +Device supports short preamble operation (for 802.11g). +.It Dv IEEE80211_C_MONITOR +Device is capable of operating in monitor mode. +.It Dv IEEE80211_C_DFS +Device supports radar detection and/or DFS. +DFS protocol support can be handled by +.Nm +but the device must be capable of detecting radar events. +.It Dv IEEE80211_C_MBSS +Device is capable of operating in MeshBSS (MBSS) mode +(as defined by 802.11s Draft 3.0). +.It Dv IEEE80211_C_WPA1 +Device supports WPA1 operation. +.It Dv IEEE80211_C_WPA2 +Device supports WPA2/802.11i operation. +.It Dv IEEE80211_C_BURST +Device supports frame bursting. +.It Dv IEEE80211_C_WME +Device supports WME/WMM operation +(at the moment this is mostly support for sending and receiving +QoS frames with EDCF). +.It Dv IEEE80211_C_WDS +Device supports transmit/receive of 4-address frames. +.It Dv IEEE80211_C_BGSCAN +Device supports background scanning. +.It Dv IEEE80211_C_TXFRAG +Device supports transmit of fragmented 802.11 frames. +.It Dv IEEE80211_C_TDMA +Device is capable of operating in TDMA mode. +.El .Pp -.\" -The -.Fn ieee80211_media_status -and -.Fn ieee80211_media_change -functions are device-independent handlers for -.Vt ifmedia -commands and are not intended to be called directly. +The follow general crypto capabilities are defined. +In general +.Nm +will fall-back to software support when a device is not capable +of hardware acceleration of a cipher. +This can be done on a per-key basis. +.Nm +can also handle software +.Dv Michael +calculation combined with hardware +.Dv AES +acceleration. +.Bl -tag -width IEEE80211_C_8023ENCAP +.It Dv IEEE80211_CRYPTO_WEP +Device supports hardware WEP cipher. +.It Dv IEEE80211_CRYPTO_TKIP +Device supports hardware TKIP cipher. +.It Dv IEEE80211_CRYPTO_AES_OCB +Device supports hardware AES-OCB cipher. +.It Dv IEEE80211_CRYPTO_AES_CCM +Device supports hardware AES-CCM cipher. +.It Dv IEEE80211_CRYPTO_TKIPMIC +Device supports hardware Michael for use with TKIP. +.It Dv IEEE80211_CRYPTO_CKIP +Devices supports hardware CKIP cipher. +.El .Pp -.\" -The -.Fn ieee80211_watchdog -function is intended to be called from a driver's -.Va if_watchdog -routine. -It is used to perform periodic cleanup of state within the software 802.11 -stack, as well as timing out scans. -.Pp -.\" -The -.Fn ieee80211_setmode -function is called from within the 802.11 stack to change the mode -of the driver's PHY; it is not intended to be called directly. -.Pp -.\" -The -.Fn ieee80211_chan2mode -function returns the PHY mode required for use with the channel -.Fa chan -on the device -.Fa ic . -This is typically used when selecting a rate set, to be advertised in -beacons, for example. -.Pp -.\" -The -.Fn ieee80211_rate2media -function converts the bit rate -.Fa rate -(measured in units of 0.5Mbps) to an -.Vt ifmedia -sub-type, for the device -.Fa ic -running in PHY mode -.Fa mode . -The -.Fn ieee80211_media2rate -performs the reverse of this conversion, returning the bit rate (in 0.5Mbps -units) corresponding to an -.Vt ifmedia -sub-type. -.\" +The follow general 802.11n capabilities are defined. +The first capabilities are defined exactly as they appear in the +802.11n specification. +Capabilities beginning with IEEE80211_HTC_AMPDU are used soley by the +.Nm +layer. +.Bl -tag -width IEEE80211_C_8023ENCAP +.It Dv IEEE80211_HTCAP_CHWIDTH40 +Device supports 20/40 channel width operation. +.It Dv IEEE80211_HTCAP_SMPS_DYNAMIC +Device supports dynamic SM power save operation. +.It Dv IEEE80211_HTCAP_SMPS_ENA +Device supports static SM power save operation. +.It Dv IEEE80211_HTCAP_GREENFIELD +Device supports Greenfield preamble. +.It Dv IEEE80211_HTCAP_SHORTGI20 +Device supports Short Guard Interval on 20MHz channels. +.It Dv IEEE80211_HTCAP_SHORTGI40 +Device supports Short Guard Interval on 40MHz channels. +.It Dv IEEE80211_HTCAP_TXSTBC +Device supports Space Time Block Convolution (STBC) for transmit. +.It Dv IEEE80211_HTCAP_RXSTBC_1STREAM +Device supports 1 spatial stream for STBC receive. +.It Dv IEEE80211_HTCAP_RXSTBC_2STREAM +Device supports 1-2 spatial streams for STBC receive. +.It Dv IEEE80211_HTCAP_RXSTBC_3STREAM +Device supports 1-3 spatial streams for STBC receive. +.It Dv IEEE80211_HTCAP_MAXAMSDU_7935 +Device supports A-MSDU frames up to 7935 octets. +.It Dv IEEE80211_HTCAP_MAXAMSDU_3839 +Device supports A-MSDU frames up to 3839 octets. +.It Dv IEEE80211_HTCAP_DSSSCCK40 +Device supports use of DSSS/CCK on 40MHz channels. +.It Dv IEEE80211_HTCAP_PSMP +Device supports PSMP. +.It Dv IEEE80211_HTCAP_40INTOLERANT +Device is intolerant of 40MHz wide channel use. +.It Dv IEEE80211_HTCAP_LSIGTXOPPROT +Device supports L-SIG TXOP protection. +.It Dv IEEE80211_HTC_AMPDU +Device supports A-MPDU aggregation. +Note that any 802.11n compliant device must support A-MPDU receive +so this implicitly means support for +.Em transmit +of A-MPDU frames. +.It Dv IEEE80211_HTC_AMSDU +Device supports A-MSDU aggregation. +Note that any 802.11n compliant device must support A-MSDU receive +so this implicitly means support for +.Em transmit +of A-MSDU frames. +.It Dv IEEE80211_HTC_HT +Device supports High Throughput (HT) operation. +This capability must be set to enable 802.11n functionality +in +.Nm . +.It Dv IEEE80211_HTC_SMPS +Device supports MIMO Power Save operation. +.It Dv IEEE80211_HTC_RIFS +Device supports Reduced Inter Frame Spacing (RIFS). +.El .Sh SEE ALSO -.Xr ieee80211_crypto 9 , +.Xr ioctl 2 , +.Xr ndis 4 , .Xr ieee80211_input 9 , -.Xr ieee80211_ioctl 9 , -.Xr ieee80211_node 9 , -.Xr ieee80211_output 9 , -.Xr ieee80211_proto 9 , -.Xr ieee80211_radiotap 9 , -.Xr ifnet 9 -.Sh HISTORY -The -.Nm ieee80211 -series of functions first appeared in -.Nx 1.5 , -and were later ported to -.Fx 4.6 . -.Sh AUTHORS -.An -nosplit -This manual page was written by -.An Bruce M. Simpson Aq bms@FreeBSD.org -and -.An Darron Broad Aq darron@kewl.org . +.Xr ieee80211_input_all 9 , +.Xr ieee80211_scan_next 9 , +.Xr ieee80211_recv_action 9 , +.Xr ieee80211_send_action 9 , +.Xr ieee80211_radiotap_attach 9 , +.Xr ifnet 9 , +.Xr malloc 9 . diff --git a/share/man/man9/ieee80211_crypto.9 b/share/man/man9/ieee80211_crypto.9 index bf4bb604917..f5a028b64b6 100644 --- a/share/man/man9/ieee80211_crypto.9 +++ b/share/man/man9/ieee80211_crypto.9 @@ -27,76 +27,233 @@ .\" $FreeBSD$ .\" $Id: ieee80211_crypto.9,v 1.3 2004/03/04 10:42:56 bruce Exp $ .\" -.Dd March 2, 2004 +.Dd August 4, 2009 .Dt IEEE80211_CRYPTO 9 .Os .Sh NAME -.Nm ieee80211_crypto_attach , ieee80211_crypto_detach , ieee80211_wep_crypt -.Nd 802.11 WEP encryption functions +.Nm ieee80211_crypto +.Nd 802.11 cryptographic support .Sh SYNOPSIS +.In net80211/ieee80211_var.h +.\" +.Pp .Ft void -.Fn ieee80211_crypto_attach "struct ifnet *ifp" +.Fn ieee80211_crypto_register "const struct ieee80211_cipher *" +.\" .Ft void -.Fn ieee80211_crypto_detach "struct ifnet *ifp" -.Ft struct mbuf * -.Fn ieee80211_wep_crypt "struct ifnet *ifp" "struct mbuf *m0" "int txflag" +.Fn ieee80211_crypto_unregister "const struct ieee80211_cipher *" +.\" +.Ft int +.Fn ieee80211_crypto_available "int cipher" +.\" +.Pp +.Ft void +.Fo ieee80211_notify_replay_failure +.Fa "struct ieee80211vap *" +.Fa "const struct ieee80211_frame *" +.Fa "const struct ieee80211_key *" +.Fa "uint64_t rsc" +.Fa "int tid" +.Fc +.\" +.Ft void +.Fo ieee80211_notify_michael_failure +.Fa "struct ieee80211vap *" +.Fa "const struct ieee80211_frame *" +.Fa "u_int keyix" +.Fc +.\" +.Ft int +.Fo ieee80211_crypto_newkey +.Fa "struct ieee80211vap * +.Fa "int cipher +.Fa "int flags +.Fa "struct ieee80211_key * +.Fc +.\" +.Ft int +.Fn ieee80211_crypto_setkey "struct ieee80211vap *" "struct ieee80211_key *" +.\" +.Ft int +.Fn ieee80211_crypto_delkey "struct ieee80211vap *" "struct ieee80211_key *" +.\" +.Ft void +.Fn ieee80211_key_update_begin "struct ieee80211vap *" +.\" +.Ft void +.Fn ieee80211_key_update_end "struct ieee80211vap *" +.\" +.Ft void +.Fn ieee80211_crypto_delglobalkeys "struct ieee80211vap *" +.\" +.Ft void +.Fn ieee80211_crypto_reload_keys "struct ieee80211com *" +.\" +.Pp +.Ft struct ieee80211_key * +.Fn ieee80211_crypto_encap "struct ieee80211_node *" "struct mbuf *" +.\" +.Ft struct ieee80211_key * +.Fn ieee80211_crypto_decap "struct ieee80211_node *" "struct mbuf *" "int flags" +.\" +.Ft int +.Fo ieee80211_crypto_demic +.Fa "struct ieee80211vap *" +.Fa "struct ieee80211_key *" +.Fa "struct mbuf *" +.Fa "int force" +.Fc +.\" +.Ft int +.Fo ieee80211_crypto_enmic +.Fa "struct ieee80211vap *" +.Fa "struct ieee80211_key *" +.Fa "struct mbuf *" +.Fa "int force" +.Fc .Sh DESCRIPTION -These functions provide software encryption support -for 802.11 device drivers. +The +.Nm net80211 +layer includes comprehensive cryptographic support for 802.11 protocols. +Software implementations of ciphers required by +WPA and 802.11i are provided as well as encap/decap processing of 802.11 frames. +Software ciphers are written as kernel modules and +register with the core crypto support. +The cryptographic framework supports hardware acceleration of ciphers +by drivers with automatic fall-back to software implementations when a +driver is unable to provide necessary hardware services. +.Sh CRYPTO CIPHER MODULES +.Nm net80211 +cipher modules register their services using +.Fn ieee80211_crypto_register +and supply a template that describes their operation. +This +.Vt ieee80211_cipher +structure defines protocol-related state such as the number of bytes +of space in the 802.11 header to reserve/remove during encap/decap +and entry points for setting up keys and doing cryptographic operations. .Pp -.\" -The -.Fn ieee80211_crypto_attach -function initializes crypto support for the interface -.Fa ifp , -and sets the initialization vector (IV) for WEP encryption to -a random number derived from a secure PRNG. +Cipher modules can associate private state to each key through the +.Vt wk_private +structure member. +If state is setup by the module it will be called before a key is destroyed +so it can reclaim resources. .Pp -.\" +Crypto modules can notify the system of two events. +When a packet replay event is recognized +.Fn ieee80111_notify_replay_failure +can be used to signal the event. +When a +.Dv TKIP +Michael failure is detected +.Fn ieee80211_notify_michael_failure +can be invoked. +Drivers may also use these routines to signal events detected by the +hardware. +.Sh CRYPTO KEY MANAGEMENT The -.Fn ieee80211_crypto_detach -function frees data structures associated with crypto support -for the interface -.Fa ifp . +.Nm net80211 +layer implements a per-vap 4-element +.Dq global key table +and a per-station +.Dq unicast key +for protocols such as WPA, 802.1x, and 802.11i. +The global key table is designed to support legacy WEP operation +and Multicast/Group keys, +though some applications also use it to implement WPA in station mode. +Keys in the global table are identified by a key index in the range 0-3. +Per-station keys are identified by the MAC address of the station and +are typically used for unicast PTK bindings. .Pp -.\" +.Nm net80211 +provides +.Xr ioctl 2 +operations for managing both global and per-station keys. +Drivers typically do not participate in software key management; +they are involved only when providing hardware acceleration of +cryptographic operations. +.Pp +.Fn ieee80211_crypto_newkey +is used to allocate a new +.Nm net80211 +key or reconfigure an existing key. +The cipher must be specified along with any fixed key index. The -.Fn ieee80211_wep_crypt -function runs the appropriate WEP encryption algorithm over the 802.11 -encapsulated frame held in the mbuf chain -.Fa m0 , -for transmission or reception on the interface -.Fa ifp . -The -.Fa txflag -argument specifies whether the frame is being received or transmitted. -A value of 0 indicates that the frame is being received and should -therefore be decrypted; a non-zero value indicates that the frame -is being transmitted -and should be encrypted. -.\" -.Sh IMPLEMENTATION NOTES -The -.Fn ieee80211_wep_crypt -function stores its IV in the interface's embedded -.Vt struct ieee80211com -instance. -.Sh SEE ALSO -.Xr awi 4 , -.Xr wi 4 , -.Xr arc4random 9 , -.Xr ieee80211 9 , -.Xr ifnet 9 -.Sh HISTORY -The -.Nm ieee80211 -series of functions first appeared in -.Nx 1.5 , -and were later ported to -.Fx 4.6 . -.Sh AUTHORS -.An -nosplit -This manual page was written by -.An Bruce M. Simpson Aq bms@FreeBSD.org +.Nm net80211 +layer will handle allocating cipher and driver resources to support the key. +.Pp +Once a key is allocated it's contents can be set using +.Fn ieee80211_crypto_setkey +and deleted with +.Fn ieee80211_crypto_delkey +(with any cipher and driver resources reclaimed). +.Pp +.Fn ieee80211_crypto_delglobalkeys +is used to reclaim all keys in the global key table for a vap; it +typically is used only within the +.Nm net80211 +layer. +.Pp +.Fn ieee80211_crypto_reload_keys +handles hardware key state reloading from software key state, such +as required after a suspend/resume cycle. +.Sh DRIVER CRYPTO SUPPORT +Drivers identify ciphers they have hardware support for through the +.Vt ic_cryptocaps +field of the +.Vt ieee80211com +structure. +If hardware support is available then a driver should also fill in the +.Dv iv_key_alloc , +.Dv iv_key_set , and -.An Darron Broad Aq darron@kewl.org . +.Dv iv_key_delete +methods of each +.Vt ieee80211vap +created for use with the device. +In addition the methods +.Dv iv_key_update_begin +and +.Dv iv_key_update_end +can be setup to handle synchronization requirements +for updating hardware key state. +.Pp +When +.Nm net80211 +allocates a software key and the driver can accelerate the +cipher operations the +.Dv iv_key_alloc +method will be invoked. +Drivers may return a token that is associated with outbound traffic +(for use in encrypting frames). +Otherwise, e.g. if hardware resources are not available, the driver will +not return a token and +.Nm net80211 +will arrange to do the work in software and pass frames +to the driver that are already prepared for transmission. +.Pp +For receive, drivers mark frames with the +.Dv M_WEP +mbuf flag to indicate the hardware has decrypted the payload. +If frames have the +.Dv IEEE80211_FC1_WEP +bit marked in their 802.11 header and are not tagged with +.Dv M_WEP +then decryption is done in software. +For more complicated scenarios the software key state is consulted; e.g. +to decide if Michael verification needs to be done in software after +the hardware has handled TKIP decryption. +.Pp +Drivers that manage complicated key data structures, e.g. faulting +software keys into a hardware key cache, can safely manipulate software +key state by bracketing their work with calls to +.Fn ieee80211_key_update_begin +and +.Fn ieee80211_key_update_end . +These calls also synchronize hardware key state update +when receive traffic is active. +.Sh SEE ALSO +.Xr ioctl 2 , +.Xr wlan_ccmp 4 , +.Xr wlan_tkip 4 , +.Xr wlan_wep 4 . diff --git a/share/man/man9/ieee80211_input.9 b/share/man/man9/ieee80211_input.9 index 21c9f253c2e..a0829eefcce 100644 --- a/share/man/man9/ieee80211_input.9 +++ b/share/man/man9/ieee80211_input.9 @@ -25,89 +25,92 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.\" $Id: ieee80211_input.9,v 1.6 2004/03/04 12:33:27 bruce Exp $ .\" -.Dd March 2, 2004 +.Dd August 4, 2009 .Dt IEEE80211_INPUT 9 .Os .Sh NAME -.Nm ieee80211_input , ieee80211_decap , ieee80211_recv_mgmt +.Nm ieee80211_input .Nd software 802.11 stack input functions .Sh SYNOPSIS .In net80211/ieee80211_var.h -.In net80211/ieee80211_proto.h .Ft void .Fo ieee80211_input -.Fa "struct ifnet *ifp" "struct mbuf *m" "struct ieee80211_node *ni" -.Fa "int rssi" "u_int32_t rstamp" +.Fa "struct ieee80211_node *" +.Fa "struct mbuf *" +.Fa "int rssi" +.Fa "int noise" .Fc -.Ft struct mbuf * -.Fn ieee80211_decap "struct ifnet *ifp" "struct mbuf *m" .Ft void -.Fo ieee80211_recv_mgmt -.Fa "struct ieee80211com *ic" "struct mbuf *m0" "struct ieee80211_node *ni" -.Fa "int subtype" "int rssi" "u_int32_t rstamp" +.Fo ieee80211_input_all +.Fa "struct ieee80211com *" +.Fa "struct mbuf *" +.Fa "int rssi" +.Fa "int noise" .Fc .Sh DESCRIPTION -These -functions process received 802.11 frames. -.Pp -.\" The +.Nm net80211 +layer that supports 802.11 device drivers requires that +receive processing be single-threaded. +Typically this is done using a dedicated driver +.Xr taskqueue 9 +thread. .Fn ieee80211_input -function takes an mbuf chain -.Fa m -containing a complete 802.11 frame from the driver -.Fa ifp -and passes it to the software 802.11 stack for input processing. -The -.Fa ni -argument specifies an instance of -.Vt struct ieee80211_node -(which may be driver-specific) representing the node from which the -frame was received. -The arguments -.Fa rssi and -.Fa stamp -are typically derived from on-card data structures; they are used for -recording the signal strength and time received of the frame respectively. +.Fn ieee80211_input_all +process received 802.11 frames and are designed +for use in that context; e.g. no driver locks may be held. .Pp -.\" -The -.Fn ieee80211_decap -function performs decapsulation of the 802.11 frame in the mbuf chain -.Fa m -received by the device -.Fa ifp , -taking the form of the 802.11 address fields into account; -the structure of 802.11 addresses vary according to the intended -source and destination of the frame. -It is typically called from within -.Fn ieee80211_input . +The frame passed up in the +.Vt mbuf +must have the 802.11 protocol header at the front; all device-specific +information and/or PLCP must be removed. +Any CRC must be stripped from the end of the frame. +The 802.11 protocol header should be 32-bit aligned for +optimal performance but receive processing does not require it. +If the frame holds a payload and that is not aligned to a 32-bit +boundary then the payload will be re-aligned so that it is suitable +for processing by protocols such as +.Xr ip 4 . +.Pp +If a device (such as +.Xr ath 4 ) +inserts padding after the 802.11 header to align +the payload to a 32-bit boundary the +.Dv IEEE80211_C_DATAPAD +capability must be set. +Otherwise header and payload are assumed contiguous in the mbuf chain. +.Pp +If a received frame must pass +through the A-MPDU receive reorder buffer then the mbuf +must be marked with the +.Dv M_AMPDU +flag. +Note that for the moment this is required of all frames received from +a station and TID where a Block ACK stream is active, not just A-MPDU +aggregates. +It is sufficient to check for +.Dv IEEE80211_NODE_HT +in the +.Vt ni_flags +of the station's node table entry, any frames that do not require reorder +processing will be dispatched with only minimal overhead. .Pp -.\" The -.Fn ieee80211_recv_mgmt -performs input processing for 802.11 management frames. -It is typically called from within -.Fn ieee80211_input . -.\" +.Vt rssi +parameter is the Receive Signal Strength Indication of the frame +measured in 0.5dBm units relative to the noise floor. +The +.Vt noise +parameter is the best approximation of the noise floor in +dBm units at the time the frame was received. +RSSI and noise are used by the +.Nm net80211 +layer to make scanning and roaming decisions in station mode +and to do auto channel selection for hostap and similar modes. +Otherwise the values are made available to user applications +(with the rssi presented as a filtered average over the last ten values +and the noise floor the last reported value). .Sh SEE ALSO -.Xr ieee80211 9 , -.Xr ifnet 9 -.Sh HISTORY -The -.Nm ieee80211 -series of functions first appeared in -.Nx 1.5 , -and were later ported to -.Fx 4.6 . -.Sh AUTHORS -.An -nosplit -This manual page was written by -.An Bruce M. Simpson Aq bms@FreeBSD.org -and -.An Darron Broad Aq darron@kewl.org . -.Sh BUGS -There is no netisr queue specifically for the software 802.11 stack yet. +.Xr ieee80211 9 . diff --git a/share/man/man9/ieee80211_ioctl.9 b/share/man/man9/ieee80211_ioctl.9 deleted file mode 100644 index 7f94bceba53..00000000000 --- a/share/man/man9/ieee80211_ioctl.9 +++ /dev/null @@ -1,92 +0,0 @@ -.\" -.\" Copyright (c) 2004 Bruce M. Simpson -.\" Copyright (c) 2004 Darron Broad -.\" 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$ -.\" $Id: ieee80211_ioctl.9,v 1.5 2004/03/04 12:33:27 bruce Exp $ -.\" -.Dd March 2, 2004 -.Dt IEEE80211_IOCTL 9 -.Os -.Sh NAME -.Nm ieee80211_cfgget , ieee80211_cfgset , ieee80211_ioctl -.Nd 802.11 interface ioctl commands -.Sh SYNOPSIS -.In net80211/ieee80211_var.h -.In net80211/ieee80211_proto.h -.In net80211/ieee80211_ioctl.h -.Ft int -.Fn ieee80211_cfgget "struct ifnet *ifp" "u_long cmd" "caddr_t data" -.Ft int -.Fn ieee80211_cfgset "struct ifnet *ifp" "u_long cmd" "caddr_t data" -.Ft int -.Fn ieee80211_ioctl "struct ifnet *ifp" "u_long cmd" "caddr_t data" -.Sh DESCRIPTION -These -functions are typically invoked by drivers in response to requests -for information or to change settings from the userland. -.Pp -.\" -The -.Fn ieee80211_cfgget -and -.Fn ieee80211_cfgset -functions implement a legacy interface for getting and setting 802.11 -interface attributes respectively. -.Pp -.\" -The -.Fn ieee80211_ioctl -function provides a default implementation of the -.Dv SIOCS80211 -and -.Dv SIOCG80211 -ifioctls commands for 802.11 drivers. -The call signature is identical to that of the -.Va if_ioctl -member found in -.Vt struct ifnet , -however, many drivers store attributes such as -.Dv IEEE80211_IOC_STATIONNAME -in the driver's private soft state structure, so driver writers may prefer -to use this as the catch-all in a switch statement to avoid code duplication. -.\" -.Sh SEE ALSO -.Xr ifconfig 8 , -.Xr ieee80211 9 , -.Xr ifnet 9 -.Sh HISTORY -The -.Nm ieee80211 -series of functions first appeared in -.Nx 1.5 , -and were later ported to -.Fx 4.6 . -.Sh AUTHORS -.An -nosplit -This manual page was written by -.An Bruce M. Simpson Aq bms@FreeBSD.org -and -.An Darron Broad Aq darron@kewl.org . diff --git a/share/man/man9/ieee80211_node.9 b/share/man/man9/ieee80211_node.9 index c9d142a31a3..59ae87095cb 100644 --- a/share/man/man9/ieee80211_node.9 +++ b/share/man/man9/ieee80211_node.9 @@ -25,269 +25,227 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.\" $Id: ieee80211_node.9,v 1.6 2004/03/04 12:33:27 bruce Exp $ .\" -.Dd July 4, 2004 +.Dd August 4, 2009 .Dt IEEE80211_NODE 9 .Os .Sh NAME -.Nm ieee80211_node_attach , -.Nm ieee80211_node_lateattach , -.Nm ieee80211_node_detach , -.Nm ieee80211_begin_scan , -.Nm ieee80211_next_scan , -.Nm ieee80211_create_ibss , -.Nm ieee80211_end_scan , -.Nm ieee80211_alloc_node , -.Nm ieee80211_dup_bss , -.Nm ieee80211_find_node , -.Nm ieee80211_lookup_node , -.Nm ieee80211_free_node , -.Nm ieee80211_free_allnodes , -.Nm ieee80211_timeout_nodes , -.Nm ieee80211_iterate_nodes +.Nm ieee80211_node .Nd software 802.11 stack node management functions .Sh SYNOPSIS .In net80211/ieee80211_var.h -.In net80211/ieee80211_proto.h -.In net80211/ieee80211_node.h -.Ft void -.Fn ieee80211_node_attach "struct ifnet *ifp" -.Ft void -.Fn ieee80211_node_lateattach "struct ifnet *ifp" -.Ft void -.Fn ieee80211_node_detach "struct ifnet *ifp" -.Ft void -.Fn ieee80211_begin_scan "struct ifnet *ifp" -.Ft void -.Fn ieee80211_next_scan "struct ifnet *ifp" -.Ft void -.Fo ieee80211_create_ibss -.Fa "struct ieee80211com *ic" "struct ieee80211_channel *chan" +.\" +.Ft struct ieee80211_node * +.Fo ieee80211_find_rxnode +.Fa "struct ieee80211com *" +.Fa "const struct ieee80211_frame_min *" .Fc -.Ft void -.Fn ieee80211_end_scan "struct ifnet *ifp" +.\" .Ft struct ieee80211_node * -.Fn ieee80211_alloc_node "struct ieee80211com *ic" "u_int8_t *macaddr" -.Ft struct ieee80211_node * -.Fn ieee80211_dup_bss "struct ieee80211com *ic" "u_int8_t *macaddr" -.Ft struct ieee80211_node * -.Fn ieee80211_find_node "struct ieee80211com *ic" "u_int8_t *macaddr" -.Ft struct ieee80211_node * -.Fo ieee80211_lookup_node -.Fa "struct ieee80211com *ic" "u_int8_t *macaddr" -.Fa "struct ieee80211_channel *chan" +.Fo ieee80211_find_rxnode_withkey +.Fa "struct ieee80211com *" +.Fa "const struct ieee80211_frame_min *" +.Fa "ieee80211_keyix" .Fc +.\" +.Ft struct ieee80211_node * +.Fn ieee80211_ref_node "struct ieee80211_node *" +.\" .Ft void -.Fn ieee80211_free_node "struct ieee80211com *ic" "struct ieee80211_node *ni" +.Fn ieee80211_unref_node "struct ieee80211_node *" +.\" .Ft void -.Fn ieee80211_free_allnodes "struct ieee80211com *ic" -.Ft void -.Fn ieee80211_timeout_nodes "struct ieee80211com *ic" +.Fn ieee80211_free_node "struct ieee80211_node *" +.\" .Ft void .Fo ieee80211_iterate_nodes -.Fa "struct ieee80211com *ic" "ieee80211_iter_func *f" "void *arg" +.Fa "struct ieee80211_node_table *" +.Fa "ieee80211_iter_func *f" +.Fa "void *arg" .Fc +.\" +.Ft void +.Fo ieee80211_dump_nodes +.Fa "struct ieee80211_node_table *" +.Fc +.\" +.Ft void +.Fo ieee80211_dump_node +.Fa "struct ieee80211_node *" +.Fc .Sh DESCRIPTION -These functions are used to manage node lists within the software -802.11 stack. -These lists are typically used for implementing host-mode AP functionality, -or providing signal quality information about neighbouring nodes. +The +.Nm net80211 +layer that supports 802.11 device drivers maintains a database of +peer stations called the +.Dq node table +in the +.Vt ic_sta +entry of the +.Vt ieee80211com +structure. +Station mode vaps create an entry for the access point +the station is associated to. +AP mode vaps create entries for associated stations. +Adhoc and mesh mode vaps create entries for neighbor stations. +WDS mode vaps create an entry for the peer station. +Stations for all vaps reside in the same table; each node +entry has a +.Vt ni_vap +field that identifies the vap that created it. +In some instances an entry is used by multiple vaps (e.g. for +dynamic WDS a station associated to an ap vap may also be the peer +of a WDS vap). .Pp -.\" +Node table entries are reference counted. +That is, there is a count of all long term references that determines +when an entry may be reclaimed. +References are held by every in-flight frame sent to a station to +insure the entry is not reclaimed while the frame is queued or otherwise +held by a driver. +Routines that lookup a table entry return a +.Dq held reference +(i.e. a pointer to a table entry with the reference count incremented). The -.Fn ieee80211_node_attach -function is called from -.Xr ieee80211_ifattach 9 -to initialize node database management callbacks for the interface -.Fa ifp -(specifically for memory allocation, node copying and node -signal inspection). -These functions may be overridden in special circumstances, -as long as this is done after calling -.Xr ieee80211_ifattach 9 -and prior to any other call which may allocate a node. -.Pp -.\" -The -.Fn ieee80211_node_lateattach -function initialises the -.Va ic_bss -node element of the interface -.Fa ifp -during -.Xr ieee80211_media_init 9 . -This late attachment is to account for certain special cases described under -.Fn ieee80211_node_attach . -.Pp -.\" -The -.Fn ieee80211_node_detach -function destroys all node database state associated with the interface -.Fa ifp , -and is usually called during device detach. -.Pp -.\" -The -.Fn ieee80211_begin_scan -function initialises the node database in preparation of an active -scan for an access point on the interface -.Fa ifp . -The scan begins on the next radio channel by calling -.Fn ieee80211_next_scan -internally. -The actual scanning for an access point is not automated; -the device driver itself only handles setting the radio frequency -of the card and stepping through the channels. -.Pp -.\" -The -.Fn ieee80211_next_scan -function is used to inform the -.Xr ieee80211 9 -layer that the interface -.Fa ifp -is now scanning for an access point on the next radio channel. -A device driver is expected to first call -.Fn ieee80211_begin_scan , -to initialize the node database, -then set the radio channel on the device; -then, after a certain time has elapsed (200ms for example), call -.Fn ieee80211_next_scan -to move to the next channel. -Typically, a callout is used to automate this process; see -.Xr callout_init 9 -for more information on how to use callouts. -.Pp -.\" -The -.Fn ieee80211_create_ibss -function sets up the net80211-specific portion of an interface's softc, -.Fa ic , -for use in IBSS mode. -.Pp -.\" -The -.Fn ieee80211_end_scan -function is called by -.Fn ieee80211_next_scan -when the state machine has peformed a full cycle of scanning on -all available radio channels. -Internally, -.Fn ieee80211_end_scan -will inspect the node cache associated with the interface -.Fa ifp -for suitable access points found during scanning, and associate with one, -should the parameters of the node match those of the configuration -requested from userland. -.Pp -.\" -The -.Fn ieee80211_alloc_node -function allocates an instance of -.Vt "struct ieee80211_node" -for a node having the MAC address -.Fa macaddr , -and associates it with the interface -.Fa ic . -If the allocation is successful, the node structure is initialised by -.Fn ieee80211_setup_node ; -otherwise, -.Dv NULL -is returned. -.Pp -.\" -The -.Fn ieee80211_dup_bss -function is similar to -.Fn ieee80211_alloc_node , -but is instead used to create a node database entry for the BSSID -.Fa macaddr -associated with the interface -.Fa ic . -If the allocation is successful, the node structure is initialised by -.Fn ieee80211_setup_node ; -otherwise, -.Dv NULL -is returned. -.Pp -.\" -The -.Fn ieee80211_find_node -function will iterate through the node list associated with the interface -.Fa ic , -searching for a node entry which matches -.Fa macaddr . -If the entry is found, its reference count is incremented, and -a pointer to the node is returned; otherwise, -.Dv NULL -will be returned. -.Pp -.\" -The -.Fn ieee80211_lookup_node -function is similar to -.Fn ieee80211_find_node , -with an additional argument -.Fa chan -which is used to specify a channel for the match. -If the entry is found, its reference count is incremented, and -a pointer to the node is returned; otherwise, -.Dv NULL -will be returned. -.Pp -.\" -The -.Fn ieee80211_free_node -function will remove the node -.Fa ni -from the node database entries associated with the interface -.Fa ic , -and free any memory associated with the node. -This private method can be overridden in -.Fn ieee80211_node_attach . -.\" -.Pp -The -.Fn ieee80211_free_allnodes -function will iterate through the node list calling -.Fn ieee80211_free_node -for all nodes associated with the interface -.Fa ic . -.Pp -.\" -The -.Fn ieee80211_timeout_nodes -checks if the inactivity timer of each node associated with the interface -.Fa ic -has exceeded the pre-defined constant -.Dv IEEE80211_INACT_MAX . -If so, then the node is freed, after sending a deauthentication message. -.Pp -.\" -The -.Fn ieee80211_iterate_nodes -function will call the user-defined callback function -.Fa f -for all nodes in the node database associated with the interface -.Fa ic . -The callback is invoked with the with the user-supplied value -.Fa arg -and a pointer to the current node. -.\" -.Sh SEE ALSO -.Xr ieee80211 9 , -.Xr ifnet 9 -.Sh HISTORY -The -.Nm ieee80211 -series of functions first appeared in -.Nx 1.5 , -and were later ported to -.Fx 4.6 . -.Sh AUTHORS -.An -nosplit -This manual page was written by -.An Bruce M. Simpson Aq bms@FreeBSD.org +.Fn ieee80211_ref_node and -.An Darron Broad Aq darron@kewl.org . +.Fn ieee80211_unref_node +calls explicitly increment/decrement the reference count of a node, +but are rarely used. +Instead most callers use +.Fn ieee80211_free_node +to release a reference and, if the count goes to zero, reclaim the +table entry. +.Pp +The station table and its entries are exposed to drivers in several ways. +Each frame transmitted to a station includes a reference to the +associated node in the +.Vt m_pkthdr.rcvif +field. +This reference must be reclaimed by the driver when transmit processing +is done. +For each frame received the driver must lookup the table entry to +use in dispatching the frame +.Dq up the stack . +This lookup implicitly obtains a reference to the table entry and +the driver must reclaim the reference when frame processing is completed. +Otherwise drivers frequently inspect the contents of the +.Vt iv_bss +node when handling state machine changes as important information +is maintained in the data structure. +.Pp +The node table is opaque to drivers. +Entries may be looked up using one of the pre-defined API's or the +.Fn ieee80211_iterate_nodes +call may be used to iterate through all entries to do per-node +processing or implement some non-standard search mechanism. +Note that +.Fn ieee80211_iterate_nodes +is single-threaded per-device +and the effort processing involved is fairly +substantial so it should be used carefully. +.Pp +Two routines are provided to print the contents of nodes to the console +for debugging: +.Fn ieee80211_dump_node +displays the contents of a single node while +.Fn ieee80211_dump_nodes +displays the contents of the specified node table. +Nodes may also be displayed using +.Xr ddb 9 +with the +.Dq show node +directive and the station node table can be displayed with +.Dq show statab . +.Sh DRIVER PRIVATE STATE +Node data structures may be extended by the driver to include +driver-private state. +This is done by overriding the +.Vt ic_node_alloc +method used to allocate a node table entry. +The driver method must allocate a structure that is an extension +of the +.Vt ieee80211_node +structure. +For example the +.Xr iwi 4 +driver defines a private node structure as: +.Bd -literal -offset indent +struct iwi_node { + struct ieee80211_node in_node; + int in_station; +}; +.Ed +.Pp +and then provides a private allocation routine that does this: +.Bd -literal -offset indent +static struct ieee80211_node * +iwi_node_alloc(struct ieee80211vap *vap, + const uint8_t mac[IEEE80211_ADDR_LEN]) +{ + struct iwi_node *in; + + in = malloc(sizeof (struct iwi_node), M_80211_NODE, + M_NOWAIT | M_ZERO); + if (in == NULL) + return NULL; + in->in_station = -1; + return &in->in_node; +} +.Ed +.Pp +Note that when reclaiming a node allocated by the driver the +.Dq parent method +must be called to ensure +.Nm net80211 +state is reclaimed; for example: +.Bd -literal -offset indent +static void +iwi_node_free(struct ieee80211_node *ni) +{ + struct ieee80211com *ic = ni->ni_ic; + struct iwi_softc *sc = ic->ic_ifp->if_softc; + struct iwi_node *in = (struct iwi_node *)ni; + + if (in->in_station != -1) + free_unr(sc->sc_unr, in->in_station); + sc->sc_node_free(ni); /* invoke net80211 free handler */ +} +.Ed +.Pp +Beware that care must be taken to avoid holding references that +might cause nodes from being reclaimed. +.Nm net80211 +will reclaim a node when the last reference is reclaimed in +its data structures. +However if a driver holds additional references then +.Nm net80211 +will not recognize this and table entries will not be reclaimed. +Such references should not be needed if the driver overrides the +.Vt ic_node_cleanup +and/or +.Vt ic_node_free +methods. +.Sh KEY TABLE SUPPORT +Node table lookups are typically done using a hash of the stations' +mac address. +When receiving frames this is sufficient to find the node table entry +for the transmitter. +But some devices also identify the sending station in the device +state received with each frame and this data can be used to optimize +lookups on receive using a companion table called the +.Dq keytab . +This table records a separate node table reference that can be fetched +without any locking using the table index. +This logic is handled with the +.Fn ieee80211_find_rxnode_withkey +call: if a keytab entry is found using the specified index then it is +returned directly; otherwise a normal lookup is done and the keytab +entry is written using the specified index. +If the specified index is +.Dv IEEE80211_KEYIX_NONE +then a normal lookup is done without a table update. +.Sh SEE ALSO +.Xr ddb 9 +.Xr ieee80211 9 , +.Xr ieee80211_proto 9 , diff --git a/share/man/man9/ieee80211_output.9 b/share/man/man9/ieee80211_output.9 index f553c4f3783..c2f9667eb4a 100644 --- a/share/man/man9/ieee80211_output.9 +++ b/share/man/man9/ieee80211_output.9 @@ -27,125 +27,168 @@ .\" $FreeBSD$ .\" $Id: ieee80211_output.9,v 1.5 2004/03/04 12:31:18 bruce Exp $ .\" -.Dd March 2, 2004 +.Dd August 4, 2009 .Dt IEEE80211_OUTPUT 9 .Os .Sh NAME -.Nm ieee80211_encap , ieee80211_add_rates , -.Nm ieee80211_add_xrates , ieee80211_send_mgmt +.Nm ieee80211_output .Nd software 802.11 stack output functions .Sh SYNOPSIS .In net80211/ieee80211_var.h -.In net80211/ieee80211_proto.h -.Ft struct mbuf * -.Fo ieee80211_encap -.Fa "struct ifnet *ifp" "struct mbuf *m" "struct ieee80211_node **pni" -.Fc -.Ft u_int8_t * -.Fn ieee80211_add_rates "u_int8_t *frm" "const struct ieee80211_rateset *rs" -.Ft u_int8_t * -.Fn ieee80211_add_xrates "u_int8_t *frm" "const struct ieee80211_rateset *rs" +.\" .Ft int -.Fo ieee80211_send_mgmt -.Fa "struct ieee80211com *ic" "struct ieee80211_node *ni" "int type" "int arg" +.Fn M_WME_GETAC "struct mbuf *" +.\" +.Ft int +.Fn M_SEQNO_GET "struct mbuf *" +.\" +.Ft struct ieee80211_key * +.Fn ieee80211_crypto_encap "struct ieee80211_node *" "struct mbuf *" +.\" +.Ft void +.Fo ieee80211_process_callback +.Fa struct ieee80211_node * +.Fa struct mbuf * +.Fa int .Fc .Sh DESCRIPTION -These functions handle the encapsulation and transmission of 802.11 frames -within the software 802.11 stack. -.Pp The -.Fn ieee80211_encap -function encapsulates an outbound data frame contained within the -mbuf chain -.Fa m -from the interface -.Fa ifp . -The argument -.Fa *pni -is a reference to the destination node. +.Nm net80211 +layer that supports 802.11 device drivers handles most of the +work required to transmit frames. +Drivers usually receive fully-encapsulated 802.11 frames that +have been classified and assigned a transmit priority; +all that is left is to do +crypto encapsulation, +prepare any hardware-specific state, +and +push the packet out to the device. +Outbound frames are either generated by the +.Nm net80211 +layer (e.g. management frames) or are passed down +from upper layers through the +.Xr ifnet 9 +transmit queue. +Data frames passed down for transmit flow through +.Nm net80211 +which handles aggregation, 802.11 encapsulation, and then +dispatches the frames to the driver through it's transmit queue. .Pp -If the function is successful, the mbuf chain is updated with the -802.11 frame header prepended, and a pointer to the head of the chain -is returned. -If an error occurs, -.Dv NULL -will be returned, and -.Fa *pni -is also set to -.Dv NULL . -The caller is responsible for freeing the node reference if -.Fa *pni -is -.Pf non- Dv NULL -on return. -The convention is that -.Va ic_bss -is not reference counted; the caller is responsible for maintaining this -reference count. +There are two control paths by which frames reach a driver for transmit. +Data packets are queued to the device's +.Vt if_snd +queue and the driver's +.Vt if_start +method is called. +Other frames are passed down using the +.Vt ic_raw_xmit +method without queueing (unless done by the driver). +The raw transmit path may include data frames from user applications +that inject them through +.Xr bpf 4 +and NullData frames generated by +.Nm net80211 +to probe for idle stations (when operating as an access point). .Pp -.\" +.Nm net80211 +handles all state-related bookkeeping and management for the handling +of data frames. +Data frames are only transmit for a vap in the +.Dv IEEE80211_S_RUN +state; there is no need, for example, to check for frames sent down +when CAC or CSA is active. +Similarly, +.Nm net80211 +handles activities such as background scanning and power save mode, +frames will not be sent to a driver unless it is operating on the +BSS channel will +.Dq full power . +.Pp +All frames passed to a driver for transmit hold a reference to a +node table entry in the +.Vt m_pkthdr.rcvif +field. +The node is associated with the frame destination. +Typically it is the receiver's entry but in some situations it may be +a placeholder entry or the +.Dq next hop station +(such as in a mesh network). +In all cases the reference must be reclaimed with +.Fn ieee80211_free_node +when the transmit work is completed. +The rule to remember is: +.Nm net80211 +passes responsibility for the +.Vt mbuf +and +.Dq node reference +to the driver with each frame it hands off for transmit. +.Sh PACKET CLASSIFICATION +All frames passed by +.Nm net80211 +for transmit are assigned a priority based on any vlan tag +assigned to the receiving station and/or any Diffserv setting +in an IP or IPv6 header. +If both vlan and Diffserv priority are present the higher of the +two is used. +If WME/WMM is being used then any ACM policy (in station mode) is +also enforced. +The resulting AC is attached to the mbuf and may be read back using the +.Fn M_WME_GETAC +macro. +.Pp +PAE/EAPOL frames are tagged with an +.Dv M_EAPOL +mbuf flag; drivers should transmit them with care, usually by +using the transmit rate for management frames. +Multicast/broadcast frames are marked with the +.Dv M_MCAST +mbuf flag. +Frames coming out of a station's power save queue and that have +more frames immediately following are marked with the +.Dv M_MORE_DATA +mbuf flag. +Such frames will be queued consecutively in the driver's +.Vt if_snd +queue and drivers should preserve the ordering when passing +them to the device. +.Sh FRAGMENTED FRAMES The -.Fn ieee80211_add_rates -utility function is used to add the rate set element -.Fa *rs -to the frame -.Fa frm . -A pointer to the location in the buffer after the addition of the rate set -is returned. -It is typically used when constructing management frames from within the -software 802.11 stack. -.Pp -.\" -The -.Fn ieee80211_add_xrates -utility function is used to add the extended rate set element -.Fa *rs -to the frame -.Fa frm . -A pointer to the location in the buffer after the addition of the rate set -is returned. -It is typically used when constructing management frames from within the -software 802.11 stack in 802.11g mode. -.Pp -.\" -The -.Fn ieee80211_send_mgmt -function transmits a management frame on the interface -.Fa ic -to the destination node -.Fa ni -of type -.Fa type . -.Pp -The argument -.Fa arg -specifies either a sequence number for authentication operations, -a status code for [re]association operations, -or a reason for deauthentication and deassociation operations. -.Pp -Nodes other than -.Va ic_bss -have their reference count incremented to reflect their use for an -indeterminate amount of time. -This reference is freed when the function returns. -.Pp -The function returns 0 if successful; if temporary buffer space is not -available, the function returns -.Er ENOMEM . -.\" +.Nm net80211 +layer will fragment data frames according to the setting of +.Vt iv_fragthreshold +if a driver marks the +.Dv IEEE80211_C_TXFRAG +capability. +Fragmented frames are placed +in the devices transmit queue with the fragments chained together with +.Vt m_nextpkt . +Each frame is marked with the +.Dv M_FRAG +mbuf flag, and the first and last are marked with +.Dv M_FIRSTFRAG +and +.Dv M_LASTFRAG , +respectively. +Drivers are expected to process all fragments or none. +.Sh TRANSMIT CALLBACKS +Frames sent by +.Nm net80211 +may be tagged with the +.Dv M_TXCB +mbuf flag to indicate a callback should be done +when their transmission completes. +The callback is done using +.Fn ieee80211_process_callback +with the last parameter set to a non-zero value if an error occurred +and zero otherwise. +Note +.Nm net80211 +understands that drivers may be incapable of determining status; +a device may not report if an ACK frame is received and/or a device may queue +transmit requests in its hardware and only report status on whether +the frame was successfully queued. .Sh SEE ALSO +.Xr bpf 4 .Xr ieee80211 9 , .Xr ifnet 9 -.Sh HISTORY -The -.Nm ieee80211 -series of functions first appeared in -.Nx 1.5 , -and were later ported to -.Fx 4.6 . -.Sh AUTHORS -.An -nosplit -This manual page was written by -.An Bruce M. Simpson Aq bms@FreeBSD.org -and -.An Darron Broad Aq darron@kewl.org . diff --git a/share/man/man9/ieee80211_proto.9 b/share/man/man9/ieee80211_proto.9 index 0de486451d3..70a3572e8f8 100644 --- a/share/man/man9/ieee80211_proto.9 +++ b/share/man/man9/ieee80211_proto.9 @@ -1,6 +1,5 @@ .\" -.\" Copyright (c) 2004 Bruce M. Simpson -.\" Copyright (c) 2004 Darron Broad +.\" Copyright (c) 2009 Sam Leffler, Errno Consulting .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -25,51 +24,218 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.\" $Id: ieee80211_proto.9,v 1.5 2004/03/04 12:33:27 bruce Exp $ .\" -.Dd March 2, 2004 +.Dd August 4, 2009 .Dt IEEE80211_PROTO 9 .Os .Sh NAME -.Nm ieee80211_proto_attach , -.Nm ieee80211_proto_detach , -.Nm ieee80211_print_essid , -.Nm ieee80211_dump_pkt , -.Nm ieee80211_fix_rate , .Nm ieee80211_proto -.Nd software 802.11 stack protocol helper functions +.Nd 802.11 state machine support .Sh SYNOPSIS .In net80211/ieee80211_var.h -.In net80211/ieee80211_proto.h +.Pp .Ft void -.Fn ieee80211_proto_attach "struct ifnet *ifp" +.Fn ieee80211_start_all "struct ieee80211com *" .Ft void -.Fn ieee80211_proto_detach "struct ifnet *ifp" +.Fn ieee80211_stop_all "struct ieee80211com *" .Ft void -.Fn ieee80211_print_essid "u_int8_t *essid" "int len" +.Fn ieee80211_suspend_all "struct ieee80211com *" .Ft void -.Fn ieee80211_dump_pkt "u_int8_t *buf" "int len" "int rate" "int rssi" +.Fn ieee80211_resume_all "struct ieee80211com *" +.Pp +.Dv enum ieee80211_state ; .Ft int -.Fo ieee80211_fix_rate -.Fa "struct ieee80211com *ic" "struct ieee80211_node *ni" "int flags" -.Fc +.Fn ieee80211_new_state "struct ieee80211vap *" "enum ieee80211_state" "int" +.Pp +.Ft void +.Fn ieee80211_wait_for_parent "struct ieee80211com *" .Sh DESCRIPTION -These -functions are helper functions used throughout the software 802.11 protocol -stack. +The +.Nm net80211 +layer that supports 802.11 device drivers uses a state machine +to control operation of vaps. +These state machines vary according to the vap operating mode. +Station mode state machines follow the 802.11 MLME states +in the protocol specification. +Other state machines are simpler and reflect operational work +such as scanning for a BSS or automatically selecting a channel to +operate on. +When multiple vaps are operational the state machines are used to +coordinate operation such as choosing a channel. +The state machine mechanism also serves to bind the +.Nm net80211 +layer to a driver; this is described more below. +.Pp +The following states are defined for state machines: +.Bl -tag -width IEEE80211_S_ASSOC +.It Dv IEEE80211_S_INIT +Default/initial state. +A vap in this state should not hold any dynamic state (e.g. entries +for associated stations in the node table). +The driver must quiesce the hardware; e.g. there should be no +interrupts firing. +.It Dv IEEE80211_S_SCAN +Scanning for a BSS or choosing a channel to operate on. +Note that scanning can also take place in other states (e.g. when +background scanning is active); this state is entered when +initially bringing a vap to an operational state or after an +event such as a beacon miss (in station mode). +.It Dv IEEE80211_S_AUTH +Authenticating to an access point (in station mode). +This state is normally reached from +.Dv IEEE80211_S_SCAN +after selecting a BSS, but may also be reached from +.Dv IEEE80211_S_ASSOC +or +.Dv IEEE80211_S_RUN +if the authentication handshake fails. +.It Dv IEEE80211_S_ASSOC +Associating to an access point (in station mode). +This state is reached from +.Dv IEEE80211_S_AUTH +after successfully authenticating or from +.Dv IEEE80211_S_RUN +if a DisAssoc frame is received. +.It Dv IEEE80211_S_CAC +Doing Channel Availability Check (CAC). +This state is entered only when DFS is enabled and the channel selected +for operation requires CAC. +.It Dv IEEE80211_S_RUN +Operational. +In this state a vap can transmit data frames, accept requests for +stations associating, etc. +Beware that data traffic is also gated by whether the associated +.Dq port +is authorized. +When WPA/802.11i/802.1x is operational authorization may happen separately; +e.g. in station mode +.Xr wpa_supplicant 8 +must complete the handshakes and plumb the necessary keys before a port +is authorized. +In this state a BSS is operational and associated state is valid and may +be used; e.g. +.Vt ic_bss +and +.Vt ic_bsschan +are guaranteed to be usable. +.It Dv IEEE80211_S_CSA +Channel Switch Annoucememnt (CSA) is pending. +This state is reached only from +.Dv IEEE80211_S_RUN +when either a CSA is received from an access point (in station mode) +or the local station is preparing to change channel. +In this state traffic may be muted depending on the Mute setting in the CSA. +.It Dv IEEE80211_S_SLEEP +Asleep to save power (in station mode). +This state is reached only from +.Dv IEEE80211_S_RUN +when power save operation is enabled and the local station is deemed +sufficiently idle to enter low power mode. +.El +.Pp +Note that states are ordered (as shown above); +e.g. a vap must be in the +.Dv IEEE80211_S_RUN +or +.Dq greater +before it can transmit frames. +Certain +.Nm net80211 +data are valid only in certain states; e.g. the +.Vt iv_bsschan +that specifies the channel for the operating BSS should never be used +except in +.Dv IEEE80211_S_RUN +or greater. +.Sh STATE CHANGES +State machine changes are typically handled internal to the +.Nm net80211 +layer in response to +.Xr ioctl 2 +requests, received frames, or external events such as a beacon miss. +The +.Fn ieee80211_new_state +function is used to initiate a state machine change on a vap. +The new state and an optional argument are supplied. +The request is initially processed to handle coordination of multiple vaps. +For example, only one vap at a time can be scanning, if multiple vaps +request a change to +.Dv IEEE80211_S_SCAN +the first will be permitted to run and the others will be +.Em deferred +until the scan operation completes at which time the selected channel +will be adopted. +Similarly +.Nm net80211 +handles coordination of combinations of vaps such as an AP and station vap +where the station may need to roam to follow the AP it is associated to +(dragging along the AP vap to the new channel). +Another important coordination is the handling of +.Dv IEEE80211_S_CAC +and +.Dv IEEE80211_S_CSA . +No more than one vap can ever be actively changing state at a time. +In fact +.Nm net80211 +single-threads the state machine logic in a dedicated +.Xr taskqueue 9 +thread that is also used to synchronize work such as scanning and +beacon miss handling. +.Pp +After multi-vap scheduling/coordination is done the per-vap +.Vt iv_newstate +method is called to carry out the state change work. +Drivers use this entry to setup private state and then dispatch +the call to the +.Nm net80211 +layer using the previously defined method pointer (in OOP-parlance they +call the +.Dq super method +). +.Pp +.Nm net80211 +handles two state changes specially. +On transition to +.Dv IEEE80211_S_RUN +the +.Dv IFF_DRV_OACTIVE +bit on the vap's transmit queue is cleared so traffic can flow. +On transition to +.Dv IEEE80211_S_INIT +any state in the scan cache associated with the vap is flushed +and any frames pending on the transmit queue are flushed. +.Sh DRIVER INTEGRATION +Drivers are expected to override the +.Vt iv_newstate +method to interpose their own code and handle setup work required +by state changes. +Otherwise drivers must call +.Fn ieee80211_start_all +in response to being marked up through an +.Dv SIOCSIFFLAGS +ioctl request and they should use +.Fn ieee80211_suspend_all +and +.Fn ieee80211_resume_all +to implement suspend/resume support. +.Pp +There is also an +.Fn ieee80211_stop_all +call to force all vaps to an +.Dv IEEE80211_S_INIT +state but this should not be needed by a driver; control is usually +handled by +.Nm net80211 +or, in the case of card eject or vap destroy, +work will be initiated outside the driver. .Sh SEE ALSO +.Xr ioctl 2 .Xr ieee80211 9 , .Xr ifnet 9 +.Xr taskqueue 9 +.Xr wpa_supplicant 8 .Sh HISTORY -The +The state machine concept was part of the original .Nm ieee80211 -series of functions first appeared in +code base that first appeared in .Nx 1.5 , -and were later ported to -.Fx 4.6 . -.Sh AUTHORS -.An -nosplit -This manual page was written by -.An Bruce M. Simpson Aq bms@FreeBSD.org -and -.An Darron Broad Aq darron@kewl.org . diff --git a/share/man/man9/ieee80211_radiotap.9 b/share/man/man9/ieee80211_radiotap.9 index 7375eec9f2d..092912fc39e 100644 --- a/share/man/man9/ieee80211_radiotap.9 +++ b/share/man/man9/ieee80211_radiotap.9 @@ -26,210 +26,280 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.\" $Id: ieee80211_radiotap.9,v 1.3 2004/03/04 11:38:52 bruce Exp $ .\" -.Dd March 17, 2008 +.Dd August 4, 2009 .Dt IEEE80211_RADIOTAP 9 .Os .Sh NAME .Nm ieee80211_radiotap -.Nd software 802.11 stack packet capture definitions +.Nd 802.11 device packet capture support .Sh SYNOPSIS .In net80211/ieee80211_var.h -.In net80211/ieee80211_ioctl.h -.In net80211/ieee80211_radiotap.h -.In net/bpf.h .\" +.Pp +.Ft void +.Fo ieee80211_radiotap_attach +.Fa "struct ieee80211com *" +.Fa "struct ieee80211_radiotap_header *th" +.Fa "int tlen" +.Fa "uint32_t tx_radiotap" +.Fa "struct ieee80211_radiotap_header *rh" +.Fa "int rlen" +.Fa "uint32_t rx_radiotap" +.Fc +.\" +.Ft int +.Fn ieee80211_radiotap_active_vap "struct ieee80211vap *" +.\" +.Ft int +.Fn ieee80211_radiotap_active "struct ieee80211com *" +.\" +.Ft void +.Fn ieee80211_radiotap_tx "struct ieee80211vap *" "struct mbuf *" .Sh DESCRIPTION The -.Nm -definitions provide a device-independent -.Xr bpf 4 -attachment for the -capture of information about 802.11 traffic which is not part of -the 802.11 frame structure. +.Nm net80211 +layer used by 802.11 drivers includes support for a device-independent +packet capture format called +.Nm radiotap +that is understood by tools such as +.Xr tcpdump 1 . +This facility is designed for capturing 802.11 traffic, +including information that is not part of the normal 802.11 frame structure. .Pp -Radiotap was designed to balance the desire for a capture format -that conserved CPU and memory bandwidth on embedded systems, -with the desire for a hardware-independent, extensible format -that would support the diverse capabilities of virtually all -802.11 -radios. -.Pp -These considerations led radiotap to settle on a format consisting of +Radiotap was designed to balance the desire for a hardware-independent, +extensible capture format against the need to +conserve CPU and memory bandwidth on embedded systems. +These considerations led to a format consisting of a standard preamble followed by an extensible bitmap indicating the presence of optional capture fields. +A +.Nm net80211 +device driver supporting +.Vt radiotap +defines two packed structures that it shares with +.Nm net80211 . +These structures embed an instance of a +.Vt ieee80211_radiotap_header +structure at the beginning, +with subsequent fields in the appropriate order, +and macros to set the bits of the +.Va it_present +bitmap to indicate which fields exist and are filled in by the driver. +This information is then supplied through the +.Fn ieee80211_radiotap_attach +call after a successful +.Fn ieee80211_ifattach +request. .Pp -The capture fields were packed into the header as compactly as possible, -modulo the requirements that they had to be packed swiftly, -with suitable alignment, in the same order as the bits indicating -their presence. +With radiotap setup, drivers just need to fill in per-packet +capture state for frames sent/received and dispatch capture state +in the transmit path (since control is not returned to the +.Nm net80211 +layer before the packet is handed to the device). +To minimize overhead this work should be done only when one +or more processes are actively capturing data; +this is checked with one of +.Fn ieee80211_radiotap_active_vap +and +.Fn ieee80211_radiotap_active . +In the transmit path capture work looks like this: .Pp -This typically includes information such as signal quality and -timestamps. -This information may be used by a variety of user agents, including -.Xr tcpdump 1 . -It is requested by using the -.Xr bpf 4 -data-link type -.Dv DLT_IEEE802_11_RADIO . -.Pp -.\" -Each frame using this attachment has the following header prepended to it: .Bd -literal -offset indent -struct ieee80211_radiotap_header { - u_int8_t it_version; /* set to 0 */ - u_int8_t it_pad; - u_int16_t it_len; /* entire length */ - u_int32_t it_present; /* fields present */ -} __attribute__((__packed__)); +if (ieee80211_radiotap_active_vap(vap)) { + ... /* record transmit state */ + ieee80211_radiotap_tx(vap, m); /* capture transmit event */ +} +.Ed +.Pp +While in the receive path capture is handled in +.Nm net80211 +but state must be captured before dispatching a frame: +.Pp +.Bd -literal -offset indent +if (ieee80211_radiotap_active(ic)) { + ... /* record receive state */ +} +\&... +ieee80211_input(...); /* packet capture handled in net80211 */ .Ed .Pp .\" -A device driver implementing -.Vt radiotap -typically defines a packed structure embedding an instance of -.Vt "struct ieee80211_radiotap_header" -at the beginning, -with subsequent fields in the appropriate order, -and a macro to set the bits of the -.Va it_present -bitmap to indicate which fields exist and are filled in by the driver. -.\" -.Pp -Radiotap headers are copied to the userland via a separate bpf attachment. -It is necessary for the driver to create this attachment after calling -.Xr ieee80211_ifattach 9 -by calling -.Fn bpfattach2 -with the data-link type set to -.Dv DLT_IEEE802_11_RADIO . -.Pp -.\" -When the the information is available, -usually immediately before a link-layer transmission or after a receive, -the driver copies it to the bpf layer using the -.Fn bpf_mtap2 -function. -.Pp -.\" -The following extension fields are defined for +The following fields are defined for .Vt radiotap , -in the order in which they should appear in the buffer copied to userland: +in the order in which they should appear in the buffer supplied +to +.Nm net80211 . .Bl -tag -width indent .It Dv IEEE80211_RADIOTAP_TSFT This field contains the unsigned 64-bit value, in microseconds, -of the MAC's 802.11 Time Synchronization Function timer, +of the MAC's 802.11 Time Synchronization Function (TSF). +In theory, for each received frame, this value is recorded when the first bit of the MPDU arrived at the MAC. -This field should be present for received frames only. +In practice, hardware snapshots the TSF otherwise and one cannot assume +this data is accurate without driver adjustment. .It Dv IEEE80211_RADIOTAP_FLAGS -This field contains a single unsigned 8-bit value, containing a bitmap -of flags specifying properties of the frame being transmitted or received. +This field contains a single unsigned 8-bit value, containing one or +more of these bit flags: +.Bl -tag -width indent +.It Dv IEEE80211_RADIOTAP_F_CFP +Frame was sent/received during the Contention Free Period (CFP). +.It Dv IEEE80211_RADIOTAP_F_SHORTPRE +Frame was sent/received with short preamble. +.It Dv IEEE80211_RADIOTAP_F_WEP +Frame was encrypted. +.It Dv IEEE80211_RADIOTAP_F_FRAG +Frame was an 802.11 fragment. +.It Dv IEEE80211_RADIOTAP_F_FCS +Frame contents includes the FCS. +.It Dv IEEE80211_RADIOTAP_F_DATAPAD +Frame contents potentially has padding between the 802.11 header and the +data payload to align the payload to a 32-bit boundary. +.It Dv IEEE80211_RADIOTAP_F_BADFCS +Frame was received with an invalid FCS. +.It Dv IEEE80211_RADIOTAP_F_SHORTGI +Frame was sent/received with Short Guard Interval. +.El .It Dv IEEE80211_RADIOTAP_RATE -This field contains a single unsigned 8-bit value, which is the data rate in -use in units of 500Kbps. +This field contains a single unsigned 8-bit value that is the data rate. +Legacy rates are in units of 500Kbps. +MCS rates (used on 802.11n/HT channels) have the high bit set and +the MCS in the low 7 bits. .It Dv IEEE80211_RADIOTAP_CHANNEL This field contains two unsigned 16-bit values. -The first value is the frequency upon which this PDU was transmitted -or received. -The second value is a bitmap containing flags which specify properties of -the channel in use. -These are documented within the header file, -.In net80211/ieee80211_radiotap.h . -.It Dv IEEE80211_RADIOTAP_FHSS -This field contains two 8-bit values. -This field should be present for frequency-hopping radios only. -The first byte is the hop set. -The second byte is the pattern in use. +The first value is the center frequency for the channel +the frame was sent/received on. +The second value is a bitmap containing flags that specify channel properties. +.Pp +This field is deprecated in favor of +.Dv IEEE80211_RADIOTAP_XCHANNEL +but may be used to save space in the capture file for legacy devices. +.\".It Dv IEEE80211_RADIOTAP_FHSS +.\"This field contains two 8-bit values. +.\"This field should be present only for frequency-hopping radios. +.\"The first byte is the hop set. +.\"The second byte is the pattern in use. .It Dv IEEE80211_RADIOTAP_DBM_ANTSIGNAL -This field contains a single signed 8-bit value, which indicates the +This field contains a single signed 8-bit value that indicates the RF signal power at the antenna, in decibels difference from 1mW. .It Dv IEEE80211_RADIOTAP_DBM_ANTNOISE -This field contains a single signed 8-bit value, which indicates the +This field contains a single signed 8-bit value that indicates the RF noise power at the antenna, in decibels difference from 1mW. -.It Dv IEEE80211_RADIOTAP_LOCK_QUALITY -This field contains a single unsigned 16-bit value, indicating the -quality of the Barker Code lock. -No unit is specified for this field. -There does not appear to be a standard way of measuring this at this time; -this quantity is often referred to as -.Dq "Signal Quality" -in some datasheets. -.It Dv IEEE80211_RADIOTAP_TX_ATTENUATION -This field contains a single unsigned 16-bit value, expressing transmit -power as unitless distance from maximum power set at factory calibration. -0 indicates maximum transmit power. -Monotonically nondecreasing with lower power levels. -.It Dv IEEE80211_RADIOTAP_DB_TX_ATTENUATION -This field contains a single unsigned 16-bit value, expressing transmit -power as decibel distance from maximum power set at factory calibration. -0 indicates maximum transmit power. -Monotonically nondecreasing with lower power levels. +.\".It Dv IEEE80211_RADIOTAP_LOCK_QUALITY +.\"This field contains a single unsigned 16-bit value, indicating the +.\"quality of the Barker Code lock. +.\"No unit is specified for this field. +.\"There does not appear to be a standard way of measuring this at this time; +.\"this quantity is often referred to as +.\".Dq "Signal Quality" +.\"in some datasheets. +.\".It Dv IEEE80211_RADIOTAP_TX_ATTENUATION +.\"This field contains a single unsigned 16-bit value, expressing transmit +.\"power as unitless distance from maximum power set at factory calibration. +.\"0 indicates maximum transmit power. +.\"Monotonically nondecreasing with lower power levels. +\.".It Dv IEEE80211_RADIOTAP_DB_TX_ATTENUATION +\."This field contains a single unsigned 16-bit value, expressing transmit +\."power as decibel distance from maximum power set at factory calibration. +\."0 indicates maximum transmit power. +\."Monotonically nondecreasing with lower power levels. .It Dv IEEE80211_RADIOTAP_DBM_TX_POWER Transmit power expressed as decibels from a 1mW reference. This field is a single signed 8-bit value. This is the absolute power level measured at the antenna port. .It Dv IEEE80211_RADIOTAP_ANTENNA -For radios which support antenna diversity, this field contains a single -unsigned 8-bit value specifying which antenna is being used to transmit -or receive this frame. -The first antenna is antenna 0. +This field contains a single unsigned 8-bit value that specifies +which antenna was used to transmit or receive the frame. +Antenna numbering is device-specific but typically the primary antenna has +the lowest number. +On transmit a value of zero may be seen which typically means +antenna selection is left to the device. .It Dv IEEE80211_RADIOTAP_DB_ANTSIGNAL -This field contains a single unsigned 8-bit value, which indicates the +This field contains a single unsigned 8-bit value that indicates the RF signal power at the antenna, in decibels difference from an arbitrary, fixed reference. .It Dv IEEE80211_RADIOTAP_DB_ANTNOISE -This field contains a single unsigned 8-bit value, which indicates the +This field contains a single unsigned 8-bit value that indicates the RF noise power at the antenna, in decibels difference from an arbitrary, fixed reference. -.It Dv IEEE80211_RADIOTAP_EXT -This bit is reserved for any future extensions to the -.Vt radiotap -structure. -It should not be used at this time. +.It Dv IEEE80211_RADIOTAP_XCHANNEL +This field containts four values: a 32-bit unsigned bitmap of +flags that describe the channel attributes, a 16-bit unsigned +freqeuncy in MHz (typically the channel center), an 8-bit +unsigned IEEE channel number, and a signed 8-bit value that +holds the maximum regulatory transmit power cap in .5 dBm +(8 bytes total). +Channel flags are defined in: +.In net80211/_ieee80211.h +(only a subset are found in +.In net80211/ieee80211_radiotap.h ). +This property supersedes +.Dv IEEE80211_RADIOTAP_CHANNEL +and is the only way to completely express all +channel attributes and the +mapping between channel freqeuncy and IEEE channel number. .El .Sh EXAMPLES -Radiotap header for the Cisco Aironet driver: +Radiotap receive definitions for the Intersil Prims driver: .Bd -literal -offset indent -struct an_rx_radiotap_header { - struct ieee80211_radiotap_header ar_ihdr; - u_int8_t ar_flags; - u_int8_t ar_rate; - u_int16_t ar_chan_freq; - u_int16_t ar_chan_flags; - u_int8_t ar_antsignal; - u_int8_t ar_antnoise; -} __attribute__((__packed__)); +#define WI_RX_RADIOTAP_PRESENT \\ + ((1 << IEEE80211_RADIOTAP_TSFT) \\ + (1 << IEEE80211_RADIOTAP_FLAGS) | \\ + (1 << IEEE80211_RADIOTAP_RATE) | \\ + (1 << IEEE80211_RADIOTAP_CHANNEL) | \\ + (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \\ + (1 << IEEE80211_RADIOTAP_DB_ANTNOISE)) + +struct wi_rx_radiotap_header { + struct ieee80211_radiotap_header wr_ihdr; + uint64_t wr_tsf; + uint8_t wr_flags; + uint8_t wr_rate; + uint16_t wr_chan_freq; + uint16_t wr_chan_flags; + uint8_t wr_antsignal; + uint8_t wr_antnoise; +} __packed; .Ed .Pp -Bitmap indicating which fields are present in the above structure: +and transmit definitions for the Atheros driver: .Bd -literal -offset indent -#define AN_RX_RADIOTAP_PRESENT \\ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \\ - (1 << IEEE80211_RADIOTAP_RATE) | \\ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \\ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \\ - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)) +#define ATH_TX_RADIOTAP_PRESENT ( \\ + (1 << IEEE80211_RADIOTAP_TSFT) | \\ + (1 << IEEE80211_RADIOTAP_FLAGS) | \\ + (1 << IEEE80211_RADIOTAP_RATE) | \\ + (1 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \\ + (1 << IEEE80211_RADIOTAP_ANTENNA) | \\ + (1 << IEEE80211_RADIOTAP_XCHANNEL) | \\ + 0) + +struct ath_tx_radiotap_header { + struct ieee80211_radiotap_header wt_ihdr; + uint64_t wt_tsf; + uint8_t wt_flags; + uint8_t wt_rate; + uint8_t wt_txpower; + uint8_t wt_antenna; + uint32_t wt_chan_flags; + uint16_t wt_chan_freq; + uint8_t wt_chan_ieee; + int8_t wt_chan_maxpow; +} __packed; .Ed .Sh SEE ALSO +.Xr tcpdump 1 , .Xr bpf 4 , .Xr ieee80211 9 .Sh HISTORY The .Nm definitions first appeared in -.Nx 1.5 , -and were later ported to -.Fx 4.6 . +.Nx 1.5 . .\" .Sh AUTHORS .An -nosplit -The -.Nm -interface was designed and implemented by -.An David Young Aq dyoung@pobox.com . .Pp -This manual page was written by +The original version of this manual page was written by .An Bruce M. Simpson Aq bms@FreeBSD.org and .An Darron Broad Aq darron@kewl.org . diff --git a/share/man/man9/kproc.9 b/share/man/man9/kproc.9 index 23ce05c28d6..bb56235453c 100644 --- a/share/man/man9/kproc.9 +++ b/share/man/man9/kproc.9 @@ -64,6 +64,28 @@ .Fa "int flags" "int pages" "char * procname" "const char *fmt" "..." .Fc .Sh DESCRIPTION +In +.Fx 8.0 , +the +.Fn kthread* 9 +family of functions was renamed to be the +.Fn kproc* 9 +family of functions, as they were misnamed +and actually produced kernel processes. +A new family of +.Em different +.Fn kthread_* 9 +functions was added to produce +.Em real +kernel +.Em threads . +See the +.Xr kthread 9 +man page for more information on those calls. +Also note that the +.Fn kproc_kthread_add 9 +function appears in both pages as its functionality is split. +.Pp The function .Fn kproc_start is used to start diff --git a/share/man/man9/kthread.9 b/share/man/man9/kthread.9 index 29d678c66dc..ffb5179614d 100644 --- a/share/man/man9/kthread.9 +++ b/share/man/man9/kthread.9 @@ -65,6 +65,27 @@ .Fa "int flags" "int pages" "char * procname" "const char *fmt" "..." .Fc .Sh DESCRIPTION +In +.Fx 8.0 , +the older family of +.Fn kthread_* 9 +functions was renamed to be the +.Fn kproc_* 9 +family of functions, +as they were previously misnamed +and actually produced kernel processes. +This new family of +.Fn kthread_* 9 +functions was added to produce +.Em real +kernel threads. +See the +.Xr kproc 9 +man page for more information on the renamed calls. +Also note that the +.Fn kproc_kthread_add 9 +function appears in both pages as its functionality is split. +.Pp The function .Fn kthread_start is used to start diff --git a/share/man/man9/sglist.9 b/share/man/man9/sglist.9 index 8c1c046ad76..e43a04b4d04 100644 --- a/share/man/man9/sglist.9 +++ b/share/man/man9/sglist.9 @@ -70,7 +70,7 @@ .Ft struct sglist * .Fn sglist_clone "struct sglist *sg" "int mflags" .Ft int -.Fn sglist_consume_uio "struct sglist *sg" "struct uio *uio" "int resid" +.Fn sglist_consume_uio "struct sglist *sg" "struct uio *uio" "size_t resid" .Ft int .Fn sglist_count "void *buf" "size_t len" .Ft void @@ -191,6 +191,8 @@ Specifically, the family of routines can be used to append the physical address ranges described by an object to the end of a scatter/gather list. All of these routines return 0 on success or an error on failure. +If a request to append an address range to a scatter/gather list fails, +the scatter/gather list will remain unchanged. .Pp The .Nm sglist_append @@ -445,6 +447,7 @@ There are not enough available segments in the scatter/gather list to append the physical address ranges from .Fa second . .El +.Pp The .Nm sglist_slice function returns the following errors on failure: @@ -470,6 +473,7 @@ list in .Fa *slice to describe the requested physical address ranges. .El +.Pp The .Nm sglist_split function returns the following errors on failure: diff --git a/share/man/man9/taskqueue.9 b/share/man/man9/taskqueue.9 index 241b20f4869..5a6f9200dbe 100644 --- a/share/man/man9/taskqueue.9 +++ b/share/man/man9/taskqueue.9 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 13, 2008 +.Dd August 18, 2009 .Dt TASKQUEUE 9 .Os .Sh NAME @@ -59,8 +59,6 @@ struct task { .Fn taskqueue_create_fast "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" .Ft void .Fn taskqueue_free "struct taskqueue *queue" -.Ft struct taskqueue * -.Fn taskqueue_find "const char *name" .Ft int .Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task" .Ft int @@ -71,6 +69,8 @@ struct task { .Fn taskqueue_run_fast "struct taskqueue *queue" .Ft void .Fn taskqueue_drain "struct taskqueue *queue" "struct task *task" +.Ft int +.Fn taskqueue_member "struct taskqueue *queue" "struct thread *td" .Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context" .Fn TASKQUEUE_DECLARE "name" .Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" @@ -113,16 +113,10 @@ should be used in place of .Pp The function .Fn taskqueue_free -should be used to remove the queue from the global list of queues -and free the memory used by the queue. +should be used to free the memory used by the queue. Any tasks that are on the queue will be executed at this time after which the thread servicing the queue will be signaled that it should exit. .Pp -The system maintains a list of all queues which can be searched using -.Fn taskqueue_find . -The first queue whose name matches is returned, otherwise -.Dv NULL . -.Pp To add a task to the list of tasks queued on a taskqueue, call .Fn taskqueue_enqueue with pointers to the queue and task. @@ -182,6 +176,18 @@ There is no guarantee that the task will not be enqueued after call to .Fn taskqueue_drain . .Pp +The +.Fn taskqueue_member +function returns +.No 1 +if the given thread +.Fa td +is part of the given taskqeueue +.Fa queue +and +.No 0 +otherwise. +.Pp A convenience macro, .Fn TASK_INIT "task" "priority" "func" "context" is provided to initialise a diff --git a/share/mklocale/Makefile b/share/mklocale/Makefile index f34987f29a2..b7f551e5e0e 100644 --- a/share/mklocale/Makefile +++ b/share/mklocale/Makefile @@ -13,11 +13,11 @@ LOCALES= UTF-8 \ ko_KR.CP949 \ ko_KR.eucKR \ la_LN.ISO8859-1 \ + la_LN.ISO8859-13 \ la_LN.ISO8859-15 \ la_LN.ISO8859-2 \ la_LN.ISO8859-4 \ la_LN.US-ASCII \ - lt_LT.ISO8859-13 \ ru_RU.CP866 \ ru_RU.ISO8859-5 \ ru_RU.KOI8-R \ @@ -47,7 +47,7 @@ FILESDIR_${locale}.out= ${LOCALEDIR}/${locale} CLEANFILES= ${FILES} ENCODINGS= CP1251 ISO8859-1 ISO8859-2 ISO8859-4 ISO8859-5 \ - ISO8859-15 US-ASCII UTF-8 + ISO8859-13 ISO8859-15 US-ASCII UTF-8 ASCIILINKS= en_AU en_CA en_GB en_NZ en_US US-ASCII_US-ASCII= ${ASCIILINKS:C/^/la_LN:/} @@ -71,6 +71,9 @@ ISO8859-4_ISO8859-4= ${LATIN4LINKS:C/^/la_LN:/} LATIN5LINKS= sr_YU uk_UA be_BY ISO8859-5_ISO8859-5= ${LATIN5LINKS:C/^/ru_RU:/} +LATIN13LINKS= lt_LT lv_LV +ISO8859-13_ISO8859-13= ${LATIN13LINKS:C/^/la_LN:/} + CP1251LINKS= ru_RU be_BY uk_UA CP1251_CP1251= ${CP1251LINKS:C/^/bg_BG:/} @@ -79,7 +82,7 @@ UTF8LINKS= af_ZA be_BY bg_BG ca_AD ca_ES ca_FR ca_IT cs_CZ \ en_AU en_CA en_GB en_IE en_NZ en_US es_ES et_EE eu_ES fi_FI \ fr_BE \ fr_CA fr_CH fr_FR he_IL hr_HR hu_HU hy_AM is_IS it_CH it_IT \ - ja_JP kk_KZ ko_KR lt_LT mn_MN \ + ja_JP kk_KZ ko_KR lt_LT lv_LV mn_MN \ nb_NO nl_BE nl_NL nn_NO no_NO pl_PL pt_BR pt_PT \ ro_RO ru_RU sk_SK sl_SI sr_YU sv_SE tr_TR uk_UA zh_CN zh_HK \ zh_TW diff --git a/share/mklocale/lt_LT.ISO8859-13.src b/share/mklocale/lt_LT.ISO8859-13.src deleted file mode 100644 index ddd248f1cc1..00000000000 --- a/share/mklocale/lt_LT.ISO8859-13.src +++ /dev/null @@ -1,49 +0,0 @@ -/* - * LOCALE_CTYPE for the iso_8859_13 Locale - * - * $FreeBSD$ - */ - -ENCODING "NONE" -VARIABLE ISO 8859-13 Latin-7 character set - -# -# This is a comment -# -ALPHA 'A' - 'Z' 'a' - 'z' -ALPHA 0xaa 0xba 0xc0 - 0xd6 0xd8 - 0xde 0xe0 - 0xf6 0xf8 - 0xfe -CONTROL 0x00 - 0x1f 0x7f - 0x9f -DIGIT '0' - '9' -GRAPH 0x21 - 0x7e 0xa1 - 0xff -LOWER 'a' - 'z' -LOWER 0xba 0xdf - 0xf6 0xf8 - 0xfe -PUNCT 0x21 - 0x2f 0x3a - 0x40 0x5b - 0x60 0x7b - 0x7e -PUNCT 0xa1 - 0xa9 0xab - 0xb9 0xbb -0xbf 0xd7 0xdf 0xf7 0xff -SPACE 0x09 - 0x0d 0x20 0xa0 -UPPER 'A' - 'Z' -UPPER 0xaa 0xc0 - 0xd6 0xd8 - 0xde -XDIGIT '0' - '9' 'a' - 'f' 'A' - 'F' -BLANK ' ' '\t' 0xa0 -PRINT 0x20 - 0x7e 0xa0 - 0xff - -MAPLOWER <'A' - 'Z' : 'a'> -MAPLOWER <'a' - 'z' : 'a'> -MAPLOWER <0xaa 0xba> -MAPLOWER <0xba 0xba> -MAPLOWER <0xc0 - 0xd6 : 0xe0> -MAPLOWER <0xd8 - 0xde : 0xf8> -MAPLOWER <0xe0 - 0xf6 : 0xe0> -MAPLOWER <0xf8 - 0xfe : 0xf8> - -MAPUPPER <'A' - 'Z' : 'A'> -MAPUPPER <'a' - 'z' : 'A'> -MAPUPPER <0xaa 0xaa> -MAPUPPER <0xba 0xaa> -MAPUPPER <0xc0 - 0xd6 : 0xc0> -MAPUPPER <0xd8 - 0xdf : 0xd8> -MAPUPPER <0xe0 - 0xf6 : 0xc0> -MAPUPPER <0xf8 - 0xfe : 0xd8> - -TODIGIT <'0' - '9' : 0> -TODIGIT <'A' - 'F' : 10> -TODIGIT <'a' - 'f' : 10> diff --git a/share/monetdef/Makefile b/share/monetdef/Makefile index f5599b5ba1f..972f149dbe3 100644 --- a/share/monetdef/Makefile +++ b/share/monetdef/Makefile @@ -44,6 +44,7 @@ LOCALES= af_ZA.ISO8859-1 \ ko_KR.eucKR \ ko_KR.UTF-8 \ lt_LT.ISO8859-13 \ + lv_LV.ISO8859-13 \ mn_MN.UTF-8 \ nl_BE.ISO8859-1 \ nl_NL.ISO8859-1 \ @@ -117,7 +118,7 @@ ISO8859-2_UTF-8= hr_HR hu_HU ro_RO sk_SK sl_SI sr_YU ISO8859-7_UTF-8= el_GR ISO8859-9_UTF-8= tr_TR ISO8859-13_ISO8859-4= lt_LT -ISO8859-13_UTF-8= lt_LT +ISO8859-13_UTF-8= lt_LT lv_LV ISO8859-15_ISO8859-15= es_ES:eu_ES ISO8859-15_UTF-8= et_EE UTF-8_Big5HKSCS= zh_HK diff --git a/share/msgdef/Makefile b/share/msgdef/Makefile index cdaa092809b..069498f84ba 100644 --- a/share/msgdef/Makefile +++ b/share/msgdef/Makefile @@ -40,6 +40,8 @@ LOCALES= af_ZA.ISO8859-1 \ ko_KR.UTF-8 \ ko_KR.eucKR \ lt_LT.ISO8859-13 \ + lv_LV.ISO8859-13 \ + lv_LV.UTF-8 \ mn_MN.UTF-8 \ nl_NL.ISO8859-1 \ no_NO.ISO8859-1 \ diff --git a/share/numericdef/Makefile b/share/numericdef/Makefile index 45f853d5657..2dc12f8e0f2 100644 --- a/share/numericdef/Makefile +++ b/share/numericdef/Makefile @@ -107,7 +107,8 @@ ISO8859-5_CP1251= uk_UA ISO8859-7_UTF-8= el_GR ISO8859-9_UTF-8= tr_TR ISO8859-13_ISO8859-4= lt_LT -ISO8859-13_UTF-8= lt_LT +ISO8859-13_ISO8859-13= lt_LT:lv_LV +ISO8859-13_UTF-8= lt_LT lt_LT:lv_LV ISO8859-15_UTF-8= et_EE KOI8-R_CP1251= ru_RU KOI8-R_CP866= ru_RU diff --git a/share/timedef/Makefile b/share/timedef/Makefile index d005ae9cb1a..5a4060d0f55 100644 --- a/share/timedef/Makefile +++ b/share/timedef/Makefile @@ -53,6 +53,8 @@ LOCALES= am_ET.UTF-8 \ lt_LT.ISO8859-4 \ lt_LT.ISO8859-13 \ lt_LT.UTF-8 \ + lv_LV.ISO8859-13 \ + lv_LV.UTF-8 \ mn_MN.UTF-8 \ nb_NO.ISO8859-1 \ nb_NO.UTF-8 \ diff --git a/share/timedef/ja_JP.UTF-8.src b/share/timedef/ja_JP.UTF-8.src index f6aecf3f15f..9ee39a5286f 100644 --- a/share/timedef/ja_JP.UTF-8.src +++ b/share/timedef/ja_JP.UTF-8.src @@ -68,13 +68,11 @@ # # am # -#åˆå‰ -AM +åˆå‰ # # pm # -#åˆå¾Œ -PM +åˆå¾Œ # # date_fmt # diff --git a/share/zoneinfo/africa b/share/zoneinfo/africa index 3f92eb4745c..ad89bb743c1 100644 --- a/share/zoneinfo/africa +++ b/share/zoneinfo/africa @@ -1,5 +1,5 @@ #
-# @(#)africa	8.21
+# @(#)africa	8.23
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -276,8 +276,27 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 # In 2009 (and for the next several years), Ramadan ends before the fourth
 # Thursday in September; Egypt is expected to revert to the last Thursday
 # in September.
+
+# From Steffen Thorsen (2009-08-11):
+# We have been able to confirm the August change with the Egyptian Cabinet 
+# Information and Decision Support Center:
+# 
+# http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html
+# 
+# 
+# The Middle East News Agency
+# 
+# http://www.mena.org.eg/index.aspx
+# 
+# also reports "Egypt starts winter time on August 21"
+# today in article numbered "71, 11/08/2009 12:25 GMT." 
+# Only the title above is available without a subscription to their service,
+# and can be found by searching for "winter" in their search engine
+# (at least today).
+
 Rule	Egypt	2008	only	-	Aug	lastThu	23:00s	0	-
-Rule	Egypt	2009	max	-	Sep	lastThu	23:00s	0	-
+Rule	Egypt	2009	only	-	Aug	20	23:00s	0	-
+Rule	Egypt	2010	max	-	Sep	lastThu	23:00s	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Cairo	2:05:00 -	LMT	1900 Oct
@@ -502,11 +521,33 @@ Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
 # http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf
 # 
 
+# From Steffen Thorsen (2009-06-05):
+# According to several sources, Mauritius will not continue to observe
+# DST the coming summer...
+#
+# Some sources, in French:
+# 
+# http://www.defimedia.info/news/946/Rashid-Beebeejaun-:-%C2%AB-L%E2%80%99heure-d%E2%80%99%C3%A9t%C3%A9-ne-sera-pas-appliqu%C3%A9e-cette-ann%C3%A9e-%C2%BB
+# 
+# 
+# http://lexpress.mu/Story/3398~Beebeejaun---Les-objectifs-d-%C3%A9conomie-d-%C3%A9nergie-de-l-heure-d-%C3%A9t%C3%A9-ont-%C3%A9t%C3%A9-atteints-
+# 
+#
+# Our wrap-up:
+# 
+# http://www.timeanddate.com/news/time/mauritius-dst-will-not-repeat.html
+# 
+
+# From Arthur David Olson (2009-07-11):
+# The "mauritius-dst-will-not-repeat" wrapup includes this: 
+# "The trial ended on March 29, 2009, when the clocks moved back by one hour
+# at 2am (or 02:00) local time..."
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule Mauritius	1982	only	-	Oct	10	0:00	1:00	S
 Rule Mauritius	1983	only	-	Mar	21	0:00	0	-
-Rule Mauritius	2008	max	-	Oct	lastSun	2:00s	1:00	S
-Rule Mauritius	2009	max	-	Mar	lastSun	2:00s	0	-
+Rule Mauritius	2008	only	-	Oct	lastSun	2:00	1:00	S
+Rule Mauritius	2009	only	-	Mar	lastSun	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Indian/Mauritius	3:50:00 -	LMT	1907		# Port Louis
 			4:00 Mauritius	MU%sT	# Mauritius Time
diff --git a/share/zoneinfo/asia b/share/zoneinfo/asia
index 2262397fa5c..13a1989251c 100644
--- a/share/zoneinfo/asia
+++ b/share/zoneinfo/asia
@@ -1,5 +1,5 @@
 # 
-# @(#)asia	8.35
+# @(#)asia	8.36
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -172,6 +172,12 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 #
 # No DST end date has been announced yet.
 
+# From Arthur David Olson (2009-07-11):
+# Arbitrarily end DST at the end of 2009 so that a POSIX-sytle time zone string
+# can appear in the Dhaka binary file and for the benefit of old glibc
+# reimplementations of the time zone software that mishandle permanent DST.
+# A change will be required once the end date is known.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dhaka	6:01:40 -	LMT	1890
 			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
@@ -180,7 +186,8 @@ Zone	Asia/Dhaka	6:01:40 -	LMT	1890
 			6:30	-	BURT	1951 Sep 30
 			6:00	-	DACT	1971 Mar 26 # Dacca Time
 			6:00	-	BDT	2009 Jun 19 23:00 # Bangladesh Time
-			6:00	1:00	BDST
+			6:00	1:00	BDST	2010
+			6:00	-	BDT
 
 # Bhutan
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
diff --git a/share/zoneinfo/australasia b/share/zoneinfo/australasia
index efcfec74d15..2fc370f8bbc 100644
--- a/share/zoneinfo/australasia
+++ b/share/zoneinfo/australasia
@@ -1,5 +1,5 @@
 # 
-# @(#)australasia	8.11
+# @(#)australasia	8.12
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -427,6 +427,22 @@ Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
 			-11:00	-	SST			# S=Samoa
 
 # Samoa
+
+# From Alexander Krivenyshev (2008-12-06):
+# The Samoa government (Western Samoa) may implement DST on the first Sunday of 
+# October 2009 (October 4, 2009) until the last Sunday of March 2010 (March 28, 
+# 2010). 
+# 
+# "Selected Committee reports to Cabinet on Daylight Saving Time",
+# Government of Samoa:
+# 
+# http://www.govt.ws/pr_article.cfm?pr_id=560
+# 
+# or
+# 
+# http://www.worldtimezone.com/dst_news/dst_news_samoa01.html
+# 
+
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
 			-11:30	-	SAMT	1950		# Samoa Time
diff --git a/share/zoneinfo/europe b/share/zoneinfo/europe
index 3f39215bf64..adf20a2828c 100644
--- a/share/zoneinfo/europe
+++ b/share/zoneinfo/europe
@@ -1,5 +1,5 @@
 # 
-# @(#)europe	8.21
+# @(#)europe	8.22
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -459,7 +459,7 @@ Rule	EU	1979	1995	-	Sep	lastSun	 1:00u	0	-
 Rule	EU	1981	max	-	Mar	lastSun	 1:00u	1:00	S
 Rule	EU	1996	max	-	Oct	lastSun	 1:00u	0	-
 # The most recent directive covers the years starting in 2002.  See:
-# 
+# 
 # Directive 2000/84/EC of the European Parliament and of the Council
 # of 19 January 2001 on summer-time arrangements.
 # 
diff --git a/share/zoneinfo/leapseconds b/share/zoneinfo/leapseconds
index 995c8a019a3..a3c95efb1c8 100644
--- a/share/zoneinfo/leapseconds
+++ b/share/zoneinfo/leapseconds
@@ -1,5 +1,5 @@
 # 
-# @(#)leapseconds	8.8
+# @(#)leapseconds	8.9
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -58,29 +58,30 @@ Leap	2008	Dec	31	23:59:60	+	S
 # 61, Av. de l'Observatoire 75014 PARIS (France)
 # Tel.      : 33 (0) 1 40 51 22 26
 # FAX       : 33 (0) 1 40 51 22 91
-# e-mail    : services.iers@obspm.fr
-# http://hpiers.obspm.fr/eop-pc
+# Internet  : services.iers@obspm.fr
 #
-# Paris, 15 January 2009
+# Paris, 4 July 2009
 #
-# Bulletin C 37
+# Bulletin C 38
 #
 # To authorities responsible
 # for the measurement and
 # distribution of time
 #
-# NO positive leap second will be introduced at the end of June 2009.
-# The difference between Coordinated Universal Time UTC and the 
-# International Atomic Time TAI is :             
-#                
-#     from 2009 January 1, 0h UTC, until further notice : UTC-TAI = -34 s
+# INFORMATION ON UTC - TAI
+#
+# NO positive leap second will be introduced at the end of December 2009.
+# The difference between Coordinated Universal Time UTC and the
+# International Atomic Time TAI is :		
+#
+# from 2009 January 1, 0h UTC, until further notice : UTC-TAI = -34 s
 #
 # Leap seconds can be introduced in UTC at the end of the months of December
-# or June, depending on the evolution of UT1-TAI. Bulletin C is mailed every
-# six months, either to announce a time step in UTC or to confirm that there
+# or June,  depending on the evolution of UT1-TAI. Bulletin C is mailed every
+# six months, either to announce a time step in UTC, or to confirm that there
 # will be no time step at the next possible date.
 #
 # Daniel GAMBIS
-# Head		
+# Director			
 # Earth Orientation Center of IERS
 # Observatoire de Paris, France
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
index c5e19cff797..d5e7a6ead78 100644
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -108,6 +109,22 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
 	(sysinit_cfunc_t) elf64_insert_brand_entry,
 	&freebsd_brand_oinfo);
 
+static Elf64_Brandinfo kfreebsd_brand_info = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_X86_64,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/lib/ld-kfreebsd-x86-64.so.1",
+	.sysvec		= &elf64_freebsd_sysvec,
+	.interp_newpath	= NULL,
+	.brand_note	= &elf64_kfreebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
+};
+
+SYSINIT(kelf64, SI_SUB_EXEC, SI_ORDER_ANY,
+	(sysinit_cfunc_t) elf64_insert_brand_entry,
+	&kfreebsd_brand_info);
+
 
 void
 elf64_dump_thread(struct thread *td __unused, void *dst __unused,
diff --git a/sys/amd64/amd64/local_apic.c b/sys/amd64/amd64/local_apic.c
index 14559f3aa45..87bec91b6c4 100644
--- a/sys/amd64/amd64/local_apic.c
+++ b/sys/amd64/amd64/local_apic.c
@@ -123,7 +123,7 @@ static struct lvt lvts[LVT_MAX + 1] = {
 	{ 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 },	/* LINT1: NMI */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_TIMER_INT },	/* Timer */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_ERROR_INT },	/* Error */
-	{ 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 },	/* PMC */
+	{ 1, 1, 1, 1, APIC_LVT_DM_NMI, 0 },	/* PMC */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_THERMAL_INT },	/* Thermal */
 };
 
@@ -305,11 +305,9 @@ lapic_setup(int boot)
 	lapic->lvt_lint0 = lvt_mode(la, LVT_LINT0, lapic->lvt_lint0);
 	lapic->lvt_lint1 = lvt_mode(la, LVT_LINT1, lapic->lvt_lint1);
 
-#ifdef	HWPMC_HOOKS
 	/* Program the PMC LVT entry if present. */
 	if (maxlvt >= LVT_PMC)
 		lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
-#endif
 
 	/* Program timer LVT and setup handler. */
 	lapic->lvt_timer = lvt_mode(la, LVT_TIMER, lapic->lvt_timer);
@@ -332,6 +330,88 @@ lapic_setup(int boot)
 	intr_restore(eflags);
 }
 
+void
+lapic_reenable_pmc(void)
+{
+#ifdef HWPMC_HOOKS
+	uint32_t value;
+
+	value =  lapic->lvt_pcint;
+	value &= ~APIC_LVT_M;
+	lapic->lvt_pcint = value;
+#endif
+}
+
+#ifdef HWPMC_HOOKS
+static void
+lapic_update_pmc(void *dummy)
+{
+	struct lapic *la;
+
+	la = &lapics[lapic_id()];
+	lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
+}
+#endif
+
+int
+lapic_enable_pmc(void)
+{
+#ifdef HWPMC_HOOKS
+	u_int32_t maxlvt;
+
+	/* Fail if the local APIC is not present. */
+	if (lapic == NULL)
+		return (0);
+
+	/* Fail if the PMC LVT is not present. */
+	maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
+	if (maxlvt < LVT_PMC)
+		return (0);
+
+	lvts[LVT_PMC].lvt_masked = 0;
+
+#ifdef SMP
+	/*
+	 * If hwpmc was loaded at boot time then the APs may not be
+	 * started yet.  In that case, don't forward the request to
+	 * them as they will program the lvt when they start.
+	 */
+	if (smp_started)
+		smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL);
+	else
+#endif
+		lapic_update_pmc(NULL);
+	return (1);
+#else
+	return (0);
+#endif
+}
+
+void
+lapic_disable_pmc(void)
+{
+#ifdef HWPMC_HOOKS
+	u_int32_t maxlvt;
+
+	/* Fail if the local APIC is not present. */
+	if (lapic == NULL)
+		return;
+
+	/* Fail if the PMC LVT is not present. */
+	maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
+	if (maxlvt < LVT_PMC)
+		return;
+
+	lvts[LVT_PMC].lvt_masked = 1;
+
+#ifdef SMP
+	/* The APs should always be started when hwpmc is unloaded. */
+	KASSERT(mp_ncpus == 1 || smp_started, ("hwpmc unloaded too early"));
+#endif
+	smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL);
+#endif
+}
+
 /*
  * Called by cpu_initclocks() on the BSP to setup the local APIC timer so
  * that it can drive hardclock, statclock, and profclock.  This function
@@ -910,18 +990,21 @@ apic_free_vector(u_int apic_id, u_int vector, u_int irq)
 	 * we don't lose an interrupt delivery race.
 	 */
 	td = curthread;
-	thread_lock(td);
-	if (sched_is_bound(td))
-		panic("apic_free_vector: Thread already bound.\n");
-	sched_bind(td, apic_cpuid(apic_id));
-	thread_unlock(td);
+	if (!rebooting) {
+		thread_lock(td);
+		if (sched_is_bound(td))
+			panic("apic_free_vector: Thread already bound.\n");
+		sched_bind(td, apic_cpuid(apic_id));
+		thread_unlock(td);
+	}
 	mtx_lock_spin(&icu_lock);
 	lapics[apic_id].la_ioint_irqs[vector - APIC_IO_INTS] = -1;
 	mtx_unlock_spin(&icu_lock);
-	thread_lock(td);
-	sched_unbind(td);
-	thread_unlock(td);
-
+	if (!rebooting) {
+		thread_lock(td);
+		sched_unbind(td);
+		thread_unlock(td);
+	}
 }
 
 /* Map an IDT vector (APIC) to an IRQ (interrupt source). */
@@ -1238,8 +1321,17 @@ lapic_ipi_vectored(u_int vector, int dest)
 	KASSERT((vector & ~APIC_VECTOR_MASK) == 0,
 	    ("%s: invalid vector %d", __func__, vector));
 
-	icrlo = vector | APIC_DELMODE_FIXED | APIC_DESTMODE_PHY |
-	    APIC_LEVEL_DEASSERT | APIC_TRIGMOD_EDGE;
+	icrlo = APIC_DESTMODE_PHY | APIC_TRIGMOD_EDGE;
+
+	/*
+	 * IPI_STOP_HARD is just a "fake" vector used to send a NMI.
+	 * Use special rules regard NMI if passed, otherwise specify
+	 * the vector.
+	 */
+	if (vector == IPI_STOP_HARD)
+		icrlo |= APIC_DELMODE_NMI | APIC_LEVEL_ASSERT;
+	else
+		icrlo |= vector | APIC_DELMODE_FIXED | APIC_LEVEL_DEASSERT;
 	destfield = 0;
 	switch (dest) {
 	case APIC_IPI_DEST_SELF:
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 8aee97524f5..0bfd7ada653 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -217,6 +217,7 @@ cpu_startup(dummy)
 		    strncmp(sysenv, "MacBook3,1", 10) == 0 ||
 		    strncmp(sysenv, "MacBookPro1,1", 13) == 0 ||
 		    strncmp(sysenv, "MacBookPro1,2", 13) == 0 ||
+		    strncmp(sysenv, "MacBookPro3,1", 13) == 0 ||
 		    strncmp(sysenv, "Macmini1,1", 10) == 0) {
 			if (bootverbose)
 				printf("Disabling LEGACY_USB_EN bit on "
@@ -235,19 +236,21 @@ cpu_startup(dummy)
 #ifdef PERFMON
 	perfmon_init();
 #endif
+	realmem = Maxmem;
+
+	/*
+	 * Display physical memory if SMBIOS reports reasonable amount.
+	 */
+	memsize = 0;
 	sysenv = getenv("smbios.memory.enabled");
 	if (sysenv != NULL) {
-		memsize = (uintmax_t)strtoul(sysenv, (char **)NULL, 10);
+		memsize = (uintmax_t)strtoul(sysenv, (char **)NULL, 10) << 10;
 		freeenv(sysenv);
-	} else
-		memsize = 0;
-	if (memsize > 0)
-		printf("real memory  = %ju (%ju MB)\n", memsize << 10,
-		    memsize >> 10);
-	else
-		printf("real memory  = %ju (%ju MB)\n", ptoa((uintmax_t)Maxmem),
-		    ptoa((uintmax_t)Maxmem) / 1048576);
-	realmem = Maxmem;
+	}
+	if (memsize < ptoa((uintmax_t)cnt.v_free_count))
+		memsize = ptoa((uintmax_t)Maxmem);
+	printf("real memory  = %ju (%ju MB)\n", memsize, memsize >> 20);
+
 	/*
 	 * Display any holes after the first chunk of extended memory.
 	 */
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index 52c209c993a..0ef80173b28 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -114,31 +114,12 @@ volatile int smp_tlb_wait;
 
 extern inthand_t IDTVEC(fast_syscall), IDTVEC(fast_syscall32);
 
-#ifdef STOP_NMI
-static volatile cpumask_t ipi_nmi_pending;
-
-static void	ipi_nmi_selected(cpumask_t cpus);
-#endif 
-
 /*
  * Local data and functions.
  */
 
-#ifdef STOP_NMI
-/* 
- * Provide an alternate method of stopping other CPUs. If another CPU has
- * disabled interrupts the conventional STOP IPI will be blocked. This 
- * NMI-based stop should get through in that case.
- */
-static int stop_cpus_with_nmi = 1;
-SYSCTL_INT(_debug, OID_AUTO, stop_cpus_with_nmi, CTLTYPE_INT | CTLFLAG_RW,
-    &stop_cpus_with_nmi, 0, "");
-TUNABLE_INT("debug.stop_cpus_with_nmi", &stop_cpus_with_nmi);
-#else
-#define	stop_cpus_with_nmi	0
-#endif
-
 static u_int logical_cpus;
+static volatile cpumask_t ipi_nmi_pending;
 
 /* used to hold the AP's until we are ready to release them */
 static struct mtx ap_boot_mtx;
@@ -1158,12 +1139,14 @@ ipi_selected(cpumask_t cpus, u_int ipi)
 		ipi = IPI_BITMAP_VECTOR;
 	}
 
-#ifdef STOP_NMI
-	if (ipi == IPI_STOP && stop_cpus_with_nmi) {
-		ipi_nmi_selected(cpus);
-		return;
-	}
-#endif
+	/*
+	 * IPI_STOP_HARD maps to a NMI and the trap handler needs a bit
+	 * of help in order to understand what is the source.
+	 * Set the mask of receiving CPUs for this purpose.
+	 */
+	if (ipi == IPI_STOP_HARD)
+		atomic_set_int(&ipi_nmi_pending, cpus);
+
 	CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi);
 	while ((cpu = ffs(cpus)) != 0) {
 		cpu--;
@@ -1194,64 +1177,43 @@ void
 ipi_all_but_self(u_int ipi)
 {
 
-	if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+	if (IPI_IS_BITMAPED(ipi)) {
 		ipi_selected(PCPU_GET(other_cpus), ipi);
 		return;
 	}
+
+	/*
+	 * IPI_STOP_HARD maps to a NMI and the trap handler needs a bit
+	 * of help in order to understand what is the source.
+	 * Set the mask of receiving CPUs for this purpose.
+	 */
+	if (ipi == IPI_STOP_HARD)
+		atomic_set_int(&ipi_nmi_pending, PCPU_GET(other_cpus));
+
 	CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
 	lapic_ipi_vectored(ipi, APIC_IPI_DEST_OTHERS);
 }
 
-#ifdef STOP_NMI
-/*
- * send NMI IPI to selected CPUs
- */
-
-#define	BEFORE_SPIN	1000000
-
-static void
-ipi_nmi_selected(cpumask_t cpus)
-{
-	int cpu;
-	register_t icrlo;
-
-	icrlo = APIC_DELMODE_NMI | APIC_DESTMODE_PHY | APIC_LEVEL_ASSERT 
-		| APIC_TRIGMOD_EDGE; 
-	
-	CTR2(KTR_SMP, "%s: cpus: %x nmi", __func__, cpus);
-
-	atomic_set_int(&ipi_nmi_pending, cpus);
-
-	while ((cpu = ffs(cpus)) != 0) {
-		cpu--;
-		cpus &= ~(1 << cpu);
-
-		KASSERT(cpu_apic_ids[cpu] != -1,
-		    ("IPI NMI to non-existent CPU %d", cpu));
-		
-		/* Wait for an earlier IPI to finish. */
-		if (!lapic_ipi_wait(BEFORE_SPIN))
-			panic("ipi_nmi_selected: previous IPI has not cleared");
-
-		lapic_ipi_raw(icrlo, cpu_apic_ids[cpu]);
-	}
-}
-
 int
-ipi_nmi_handler(void)
+ipi_nmi_handler()
 {
-	int cpumask = PCPU_GET(cpumask);
+	cpumask_t cpumask;
 
-	if (!(ipi_nmi_pending & cpumask))
-		return 1;
+	/*
+	 * As long as there is not a simple way to know about a NMI's
+	 * source, if the bitmask for the current CPU is present in
+	 * the global pending bitword an IPI_STOP_HARD has been issued
+	 * and should be handled.
+	 */
+	cpumask = PCPU_GET(cpumask);
+	if ((ipi_nmi_pending & cpumask) == 0)
+		return (1);
 
 	atomic_clear_int(&ipi_nmi_pending, cpumask);
 	cpustop_handler();
-	return 0;
+	return (0);
 }
      
-#endif /* STOP_NMI */
-
 /*
  * Handle an IPI_STOP by saving our current context and spinning until we
  * are resumed.
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 622ed629b01..4febfb3b886 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -178,6 +178,8 @@ static vm_paddr_t dmaplimit;
 vm_offset_t kernel_vm_end = VM_MIN_KERNEL_ADDRESS;
 pt_entry_t pg_nx;
 
+static int pat_works = 0;		/* Is page attribute table sane? */
+
 SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
 
 static int pg_ps_enabled = 1;
@@ -590,20 +592,56 @@ void
 pmap_init_pat(void)
 {
 	uint64_t pat_msr;
+	char *sysenv;
+	static int pat_tested = 0;
 
 	/* Bail if this CPU doesn't implement PAT. */
 	if (!(cpu_feature & CPUID_PAT))
 		panic("no PAT??");
 
 	/*
-	 * Leave the indices 0-3 at the default of WB, WT, UC, and UC-.
-	 * Program 4 and 5 as WP and WC.
-	 * Leave 6 and 7 as UC and UC-.
+	 * Some Apple Macs based on nVidia chipsets cannot enter ACPI mode
+	 * via SMI# when we use upper 4 PAT entries for unknown reason.
 	 */
-	pat_msr = rdmsr(MSR_PAT);
-	pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
-	pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
-	    PAT_VALUE(5, PAT_WRITE_COMBINING);
+	if (!pat_tested) {
+		pat_works = 1;
+		sysenv = getenv("smbios.system.product");
+		if (sysenv != NULL) {
+			if (strncmp(sysenv, "MacBook5,1", 10) == 0 ||
+			    strncmp(sysenv, "MacBookPro5,5", 13) == 0 ||
+			    strncmp(sysenv, "Macmini3,1", 10) == 0)
+				pat_works = 0;
+			freeenv(sysenv);
+		}
+		pat_tested = 1;
+	}
+
+	/* Initialize default PAT entries. */
+	pat_msr = PAT_VALUE(0, PAT_WRITE_BACK) |
+	    PAT_VALUE(1, PAT_WRITE_THROUGH) |
+	    PAT_VALUE(2, PAT_UNCACHED) |
+	    PAT_VALUE(3, PAT_UNCACHEABLE) |
+	    PAT_VALUE(4, PAT_WRITE_BACK) |
+	    PAT_VALUE(5, PAT_WRITE_THROUGH) |
+	    PAT_VALUE(6, PAT_UNCACHED) |
+	    PAT_VALUE(7, PAT_UNCACHEABLE);
+
+	if (pat_works) {
+		/*
+		 * Leave the indices 0-3 at the default of WB, WT, UC-, and UC.
+		 * Program 4 and 5 as WP and WC.
+		 * Leave 6 and 7 as UC- and UC.
+		 */
+		pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
+		pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
+		    PAT_VALUE(5, PAT_WRITE_COMBINING);
+	} else {
+		/*
+		 * Just replace PAT Index 2 with WC instead of UC-.
+		 */
+		pat_msr &= ~PAT_MASK(2);
+		pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
+	}
 	wrmsr(MSR_PAT, pat_msr);
 }
 
@@ -754,27 +792,48 @@ pmap_cache_bits(int mode, boolean_t is_pde)
 	pat_flag = is_pde ? PG_PDE_PAT : PG_PTE_PAT;
 
 	/* Map the caching mode to a PAT index. */
-	switch (mode) {
-	case PAT_UNCACHEABLE:
-		pat_index = 3;
-		break;
-	case PAT_WRITE_THROUGH:
-		pat_index = 1;
-		break;
-	case PAT_WRITE_BACK:
-		pat_index = 0;
-		break;
-	case PAT_UNCACHED:
-		pat_index = 2;
-		break;
-	case PAT_WRITE_COMBINING:
-		pat_index = 5;
-		break;
-	case PAT_WRITE_PROTECTED:
-		pat_index = 4;
-		break;
-	default:
-		panic("Unknown caching mode %d\n", mode);
+	if (pat_works) {
+		switch (mode) {
+		case PAT_UNCACHEABLE:
+			pat_index = 3;
+			break;
+		case PAT_WRITE_THROUGH:
+			pat_index = 1;
+			break;
+		case PAT_WRITE_BACK:
+			pat_index = 0;
+			break;
+		case PAT_UNCACHED:
+			pat_index = 2;
+			break;
+		case PAT_WRITE_COMBINING:
+			pat_index = 5;
+			break;
+		case PAT_WRITE_PROTECTED:
+			pat_index = 4;
+			break;
+		default:
+			panic("Unknown caching mode %d\n", mode);
+		}
+	} else {
+		switch (mode) {
+		case PAT_UNCACHED:
+		case PAT_UNCACHEABLE:
+		case PAT_WRITE_PROTECTED:
+			pat_index = 3;
+			break;
+		case PAT_WRITE_THROUGH:
+			pat_index = 1;
+			break;
+		case PAT_WRITE_BACK:
+			pat_index = 0;
+			break;
+		case PAT_WRITE_COMBINING:
+			pat_index = 2;
+			break;
+		default:
+			panic("Unknown caching mode %d\n", mode);
+		}
 	}
 
 	/* Map the 3-bit index value into the PAT, PCD, and PWT bits. */
@@ -943,8 +1002,8 @@ pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva)
 		 * coherence domain.
 		 */
 		mfence();
-		for (; eva < sva; eva += cpu_clflush_line_size)
-			clflush(eva);
+		for (; sva < eva; sva += cpu_clflush_line_size)
+			clflush(sva);
 		mfence();
 	} else {
 
@@ -2261,6 +2320,8 @@ pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va)
 			    " in pmap %p", va, pmap);
 			return (FALSE);
 		}
+		if (va < VM_MAXUSER_ADDRESS)
+			pmap->pm_stats.resident_count++;
 	}
 	mptepa = VM_PAGE_TO_PHYS(mpte);
 	firstpte = (pt_entry_t *)PHYS_TO_DMAP(mptepa);
@@ -4474,7 +4535,8 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
 	if (base < DMAP_MIN_ADDRESS)
 		return (EINVAL);
 
-	cache_bits_pde = cache_bits_pte = -1;
+	cache_bits_pde = pmap_cache_bits(mode, 1);
+	cache_bits_pte = pmap_cache_bits(mode, 0);
 	changed = FALSE;
 
 	/*
@@ -4491,8 +4553,6 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
 			 * memory type, then we need not demote this page. Just
 			 * increment tmpva to the next 1GB page frame.
 			 */
-			if (cache_bits_pde < 0)
-				cache_bits_pde = pmap_cache_bits(mode, 1);
 			if ((*pdpe & PG_PDE_CACHE) == cache_bits_pde) {
 				tmpva = trunc_1gpage(tmpva) + NBPDP;
 				continue;
@@ -4520,8 +4580,6 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
 			 * memory type, then we need not demote this page. Just
 			 * increment tmpva to the next 2MB page frame.
 			 */
-			if (cache_bits_pde < 0)
-				cache_bits_pde = pmap_cache_bits(mode, 1);
 			if ((*pde & PG_PDE_CACHE) == cache_bits_pde) {
 				tmpva = trunc_2mpage(tmpva) + NBPDR;
 				continue;
@@ -4555,12 +4613,9 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
 	for (tmpva = base; tmpva < base + size; ) {
 		pdpe = pmap_pdpe(kernel_pmap, tmpva);
 		if (*pdpe & PG_PS) {
-			if (cache_bits_pde < 0)
-				cache_bits_pde = pmap_cache_bits(mode, 1);
 			if ((*pdpe & PG_PDE_CACHE) != cache_bits_pde) {
 				pmap_pde_attr(pdpe, cache_bits_pde);
-				if (!changed)
-					changed = TRUE;
+				changed = TRUE;
 			}
 			if (tmpva >= VM_MIN_KERNEL_ADDRESS) {
 				if (pa_start == pa_end) {
@@ -4586,12 +4641,9 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
 		}
 		pde = pmap_pdpe_to_pde(pdpe, tmpva);
 		if (*pde & PG_PS) {
-			if (cache_bits_pde < 0)
-				cache_bits_pde = pmap_cache_bits(mode, 1);
 			if ((*pde & PG_PDE_CACHE) != cache_bits_pde) {
 				pmap_pde_attr(pde, cache_bits_pde);
-				if (!changed)
-					changed = TRUE;
+				changed = TRUE;
 			}
 			if (tmpva >= VM_MIN_KERNEL_ADDRESS) {
 				if (pa_start == pa_end) {
@@ -4614,13 +4666,10 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
 			}
 			tmpva = trunc_2mpage(tmpva) + NBPDR;
 		} else {
-			if (cache_bits_pte < 0)
-				cache_bits_pte = pmap_cache_bits(mode, 0);
 			pte = pmap_pde_to_pte(pde, tmpva);
 			if ((*pte & PG_PTE_CACHE) != cache_bits_pte) {
 				pmap_pte_attr(pte, cache_bits_pte);
-				if (!changed)
-					changed = TRUE;
+				changed = TRUE;
 			}
 			if (tmpva >= VM_MIN_KERNEL_ADDRESS) {
 				if (pa_start == pa_end) {
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index fee3caf6a9d..65f761eaa4a 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -239,13 +239,11 @@ trap(struct trapframe *frame)
 	type = frame->tf_trapno;
 
 #ifdef SMP
-#ifdef STOP_NMI
 	/* Handler for NMI IPIs used for stopping CPUs. */
 	if (type == T_NMI) {
 	         if (ipi_nmi_handler() == 0)
 	                   goto out;
 	}
-#endif /* STOP_NMI */
 #endif /* SMP */
 
 #ifdef KDB
@@ -411,7 +409,9 @@ trap(struct trapframe *frame)
 					 * This check also covers the images
 					 * without the ABI-tag ELF note.
 					 */
-					if (p->p_osrel >= 700004) {
+					if (SV_CURPROC_ABI() ==
+					    SV_ABI_FREEBSD &&
+					    p->p_osrel >= 700004) {
 						i = SIGSEGV;
 						ucode = SEGV_ACCERR;
 					} else {
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 73a4fb66e4d..a49f7bca10c 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -69,7 +69,6 @@ options 	P1003_1B_SEMAPHORES	# POSIX-style semaphores
 options 	_KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
 options 	PRINTF_BUFR_SIZE=128	# Prevent printf output being interspersed.
 options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
-options 	STOP_NMI		# Stop CPUS using NMI instead of IPI
 options 	HWPMC_HOOKS		# Necessary kernel hooks for hwpmc(4)
 options 	AUDIT			# Security event auditing
 options 	MAC			# TrustedBSD MAC Framework
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 088a381f177..27fe0680580 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -30,11 +30,6 @@ device		mptable			# Optional MPSPEC mptable support
 #
 options 	MP_WATCHDOG
 
-# 
-# Debugging options.
-#
-options 	STOP_NMI		# Stop CPUS using NMI instead of IPI
-
 
 
 #####################################################################
diff --git a/sys/amd64/conf/XENHVM b/sys/amd64/conf/XENHVM
index 5e108d51ea2..1536e3c74b6 100644
--- a/sys/amd64/conf/XENHVM
+++ b/sys/amd64/conf/XENHVM
@@ -68,7 +68,6 @@ options 	SYSVMSG			# SYSV-style message queues
 options 	SYSVSEM			# SYSV-style semaphores
 options 	_KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
 options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
-options 	STOP_NMI		# Stop CPUS using NMI instead of IPI
 options 	HWPMC_HOOKS		# Necessary kernel hooks for hwpmc(4)
 options 	AUDIT			# Security event auditing
 #options 	KDTRACE_FRAME		# Ensure frames are compiled in
diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h
index 84ba3b8fa88..9d6d538de1d 100644
--- a/sys/amd64/include/apicvar.h
+++ b/sys/amd64/include/apicvar.h
@@ -102,11 +102,6 @@
  * smp_ipi_mtx and waits for the completion of the IPI (Only one IPI user 
  * at a time) The second group uses a single interrupt and a bitmap to avoid
  * redundant IPI interrupts.
- *
- * Right now IPI_STOP used by kdb shares the interrupt priority class with
- * the two IPI groups mentioned above. As such IPI_STOP may cause a deadlock.
- * Eventually IPI_STOP should use NMI IPIs - this would eliminate this and
- * other deadlocks caused by IPI_STOP.
  */ 
 
 /* Interrupts for local APIC LVT entries other than the timer. */
@@ -134,6 +129,7 @@
 
 #define	IPI_STOP	(APIC_IPI_INTS + 7)	/* Stop CPU until restarted. */
 #define	IPI_SUSPEND	(APIC_IPI_INTS + 8)	/* Suspend CPU until restarted. */
+#define	IPI_STOP_HARD	(APIC_IPI_INTS + 9)	/* Stop CPU with a NMI. */
 
 /*
  * The spurious interrupt can share the priority class with the IPIs since
@@ -205,7 +201,9 @@ int	ioapic_set_triggermode(void *cookie, u_int pin,
 int	ioapic_set_smi(void *cookie, u_int pin);
 void	lapic_create(u_int apic_id, int boot_cpu);
 void	lapic_disable(void);
+void	lapic_disable_pmc(void);
 void	lapic_dump(const char *str);
+int	lapic_enable_pmc(void);
 void	lapic_eoi(void);
 u_int	lapic_error(void);
 int	lapic_id(void);
@@ -216,6 +214,7 @@ void	lapic_ipi_vectored(u_int vector, int dest);
 int	lapic_ipi_wait(int delay);
 void	lapic_handle_intr(int vector, struct trapframe *frame);
 void	lapic_handle_timer(struct trapframe *frame);
+void	lapic_reenable_pmc(void);
 void	lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id);
 int	lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked);
 int	lapic_set_lvt_mode(u_int apic_id, u_int lvt, u_int32_t mode);
diff --git a/sys/amd64/include/param.h b/sys/amd64/include/param.h
index edcf427df3e..746ba30385c 100644
--- a/sys/amd64/include/param.h
+++ b/sys/amd64/include/param.h
@@ -39,6 +39,9 @@
  * $FreeBSD$
  */
 
+#ifndef _AMD64_INCLUDE_PARAM_H_
+#define	_AMD64_INCLUDE_PARAM_H_
+
 /*
  * Machine dependent constants for AMD64.
  */
@@ -60,9 +63,6 @@
 #define __HAVE_ACPI
 #define __PCI_REROUTE_INTERRUPT
 
-#ifndef _MACHINE_PARAM_H_
-#define	_MACHINE_PARAM_H_
-
 #ifndef MACHINE
 #define	MACHINE		"amd64"
 #endif
@@ -150,5 +150,5 @@
 
 #define	pgtok(x)	((unsigned long)(x) * (PAGE_SIZE / 1024)) 
 
-#endif /* !_MACHINE_PARAM_H_ */
 #endif /* !_NO_NAMESPACE_POLLUTION */
+#endif /* !_AMD64_INCLUDE_PARAM_H_ */
diff --git a/sys/amd64/include/pmc_mdep.h b/sys/amd64/include/pmc_mdep.h
index f8c26f2ec90..f233a510d3c 100644
--- a/sys/amd64/include/pmc_mdep.h
+++ b/sys/amd64/include/pmc_mdep.h
@@ -115,7 +115,6 @@ union pmc_md_pmc {
  */
 
 void	start_exceptions(void), end_exceptions(void);
-void	pmc_x86_lapic_enable_pmc_interrupt(void);
 
 struct pmc_mdep *pmc_amd_initialize(void);
 void	pmc_amd_finalize(struct pmc_mdep *_md);
diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h
index d2957158027..1cc21a447f0 100644
--- a/sys/amd64/include/smp.h
+++ b/sys/amd64/include/smp.h
@@ -52,6 +52,7 @@ void	cpu_add(u_int apic_id, char boot_cpu);
 void	cpustop_handler(void);
 void	cpususpend_handler(void);
 void	init_secondary(void);
+int	ipi_nmi_handler(void);
 void	ipi_selected(cpumask_t cpus, u_int ipi);
 void	ipi_all_but_self(u_int ipi);
 void 	ipi_bitmap_handler(struct trapframe frame);
@@ -66,10 +67,6 @@ void	smp_masked_invlpg_range(cpumask_t mask, vm_offset_t startva,
 void	smp_invltlb(void);
 void	smp_masked_invltlb(cpumask_t mask);
 
-#ifdef STOP_NMI
-int	ipi_nmi_handler(void);
-#endif
-
 #endif /* !LOCORE */
 #endif /* SMP */
 
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 77186a1d37d..54a04eea581 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -127,6 +127,7 @@ static void     linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
 static void	exec_linux_setregs(struct thread *td, u_long entry,
 				   u_long stack, u_long ps_strings);
 static void	linux32_fixlimit(struct rlimit *rl, int which);
+static boolean_t linux32_trans_osrel(const Elf_Note *note, int32_t *osrel);
 
 static eventhandler_tag linux_exit_tag;
 static eventhandler_tag linux_schedtail_tag;
@@ -1066,14 +1067,38 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_flags	= SV_ABI_LINUX | SV_ILP32 | SV_IA32
 };
 
-static char GNULINUX_ABI_VENDOR[] = "GNU";
+static char GNU_ABI_VENDOR[] = "GNU";
+static int GNULINUX_ABI_DESC = 0;
+
+static boolean_t
+linux32_trans_osrel(const Elf_Note *note, int32_t *osrel)
+{
+	const Elf32_Word *desc;
+	uintptr_t p;
+
+	p = (uintptr_t)(note + 1);
+	p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
+
+	desc = (const Elf32_Word *)p;
+	if (desc[0] != GNULINUX_ABI_DESC)
+		return (FALSE);
+
+	/*
+	 * For linux we encode osrel as follows (see linux_mib.c):
+	 * VVVMMMIII (version, major, minor), see linux_mib.c.
+	 */
+	*osrel = desc[1] * 1000000 + desc[2] * 1000 + desc[3];
+
+	return (TRUE);
+}
 
 static Elf_Brandnote linux32_brandnote = {
-	.hdr.n_namesz	= sizeof(GNULINUX_ABI_VENDOR),
-	.hdr.n_descsz	= 16,
+	.hdr.n_namesz	= sizeof(GNU_ABI_VENDOR),
+	.hdr.n_descsz	= 16,	/* XXX at least 16 */
 	.hdr.n_type	= 1,
-	.vendor		= GNULINUX_ABI_VENDOR,
-	.flags		= 0
+	.vendor		= GNU_ABI_VENDOR,
+	.flags		= BN_TRANSLATE_OSREL,
+	.trans_osrel	= linux32_trans_osrel
 };
 
 static Elf32_Brandinfo linux_brand = {
diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
index 19c7236f173..1b9bf81f174 100644
--- a/sys/arm/arm/pmap.c
+++ b/sys/arm/arm/pmap.c
@@ -1212,7 +1212,7 @@ pmap_l2cache_wbinv_range(pmap_t pm, vm_offset_t va, vm_size_t len)
 		CTR4(KTR_PMAP, "pmap_l2cache_wbinv_range: pmap %p is_kernel %d "
 		    "va 0x%08x len 0x%x ", pm, pm == pmap_kernel(), va, rest);
 		if (pmap_get_pde_pte(pm, va, &pde, &ptep) && l2pte_valid(*ptep))
-			cpu_l2cache_wb_range(va, rest);
+			cpu_l2cache_wbinv_range(va, rest);
 
 		len -= rest;
 		va += rest;
diff --git a/sys/arm/arm/undefined.c b/sys/arm/arm/undefined.c
index 5b04c03b46e..fa02023c656 100644
--- a/sys/arm/arm/undefined.c
+++ b/sys/arm/arm/undefined.c
@@ -82,11 +82,10 @@ __FBSDID("$FreeBSD$");
 
 #ifdef DDB
 #include 
-#include 
 #endif
 
-#ifdef acorn26
-#include 
+#ifdef KDB
+#include 
 #endif
 
 static int gdb_trapper(u_int, u_int, struct trapframe *, int);
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index 1a907cc7577..6bd57999d3a 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -119,9 +119,6 @@ cpu_fork(register struct thread *td1, register struct proc *p2,
 #ifdef __XSCALE__
 #ifndef CPU_XSCALE_CORE3
 	pmap_use_minicache(td2->td_kstack, td2->td_kstack_pages * PAGE_SIZE);
-	if (td2->td_altkstack)
-		pmap_use_minicache(td2->td_altkstack, td2->td_altkstack_pages *
-		    PAGE_SIZE);
 #endif
 #endif
 	td2->td_pcb = pcb2;
diff --git a/sys/arm/at91/uart_dev_at91usart.c b/sys/arm/at91/uart_dev_at91usart.c
index 0f50fb42612..77ab0ca8c10 100644
--- a/sys/arm/at91/uart_dev_at91usart.c
+++ b/sys/arm/at91/uart_dev_at91usart.c
@@ -307,6 +307,10 @@ static kobj_method_t at91_usart_methods[] = {
 int
 at91_usart_bus_probe(struct uart_softc *sc)
 {
+
+	sc->sc_txfifosz = USART_BUFFER_SIZE;
+	sc->sc_rxfifosz = USART_BUFFER_SIZE;
+	sc->sc_hwiflow = 0;
 	return (0);
 }
 
@@ -344,10 +348,6 @@ at91_usart_bus_attach(struct uart_softc *sc)
 		atsc->flags |= HAS_TIMEOUT;
 	WR4(&sc->sc_bas, USART_IDR, 0xffffffff);
 
-	sc->sc_txfifosz = USART_BUFFER_SIZE;
-	sc->sc_rxfifosz = USART_BUFFER_SIZE;
-	sc->sc_hwiflow = 0;
-
 #ifndef SKYEYE_WORKAROUNDS
 	/*
 	 * Allocate DMA tags and maps
diff --git a/sys/arm/mv/common.c b/sys/arm/mv/common.c
index b2d13dd5a34..d31e0819762 100644
--- a/sys/arm/mv/common.c
+++ b/sys/arm/mv/common.c
@@ -32,8 +32,10 @@
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -62,6 +64,76 @@ static void decode_win_usb_dump(void);
 
 static uint32_t used_cpu_wins;
 
+static __inline int
+pm_is_disabled(uint32_t mask)
+{
+
+	return (soc_power_ctrl_get(mask) == mask ? 0 : 1);
+}
+
+static __inline uint32_t
+obio_get_pm_mask(uint32_t base)
+{
+	struct obio_device *od;
+
+	for (od = obio_devices; od->od_name != NULL; od++)
+		if (od->od_base == base)
+			return (od->od_pwr_mask);
+
+	return (CPU_PM_CTRL_NONE);
+}
+
+/*
+ * Disable device using power management register.
+ * 1 - Device Power On
+ * 0 - Device Power Off
+ * Mask can be set in loader.
+ * EXAMPLE:
+ * loader> set hw.pm-disable-mask=0x2
+ *
+ * Common mask:
+ * |-------------------------------|
+ * | Device | Kirkwood | Discovery |
+ * |-------------------------------|
+ * | USB0   | 0x00008  | 0x020000  |
+ * |-------------------------------|
+ * | USB1   |     -    | 0x040000  |
+ * |-------------------------------|
+ * | USB2   |     -    | 0x080000  |
+ * |-------------------------------|
+ * | GE0    | 0x00001  | 0x000002  |
+ * |-------------------------------|
+ * | GE1    |     -    | 0x000004  |
+ * |-------------------------------|
+ * | IDMA   |     -    | 0x100000  |
+ * |-------------------------------|
+ * | XOR    | 0x10000  | 0x200000  |
+ * |-------------------------------|
+ * | CESA   | 0x20000  | 0x400000  |
+ * |-------------------------------|
+ * | SATA   | 0x04000  | 0x004000  |
+ * --------------------------------|
+ * This feature can be used only on Kirkwood and Discovery
+ * machines.
+ */
+static __inline void
+pm_disable_device(int mask)
+{
+#ifdef DIAGNOSTIC
+	uint32_t reg;
+
+	reg = soc_power_ctrl_get(CPU_PM_CTRL_ALL);
+	printf("Power Management Register: 0%x\n", reg);
+
+	reg &= ~mask;
+	soc_power_ctrl_set(reg);
+	printf("Device %x is disabled\n", mask);
+
+	reg = soc_power_ctrl_get(CPU_PM_CTRL_ALL);
+	printf("Power Management Register: 0%x\n", reg);
+#endif
+}
+
 uint32_t
 read_cpu_ctrl(uint32_t reg)
 {
@@ -103,14 +175,36 @@ cpu_extra_feat(void)
 	return (ef);
 }
 
+/*
+ * Get the power status of device. This feature is only supported on
+ * Kirkwood and Discovery SoCs.
+ */
 uint32_t
 soc_power_ctrl_get(uint32_t mask)
 {
 
+#ifndef SOC_MV_ORION
 	if (mask != CPU_PM_CTRL_NONE)
 		mask &= read_cpu_ctrl(CPU_PM_CTRL);
 
 	return (mask);
+#else
+	return (mask);
+#endif
+}
+
+/*
+ * Set the power status of device. This feature is only supported on
+ * Kirkwood and Discovery SoCs.
+ */
+void
+soc_power_ctrl_set(uint32_t mask)
+{
+
+#ifndef SOC_MV_ORION
+	if (mask != CPU_PM_CTRL_NONE)
+		write_cpu_ctrl(CPU_PM_CTRL, mask);
+#endif
 }
 
 void
@@ -191,6 +285,13 @@ int
 soc_decode_win(void)
 {
 	uint32_t dev, rev;
+	int mask;
+
+	mask = 0;
+	TUNABLE_INT_FETCH("hw.pm-disable-mask", &mask);
+
+	if (mask != 0)
+		pm_disable_device(mask);
 
 	/* Retrieve our ID: some windows facilities vary between SoC models */
 	soc_id(&dev, &rev);
@@ -623,8 +724,12 @@ decode_win_usb_setup(void)
 
 	/* Disable and clear all USB windows for all ports */
 	m = usb_max_ports();
+
 	for (p = 0; p < m; p++) {
 
+		if (pm_is_disabled(CPU_PM_CTRL_USB(p)))
+			continue;
+
 		for (i = 0; i < MV_WIN_USB_MAX; i++) {
 			win_usb_cr_write(i, p, 0);
 			win_usb_br_write(i, p, 0);
@@ -710,6 +815,9 @@ decode_win_eth_setup(uint32_t base)
 	uint32_t br, sz;
 	int i, j;
 
+	if (pm_is_disabled(obio_get_pm_mask(base)))
+		return;
+
 	/* Disable, clear and revoke protection for all ETH windows */
 	for (i = 0; i < MV_WIN_ETH_MAX; i++) {
 
@@ -880,6 +988,8 @@ decode_win_idma_setup(void)
 	uint32_t br, sz;
 	int i, j;
 
+	if (pm_is_disabled(CPU_PM_CTRL_IDMA))
+		return;
 	/*
 	 * Disable and clear all IDMA windows, revoke protection for all channels
 	 */
@@ -1172,6 +1282,9 @@ decode_win_xor_setup(void)
 	uint32_t br, sz;
 	int i, j, z, e = 1, m, window;
 
+	if (pm_is_disabled(CPU_PM_CTRL_XOR))
+		return;
+
 	/*
 	 * Disable and clear all XOR windows, revoke protection for all
 	 * channels
@@ -1364,6 +1477,9 @@ decode_win_cesa_setup(void)
 	uint32_t br, cr;
 	int i, j;
 
+	if (pm_is_disabled(CPU_PM_CTRL_CRYPTO))
+		return;
+
 	/* Disable and clear all CESA windows */
 	for (i = 0; i < MV_WIN_CESA_MAX; i++) {
 		win_cesa_cr_write(i, 0);
@@ -1432,6 +1548,9 @@ decode_win_sata_setup(void)
 	uint32_t cr, br;
 	int i, j;
 
+	if (pm_is_disabled(CPU_PM_CTRL_SATA))
+		return;
+
 	for (i = 0; i < MV_WIN_SATA_MAX; i++) {
 		win_sata_cr_write(i, 0);
 		win_sata_br_write(i, 0);
diff --git a/sys/arm/mv/discovery/db78xxx.c b/sys/arm/mv/discovery/db78xxx.c
index 98b2dff86fd..df68f50af68 100644
--- a/sys/arm/mv/discovery/db78xxx.c
+++ b/sys/arm/mv/discovery/db78xxx.c
@@ -68,11 +68,8 @@ __FBSDID("$FreeBSD$");
  * 0xffff_2000 - 0xffff_ffff	: unused (~55KB)
  */
 
-const struct pmap_devmap *pmap_devmap_bootstrap_table;
-vm_offset_t pmap_bootstrap_lastaddr;
-
 /* Static device mappings. */
-static const struct pmap_devmap pmap_devmap[] = {
+const struct pmap_devmap pmap_devmap[] = {
 	/*
 	 * Map the on-board devices VA == PA so that we can access them
 	 * with the MMU on or off.
@@ -105,16 +102,6 @@ const struct gpio_config mv_gpio_config[] = {
 	{ -1, -1, -1 }
 };
 
-int
-platform_pmap_init(void)
-{
-
-	pmap_bootstrap_lastaddr = MV_BASE - ARM_NOCACHE_KVA_SIZE;
-	pmap_devmap_bootstrap_table = &pmap_devmap[0];
-
-	return (0);
-}
-
 void
 platform_mpp_init(void)
 {
diff --git a/sys/arm/mv/kirkwood/db88f6xxx.c b/sys/arm/mv/kirkwood/db88f6xxx.c
index 5f8901062cf..6e41ef84e4f 100644
--- a/sys/arm/mv/kirkwood/db88f6xxx.c
+++ b/sys/arm/mv/kirkwood/db88f6xxx.c
@@ -68,11 +68,8 @@ __FBSDID("$FreeBSD$");
  * 0xffff_2000 - 0xffff_ffff	: unused (~55KB)
  */
 
-const struct pmap_devmap *pmap_devmap_bootstrap_table;
-vm_offset_t pmap_bootstrap_lastaddr;
-
 /* Static device mappings. */
-static const struct pmap_devmap pmap_devmap[] = {
+const struct pmap_devmap pmap_devmap[] = {
 	/*
 	 * Map the on-board devices VA == PA so that we can access them
 	 * with the MMU on or off.
@@ -105,16 +102,6 @@ const struct gpio_config mv_gpio_config[] = {
 	{ -1, -1, -1 }
 };
 
-int
-platform_pmap_init(void)
-{
-
-	pmap_bootstrap_lastaddr = MV_BASE - ARM_NOCACHE_KVA_SIZE;
-	pmap_devmap_bootstrap_table = &pmap_devmap[0];
-
-	return (0);
-}
-
 void
 platform_mpp_init(void)
 {
diff --git a/sys/arm/mv/kirkwood/files.db88f6xxx b/sys/arm/mv/kirkwood/files.db88f6xxx
index c0de03c4f94..7ee367318fa 100644
--- a/sys/arm/mv/kirkwood/files.db88f6xxx
+++ b/sys/arm/mv/kirkwood/files.db88f6xxx
@@ -1,5 +1,4 @@
 # $FreeBSD$
 
-arm/mv/rtc.c			standard
-arm/mv/kirkwood/kirkwood.c	standard
+include "arm/mv/kirkwood/files.kirkwood"
 arm/mv/kirkwood/db88f6xxx.c	standard
diff --git a/sys/arm/mv/kirkwood/std.db88f6xxx b/sys/arm/mv/kirkwood/std.db88f6xxx
index 84af354e507..3a00f967540 100644
--- a/sys/arm/mv/kirkwood/std.db88f6xxx
+++ b/sys/arm/mv/kirkwood/std.db88f6xxx
@@ -1,13 +1,8 @@
 # $FreeBSD$
 
 include	"../mv/std.mv"
+include "../mv/kirkwood/std.kirkwood"
 files	"../mv/kirkwood/files.db88f6xxx"
 
-makeoptions	KERNPHYSADDR=0x00900000
-makeoptions	KERNVIRTADDR=0xc0900000
 
-options		KERNPHYSADDR=0x00900000
-options		KERNVIRTADDR=0xc0900000
-options		PHYSADDR=0x00000000
 options		PHYSMEM_SIZE=0x20000000
-options		STARTUP_PAGETABLE_ADDR=0x00100000
diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c
index 59836fc8dbf..2dc20ceb08e 100644
--- a/sys/arm/mv/mv_machdep.c
+++ b/sys/arm/mv/mv_machdep.c
@@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$");
 #include 
 
 #include 	/* XXX eventually this should be eliminated */
+#include 
 
 #ifdef  DEBUG
 #define debugf(fmt, args...) printf(fmt, ##args)
@@ -133,7 +134,9 @@ struct pcpu *pcpup = &__pcpu;
 vm_paddr_t phys_avail[10];
 vm_paddr_t dump_avail[4];
 vm_offset_t physical_pages;
+vm_offset_t pmap_bootstrap_lastaddr;
 
+const struct pmap_devmap *pmap_devmap_bootstrap_table;
 struct pv_addr systempage;
 struct pv_addr msgbufpv;
 struct pv_addr irqstack;
@@ -423,8 +426,8 @@ initarm(void *mdp, void *unused __unused)
 		while (1);
 
 	/* Platform-specific initialisation */
-	if (platform_pmap_init() != 0)
-		return (NULL);
+	pmap_bootstrap_lastaddr = MV_BASE - ARM_NOCACHE_KVA_SIZE;
+	pmap_devmap_bootstrap_table = &pmap_devmap[0];
 
 	pcpu_init(pcpup, 0, sizeof(struct pcpu));
 	PCPU_SET(curthread, &thread0);
diff --git a/sys/arm/mv/mvreg.h b/sys/arm/mv/mvreg.h
index 271addc2fc7..28e342adcce 100644
--- a/sys/arm/mv/mvreg.h
+++ b/sys/arm/mv/mvreg.h
@@ -218,6 +218,7 @@
  */
 #define CPU_PM_CTRL		0x1C
 #define CPU_PM_CTRL_NONE	0
+#define CPU_PM_CTRL_ALL		~0x0
 
 #if defined(SOC_MV_KIRKWOOD)
 #define CPU_PM_CTRL_GE0		(1 << 0)
@@ -234,8 +235,11 @@
 #define CPU_PM_CTRL_SATA1	(1 << 15)
 #define CPU_PM_CTRL_XOR1	(1 << 16)
 #define CPU_PM_CTRL_CRYPTO	(1 << 17)
-#define CPU_PM_CTRL_GE1		(1 << 18)
-#define CPU_PM_CTRL_TDM		(1 << 19)
+#define CPU_PM_CTRL_GE1		(1 << 19)
+#define CPU_PM_CTRL_TDM		(1 << 20)
+#define CPU_PM_CTRL_XOR		(CPU_PM_CTRL_XOR0 | CPU_PM_CTRL_XOR1)
+#define CPU_PM_CTRL_USB(u)	(CPU_PM_CTRL_USB0)
+#define CPU_PM_CTRL_SATA	(CPU_PM_CTRL_SATA0 | CPU_PM_CTRL_SATA1)
 #elif defined(SOC_MV_DISCOVERY)
 #define CPU_PM_CTRL_GE0		(1 << 1)
 #define CPU_PM_CTRL_GE1		(1 << 2)
@@ -258,6 +262,14 @@
 #define CPU_PM_CTRL_XOR		(1 << 21)
 #define CPU_PM_CTRL_CRYPTO	(1 << 22)
 #define CPU_PM_CTRL_DEVICE	(1 << 23)
+#define CPU_PM_CTRL_USB(u)	(1 << (17 + (u)))
+#define CPU_PM_CTRL_SATA	(CPU_PM_CTRL_SATA0 | CPU_PM_CTRL_SATA1)
+#else
+#define CPU_PM_CTRL_CRYPTO	(CPU_PM_CTRL_NONE)
+#define CPU_PM_CTRL_IDMA	(CPU_PM_CTRL_NONE)
+#define CPU_PM_CTRL_XOR		(CPU_PM_CTRL_NONE)
+#define CPU_PM_CTRL_SATA	(CPU_PM_CTRL_NONE)
+#define CPU_PM_CTRL_USB(u)	(CPU_PM_CTRL_NONE)
 #endif
 
 /*
diff --git a/sys/arm/mv/mvvar.h b/sys/arm/mv/mvvar.h
index 061f3633d89..7d7de32f7c8 100644
--- a/sys/arm/mv/mvvar.h
+++ b/sys/arm/mv/mvvar.h
@@ -41,6 +41,10 @@
 #define _MVVAR_H_
 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #define	MV_TYPE_PCI		0
 #define	MV_TYPE_PCIE		1
@@ -104,6 +108,7 @@ struct decode_win {
 	int		remap;
 };
 
+extern const struct pmap_devmap pmap_devmap[];
 extern const struct obio_pci mv_pci_info[];
 extern const struct gpio_config mv_gpio_config[];
 extern bus_space_tag_t obio_tag;
@@ -124,13 +129,13 @@ int mv_gpio_configure(uint32_t pin, uint32_t flags, uint32_t mask);
 void mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable);
 uint8_t mv_gpio_in(uint32_t pin);
 
-int platform_pmap_init(void);
 void platform_mpp_init(void);
 int soc_decode_win(void);
 void soc_id(uint32_t *dev, uint32_t *rev);
 void soc_identify(void);
 void soc_dump_decode_win(void);
 uint32_t soc_power_ctrl_get(uint32_t mask);
+void soc_power_ctrl_set(uint32_t mask);
 
 int decode_win_cpu_set(int target, int attr, vm_paddr_t base, uint32_t size,
     int remap);
diff --git a/sys/arm/mv/orion/db88f5xxx.c b/sys/arm/mv/orion/db88f5xxx.c
index 8b40f5447ab..02759bea7f6 100644
--- a/sys/arm/mv/orion/db88f5xxx.c
+++ b/sys/arm/mv/orion/db88f5xxx.c
@@ -70,12 +70,10 @@ __FBSDID("$FreeBSD$");
  * 0xffff_2000 - 0xffff_ffff	: unused (~55KB)
  */
 
-const struct pmap_devmap *pmap_devmap_bootstrap_table;
-vm_offset_t pmap_bootstrap_lastaddr;
 int platform_pci_get_irq(u_int bus, u_int slot, u_int func, u_int pin);
 
 /* Static device mappings. */
-static const struct pmap_devmap pmap_devmap[] = {
+const struct pmap_devmap pmap_devmap[] = {
 	/*
 	 * Map the on-board devices VA == PA so that we can access them
 	 * with the MMU on or off.
@@ -184,16 +182,6 @@ const struct gpio_config mv_gpio_config[] = {
 };
 #endif
 
-int
-platform_pmap_init(void)
-{
-
-	pmap_bootstrap_lastaddr = MV_BASE - ARM_NOCACHE_KVA_SIZE;
-	pmap_devmap_bootstrap_table = &pmap_devmap[0];
-
-	return (0);
-}
-
 void
 platform_mpp_init(void)
 {
diff --git a/sys/arm/xscale/ixp425/ixdp425_pci.c b/sys/arm/xscale/ixp425/ixdp425_pci.c
index d103a63b734..817e6aff162 100644
--- a/sys/arm/xscale/ixp425/ixdp425_pci.c
+++ b/sys/arm/xscale/ixp425/ixdp425_pci.c
@@ -62,12 +62,12 @@ ixp425_md_attach(device_t dev)
 	/* PCI Reset Assert */
 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
 	reg &= ~(1U << GPIO_PCI_RESET);
-	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg & ~(1U << GPIO_PCI_RESET));
+	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
 
 	/* PCI Clock Disable */
 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
 	reg &= ~GPCLKR_MUX14;
-	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg & ~GPCLKR_MUX14);
+	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg);
 
 	/*
 	 * set GPIO Direction
diff --git a/sys/boot/i386/gptboot/gptboot.c b/sys/boot/i386/gptboot/gptboot.c
index 405b92e6286..89df2ecb104 100644
--- a/sys/boot/i386/gptboot/gptboot.c
+++ b/sys/boot/i386/gptboot/gptboot.c
@@ -466,16 +466,13 @@ parse(void)
 		dsk.type = i;
 		arg += 3;
 		dsk.unit = *arg - '0';
-		if (arg[1] != ',' || dsk.unit > 9)
+		if (arg[1] != 'p' || dsk.unit > 9)
 		    return -1;
 		arg += 2;
-		dsk.part = -1;
-		if (arg[1] == ',') {
-		    dsk.part = *arg - '0';
-		    if (dsk.part < 1 || dsk.part > 9)
-			return -1;
-		    arg += 2;
-		}
+		dsk.part = *arg - '0';
+		if (dsk.part < 1 || dsk.part > 9)
+		    return -1;
+		arg++;
 		if (arg[0] != ')')
 		    return -1;
 		arg++;
diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c
index 1e6eecec820..e75c109f7ee 100644
--- a/sys/cam/ata/ata_all.c
+++ b/sys/cam/ata/ata_all.c
@@ -91,7 +91,7 @@ ata_print_ident(struct ata_params *ident_data)
 }
 
 void
-ata_36bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features,
+ata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features,
     uint32_t lba, uint8_t sector_count)
 {
 	bzero(&ataio->cmd, sizeof(ataio->cmd));
diff --git a/sys/cam/ata/ata_all.h b/sys/cam/ata/ata_all.h
index 60129956db7..748035f8602 100644
--- a/sys/cam/ata/ata_all.h
+++ b/sys/cam/ata/ata_all.h
@@ -83,7 +83,7 @@ struct ata_res {
 int	ata_version(int ver);
 void	ata_print_ident(struct ata_params *ident_data);
 
-void	ata_36bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features,
+void	ata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features,
     uint32_t lba, uint8_t sector_count);
 void	ata_48bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint16_t features,
     uint64_t lba, uint16_t sector_count);
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index 42ba74566b9..7d7230b154f 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -287,7 +287,7 @@ adaclose(struct disk *dp)
 		if (softc->flags & ADA_FLAG_CAN_48BIT)
 			ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE48, 0, 0, 0);
 		else
-			ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0);
+			ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0);
 		cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
 		    /*sense_flags*/SF_RETRY_UA,
 		    softc->disk->d_devstat);
@@ -411,7 +411,7 @@ adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len
 			ata_48bit_cmd(&ccb.ataio, ATA_WRITE_DMA48,
 			    0, lba, count);
 		} else {
-			ata_36bit_cmd(&ccb.ataio, ATA_WRITE_DMA,
+			ata_28bit_cmd(&ccb.ataio, ATA_WRITE_DMA,
 			    0, lba, count);
 		}
 		xpt_polled_action(&ccb);
@@ -441,7 +441,7 @@ adadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t len
 		if (softc->flags & ADA_FLAG_CAN_48BIT)
 			ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0);
 		else
-			ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
+			ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
 		xpt_polled_action(&ccb);
 
 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
@@ -856,10 +856,10 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
 					}
 				} else {
 					if (bp->bio_cmd == BIO_READ) {
-						ata_36bit_cmd(ataio, ATA_READ_DMA,
+						ata_28bit_cmd(ataio, ATA_READ_DMA,
 						    0, lba, count);
 					} else {
-						ata_36bit_cmd(ataio, ATA_WRITE_DMA,
+						ata_28bit_cmd(ataio, ATA_WRITE_DMA,
 						    0, lba, count);
 					}
 				}
@@ -878,7 +878,7 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
 				if (softc->flags & ADA_FLAG_CAN_48BIT)
 					ata_48bit_cmd(ataio, ATA_FLUSHCACHE48, 0, 0, 0);
 				else
-					ata_48bit_cmd(ataio, ATA_FLUSHCACHE, 0, 0, 0);
+					ata_28bit_cmd(ataio, ATA_FLUSHCACHE, 0, 0, 0);
 				break;
 			}
 			start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO;
@@ -1126,7 +1126,7 @@ adashutdown(void * arg, int howto)
 		if (softc->flags & ADA_FLAG_CAN_48BIT)
 			ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE48, 0, 0, 0);
 		else
-			ata_48bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
+			ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
 		xpt_polled_action(&ccb);
 
 		if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c
index 0116b5b7459..5acb9a35d0c 100644
--- a/sys/cam/ata/ata_xpt.c
+++ b/sys/cam/ata/ata_xpt.c
@@ -357,9 +357,9 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
 		      /*dxfer_len*/sizeof(struct ata_params),
 		      30 * 1000);
 		if (periph->path->device->protocol == PROTO_ATA)
-			ata_36bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
+			ata_28bit_cmd(ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
 		else
-			ata_36bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
+			ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
 		break;
 	}
 	case PROBE_SETMODE:
@@ -370,12 +370,12 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
 		cam_fill_ataio(ataio,
 		      1,
 		      probedone,
-		      /*flags*/CAM_DIR_IN,
-		      MSG_SIMPLE_Q_TAG,
-		      /*data_ptr*/(u_int8_t *)ident_buf,
-		      /*dxfer_len*/sizeof(struct ata_params),
+		      /*flags*/CAM_DIR_NONE,
+		      0,
+		      /*data_ptr*/NULL,
+		      /*dxfer_len*/0,
 		      30 * 1000);
-		ata_36bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
+		ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
 		    ata_max_mode(ident_buf, ATA_UDMA6, ATA_UDMA6));
 		break;
 	}
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 61a57e3b2ab..a750d935f43 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -243,6 +243,7 @@ typedef enum {
 	XPORT_ATA,	/* AT Attachment */
 	XPORT_SAS,	/* Serial Attached SCSI */
 	XPORT_SATA,	/* Serial AT Attachment */
+	XPORT_ISCSI,	/* iSCSI */
 } cam_xport;
 
 #define PROTO_VERSION_UNKNOWN (UINT_MAX - 1)
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index ea259668acf..b506481bb26 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -1033,11 +1033,12 @@ xpt_announce_periph(struct cam_periph *periph, char *announce_string)
 	 * To ensure that this is printed in one piece,
 	 * mask out CAM interrupts.
 	 */
-	printf("%s%d at %s%d bus %d target %d lun %d\n",
+	printf("%s%d at %s%d bus %d scbus%d target %d lun %d\n",
 	       periph->periph_name, periph->unit_number,
 	       path->bus->sim->sim_name,
 	       path->bus->sim->unit_number,
 	       path->bus->sim->bus_id,
+	       path->bus->path_id,
 	       path->target->target_id,
 	       path->device->lun_id);
 	printf("%s%d: ", periph->periph_name, periph->unit_number);
@@ -2471,7 +2472,7 @@ xpt_action_default(union ccb *start_ccb)
 		path = start_ccb->ccb_h.path;
 
 		cam_ccbq_insert_ccb(&path->device->ccbq, start_ccb);
-		if (path->device->qfrozen_cnt == 0)
+		if (path->device->ccbq.queue.qfrozen_cnt == 0)
 			runq = xpt_schedule_dev_sendq(path->bus, path->device);
 		else
 			runq = 0;
@@ -2930,7 +2931,7 @@ xpt_action_default(union ccb *start_ccb)
 			xpt_release_devq(crs->ccb_h.path, /*count*/1,
 					 /*run_queue*/TRUE);
 		}
-		start_ccb->crs.qfrozen_cnt = dev->qfrozen_cnt;
+		start_ccb->crs.qfrozen_cnt = dev->ccbq.queue.qfrozen_cnt;
 		start_ccb->ccb_h.status = CAM_REQ_CMP;
 		break;
 	}
@@ -3226,7 +3227,7 @@ xpt_run_dev_sendq(struct cam_eb *bus)
 		 * If the device has been "frozen", don't attempt
 		 * to run it.
 		 */
-		if (device->qfrozen_cnt > 0) {
+		if (device->ccbq.queue.qfrozen_cnt > 0) {
 			continue;
 		}
 
@@ -3249,7 +3250,7 @@ xpt_run_dev_sendq(struct cam_eb *bus)
 				 * the device queue until we have a slot
 				 * available.
 				 */
-				device->qfrozen_cnt++;
+				device->ccbq.queue.qfrozen_cnt++;
 				STAILQ_INSERT_TAIL(&xsoftc.highpowerq,
 						   &work_ccb->ccb_h,
 						   xpt_links.stqe);
@@ -3281,7 +3282,7 @@ xpt_run_dev_sendq(struct cam_eb *bus)
 			 * The client wants to freeze the queue
 			 * after this CCB is sent.
 			 */
-			device->qfrozen_cnt++;
+			device->ccbq.queue.qfrozen_cnt++;
 		}
 
 		/* In Target mode, the peripheral driver knows best... */
@@ -3803,6 +3804,8 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
 		case XPORT_SAS:
 		case XPORT_FC:
 		case XPORT_USB:
+		case XPORT_ISCSI:
+		case XPORT_PPB:
 			new_bus->xport = scsi_get_xport();
 			break;
 		case XPORT_ATA:
@@ -4028,7 +4031,7 @@ xpt_freeze_devq(struct cam_path *path, u_int count)
 
 	mtx_assert(path->bus->sim->mtx, MA_OWNED);
 
-	path->device->qfrozen_cnt += count;
+	path->device->ccbq.queue.qfrozen_cnt += count;
 
 	/*
 	 * Mark the last CCB in the queue as needing
@@ -4046,7 +4049,7 @@ xpt_freeze_devq(struct cam_path *path, u_int count)
 	ccbh = TAILQ_LAST(&path->device->ccbq.active_ccbs, ccb_hdr_tailq);
 	if (ccbh && ccbh->status == CAM_REQ_INPROG)
 		ccbh->status = CAM_REQUEUE_REQ;
-	return (path->device->qfrozen_cnt);
+	return (path->device->ccbq.queue.qfrozen_cnt);
 }
 
 u_int32_t
@@ -4090,11 +4093,12 @@ xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue)
 	int	rundevq;
 
 	rundevq = 0;
-	if (dev->qfrozen_cnt > 0) {
+	if (dev->ccbq.queue.qfrozen_cnt > 0) {
 
-		count = (count > dev->qfrozen_cnt) ? dev->qfrozen_cnt : count;
-		dev->qfrozen_cnt -= count;
-		if (dev->qfrozen_cnt == 0) {
+		count = (count > dev->ccbq.queue.qfrozen_cnt) ?
+		    dev->ccbq.queue.qfrozen_cnt : count;
+		dev->ccbq.queue.qfrozen_cnt -= count;
+		if (dev->ccbq.queue.qfrozen_cnt == 0) {
 
 			/*
 			 * No longer need to wait for a successful
@@ -4196,12 +4200,12 @@ xpt_done(union ccb *done_ccb)
 				mtx_lock(&cam_simq_lock);
 				TAILQ_INSERT_TAIL(&cam_simq, sim,
 						  links);
-				sim->flags |= CAM_SIM_ON_DONEQ;
 				mtx_unlock(&cam_simq_lock);
+				sim->flags |= CAM_SIM_ON_DONEQ;
+				if ((done_ccb->ccb_h.path->periph->flags &
+				    CAM_PERIPH_POLLED) == 0)
+					swi_sched(cambio_ih, 0);
 			}
-			if ((done_ccb->ccb_h.path->periph->flags &
-			    CAM_PERIPH_POLLED) == 0)
-				swi_sched(cambio_ih, 0);
 			break;
 		default:
 			panic("unknown periph type %d",
@@ -4399,15 +4403,11 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
 		SLIST_INIT(&device->periphs);
 		device->generation = 0;
 		device->owner = NULL;
-		device->qfrozen_cnt = 0;
 		device->flags = CAM_DEV_UNCONFIGURED;
 		device->tag_delay_count = 0;
 		device->tag_saved_openings = 0;
 		device->refcount = 1;
-		if (bus->sim->flags & CAM_SIM_MPSAFE)
-			callout_init_mtx(&device->callout, bus->sim->mtx, 0);
-		else
-			callout_init_mtx(&device->callout, &Giant, 0);
+		callout_init_mtx(&device->callout, bus->sim->mtx, 0);
 
 		/*
 		 * Hold a reference to our parent target so it
@@ -4602,7 +4602,7 @@ xptconfigfunc(struct cam_eb *bus, void *arg)
 					      CAM_TARGET_WILDCARD,
 					      CAM_LUN_WILDCARD)) !=CAM_REQ_CMP){
 			printf("xptconfigfunc: xpt_create_path failed with "
-			       "status %#x for bus %d\n", status, bus->path_id);
+			       "status %#x for scbus%d\n", status, bus->path_id);
 			printf("xptconfigfunc: halting bus configuration\n");
 			xpt_free_ccb(work_ccb);
 			busses_to_config--;
@@ -4613,7 +4613,7 @@ xptconfigfunc(struct cam_eb *bus, void *arg)
 		work_ccb->ccb_h.func_code = XPT_PATH_INQ;
 		xpt_action(work_ccb);
 		if (work_ccb->ccb_h.status != CAM_REQ_CMP) {
-			printf("xptconfigfunc: CPI failed on bus %d "
+			printf("xptconfigfunc: CPI failed on scbus%d "
 			       "with status %d\n", bus->path_id,
 			       work_ccb->ccb_h.status);
 			xpt_finishconfig(xpt_periph, work_ccb);
@@ -4887,16 +4887,20 @@ camisr(void *dummy)
 
 	mtx_lock(&cam_simq_lock);
 	TAILQ_INIT(&queue);
-	TAILQ_CONCAT(&queue, &cam_simq, links);
-	mtx_unlock(&cam_simq_lock);
+	while (!TAILQ_EMPTY(&cam_simq)) {
+		TAILQ_CONCAT(&queue, &cam_simq, links);
+		mtx_unlock(&cam_simq_lock);
 
-	while ((sim = TAILQ_FIRST(&queue)) != NULL) {
-		TAILQ_REMOVE(&queue, sim, links);
-		CAM_SIM_LOCK(sim);
-		sim->flags &= ~CAM_SIM_ON_DONEQ;
-		camisr_runqueue(&sim->sim_doneq);
-		CAM_SIM_UNLOCK(sim);
+		while ((sim = TAILQ_FIRST(&queue)) != NULL) {
+			TAILQ_REMOVE(&queue, sim, links);
+			CAM_SIM_LOCK(sim);
+			sim->flags &= ~CAM_SIM_ON_DONEQ;
+			camisr_runqueue(&sim->sim_doneq);
+			CAM_SIM_UNLOCK(sim);
+		}
+		mtx_lock(&cam_simq_lock);
 	}
+	mtx_unlock(&cam_simq_lock);
 }
 
 static void
@@ -4967,7 +4971,7 @@ camisr_runqueue(void *V_queue)
 				xpt_start_tags(ccb_h->path);
 
 			if ((dev->ccbq.queue.entries > 0)
-			 && (dev->qfrozen_cnt == 0)
+			 && (dev->ccbq.queue.qfrozen_cnt == 0)
 			 && (device_is_send_queued(dev) == 0)) {
 				runq = xpt_schedule_dev_sendq(ccb_h->path->bus,
 							      dev);
diff --git a/sys/cam/cam_xpt_internal.h b/sys/cam/cam_xpt_internal.h
index 12c5c2f556f..e40cde84b57 100644
--- a/sys/cam/cam_xpt_internal.h
+++ b/sys/cam/cam_xpt_internal.h
@@ -106,7 +106,6 @@ struct cam_ed {
 	u_int8_t	 queue_flags;	/* Queue flags from the control page */
 	u_int8_t	 serial_num_len;
 	u_int8_t	*serial_num;
-	u_int32_t	 qfrozen_cnt;
 	u_int32_t	 flags;
 #define CAM_DEV_UNCONFIGURED	 	0x01
 #define CAM_DEV_REL_TIMEOUT_PENDING	0x02
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index 287c6b626f3..52f73113d64 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -2528,7 +2528,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
 
 			error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
 			if (error) {
-				free(¶ms, M_SCSICD);
+				free(¶ms.mode_buf, M_SCSICD);
 				cam_periph_unlock(periph);
 				break;
 			}
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index f5ec895909b..e3ad7e1abfa 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -554,6 +554,14 @@ static struct da_quirk_entry da_quirk_table[] =
 	{
 		{T_DIRECT, SIP_MEDIA_REMOVABLE, "Netac", "OnlyDisk*",
 		 "2000"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+	},
+	{
+		/*
+		 * Sony Cyber-Shot DSC cameras
+		 * PR: usb/137035
+		 */
+		{T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "Sony DSC", "*"},
+		/*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_PREVENT
 	}
 };
 
@@ -1258,6 +1266,8 @@ daregister(struct cam_periph *periph, void *arg)
 	softc->disk->d_flags = 0;
 	if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
 		softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
+	strlcpy(softc->disk->d_ident, cgd->serial_num,
+	    MIN(sizeof(softc->disk->d_ident), cgd->serial_num_len + 1));
 	disk_create(softc->disk, DISK_VERSION);
 	mtx_lock(periph->sim->mtx);
 
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris.c b/sys/cddl/compat/opensolaris/kern/opensolaris.c
index 443ac0ad79e..54118eb3835 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris.c
@@ -49,10 +49,6 @@ opensolaris_load(void *dummy)
 {
 	int i;
 
-	printf("This module (opensolaris) contains code covered by the\n");
-	printf("Common Development and Distribution License (CDDL)\n");
-	printf("see http://opensolaris.org/os/licensing/opensolaris_license/\n");
-
 	/*
 	 * "Enable" all CPUs even though they may not exist just so
 	 * that the asserts work. On FreeBSD, if a CPU exists, it is
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c b/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c
index c2144888aed..d79434511e5 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c
@@ -69,7 +69,7 @@ kobj_open_file_vnode(const char *file)
 	struct thread *td = curthread;
 	struct filedesc *fd;
 	struct nameidata nd;
-	int error, flags;
+	int error, flags, vfslocked;
 
 	fd = td->td_proc->p_fd;
 	FILEDESC_XLOCK(fd);
@@ -86,11 +86,13 @@ kobj_open_file_vnode(const char *file)
 	flags = FREAD | O_NOFOLLOW;
 	NDINIT(&nd, LOOKUP, MPSAFE, UIO_SYSSPACE, file, td);
 	error = vn_open_cred(&nd, &flags, 0, 0, curthread->td_ucred, NULL);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
 	if (error != 0)
 		return (NULL);
+	vfslocked = NDHASGIANT(&nd);
+	NDFREE(&nd, NDF_ONLY_PNBUF);
 	/* We just unlock so we hold a reference. */
 	VOP_UNLOCK(nd.ni_vp, 0);
+	VFS_UNLOCK_GIANT(vfslocked);
 	return (nd.ni_vp);
 }
 
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c b/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c
new file mode 100644
index 00000000000..584be24100e
--- /dev/null
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2009 Pawel Jakub Dawidek 
+ * 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 AUTHORS 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 AUTHORS 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+static uma_zone_t taskq_zone;
+
+struct ostask {
+	struct task	ost_task;
+	task_func_t	*ost_func;
+	void		*ost_arg;
+};
+
+taskq_t *system_taskq = NULL;
+
+static void
+system_taskq_init(void *arg)
+{
+
+	system_taskq = (taskq_t *)taskqueue_thread;
+	taskq_zone = uma_zcreate("taskq_zone", sizeof(struct ostask),
+	    NULL, NULL, NULL, NULL, 0, 0);
+}
+SYSINIT(system_taskq_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_init, NULL);
+
+static void
+system_taskq_fini(void *arg)
+{
+
+	uma_zdestroy(taskq_zone);
+}
+SYSUNINIT(system_taskq_fini, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_fini, NULL);
+
+taskq_t *
+taskq_create(const char *name, int nthreads, pri_t pri, int minalloc __unused,
+    int maxalloc __unused, uint_t flags)
+{
+	taskq_t *tq;
+
+	if ((flags & TASKQ_THREADS_CPU_PCT) != 0) {
+		/* TODO: Calculate number od threads. */
+		printf("%s: TASKQ_THREADS_CPU_PCT\n", __func__);
+	}
+
+	tq = kmem_alloc(sizeof(*tq), KM_SLEEP);
+	tq->tq_queue = taskqueue_create(name, M_WAITOK, taskqueue_thread_enqueue,
+	    &tq->tq_queue);
+	(void) taskqueue_start_threads(&tq->tq_queue, nthreads, pri, name);
+
+	return ((taskq_t *)tq);
+}
+
+void
+taskq_destroy(taskq_t *tq)
+{
+
+	taskqueue_free(tq->tq_queue);
+	kmem_free(tq, sizeof(*tq));
+}
+
+int
+taskq_member(taskq_t *tq, kthread_t *thread)
+{
+
+	return (taskqueue_member(tq->tq_queue, thread));
+}
+
+static void
+taskq_run(void *arg, int pending __unused)
+{
+	struct ostask *task = arg;
+
+	task->ost_func(task->ost_arg);
+
+	uma_zfree(taskq_zone, task);
+}
+
+taskqid_t
+taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
+{
+	struct ostask *task;
+	int mflag;
+
+	if ((flags & (TQ_SLEEP | TQ_NOQUEUE)) == TQ_SLEEP)
+		mflag = M_WAITOK;
+	else
+		mflag = M_NOWAIT;
+
+	task = uma_zalloc(taskq_zone, mflag);
+	if (task == NULL)
+		return (0);
+
+	task->ost_func = func;
+	task->ost_arg = arg;
+
+	TASK_INIT(&task->ost_task, 0, taskq_run, task);
+	taskqueue_enqueue(tq->tq_queue, &task->ost_task);
+
+	return ((taskqid_t)(void *)task);
+}
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
index a716b6395fb..d02f5ea8cfe 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
@@ -45,20 +45,33 @@ vfs_setmntopt(vfs_t *vfsp, const char *name, const char *arg,
 {
 	struct vfsopt *opt;
 	size_t namesize;
+	int locked;
+
+	if (!(locked = mtx_owned(MNT_MTX(vfsp))))
+		MNT_ILOCK(vfsp);
 
 	if (vfsp->mnt_opt == NULL) {
-		vfsp->mnt_opt = malloc(sizeof(*vfsp->mnt_opt), M_MOUNT, M_WAITOK);
-		TAILQ_INIT(vfsp->mnt_opt);
+		void *opts;
+
+		MNT_IUNLOCK(vfsp);
+		opts = malloc(sizeof(*vfsp->mnt_opt), M_MOUNT, M_WAITOK);
+		MNT_ILOCK(vfsp);
+		if (vfsp->mnt_opt == NULL) {
+			vfsp->mnt_opt = opts;
+			TAILQ_INIT(vfsp->mnt_opt);
+		} else {
+			free(opts, M_MOUNT);
+		}
 	}
 
-	opt = malloc(sizeof(*opt), M_MOUNT, M_WAITOK);
+	MNT_IUNLOCK(vfsp);
 
+	opt = malloc(sizeof(*opt), M_MOUNT, M_WAITOK);
 	namesize = strlen(name) + 1;
 	opt->name = malloc(namesize, M_MOUNT, M_WAITOK);
 	strlcpy(opt->name, name, namesize);
 	opt->pos = -1;
 	opt->seen = 1;
-
 	if (arg == NULL) {
 		opt->value = NULL;
 		opt->len = 0;
@@ -67,16 +80,23 @@ vfs_setmntopt(vfs_t *vfsp, const char *name, const char *arg,
 		opt->value = malloc(opt->len, M_MOUNT, M_WAITOK);
 		bcopy(arg, opt->value, opt->len);
 	}
-	/* TODO: Locking. */
+
+	MNT_ILOCK(vfsp);
 	TAILQ_INSERT_TAIL(vfsp->mnt_opt, opt, link);
+	if (!locked)
+		MNT_IUNLOCK(vfsp);
 }
 
 void
 vfs_clearmntopt(vfs_t *vfsp, const char *name)
 {
+	int locked;
 
-	/* TODO: Locking. */
+	if (!(locked = mtx_owned(MNT_MTX(vfsp))))
+		MNT_ILOCK(vfsp);
 	vfs_deleteopt(vfsp->mnt_opt, name);
+	if (!locked)
+		MNT_IUNLOCK(vfsp);
 }
 
 int
diff --git a/sys/cddl/compat/opensolaris/rpc/xdr.h b/sys/cddl/compat/opensolaris/rpc/xdr.h
index 5802f3f12ba..277e0c338f0 100644
--- a/sys/cddl/compat/opensolaris/rpc/xdr.h
+++ b/sys/cddl/compat/opensolaris/rpc/xdr.h
@@ -1,37 +1,30 @@
 /*
- * CDDL HEADER START
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
  *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
  *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
  *
- * CDDL HEADER END
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
  *
- * $FreeBSD$
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
-/*	  All Rights Reserved  	*/
-
-/*
- * Portions of this source code were derived from Berkeley 4.3 BSD
- * under license from the Regents of the University of California.
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
  */
 
 #ifndef	_OPENSOLARIS_RPC_XDR_H_
@@ -40,73 +33,38 @@
 #include_next 
 
 #ifndef _KERNEL
-#include_next 
+
+#include 
 
 /*
- * Strangely, my glibc version (2.3.6) doesn't have xdr_control(), so
- * we have to hack it in here (source taken from OpenSolaris).
- * By the way, it is assumed the xdrmem implementation is used.
- */
-
-#undef xdr_control
-#define xdr_control(a,b,c) xdrmem_control(a,b,c)
-
-/*
- * These are the request arguments to XDR_CONTROL.
+ * Taken from sys/xdr/xdr_mem.c.
  *
- * XDR_PEEK - returns the contents of the next XDR unit on the XDR stream.
- * XDR_SKIPBYTES - skips the next N bytes in the XDR stream.
- * XDR_RDMAGET - for xdr implementation over RDMA, gets private flags from
- *		 the XDR stream being moved over RDMA
- * XDR_RDMANOCHUNK - for xdr implementaion over RDMA, sets private flags in
- *                   the XDR stream moving over RDMA.
+ * FreeBSD's userland XDR doesn't implement control method (only the kernel),
+ * but OpenSolaris nvpair still depend on it, so we have to implement it here.
  */
-#define XDR_PEEK      2
-#define XDR_SKIPBYTES 3
-#define XDR_RDMAGET   4
-#define XDR_RDMASET   5
-
-/* FIXME: probably doesn't work */
 static __inline bool_t
 xdrmem_control(XDR *xdrs, int request, void *info)
 {
 	xdr_bytesrec *xptr;
-	int32_t *int32p;
-	int len;
 
 	switch (request) {
-
 	case XDR_GET_BYTES_AVAIL:
 		xptr = (xdr_bytesrec *)info;
 		xptr->xc_is_last_record = TRUE;
 		xptr->xc_num_avail = xdrs->x_handy;
 		return (TRUE);
-
-	case XDR_PEEK:
-		/*
-		 * Return the next 4 byte unit in the XDR stream.
-		 */
-		if (xdrs->x_handy < sizeof (int32_t))
-			return (FALSE);
-		int32p = (int32_t *)info;
-		*int32p = (int32_t)ntohl((uint32_t)
-		    (*((int32_t *)(xdrs->x_private))));
-		return (TRUE);
-
-	case XDR_SKIPBYTES:
-		/*
-		 * Skip the next N bytes in the XDR stream.
-		 */
-		int32p = (int32_t *)info;
-		len = RNDUP((int)(*int32p));
-		if ((xdrs->x_handy -= len) < 0)
-			return (FALSE);
-		xdrs->x_private += len;
-		return (TRUE);
-
+	default:
+		assert(!"unexpected request");
 	}
 	return (FALSE);
 }
+
+#undef XDR_CONTROL
+#define	XDR_CONTROL(xdrs, req, op)					\
+	(((xdrs)->x_ops->x_control == NULL) ?				\
+	    xdrmem_control((xdrs), (req), (op)) :			\
+	    (*(xdrs)->x_ops->x_control)(xdrs, req, op))   
+
 #endif	/* !_KERNEL */
 
 #endif	/* !_OPENSOLARIS_RPC_XDR_H_ */
diff --git a/sys/cddl/compat/opensolaris/sys/mutex.h b/sys/cddl/compat/opensolaris/sys/mutex.h
index 8756cd0534f..f6858a7b161 100644
--- a/sys/cddl/compat/opensolaris/sys/mutex.h
+++ b/sys/cddl/compat/opensolaris/sys/mutex.h
@@ -32,9 +32,9 @@
 #ifdef _KERNEL
 
 #include 
-#include 
 #include 
 #include_next 
+#include 
 #include 
 
 typedef enum {
diff --git a/sys/cddl/compat/opensolaris/sys/proc.h b/sys/cddl/compat/opensolaris/sys/proc.h
index 73fbcdadf1d..e0b7bc5758e 100644
--- a/sys/cddl/compat/opensolaris/sys/proc.h
+++ b/sys/cddl/compat/opensolaris/sys/proc.h
@@ -34,13 +34,17 @@
 #include_next 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include 
 
 #ifdef _KERNEL
 
 #define	CPU		curcpu
-#define	minclsyspri	0
-#define	maxclsyspri	0
+#define	minclsyspri	PRIBIO
+#define	maxclsyspri	PVM
 #define	max_ncpus	mp_ncpus
 #define	boot_max_ncpus	mp_ncpus
 
@@ -54,11 +58,13 @@ typedef	struct thread	kthread_t;
 typedef struct thread	*kthread_id_t;
 typedef struct proc	proc_t;
 
+extern struct proc *zfsproc;
+
 static __inline kthread_t *
 thread_create(caddr_t stk, size_t stksize, void (*proc)(void *), void *arg,
     size_t len, proc_t *pp, int state, pri_t pri)
 {
-	proc_t *p;
+	kthread_t *td = NULL;
 	int error;
 
 	/*
@@ -67,13 +73,20 @@ thread_create(caddr_t stk, size_t stksize, void (*proc)(void *), void *arg,
 	ASSERT(stk == NULL);
 	ASSERT(len == 0);
 	ASSERT(state == TS_RUN);
+	ASSERT(pp == &p0);
 
-	error = kproc_create(proc, arg, &p, 0, stksize / PAGE_SIZE,
-	    "solthread %p", proc);
-	return (error == 0 ? FIRST_THREAD_IN_PROC(p) : NULL);
+	error = kproc_kthread_add(proc, arg, &zfsproc, &td, RFSTOPPED,
+	    stksize / PAGE_SIZE, "zfskern", "solthread %p", proc);
+	if (error == 0) {
+		thread_lock(td);
+		sched_prio(td, pri);
+		sched_add(td, SRQ_BORING);
+		thread_unlock(td);
+	}
+	return (td);
 }
 
-#define	thread_exit()	kproc_exit(0)
+#define	thread_exit()	kthread_exit()
 
 #endif	/* _KERNEL */
 
diff --git a/sys/cddl/compat/opensolaris/sys/taskq_impl.h b/sys/cddl/compat/opensolaris/sys/taskq_impl.h
deleted file mode 100644
index a9b59bb755e..00000000000
--- a/sys/cddl/compat/opensolaris/sys/taskq_impl.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- * $FreeBSD$
- */
-/*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SYS_TASKQ_IMPL_H
-#define	_SYS_TASKQ_IMPL_H
-
-#pragma ident	"@(#)taskq_impl.h	1.6	05/06/08 SMI"
-
-#include 
-#include 
-#include 
-#include 
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-typedef struct taskq_bucket taskq_bucket_t;
-
-typedef struct taskq_ent {
-	struct taskq_ent	*tqent_next;
-	struct taskq_ent	*tqent_prev;
-	task_func_t		*tqent_func;
-	void			*tqent_arg;
-	taskq_bucket_t		*tqent_bucket;
-	kthread_t		*tqent_thread;
-	kcondvar_t		tqent_cv;
-} taskq_ent_t;
-
-/*
- * Taskq Statistics fields are not protected by any locks.
- */
-typedef struct tqstat {
-	uint_t		tqs_hits;
-	uint_t		tqs_misses;
-	uint_t		tqs_overflow;	/* no threads to allocate   */
-	uint_t		tqs_tcreates;	/* threads created 	*/
-	uint_t		tqs_tdeaths;	/* threads died		*/
-	uint_t		tqs_maxthreads;	/* max # of alive threads */
-	uint_t		tqs_nomem;	/* # of times there were no memory */
-	uint_t		tqs_disptcreates;
-} tqstat_t;
-
-/*
- * Per-CPU hash bucket manages taskq_bent_t structures using freelist.
- */
-struct taskq_bucket {
-	kmutex_t	tqbucket_lock;
-	taskq_t		*tqbucket_taskq;	/* Enclosing taskq */
-	taskq_ent_t	tqbucket_freelist;
-	uint_t		tqbucket_nalloc;	/* # of allocated entries */
-	uint_t		tqbucket_nfree;		/* # of free entries */
-	kcondvar_t	tqbucket_cv;
-	ushort_t	tqbucket_flags;
-	hrtime_t	tqbucket_totaltime;
-	tqstat_t	tqbucket_stat;
-};
-
-/*
- * Bucket flags.
- */
-#define	TQBUCKET_CLOSE		0x01
-#define	TQBUCKET_SUSPEND	0x02
-
-/*
- * taskq implementation flags: bit range 16-31
- */
-#define	TASKQ_ACTIVE		0x00010000
-#define	TASKQ_SUSPENDED		0x00020000
-#define	TASKQ_NOINSTANCE	0x00040000
-
-struct taskq {
-	char		tq_name[TASKQ_NAMELEN + 1];
-	kmutex_t	tq_lock;
-	krwlock_t	tq_threadlock;
-	kcondvar_t	tq_dispatch_cv;
-	kcondvar_t	tq_wait_cv;
-	uint_t		tq_flags;
-	int		tq_active;
-	int		tq_nthreads;
-	int		tq_nalloc;
-	int		tq_minalloc;
-	int		tq_maxalloc;
-	taskq_ent_t	*tq_freelist;
-	taskq_ent_t	tq_task;
-	int		tq_maxsize;
-	pri_t		tq_pri;		/* Scheduling priority	    */
-	taskq_bucket_t	*tq_buckets;	/* Per-cpu array of buckets */
-	uint_t		tq_nbuckets;	/* # of buckets	(2^n)	    */
-	union {
-		kthread_t *_tq_thread;
-		kthread_t **_tq_threadlist;
-	}		tq_thr;
-	/*
-	 * Statistics.
-	 */
-	hrtime_t	tq_totaltime;	/* Time spent processing tasks */
-	int		tq_tasks;	/* Total # of tasks posted */
-	int		tq_executed;	/* Total # of tasks executed */
-	int		tq_maxtasks;	/* Max number of tasks in the queue */
-	int		tq_tcreates;
-	int		tq_tdeaths;
-};
-
-#define	tq_thread tq_thr._tq_thread
-#define	tq_threadlist tq_thr._tq_threadlist
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_TASKQ_IMPL_H */
diff --git a/sys/cddl/compat/opensolaris/sys/vnode.h b/sys/cddl/compat/opensolaris/sys/vnode.h
index bf11e674ea6..7611a3f8201 100644
--- a/sys/cddl/compat/opensolaris/sys/vnode.h
+++ b/sys/cddl/compat/opensolaris/sys/vnode.h
@@ -75,7 +75,6 @@ vn_is_readonly(vnode_t *vp)
 #define	VN_HOLD(v)	vref(v)
 #define	VN_RELE(v)	vrele(v)
 #define	VN_URELE(v)	vput(v)
-#define	VN_RELE_ASYNC(v, tq)	vn_rele_async(v, tq); 
 
 #define	VOP_REALVP(vp, vpp, ct)	(*(vpp) = (vp), 0)
 
diff --git a/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c b/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c
index e5733344a82..eb824c7ef17 100644
--- a/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c
+++ b/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c
@@ -2523,14 +2523,15 @@ nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
 {
 	if (nvs->nvs_op == NVS_OP_ENCODE) {
 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
-		nvlist_t *packed = (void *)
+		char *packed = (void *)
 		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
 		/*
 		 * Null out the pointer that is meaningless in the packed
 		 * structure. The address may not be aligned, so we have
 		 * to use bzero.
 		 */
-		bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
+		bzero(packed + offsetof(nvlist_t, nvl_priv),
+		    sizeof(((nvlist_t *)NULL)->nvl_priv));
 	}
 
 	return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
index bf613e5adb5..f4e2449f018 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,12 +36,10 @@
  * contributors.
  */
 
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include 
 #include 
 #include 
+#include 
 #include 
 
 /* Extensible attribute (xva) routines. */
@@ -74,15 +72,12 @@ xva_getxoptattr(xvattr_t *xvap)
 	return (xoap);
 }
 
-static STAILQ_HEAD(, vnode) vn_rele_async_list;
-static struct mtx vn_rele_async_lock;
-static struct cv vn_rele_async_cv;
-static int vn_rele_list_length;
-static int vn_rele_async_thread_exit;
+static void
+vn_rele_inactive(vnode_t *vp)
+{
 
-typedef struct  {
-	struct vnode *stqe_next;
-} vnode_link_t;
+	vrele(vp);
+}
 
 /*
  * Like vn_rele() except if we are going to call VOP_INACTIVE() then do it
@@ -95,117 +90,16 @@ typedef struct  {
  * This is because taskqs throttle back allocation if too many are created.
  */
 void
-vn_rele_async(vnode_t *vp, taskq_t *taskq /* unused */)
+vn_rele_async(vnode_t *vp, taskq_t *taskq)
 {
-	
-	KASSERT(vp != NULL, ("vrele: null vp"));
-	VFS_ASSERT_GIANT(vp->v_mount);
+	VERIFY(vp->v_count > 0);
 	VI_LOCK(vp);
-
-	if (vp->v_usecount > 1 || ((vp->v_iflag & VI_DOINGINACT) &&
-	    vp->v_usecount == 1)) {
-		vp->v_usecount--;
-		vdropl(vp);
-		return;
-	}	
-	if (vp->v_usecount != 1) {
-#ifdef DIAGNOSTIC
-		vprint("vrele: negative ref count", vp);
-#endif
+	if (vp->v_count == 1 && !(vp->v_iflag & VI_DOINGINACT)) {
 		VI_UNLOCK(vp);
-		panic("vrele: negative ref cnt");
-	}
-	/*
-	 * We are exiting
-	 */
-	if (vn_rele_async_thread_exit != 0) {
-		vrele(vp);
+		VERIFY(taskq_dispatch((taskq_t *)taskq,
+		    (task_func_t *)vn_rele_inactive, vp, TQ_SLEEP) != 0);
 		return;
 	}
-	
-	mtx_lock(&vn_rele_async_lock);
-
-	/*  STAILQ_INSERT_TAIL 			*/
-	(*(vnode_link_t *)&vp->v_cstart).stqe_next = NULL;
-	*vn_rele_async_list.stqh_last = vp;
-	vn_rele_async_list.stqh_last =
-	    &((vnode_link_t *)&vp->v_cstart)->stqe_next;
-
-	/****************************************/
-	vn_rele_list_length++;
-	if ((vn_rele_list_length % 100) == 0)
-		cv_signal(&vn_rele_async_cv);
-	mtx_unlock(&vn_rele_async_lock);
-	VI_UNLOCK(vp);
+	vp->v_usecount--;
+	vdropl(vp);
 }
-
-static void
-vn_rele_async_init(void *arg)
-{
-
-	mtx_init(&vn_rele_async_lock, "valock", NULL, MTX_DEF);
-	STAILQ_INIT(&vn_rele_async_list);
-
-	/* cv_init(&vn_rele_async_cv, "vacv"); */
-	vn_rele_async_cv.cv_description = "vacv";
-	vn_rele_async_cv.cv_waiters = 0;
-}
-
-void
-vn_rele_async_fini(void)
-{
-
-	mtx_lock(&vn_rele_async_lock);
-	vn_rele_async_thread_exit = 1;
-	cv_signal(&vn_rele_async_cv);
-	while (vn_rele_async_thread_exit != 0)
-		cv_wait(&vn_rele_async_cv, &vn_rele_async_lock);
-	mtx_unlock(&vn_rele_async_lock);
-	mtx_destroy(&vn_rele_async_lock);
-}
-
-
-static void
-vn_rele_async_cleaner(void)
-{
-	STAILQ_HEAD(, vnode) vn_tmp_list;
-	struct vnode *curvnode;
-
-	STAILQ_INIT(&vn_tmp_list);
-	mtx_lock(&vn_rele_async_lock);
-	while (vn_rele_async_thread_exit == 0) {
-		STAILQ_CONCAT(&vn_tmp_list, &vn_rele_async_list);
-		vn_rele_list_length = 0;
-		mtx_unlock(&vn_rele_async_lock);
-		
-		while (!STAILQ_EMPTY(&vn_tmp_list)) {
-			curvnode = STAILQ_FIRST(&vn_tmp_list);
-
-			/*   STAILQ_REMOVE_HEAD */
-			STAILQ_FIRST(&vn_tmp_list) =
-			    ((vnode_link_t *)&curvnode->v_cstart)->stqe_next;
-			if (STAILQ_FIRST(&vn_tmp_list) == NULL)
-				         vn_tmp_list.stqh_last = &STAILQ_FIRST(&vn_tmp_list);
-			/***********************/
-			vrele(curvnode);
-		}
-		mtx_lock(&vn_rele_async_lock);
-		if (vn_rele_list_length == 0)
-			cv_timedwait(&vn_rele_async_cv, &vn_rele_async_lock,
-			    hz/10);
-	}
-
-	vn_rele_async_thread_exit = 0;
-	cv_broadcast(&vn_rele_async_cv);
-	mtx_unlock(&vn_rele_async_lock);
-	thread_exit();
-}
-
-static struct proc *vn_rele_async_proc;
-static struct kproc_desc up_kp = {
-	"vaclean",
-	vn_rele_async_cleaner,
-	&vn_rele_async_proc
-};
-SYSINIT(vaclean, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &up_kp);
-SYSINIT(vn_rele_async_setup, SI_SUB_VFS, SI_ORDER_FIRST, vn_rele_async_init, NULL);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
index df2fc3e01a9..64fded4712e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
@@ -3557,15 +3557,19 @@ arc_init(void)
 	
 #ifdef __i386__
 	if (prefetch_tunable_set == 0) {
-		printf("ZFS NOTICE: prefetch is disabled by default on i386"
-		    " - add enable to tunable to change.\n" );
+		printf("ZFS NOTICE: Prefetch is disabled by default on i386 "
+		    "-- to enable,\n");
+		printf("            add \"vfs.zfs.prefetch_disable=0\" "
+		    "to /boot/loader.conf.\n");
 		zfs_prefetch_disable=1;
 	}
 #else	
 	if ((((uint64_t)physmem * PAGESIZE) < (1ULL << 32)) &&
 	    prefetch_tunable_set == 0) {
-		printf("ZFS NOTICE: system has less than 4GB and prefetch enable is not set"
-		    "... disabling.\n");
+		printf("ZFS NOTICE: Prefetch is disabled by default if less "
+		    "than 4GB of RAM is present;\n"
+		    "            to enable, add \"vfs.zfs.prefetch_disable=0\" "
+		    "to /boot/loader.conf.\n");
 		zfs_prefetch_disable=1;
 	}
 #endif	
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
index 842677bc4e5..377efb9d105 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
@@ -1199,9 +1199,6 @@ dmu_init(void)
 void
 dmu_fini(void)
 {
-#ifdef _KERNEL
-	vn_rele_async_fini();
-#endif
 	arc_fini();
 	dnode_fini();
 	dbuf_fini();
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
index 1294581a713..15bb65d6a44 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -864,10 +864,11 @@ restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
 		/* currently allocated, want to be allocated */
 		dmu_tx_hold_bonus(tx, drro->drr_object);
 		/*
-		 * We may change blocksize, so need to
-		 * hold_write
+		 * We may change blocksize and delete old content,
+		 * so need to hold_write and hold_free.
 		 */
 		dmu_tx_hold_write(tx, drro->drr_object, 0, 1);
+		dmu_tx_hold_free(tx, drro->drr_object, 0, DMU_OBJECT_END);
 		err = dmu_tx_assign(tx, TXG_WAIT);
 		if (err) {
 			dmu_tx_abort(tx);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
index 5adbc3c0ff5..604d52d8bb5 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
@@ -415,7 +415,7 @@ void
 dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
     dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
 {
-	int i, old_nblkptr;
+	int i, nblkptr;
 	dmu_buf_impl_t *db = NULL;
 
 	ASSERT3U(blocksize, >=, SPA_MINBLOCKSIZE);
@@ -445,6 +445,8 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
 		dnode_free_range(dn, 0, -1ULL, tx);
 	}
 
+	nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
+
 	/* change blocksize */
 	rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
 	if (blocksize != dn->dn_datablksz &&
@@ -457,6 +459,8 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
 	dnode_setdirty(dn, tx);
 	dn->dn_next_bonuslen[tx->tx_txg&TXG_MASK] = bonuslen;
 	dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = blocksize;
+	if (dn->dn_nblkptr != nblkptr)
+		dn->dn_next_nblkptr[tx->tx_txg&TXG_MASK] = nblkptr;
 	rw_exit(&dn->dn_struct_rwlock);
 	if (db)
 		dbuf_rele(db, FTAG);
@@ -466,19 +470,15 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
 
 	/* change bonus size and type */
 	mutex_enter(&dn->dn_mtx);
-	old_nblkptr = dn->dn_nblkptr;
 	dn->dn_bonustype = bonustype;
 	dn->dn_bonuslen = bonuslen;
-	dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
+	dn->dn_nblkptr = nblkptr;
 	dn->dn_checksum = ZIO_CHECKSUM_INHERIT;
 	dn->dn_compress = ZIO_COMPRESS_INHERIT;
 	ASSERT3U(dn->dn_nblkptr, <=, DN_MAX_NBLKPTR);
 
-	/* XXX - for now, we can't make nblkptr smaller */
-	ASSERT3U(dn->dn_nblkptr, >=, old_nblkptr);
-
-	/* fix up the bonus db_size if dn_nblkptr has changed */
-	if (dn->dn_bonus && dn->dn_bonuslen != old_nblkptr) {
+	/* fix up the bonus db_size */
+	if (dn->dn_bonus) {
 		dn->dn_bonus->db.db_size =
 		    DN_MAX_BONUSLEN - (dn->dn_nblkptr-1) * sizeof (blkptr_t);
 		ASSERT(dn->dn_bonuslen <= dn->dn_bonus->db.db_size);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
index a46d4e70abc..1b729e391a8 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include 
 #include 
 #include 
@@ -534,18 +532,12 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
 			/* XXX shouldn't the phys already be zeroed? */
 			bzero(dnp, DNODE_CORE_SIZE);
 			dnp->dn_nlevels = 1;
+			dnp->dn_nblkptr = dn->dn_nblkptr;
 		}
 
-		if (dn->dn_nblkptr > dnp->dn_nblkptr) {
-			/* zero the new blkptrs we are gaining */
-			bzero(dnp->dn_blkptr + dnp->dn_nblkptr,
-			    sizeof (blkptr_t) *
-			    (dn->dn_nblkptr - dnp->dn_nblkptr));
-		}
 		dnp->dn_type = dn->dn_type;
 		dnp->dn_bonustype = dn->dn_bonustype;
 		dnp->dn_bonuslen = dn->dn_bonuslen;
-		dnp->dn_nblkptr = dn->dn_nblkptr;
 	}
 
 	ASSERT(dnp->dn_nlevels > 1 ||
@@ -605,6 +597,30 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
 		return;
 	}
 
+	if (dn->dn_next_nblkptr[txgoff]) {
+		/* this should only happen on a realloc */
+		ASSERT(dn->dn_allocated_txg == tx->tx_txg);
+		if (dn->dn_next_nblkptr[txgoff] > dnp->dn_nblkptr) {
+			/* zero the new blkptrs we are gaining */
+			bzero(dnp->dn_blkptr + dnp->dn_nblkptr,
+			    sizeof (blkptr_t) *
+			    (dn->dn_next_nblkptr[txgoff] - dnp->dn_nblkptr));
+#ifdef ZFS_DEBUG
+		} else {
+			int i;
+			ASSERT(dn->dn_next_nblkptr[txgoff] < dnp->dn_nblkptr);
+			/* the blkptrs we are losing better be unallocated */
+			for (i = dn->dn_next_nblkptr[txgoff];
+			    i < dnp->dn_nblkptr; i++)
+				ASSERT(BP_IS_HOLE(&dnp->dn_blkptr[i]));
+#endif
+		}
+		mutex_enter(&dn->dn_mtx);
+		dnp->dn_nblkptr = dn->dn_next_nblkptr[txgoff];
+		dn->dn_next_nblkptr[txgoff] = 0;
+		mutex_exit(&dn->dn_mtx);
+	}
+
 	if (dn->dn_next_nlevels[txgoff]) {
 		dnode_increase_indirection(dn, tx);
 		dn->dn_next_nlevels[txgoff] = 0;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
index 20d8ec85cc9..a27150b093b 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
@@ -1419,6 +1419,7 @@ dsl_dataset_drain_refs(dsl_dataset_t *ds, void *tag)
 {
 	struct refsarg arg;
 
+	bzero(&arg, sizeof(arg));
 	mutex_init(&arg.lock, NULL, MUTEX_DEFAULT, NULL);
 	cv_init(&arg.cv, NULL, CV_DEFAULT, NULL);
 	arg.gone = FALSE;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
index 4585dc805fe..03af3d1583c 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
@@ -91,6 +91,9 @@ dsl_pool_open_impl(spa_t *spa, uint64_t txg)
 	mutex_init(&dp->dp_lock, NULL, MUTEX_DEFAULT, NULL);
 	mutex_init(&dp->dp_scrub_cancel_lock, NULL, MUTEX_DEFAULT, NULL);
 
+	dp->dp_vnrele_taskq = taskq_create("zfs_vn_rele_taskq", 1, minclsyspri,
+	    1, 4, 0);
+
 	return (dp);
 }
 
@@ -228,6 +231,7 @@ dsl_pool_close(dsl_pool_t *dp)
 	rw_destroy(&dp->dp_config_rwlock);
 	mutex_destroy(&dp->dp_lock);
 	mutex_destroy(&dp->dp_scrub_cancel_lock);
+	taskq_destroy(dp->dp_vnrele_taskq);
 	kmem_free(dp, sizeof (dsl_pool_t));
 }
 
@@ -611,3 +615,9 @@ dsl_pool_create_origin(dsl_pool_t *dp, dmu_tx_t *tx)
 	dsl_dataset_rele(ds, FTAG);
 	rw_exit(&dp->dp_config_rwlock);
 }
+
+taskq_t *
+dsl_pool_vnrele_taskq(dsl_pool_t *dp)
+{
+	return (dp->dp_vnrele_taskq);
+}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
index c79ff48a60c..be9e5690832 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -160,6 +160,7 @@ typedef struct dnode {
 	uint16_t dn_datablkszsec;	/* in 512b sectors */
 	uint32_t dn_datablksz;		/* in bytes */
 	uint64_t dn_maxblkid;
+	uint8_t dn_next_nblkptr[TXG_SIZE];
 	uint8_t dn_next_nlevels[TXG_SIZE];
 	uint8_t dn_next_indblkshift[TXG_SIZE];
 	uint16_t dn_next_bonuslen[TXG_SIZE];
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
index 4dd88fe6fa5..dcf5a4414fd 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
@@ -57,6 +57,7 @@ typedef struct dsl_pool {
 	struct dsl_dir *dp_mos_dir;
 	struct dsl_dataset *dp_origin_snap;
 	uint64_t dp_root_dir_obj;
+	struct taskq *dp_vnrele_taskq;
 
 	/* No lock needed - sync context only */
 	blkptr_t dp_meta_rootbp;
@@ -119,6 +120,8 @@ int dsl_pool_scrub_clean(dsl_pool_t *dp);
 void dsl_pool_scrub_sync(dsl_pool_t *dp, dmu_tx_t *tx);
 void dsl_pool_scrub_restart(dsl_pool_t *dp);
 
+taskq_t *dsl_pool_vnrele_taskq(dsl_pool_t *dp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h
index 76fdc0dce7a..0dd8f4f5c50 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h
@@ -49,6 +49,7 @@ extern "C" {
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
index 54ba8bd7105..b4bec95f5fb 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -194,6 +194,10 @@ vdev_geom_worker(void *arg)
 	zio_t *zio;
 	struct bio *bp;
 
+	thread_lock(curthread);
+	sched_prio(curthread, PRIBIO);
+	thread_unlock(curthread);
+
 	ctx = arg;
 	for (;;) {
 		mtx_lock(&ctx->gc_queue_mtx);
@@ -203,7 +207,7 @@ vdev_geom_worker(void *arg)
 				ctx->gc_state = 2;
 				wakeup_one(&ctx->gc_state);
 				mtx_unlock(&ctx->gc_queue_mtx);
-				kproc_exit(0);
+				kthread_exit();
 			}
 			msleep(&ctx->gc_queue, &ctx->gc_queue_mtx,
 			    PRIBIO | PDROP, "vgeom:io", 0);
@@ -530,8 +534,8 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
 	vd->vdev_tsd = ctx;
 	pp = cp->provider;
 
-	kproc_create(vdev_geom_worker, ctx, NULL, 0, 0, "vdev:worker %s",
-	    pp->name);
+	kproc_kthread_add(vdev_geom_worker, ctx, &zfsproc, NULL, 0, 0,
+	    "zfskern", "vdev %s", pp->name);
 
 	/*
 	 * Determine the actual size of the device.
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
index eef1d21bb97..e845a99ab87 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
@@ -669,9 +669,12 @@ zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr,
 	if (sep) {
 		avl_remove(&sdp->sd_snaps, sep);
 		err = zfsctl_unmount_snap(sep, MS_FORCE, cr);
-		if (err)
-			avl_add(&sdp->sd_snaps, sep);
-		else
+		if (err) {
+			avl_index_t where;
+
+			if (avl_find(&sdp->sd_snaps, sep, &where) == NULL)
+				avl_insert(&sdp->sd_snaps, sep, where);
+		} else
 			err = dmu_objset_destroy(snapname);
 	} else {
 		err = ENOENT;
@@ -879,9 +882,25 @@ domount:
 	    dvp->v_vfsp->mnt_stat.f_mntonname, nm);
 	err = domount(curthread, *vpp, "zfs", mountpoint, snapname, 0);
 	kmem_free(mountpoint, mountpoint_len);
-	/* FreeBSD: This line was moved from below to avoid a lock recursion. */
-	if (err == 0)
-		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
+	if (err == 0) {
+		vnode_t *mvp;
+
+		ASSERT((*vpp)->v_mountedhere != NULL);
+		err = VFS_ROOT((*vpp)->v_mountedhere, LK_EXCLUSIVE, &mvp);
+		ASSERT(err == 0);
+		VN_RELE(*vpp);
+		*vpp = mvp;
+
+		/*
+		 * Fix up the root vnode mounted on .zfs/snapshot/.
+		 *
+		 * This is where we lie about our v_vfsp in order to
+		 * make .zfs/snapshot/ accessible over NFS
+		 * without requiring manual mounts of .
+		 */
+		ASSERT(VTOZ(*vpp)->z_zfsvfs != zfsvfs);
+		VTOZ(*vpp)->z_zfsvfs->z_parent = zfsvfs;
+	}
 	mutex_exit(&sdp->sd_lock);
 	/*
 	 * If we had an error, drop our hold on the vnode and
@@ -1195,6 +1214,48 @@ zfsctl_snapshot_lookup(ap)
 	return (error);
 }
 
+static int
+zfsctl_snapshot_vptocnp(struct vop_vptocnp_args *ap)
+{
+	zfsvfs_t *zfsvfs = ap->a_vp->v_vfsp->vfs_data;
+	vnode_t *dvp, *vp;
+	zfsctl_snapdir_t *sdp;
+	zfs_snapentry_t *sep;
+	int error;
+
+	ASSERT(zfsvfs->z_ctldir != NULL);
+	error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp,
+	    NULL, 0, NULL, kcred, NULL, NULL, NULL);
+	if (error != 0)
+		return (error);
+	sdp = dvp->v_data;
+
+	mutex_enter(&sdp->sd_lock);
+	sep = avl_first(&sdp->sd_snaps);
+	while (sep != NULL) {
+		vp = sep->se_root;
+		if (vp == ap->a_vp)
+			break;
+		sep = AVL_NEXT(&sdp->sd_snaps, sep);
+	}
+	if (sep == NULL) {
+		mutex_exit(&sdp->sd_lock);
+		error = ENOENT;
+	} else {
+		size_t len;
+
+		len = strlen(sep->se_name);
+		*ap->a_buflen -= len;
+		bcopy(sep->se_name, ap->a_buf + *ap->a_buflen, len);
+		mutex_exit(&sdp->sd_lock);
+		vhold(dvp);
+		*ap->a_vpp = dvp;
+	}
+	VN_RELE(dvp);
+
+	return (error);
+}
+
 /*
  * These VP's should never see the light of day.  They should always
  * be covered.
@@ -1206,6 +1267,7 @@ static struct vop_vector zfsctl_ops_snapshot = {
 	.vop_reclaim =	zfsctl_common_reclaim,
 	.vop_getattr =	zfsctl_snapshot_getattr,
 	.vop_fid =	zfsctl_snapshot_fid,
+	.vop_vptocnp =	zfsctl_snapshot_vptocnp,
 };
 
 int
@@ -1301,7 +1363,17 @@ zfsctl_umount_snapshots(vfs_t *vfsp, int fflags, cred_t *cr)
 		if (vn_ismntpt(sep->se_root)) {
 			error = zfsctl_unmount_snap(sep, fflags, cr);
 			if (error) {
-				avl_add(&sdp->sd_snaps, sep);
+				avl_index_t where;
+
+				/*
+				 * Before reinserting snapshot to the tree,
+				 * check if it was actually removed. For example
+				 * when snapshot mount point is busy, we will
+				 * have an error here, but there will be no need
+				 * to reinsert snapshot.
+				 */
+				if (avl_find(&sdp->sd_snaps, sep, &where) == NULL)
+					avl_insert(&sdp->sd_snaps, sep, where);
 				break;
 			}
 		}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index f2c6e76dca8..e25f5494e68 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -3021,8 +3021,10 @@ zfsdev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
 	if (error == 0)
 		error = zfs_ioc_vec[vec].zvec_func(zc);
 
-	if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE)
-		zfs_log_history(zc);
+	if (error == 0) {
+		if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE)
+			zfs_log_history(zc);
+	}
 
 	return (error);
 }
@@ -3056,44 +3058,36 @@ zfsdev_fini(void)
 		destroy_dev(zfsdev);
 }
 
-static struct task zfs_start_task;
 static struct root_hold_token *zfs_root_token;
-
+struct proc *zfsproc;
 
 uint_t zfs_fsyncer_key;
 extern uint_t rrw_tsd_key;
 
-static void
-zfs_start(void *context __unused, int pending __unused)
-{
-
-	zfsdev_init();
-	spa_init(FREAD | FWRITE);
-	zfs_init();
-	zvol_init();
-
-	tsd_create(&zfs_fsyncer_key, NULL);
-	tsd_create(&rrw_tsd_key, NULL);
-
-	printf("ZFS storage pool version " SPA_VERSION_STRING "\n");
-	root_mount_rel(zfs_root_token);
-}
-
 static int
 zfs_modevent(module_t mod, int type, void *unused __unused)
 {
-	int error;
+	int error = 0;
 
-	error = EOPNOTSUPP;
 	switch (type) {
 	case MOD_LOAD:
 		zfs_root_token = root_mount_hold("ZFS");
 		printf("WARNING: ZFS is considered to be an experimental "
 		    "feature in FreeBSD.\n");
-		TASK_INIT(&zfs_start_task, 0, zfs_start, NULL);
-		taskqueue_enqueue(taskqueue_thread, &zfs_start_task);
+
 		mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
-		error = 0;
+
+		spa_init(FREAD | FWRITE);
+		zfs_init();
+		zvol_init();
+
+		tsd_create(&zfs_fsyncer_key, NULL);
+		tsd_create(&rrw_tsd_key, NULL);
+
+		printf("ZFS storage pool version " SPA_VERSION_STRING "\n");
+		root_mount_rel(zfs_root_token);
+
+		zfsdev_init();
 		break;
 	case MOD_UNLOAD:
 		if (spa_busy() || zfs_busy() || zvol_busy() ||
@@ -3101,14 +3095,19 @@ zfs_modevent(module_t mod, int type, void *unused __unused)
 			error = EBUSY;
 			break;
 		}
+
+		zfsdev_fini();
 		zvol_fini();
 		zfs_fini();
 		spa_fini();
-		zfsdev_fini();
+
 		tsd_destroy(&zfs_fsyncer_key);
 		tsd_destroy(&rrw_tsd_key);
+
 		mutex_destroy(&zfs_share_lock);
-		error = 0;
+		break;
+	default:
+		error = EOPNOTSUPP;
 		break;
 	}
 	return (error);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
index a2bf4608d46..86d9cc8c481 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -97,6 +97,8 @@ static int zfs_root(vfs_t *vfsp, int flags, vnode_t **vpp);
 static int zfs_statfs(vfs_t *vfsp, struct statfs *statp);
 static int zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp);
 static int zfs_sync(vfs_t *vfsp, int waitfor);
+static int zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp,
+    struct ucred **credanonp, int *numsecflavors, int **secflavors);
 static int zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp);
 static void zfs_objset_close(zfsvfs_t *zfsvfs);
 static void zfs_freevfs(vfs_t *vfsp);
@@ -108,6 +110,7 @@ static struct vfsops zfs_vfsops = {
 	.vfs_statfs =		zfs_statfs,
 	.vfs_vget =		zfs_vget,
 	.vfs_sync =		zfs_sync,
+	.vfs_checkexp =		zfs_checkexp,
 	.vfs_fhtovp =		zfs_fhtovp,
 };
 
@@ -336,6 +339,13 @@ zfs_register_callbacks(vfs_t *vfsp)
 	ASSERT(zfsvfs);
 	os = zfsvfs->z_os;
 
+	/*
+	 * This function can be called for a snapshot when we update snapshot's
+	 * mount point, which isn't really supported.
+	 */
+	if (dmu_objset_is_snapshot(os))
+		return (EOPNOTSUPP);
+
 	/*
 	 * The act of registering our callbacks will destroy any mount
 	 * options we may have.  In order to enable temporary overrides
@@ -719,7 +729,10 @@ zfs_mount(vfs_t *vfsp)
 	error = secpolicy_fs_mount(cr, mvp, vfsp);
 	if (error) {
 		error = dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr);
-		if (error == 0) {
+		if (error != 0)
+			goto out;
+
+		if (!(vfsp->vfs_flag & MS_REMOUNT)) {
 			vattr_t		vattr;
 
 			/*
@@ -729,7 +742,9 @@ zfs_mount(vfs_t *vfsp)
 
 			vattr.va_mask = AT_UID;
 
+			vn_lock(mvp, LK_SHARED | LK_RETRY);
 			if (error = VOP_GETATTR(mvp, &vattr, cr)) {
+				VOP_UNLOCK(mvp, 0);
 				goto out;
 			}
 
@@ -741,18 +756,19 @@ zfs_mount(vfs_t *vfsp)
 			}
 #else
 			if (error = secpolicy_vnode_owner(mvp, cr, vattr.va_uid)) {
+				VOP_UNLOCK(mvp, 0);
 				goto out;
 			}
 
 			if (error = VOP_ACCESS(mvp, VWRITE, cr, td)) {
+				VOP_UNLOCK(mvp, 0);
 				goto out;
 			}
+			VOP_UNLOCK(mvp, 0);
 #endif
-
-			secpolicy_fs_mount_clearopts(cr, vfsp);
-		} else {
-			goto out;
 		}
+
+		secpolicy_fs_mount_clearopts(cr, vfsp);
 	}
 
 	/*
@@ -917,7 +933,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
 	for (zp = list_head(&zfsvfs->z_all_znodes); zp != NULL;
 	    zp = list_next(&zfsvfs->z_all_znodes, zp))
 		if (zp->z_dbuf) {
-			ASSERT(ZTOV(zp)->v_count > 0);
+			ASSERT(ZTOV(zp)->v_count >= 0);
 			zfs_znode_dmu_fini(zp);
 		}
 	mutex_exit(&zfsvfs->z_znodes_lock);
@@ -1102,6 +1118,26 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp)
 	return (err);
 }
 
+static int
+zfs_checkexp(vfs_t *vfsp, struct sockaddr *nam, int *extflagsp,
+    struct ucred **credanonp, int *numsecflavors, int **secflavors)
+{
+	zfsvfs_t *zfsvfs = vfsp->vfs_data;
+
+	/*
+	 * If this is regular file system vfsp is the same as
+	 * zfsvfs->z_parent->z_vfs, but if it is snapshot,
+	 * zfsvfs->z_parent->z_vfs represents parent file system
+	 * which we have to use here, because only this file system
+	 * has mnt_export configured.
+	 */
+	vfsp = zfsvfs->z_parent->z_vfs;
+
+	return (vfs_stdcheckexp(zfsvfs->z_parent->z_vfs, nam, extflagsp,
+	    credanonp, numsecflavors, secflavors));
+}
+
+
 static int
 zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp)
 {
@@ -1117,6 +1153,11 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp)
 
 	ZFS_ENTER(zfsvfs);
 
+	/*
+	 * On FreeBSD we are already called with snapshot's mount point
+	 * and not the mount point of its parent.
+	 */
+#ifndef __FreeBSD__
 	if (fidp->fid_len == LONG_FID_LEN) {
 		zfid_long_t	*zlfid = (zfid_long_t *)fidp;
 		uint64_t	objsetid = 0;
@@ -1135,6 +1176,7 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp)
 			return (EINVAL);
 		ZFS_ENTER(zfsvfs);
 	}
+#endif
 
 	if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) {
 		zfid_short_t	*zfid = (zfid_short_t *)fidp;
@@ -1160,9 +1202,8 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp)
 		} else {
 			VN_HOLD(*vpp);
 		}
-		ZFS_EXIT(zfsvfs);
-		/* XXX: LK_RETRY? */
 		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
+		ZFS_EXIT(zfsvfs);
 		return (0);
 	}
 
@@ -1184,7 +1225,6 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, vnode_t **vpp)
 	}
 
 	*vpp = ZTOV(zp);
-	/* XXX: LK_RETRY? */
 	vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
 	vnode_create_vobject(*vpp, zp->z_phys->zp_size, curthread);
 	ZFS_EXIT(zfsvfs);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index 8e2f337a7da..c533f6faaff 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -924,6 +924,7 @@ zfs_get_done(dmu_buf_t *db, void *vzgd)
 	zgd_t *zgd = (zgd_t *)vzgd;
 	rl_t *rl = zgd->zgd_rl;
 	vnode_t *vp = ZTOV(rl->r_zp);
+	objset_t *os = rl->r_zp->z_zfsvfs->z_os;
 	int vfslocked;
 
 	vfslocked = VFS_LOCK_GIANT(vp->v_vfsp);
@@ -933,7 +934,7 @@ zfs_get_done(dmu_buf_t *db, void *vzgd)
 	 * Release the vnode asynchronously as we currently have the
 	 * txg stopped from syncing.
 	 */
-	VN_RELE_ASYNC(vp, NULL);
+	VN_RELE_ASYNC(vp, dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
 	zil_add_block(zgd->zgd_zilog, zgd->zgd_bp);
 	kmem_free(zgd, sizeof (zgd_t));
 	VFS_UNLOCK_GIANT(vfslocked);
@@ -968,8 +969,8 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
 		 * Release the vnode asynchronously as we currently have the
 		 * txg stopped from syncing.
 		 */
-		VN_RELE_ASYNC(ZTOV(zp), NULL);
-
+		VN_RELE_ASYNC(ZTOV(zp),
+		    dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
 		return (ENOENT);
 	}
 
@@ -1045,7 +1046,7 @@ out:
 	 * Release the vnode asynchronously as we currently have the
 	 * txg stopped from syncing.
 	 */
-	VN_RELE_ASYNC(ZTOV(zp), NULL);
+	VN_RELE_ASYNC(ZTOV(zp), dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
 	return (error);
 }
 
@@ -3709,12 +3710,11 @@ zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
 		 * The fs has been unmounted, or we did a
 		 * suspend/resume and this file no longer exists.
 		 */
-		mutex_enter(&zp->z_lock);
 		VI_LOCK(vp);
 		vp->v_count = 0; /* count arrives as 1 */
-		mutex_exit(&zp->z_lock);
+		VI_UNLOCK(vp);
+		vrecycle(vp, curthread);
 		rw_exit(&zfsvfs->z_teardown_inactive_lock);
-		zfs_znode_free(zp);
 		return;
 	}
 
@@ -3834,7 +3834,15 @@ zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
 #endif
 
 	case _PC_ACL_EXTENDED:
-		*valp = 0;	/* TODO */
+		*valp = 0;
+		return (0);
+
+	case _PC_ACL_NFS4:
+		*valp = 1;
+		return (0);
+
+	case _PC_ACL_PATH_MAX:
+		*valp = ACL_MAX_ENTRIES;
 		return (0);
 
 	case _PC_MIN_HOLE_SIZE:
@@ -4351,7 +4359,6 @@ zfs_freebsd_reclaim(ap)
 {
 	vnode_t	*vp = ap->a_vp;
 	znode_t	*zp = VTOZ(vp);
-	zfsvfs_t *zfsvfs;
 
 	ASSERT(zp != NULL);
 
@@ -4361,13 +4368,18 @@ zfs_freebsd_reclaim(ap)
 	vnode_destroy_vobject(vp);
 
 	mutex_enter(&zp->z_lock);
-	ASSERT(zp->z_phys);
+	ASSERT(zp->z_phys != NULL);
 	ZTOV(zp) = NULL;
-	if (!zp->z_unlinked) {
+	mutex_exit(&zp->z_lock);
+
+	if (zp->z_unlinked)
+		;	/* Do nothing. */
+	else if (zp->z_dbuf == NULL)
+		zfs_znode_free(zp);
+	else /* if (!zp->z_unlinked && zp->z_dbuf != NULL) */ {
+		zfsvfs_t *zfsvfs = zp->z_zfsvfs;
 		int locked;
 
-		zfsvfs = zp->z_zfsvfs;
-		mutex_exit(&zp->z_lock);
 		locked = MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id)) ? 2 :
 		    ZFS_OBJ_HOLD_TRYENTER(zfsvfs, zp->z_id);
 		if (locked == 0) {
@@ -4383,8 +4395,6 @@ zfs_freebsd_reclaim(ap)
 				ZFS_OBJ_HOLD_EXIT(zfsvfs, zp->z_id);
 			zfs_znode_free(zp);
 		}
-	} else {
-		mutex_exit(&zp->z_lock);
 	}
 	VI_LOCK(vp);
 	vp->v_data = NULL;
@@ -4423,6 +4433,26 @@ zfs_freebsd_pathconf(ap)
 	return (error);
 }
 
+static int
+zfs_freebsd_fifo_pathconf(ap)
+	struct vop_pathconf_args /* {
+		struct vnode *a_vp;
+		int a_name;
+		register_t *a_retval;
+	} */ *ap;
+{
+
+	switch (ap->a_name) {
+	case _PC_ACL_EXTENDED:
+	case _PC_ACL_NFS4:
+	case _PC_ACL_PATH_MAX:
+	case _PC_MAC_PRESENT:
+		return (zfs_freebsd_pathconf(ap));
+	default:
+		return (fifo_specops.vop_pathconf(ap));
+	}
+}
+
 /*
  * FreeBSD's extended attributes namespace defines file name prefix for ZFS'
  * extended attribute name:
@@ -4528,9 +4558,9 @@ vop_getextattr {
 	vp = nd.ni_vp;
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	if (error != 0) {
+		ZFS_EXIT(zfsvfs);
 		if (error == ENOENT)
 			error = ENOATTR;
-		ZFS_EXIT(zfsvfs);
 		return (error);
 	}
 
@@ -4596,9 +4626,9 @@ vop_deleteextattr {
 	vp = nd.ni_vp;
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	if (error != 0) {
+		ZFS_EXIT(zfsvfs);
 		if (error == ENOENT)
 			error = ENOATTR;
-		ZFS_EXIT(zfsvfs);
 		return (error);
 	}
 	error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
@@ -4711,7 +4741,7 @@ vop_listextattr {
 
 	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
 	    ap->a_cred, ap->a_td, VREAD);
-	if (error)
+	if (error != 0)
 		return (error);
 
 	error = zfs_create_attrname(ap->a_attrnamespace, "", attrprefix,
@@ -4728,13 +4758,13 @@ vop_listextattr {
 	error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td,
 	    LOOKUP_XATTR);
 	if (error != 0) {
+		ZFS_EXIT(zfsvfs);
 		/*
 		 * ENOATTR means that the EA directory does not yet exist,
 		 * i.e. there are no extended attributes there.
 		 */
 		if (error == ENOATTR)
 			error = 0;
-		ZFS_EXIT(zfsvfs);
 		return (error);
 	}
 
@@ -4824,10 +4854,10 @@ zfs_freebsd_getacl(ap)
 		return (error);
 
 	error = acl_from_aces(ap->a_aclp, vsecattr.vsa_aclentp, vsecattr.vsa_aclcnt);
-        if (vsecattr.vsa_aclentp != NULL)
-                kmem_free(vsecattr.vsa_aclentp, vsecattr.vsa_aclentsz);
+	if (vsecattr.vsa_aclentp != NULL)
+		kmem_free(vsecattr.vsa_aclentp, vsecattr.vsa_aclentsz);
 
-        return (error);
+	return (error);
 }
 
 int
@@ -4852,7 +4882,7 @@ zfs_freebsd_setacl(ap)
 		return (EINVAL);
 
 	/*
-	 * With NFS4 ACLs, chmod(2) may need to add additional entries,
+	 * With NFSv4 ACLs, chmod(2) may need to add additional entries,
 	 * splitting every entry into two and appending "canonical six"
 	 * entries at the end.  Don't allow for setting an ACL that would
 	 * cause chmod(2) to run out of ACL entries.
@@ -4926,11 +4956,9 @@ struct vop_vector zfs_vnodeops = {
 	.vop_deleteextattr =	zfs_deleteextattr,
 	.vop_setextattr =	zfs_setextattr,
 	.vop_listextattr =	zfs_listextattr,
-#ifdef notyet
 	.vop_getacl =		zfs_freebsd_getacl,
 	.vop_setacl =		zfs_freebsd_setacl,
 	.vop_aclcheck =		zfs_freebsd_aclcheck,
-#endif
 };
 
 struct vop_vector zfs_fifoops = {
@@ -4943,10 +4971,9 @@ struct vop_vector zfs_fifoops = {
 	.vop_reclaim =		zfs_freebsd_reclaim,
 	.vop_setattr =		zfs_freebsd_setattr,
 	.vop_write =		VOP_PANIC,
+	.vop_pathconf = 	zfs_freebsd_fifo_pathconf,
 	.vop_fid =		zfs_freebsd_fid,
-#ifdef notyet
 	.vop_getacl =		zfs_freebsd_getacl,
 	.vop_setacl =		zfs_freebsd_setacl,
 	.vop_aclcheck =		zfs_freebsd_aclcheck,
-#endif
 };
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
index db0ebf29b7c..e9b00cbbb68 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
@@ -153,7 +153,22 @@ static int zvol_dump_init(zvol_state_t *zv, boolean_t resize);
 static void
 zvol_size_changed(zvol_state_t *zv, major_t maj)
 {
+	struct g_provider *pp;
 
+	g_topology_assert();
+
+	pp = zv->zv_provider;
+	if (pp == NULL)
+		return;
+	if (zv->zv_volsize == pp->mediasize)
+		return;
+	/*
+	 * Changing provider size is not really supported by GEOM, but it
+	 * should be safe when provider is closed.
+	 */
+	if (zv->zv_total_opens > 0)
+		return;
+	pp->mediasize = zv->zv_volsize;
 }
 
 int
@@ -263,6 +278,7 @@ zvol_access(struct g_provider *pp, int acr, int acw, int ace)
 	}
 
 	zv->zv_total_opens += acr + acw + ace;
+	zvol_size_changed(zv, 0);
 
 	mutex_exit(&zvol_state_lock);
 
@@ -402,6 +418,10 @@ zvol_worker(void *arg)
 	zvol_state_t *zv;
 	struct bio *bp;
 
+	thread_lock(curthread);
+	sched_prio(curthread, PRIBIO);
+	thread_unlock(curthread);
+
 	zv = arg;
 	for (;;) {
 		mtx_lock(&zv->zv_queue_mtx);
@@ -411,7 +431,7 @@ zvol_worker(void *arg)
 				zv->zv_state = 2;
 				wakeup(&zv->zv_state);
 				mtx_unlock(&zv->zv_queue_mtx);
-				kproc_exit(0);
+				kthread_exit();
 			}
 			msleep(&zv->zv_queue, &zv->zv_queue_mtx, PRIBIO | PDROP,
 			    "zvol:io", 0);
@@ -824,7 +844,8 @@ zvol_create_minor(const char *name, major_t maj)
 	bioq_init(&zv->zv_queue);
 	mtx_init(&zv->zv_queue_mtx, "zvol", NULL, MTX_DEF);
 	zv->zv_state = 0;
-	kproc_create(zvol_worker, zv, NULL, 0, 0, "zvol:worker %s", pp->name);
+	kproc_kthread_add(zvol_worker, zv, &zfsproc, NULL, 0, 0, "zfskern",
+	    "zvol %s", pp->name + strlen(ZVOL_DEV_DIR) + 1);
 
 	zvol_minors++;
 end:
@@ -1067,11 +1088,6 @@ zvol_set_volblocksize(const char *name, uint64_t volblocksize)
 		if (error == ENOTSUP)
 			error = EBUSY;
 		dmu_tx_commit(tx);
-		/* XXX: Not supported. */
-#if 0
-		if (error == 0)
-			zv->zv_provider->sectorsize = zc->zc_volblocksize;
-#endif
 	}
 end:
 	mutex_exit(&zvol_state_lock);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/os/taskq.c b/sys/cddl/contrib/opensolaris/uts/common/os/taskq.c
deleted file mode 100644
index 154ead4b8c2..00000000000
--- a/sys/cddl/contrib/opensolaris/uts/common/os/taskq.c
+++ /dev/null
@@ -1,1041 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * Kernel task queues: general-purpose asynchronous task scheduling.
- *
- * A common problem in kernel programming is the need to schedule tasks
- * to be performed later, by another thread. There are several reasons
- * you may want or need to do this:
- *
- * (1) The task isn't time-critical, but your current code path is.
- *
- * (2) The task may require grabbing locks that you already hold.
- *
- * (3) The task may need to block (e.g. to wait for memory), but you
- *     cannot block in your current context.
- *
- * (4) Your code path can't complete because of some condition, but you can't
- *     sleep or fail, so you queue the task for later execution when condition
- *     disappears.
- *
- * (5) You just want a simple way to launch multiple tasks in parallel.
- *
- * Task queues provide such a facility. In its simplest form (used when
- * performance is not a critical consideration) a task queue consists of a
- * single list of tasks, together with one or more threads to service the
- * list. There are some cases when this simple queue is not sufficient:
- *
- * (1) The task queues are very hot and there is a need to avoid data and lock
- *	contention over global resources.
- *
- * (2) Some tasks may depend on other tasks to complete, so they can't be put in
- *	the same list managed by the same thread.
- *
- * (3) Some tasks may block for a long time, and this should not block other
- * 	tasks in the queue.
- *
- * To provide useful service in such cases we define a "dynamic task queue"
- * which has an individual thread for each of the tasks. These threads are
- * dynamically created as they are needed and destroyed when they are not in
- * use. The API for managing task pools is the same as for managing task queues
- * with the exception of a taskq creation flag TASKQ_DYNAMIC which tells that
- * dynamic task pool behavior is desired.
- *
- * Dynamic task queues may also place tasks in the normal queue (called "backing
- * queue") when task pool runs out of resources. Users of task queues may
- * disallow such queued scheduling by specifying TQ_NOQUEUE in the dispatch
- * flags.
- *
- * The backing task queue is also used for scheduling internal tasks needed for
- * dynamic task queue maintenance.
- *
- * INTERFACES:
- *
- * taskq_t *taskq_create(name, nthreads, pri_t pri, minalloc, maxall, flags);
- *
- *	Create a taskq with specified properties.
- *	Possible 'flags':
- *
- *	  TASKQ_DYNAMIC: Create task pool for task management. If this flag is
- * 		specified, 'nthreads' specifies the maximum number of threads in
- *		the task queue. Task execution order for dynamic task queues is
- *		not predictable.
- *
- *		If this flag is not specified (default case) a
- * 		single-list task queue is created with 'nthreads' threads
- * 		servicing it. Entries in this queue are managed by
- * 		taskq_ent_alloc() and taskq_ent_free() which try to keep the
- * 		task population between 'minalloc' and 'maxalloc', but the
- *		latter limit is only advisory for TQ_SLEEP dispatches and the
- *		former limit is only advisory for TQ_NOALLOC dispatches. If
- *		TASKQ_PREPOPULATE is set in 'flags', the taskq will be
- *		prepopulated with 'minalloc' task structures.
- *
- *		Since non-DYNAMIC taskqs are queues, tasks are guaranteed to be
- *		executed in the order they are scheduled if nthreads == 1.
- *		If nthreads > 1, task execution order is not predictable.
- *
- *	  TASKQ_PREPOPULATE: Prepopulate task queue with threads.
- *		Also prepopulate the task queue with 'minalloc' task structures.
- *
- *	  TASKQ_CPR_SAFE: This flag specifies that users of the task queue will
- * 		use their own protocol for handling CPR issues. This flag is not
- *		supported for DYNAMIC task queues.
- *
- *	The 'pri' field specifies the default priority for the threads that
- *	service all scheduled tasks.
- *
- * void taskq_destroy(tap):
- *
- *	Waits for any scheduled tasks to complete, then destroys the taskq.
- *	Caller should guarantee that no new tasks are scheduled in the closing
- *	taskq.
- *
- * taskqid_t taskq_dispatch(tq, func, arg, flags):
- *
- *	Dispatches the task "func(arg)" to taskq. The 'flags' indicates whether
- *	the caller is willing to block for memory.  The function returns an
- *	opaque value which is zero iff dispatch fails.  If flags is TQ_NOSLEEP
- *	or TQ_NOALLOC and the task can't be dispatched, taskq_dispatch() fails
- *	and returns (taskqid_t)0.
- *
- *	ASSUMES: func != NULL.
- *
- *	Possible flags:
- *	  TQ_NOSLEEP: Do not wait for resources; may fail.
- *
- *	  TQ_NOALLOC: Do not allocate memory; may fail.  May only be used with
- *		non-dynamic task queues.
- *
- *	  TQ_NOQUEUE: Do not enqueue a task if it can't dispatch it due to
- *		lack of available resources and fail. If this flag is not
- * 		set, and the task pool is exhausted, the task may be scheduled
- *		in the backing queue. This flag may ONLY be used with dynamic
- *		task queues.
- *
- *		NOTE: This flag should always be used when a task queue is used
- *		for tasks that may depend on each other for completion.
- *		Enqueueing dependent tasks may create deadlocks.
- *
- *	  TQ_SLEEP:   May block waiting for resources. May still fail for
- * 		dynamic task queues if TQ_NOQUEUE is also specified, otherwise
- *		always succeed.
- *
- *	NOTE: Dynamic task queues are much more likely to fail in
- *		taskq_dispatch() (especially if TQ_NOQUEUE was specified), so it
- *		is important to have backup strategies handling such failures.
- *
- * void taskq_wait(tq):
- *
- *	Waits for all previously scheduled tasks to complete.
- *
- *	NOTE: It does not stop any new task dispatches.
- *	      Do NOT call taskq_wait() from a task: it will cause deadlock.
- *
- * void taskq_suspend(tq)
- *
- *	Suspend all task execution. Tasks already scheduled for a dynamic task
- *	queue will still be executed, but all new scheduled tasks will be
- *	suspended until taskq_resume() is called.
- *
- * int  taskq_suspended(tq)
- *
- *	Returns 1 if taskq is suspended and 0 otherwise. It is intended to
- *	ASSERT that the task queue is suspended.
- *
- * void taskq_resume(tq)
- *
- *	Resume task queue execution.
- *
- * int  taskq_member(tq, thread)
- *
- *	Returns 1 if 'thread' belongs to taskq 'tq' and 0 otherwise. The
- *	intended use is to ASSERT that a given function is called in taskq
- *	context only.
- *
- * system_taskq
- *
- *	Global system-wide dynamic task queue for common uses. It may be used by
- *	any subsystem that needs to schedule tasks and does not need to manage
- *	its own task queues. It is initialized quite early during system boot.
- *
- * IMPLEMENTATION.
- *
- * This is schematic representation of the task queue structures.
- *
- *   taskq:
- *   +-------------+
- *   |tq_lock      | +---< taskq_ent_free()
- *   +-------------+ |
- *   |...          | | tqent:                  tqent:
- *   +-------------+ | +------------+          +------------+
- *   | tq_freelist |-->| tqent_next |--> ... ->| tqent_next |
- *   +-------------+   +------------+          +------------+
- *   |...          |   | ...        |          | ...        |
- *   +-------------+   +------------+          +------------+
- *   | tq_task     |    |
- *   |             |    +-------------->taskq_ent_alloc()
- * +--------------------------------------------------------------------------+
- * | |                     |            tqent                   tqent         |
- * | +---------------------+     +--> +------------+     +--> +------------+  |
- * | | ...		   |     |    | func, arg  |     |    | func, arg  |  |
- * +>+---------------------+ <---|-+  +------------+ <---|-+  +------------+  |
- *   | tq_taskq.tqent_next | ----+ |  | tqent_next | --->+ |  | tqent_next |--+
- *   +---------------------+	   |  +------------+     ^ |  +------------+
- * +-| tq_task.tqent_prev  |	   +--| tqent_prev |     | +--| tqent_prev |  ^
- * | +---------------------+	      +------------+     |    +------------+  |
- * | |...		   |	      | ...        |     |    | ...        |  |
- * | +---------------------+	      +------------+     |    +------------+  |
- * |                                      ^              |                    |
- * |                                      |              |                    |
- * +--------------------------------------+--------------+       TQ_APPEND() -+
- *   |             |                      |
- *   |...          |   taskq_thread()-----+
- *   +-------------+
- *   | tq_buckets  |--+-------> [ NULL ] (for regular task queues)
- *   +-------------+  |
- *                    |   DYNAMIC TASK QUEUES:
- *                    |
- *                    +-> taskq_bucket[nCPU]       	taskq_bucket_dispatch()
- *                        +-------------------+                    ^
- *                   +--->| tqbucket_lock     |                    |
- *                   |    +-------------------+   +--------+      +--------+
- *                   |    | tqbucket_freelist |-->| tqent  |-->...| tqent  | ^
- *                   |    +-------------------+<--+--------+<--...+--------+ |
- *                   |    | ...               |   | thread |      | thread | |
- *                   |    +-------------------+   +--------+      +--------+ |
- *                   |    +-------------------+                              |
- * taskq_dispatch()--+--->| tqbucket_lock     |             TQ_APPEND()------+
- *      TQ_HASH()    |    +-------------------+   +--------+      +--------+
- *                   |    | tqbucket_freelist |-->| tqent  |-->...| tqent  |
- *                   |    +-------------------+<--+--------+<--...+--------+
- *                   |    | ...               |   | thread |      | thread |
- *                   |    +-------------------+   +--------+      +--------+
- *		     +---> 	...
- *
- *
- * Task queues use tq_task field to link new entry in the queue. The queue is a
- * circular doubly-linked list. Entries are put in the end of the list with
- * TQ_APPEND() and processed from the front of the list by taskq_thread() in
- * FIFO order. Task queue entries are cached in the free list managed by
- * taskq_ent_alloc() and taskq_ent_free() functions.
- *
- *	All threads used by task queues mark t_taskq field of the thread to
- *	point to the task queue.
- *
- * Dynamic Task Queues Implementation.
- *
- * For a dynamic task queues there is a 1-to-1 mapping between a thread and
- * taskq_ent_structure. Each entry is serviced by its own thread and each thread
- * is controlled by a single entry.
- *
- * Entries are distributed over a set of buckets. To avoid using modulo
- * arithmetics the number of buckets is 2^n and is determined as the nearest
- * power of two roundown of the number of CPUs in the system. Tunable
- * variable 'taskq_maxbuckets' limits the maximum number of buckets. Each entry
- * is attached to a bucket for its lifetime and can't migrate to other buckets.
- *
- * Entries that have scheduled tasks are not placed in any list. The dispatch
- * function sets their "func" and "arg" fields and signals the corresponding
- * thread to execute the task. Once the thread executes the task it clears the
- * "func" field and places an entry on the bucket cache of free entries pointed
- * by "tqbucket_freelist" field. ALL entries on the free list should have "func"
- * field equal to NULL. The free list is a circular doubly-linked list identical
- * in structure to the tq_task list above, but entries are taken from it in LIFO
- * order - the last freed entry is the first to be allocated. The
- * taskq_bucket_dispatch() function gets the most recently used entry from the
- * free list, sets its "func" and "arg" fields and signals a worker thread.
- *
- * After executing each task a per-entry thread taskq_d_thread() places its
- * entry on the bucket free list and goes to a timed sleep. If it wakes up
- * without getting new task it removes the entry from the free list and destroys
- * itself. The thread sleep time is controlled by a tunable variable
- * `taskq_thread_timeout'.
- *
- * There is various statistics kept in the bucket which allows for later
- * analysis of taskq usage patterns. Also, a global copy of taskq creation and
- * death statistics is kept in the global taskq data structure. Since thread
- * creation and death happen rarely, updating such global data does not present
- * a performance problem.
- *
- * NOTE: Threads are not bound to any CPU and there is absolutely no association
- *       between the bucket and actual thread CPU, so buckets are used only to
- *	 split resources and reduce resource contention. Having threads attached
- *	 to the CPU denoted by a bucket may reduce number of times the job
- *	 switches between CPUs.
- *
- *	 Current algorithm creates a thread whenever a bucket has no free
- *	 entries. It would be nice to know how many threads are in the running
- *	 state and don't create threads if all CPUs are busy with existing
- *	 tasks, but it is unclear how such strategy can be implemented.
- *
- *	 Currently buckets are created statically as an array attached to task
- *	 queue. On some system with nCPUs < max_ncpus it may waste system
- *	 memory. One solution may be allocation of buckets when they are first
- *	 touched, but it is not clear how useful it is.
- *
- * SUSPEND/RESUME implementation.
- *
- *	Before executing a task taskq_thread() (executing non-dynamic task
- *	queues) obtains taskq's thread lock as a reader. The taskq_suspend()
- *	function gets the same lock as a writer blocking all non-dynamic task
- *	execution. The taskq_resume() function releases the lock allowing
- *	taskq_thread to continue execution.
- *
- *	For dynamic task queues, each bucket is marked as TQBUCKET_SUSPEND by
- *	taskq_suspend() function. After that taskq_bucket_dispatch() always
- *	fails, so that taskq_dispatch() will either enqueue tasks for a
- *	suspended backing queue or fail if TQ_NOQUEUE is specified in dispatch
- *	flags.
- *
- *	NOTE: taskq_suspend() does not immediately block any tasks already
- *	      scheduled for dynamic task queues. It only suspends new tasks
- *	      scheduled after taskq_suspend() was called.
- *
- *	taskq_member() function works by comparing a thread t_taskq pointer with
- *	the passed thread pointer.
- *
- * LOCKS and LOCK Hierarchy:
- *
- *   There are two locks used in task queues.
- *
- *   1) Task queue structure has a lock, protecting global task queue state.
- *
- *   2) Each per-CPU bucket has a lock for bucket management.
- *
- *   If both locks are needed, task queue lock should be taken only after bucket
- *   lock.
- *
- * DEBUG FACILITIES.
- *
- * For DEBUG kernels it is possible to induce random failures to
- * taskq_dispatch() function when it is given TQ_NOSLEEP argument. The value of
- * taskq_dmtbf and taskq_smtbf tunables control the mean time between induced
- * failures for dynamic and static task queues respectively.
- *
- * Setting TASKQ_STATISTIC to 0 will disable per-bucket statistics.
- *
- * TUNABLES
- *
- *	system_taskq_size	- Size of the global system_taskq.
- *				  This value is multiplied by nCPUs to determine
- *				  actual size.
- *				  Default value: 64
- *
- *	taskq_thread_timeout	- Maximum idle time for taskq_d_thread()
- *				  Default value: 5 minutes
- *
- *	taskq_maxbuckets	- Maximum number of buckets in any task queue
- *				  Default value: 128
- *
- *	taskq_search_depth	- Maximum # of buckets searched for a free entry
- *				  Default value: 4
- *
- *	taskq_dmtbf		- Mean time between induced dispatch failures
- *				  for dynamic task queues.
- *				  Default value: UINT_MAX (no induced failures)
- *
- *	taskq_smtbf		- Mean time between induced dispatch failures
- *				  for static task queues.
- *				  Default value: UINT_MAX (no induced failures)
- *
- * CONDITIONAL compilation.
- *
- *    TASKQ_STATISTIC	- If set will enable bucket statistic (default).
- *
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-static kmem_cache_t *taskq_ent_cache, *taskq_cache;
-
-/* Global system task queue for common use */
-taskq_t *system_taskq;
-
-/*
- * Maxmimum number of entries in global system taskq is
- *      system_taskq_size * max_ncpus
- */
-#define SYSTEM_TASKQ_SIZE 1
-int system_taskq_size = SYSTEM_TASKQ_SIZE;
-
-/*
- * Dynamic task queue threads that don't get any work within
- * taskq_thread_timeout destroy themselves
- */
-#define	TASKQ_THREAD_TIMEOUT (60 * 5)
-int taskq_thread_timeout = TASKQ_THREAD_TIMEOUT;
-
-#define	TASKQ_MAXBUCKETS 128
-int taskq_maxbuckets = TASKQ_MAXBUCKETS;
-
-/*
- * When a bucket has no available entries another buckets are tried.
- * taskq_search_depth parameter limits the amount of buckets that we search
- * before failing. This is mostly useful in systems with many CPUs where we may
- * spend too much time scanning busy buckets.
- */
-#define	TASKQ_SEARCH_DEPTH 4
-int taskq_search_depth = TASKQ_SEARCH_DEPTH;
-
-/*
- * Hashing function: mix various bits of x. May be pretty much anything.
- */
-#define	TQ_HASH(x) ((x) ^ ((x) >> 11) ^ ((x) >> 17) ^ ((x) ^ 27))
-
-/*
- * We do not create any new threads when the system is low on memory and start
- * throttling memory allocations. The following macro tries to estimate such
- * condition.
- */
-#define	ENOUGH_MEMORY() (freemem > throttlefree)
-
-/*
- * Static functions.
- */
-static taskq_t	*taskq_create_common(const char *, int, int, pri_t, int,
-    int, uint_t);
-static void taskq_thread(void *);
-static int  taskq_constructor(void *, void *, int);
-static void taskq_destructor(void *, void *);
-static int  taskq_ent_constructor(void *, void *, int);
-static void taskq_ent_destructor(void *, void *);
-static taskq_ent_t *taskq_ent_alloc(taskq_t *, int);
-static void taskq_ent_free(taskq_t *, taskq_ent_t *);
-
-/*
- * Collect per-bucket statistic when TASKQ_STATISTIC is defined.
- */
-#define	TASKQ_STATISTIC 1
-
-#if TASKQ_STATISTIC
-#define	TQ_STAT(b, x)	b->tqbucket_stat.x++
-#else
-#define	TQ_STAT(b, x)
-#endif
-
-/*
- * Random fault injection.
- */
-uint_t taskq_random;
-uint_t taskq_dmtbf = UINT_MAX;    /* mean time between injected failures */
-uint_t taskq_smtbf = UINT_MAX;    /* mean time between injected failures */
-
-/*
- * TQ_NOSLEEP dispatches on dynamic task queues are always allowed to fail.
- *
- * TQ_NOSLEEP dispatches on static task queues can't arbitrarily fail because
- * they could prepopulate the cache and make sure that they do not use more
- * then minalloc entries.  So, fault injection in this case insures that
- * either TASKQ_PREPOPULATE is not set or there are more entries allocated
- * than is specified by minalloc.  TQ_NOALLOC dispatches are always allowed
- * to fail, but for simplicity we treat them identically to TQ_NOSLEEP
- * dispatches.
- */
-#ifdef DEBUG
-#define	TASKQ_D_RANDOM_DISPATCH_FAILURE(tq, flag)		\
-	taskq_random = (taskq_random * 2416 + 374441) % 1771875;\
-	if ((flag & TQ_NOSLEEP) &&				\
-	    taskq_random < 1771875 / taskq_dmtbf) {		\
-		return (NULL);					\
-	}
-
-#define	TASKQ_S_RANDOM_DISPATCH_FAILURE(tq, flag)		\
-	taskq_random = (taskq_random * 2416 + 374441) % 1771875;\
-	if ((flag & (TQ_NOSLEEP | TQ_NOALLOC)) &&		\
-	    (!(tq->tq_flags & TASKQ_PREPOPULATE) ||		\
-	    (tq->tq_nalloc > tq->tq_minalloc)) &&		\
-	    (taskq_random < (1771875 / taskq_smtbf))) {		\
-		mutex_exit(&tq->tq_lock);			\
-		return ((taskqid_t)0);				\
-	}
-#else
-#define	TASKQ_S_RANDOM_DISPATCH_FAILURE(tq, flag)
-#define	TASKQ_D_RANDOM_DISPATCH_FAILURE(tq, flag)
-#endif
-
-#define	IS_EMPTY(l) (((l).tqent_prev == (l).tqent_next) &&	\
-	((l).tqent_prev == &(l)))
-
-/*
- * Append `tqe' in the end of the doubly-linked list denoted by l.
- */
-#define	TQ_APPEND(l, tqe) {					\
-	tqe->tqent_next = &l;					\
-	tqe->tqent_prev = l.tqent_prev;				\
-	tqe->tqent_next->tqent_prev = tqe;			\
-	tqe->tqent_prev->tqent_next = tqe;			\
-}
-
-/*
- * Schedule a task specified by func and arg into the task queue entry tqe.
- */
-#define	TQ_ENQUEUE(tq, tqe, func, arg) {			\
-	ASSERT(MUTEX_HELD(&tq->tq_lock));			\
-	TQ_APPEND(tq->tq_task, tqe);				\
-	tqe->tqent_func = (func);				\
-	tqe->tqent_arg = (arg);					\
-	tq->tq_tasks++;						\
-	if (tq->tq_tasks - tq->tq_executed > tq->tq_maxtasks)	\
-		tq->tq_maxtasks = tq->tq_tasks - tq->tq_executed;	\
-	cv_signal(&tq->tq_dispatch_cv);				\
-	DTRACE_PROBE2(taskq__enqueue, taskq_t *, tq, taskq_ent_t *, tqe); \
-}
-
-/*
- * Do-nothing task which may be used to prepopulate thread caches.
- */
-/*ARGSUSED*/
-void
-nulltask(void *unused)
-{
-}
-
-
-/*ARGSUSED*/
-static int
-taskq_constructor(void *buf, void *cdrarg, int kmflags)
-{
-	taskq_t *tq = buf;
-
-	bzero(tq, sizeof (taskq_t));
-
-	mutex_init(&tq->tq_lock, NULL, MUTEX_DEFAULT, NULL);
-	rw_init(&tq->tq_threadlock, NULL, RW_DEFAULT, NULL);
-	cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL);
-	cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL);
-
-	tq->tq_task.tqent_next = &tq->tq_task;
-	tq->tq_task.tqent_prev = &tq->tq_task;
-
-	return (0);
-}
-
-/*ARGSUSED*/
-static void
-taskq_destructor(void *buf, void *cdrarg)
-{
-	taskq_t *tq = buf;
-
-	mutex_destroy(&tq->tq_lock);
-	rw_destroy(&tq->tq_threadlock);
-	cv_destroy(&tq->tq_dispatch_cv);
-	cv_destroy(&tq->tq_wait_cv);
-}
-
-/*ARGSUSED*/
-static int
-taskq_ent_constructor(void *buf, void *cdrarg, int kmflags)
-{
-	taskq_ent_t *tqe = buf;
-
-	tqe->tqent_thread = NULL;
-	cv_init(&tqe->tqent_cv, NULL, CV_DEFAULT, NULL);
-
-	return (0);
-}
-
-/*ARGSUSED*/
-static void
-taskq_ent_destructor(void *buf, void *cdrarg)
-{
-	taskq_ent_t *tqe = buf;
-
-	ASSERT(tqe->tqent_thread == NULL);
-	cv_destroy(&tqe->tqent_cv);
-}
-
-/*
- * Create global system dynamic task queue.
- */
-void
-system_taskq_init(void)
-{
-	system_taskq = taskq_create_common("system_taskq", 0,
-	    system_taskq_size * max_ncpus, minclsyspri, 4, 512,
-	    TASKQ_PREPOPULATE);
-}
-
-void
-system_taskq_fini(void)
-{
-	taskq_destroy(system_taskq);
-}
-
-static void
-taskq_init(void *dummy __unused)
-{
-	taskq_ent_cache = kmem_cache_create("taskq_ent_cache",
-	    sizeof (taskq_ent_t), 0, taskq_ent_constructor,
-	    taskq_ent_destructor, NULL, NULL, NULL, 0);
-	taskq_cache = kmem_cache_create("taskq_cache", sizeof (taskq_t),
-	    0, taskq_constructor, taskq_destructor, NULL, NULL, NULL, 0);
-	system_taskq_init();
-}
-
-static void
-taskq_fini(void *dummy __unused)
-{
-	system_taskq_fini();
-	kmem_cache_destroy(taskq_cache);
-	kmem_cache_destroy(taskq_ent_cache);
-}
-
-/*
- * taskq_ent_alloc()
- *
- * Allocates a new taskq_ent_t structure either from the free list or from the
- * cache. Returns NULL if it can't be allocated.
- *
- * Assumes: tq->tq_lock is held.
- */
-static taskq_ent_t *
-taskq_ent_alloc(taskq_t *tq, int flags)
-{
-	int kmflags = (flags & TQ_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;
-
-	taskq_ent_t *tqe;
-
-	ASSERT(MUTEX_HELD(&tq->tq_lock));
-
-	/*
-	 * TQ_NOALLOC allocations are allowed to use the freelist, even if
-	 * we are below tq_minalloc.
-	 */
-	if ((tqe = tq->tq_freelist) != NULL &&
-	    ((flags & TQ_NOALLOC) || tq->tq_nalloc >= tq->tq_minalloc)) {
-		tq->tq_freelist = tqe->tqent_next;
-	} else {
-		if (flags & TQ_NOALLOC)
-			return (NULL);
-
-		mutex_exit(&tq->tq_lock);
-		if (tq->tq_nalloc >= tq->tq_maxalloc) {
-			if (kmflags & KM_NOSLEEP) {
-				mutex_enter(&tq->tq_lock);
-				return (NULL);
-			}
-			/*
-			 * We don't want to exceed tq_maxalloc, but we can't
-			 * wait for other tasks to complete (and thus free up
-			 * task structures) without risking deadlock with
-			 * the caller.  So, we just delay for one second
-			 * to throttle the allocation rate.
-			 */
-			delay(hz);
-		}
-		tqe = kmem_cache_alloc(taskq_ent_cache, kmflags);
-		mutex_enter(&tq->tq_lock);
-		if (tqe != NULL)
-			tq->tq_nalloc++;
-	}
-	return (tqe);
-}
-
-/*
- * taskq_ent_free()
- *
- * Free taskq_ent_t structure by either putting it on the free list or freeing
- * it to the cache.
- *
- * Assumes: tq->tq_lock is held.
- */
-static void
-taskq_ent_free(taskq_t *tq, taskq_ent_t *tqe)
-{
-	ASSERT(MUTEX_HELD(&tq->tq_lock));
-
-	if (tq->tq_nalloc <= tq->tq_minalloc) {
-		tqe->tqent_next = tq->tq_freelist;
-		tq->tq_freelist = tqe;
-	} else {
-		tq->tq_nalloc--;
-		mutex_exit(&tq->tq_lock);
-		kmem_cache_free(taskq_ent_cache, tqe);
-		mutex_enter(&tq->tq_lock);
-	}
-}
-
-/*
- * Dispatch a task.
- *
- * Assumes: func != NULL
- *
- * Returns: NULL if dispatch failed.
- *	    non-NULL if task dispatched successfully.
- *	    Actual return value is the pointer to taskq entry that was used to
- *	    dispatch a task. This is useful for debugging.
- */
-/* ARGSUSED */
-taskqid_t
-taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
-{
-	taskq_ent_t *tqe = NULL;
-
-	ASSERT(tq != NULL);
-	ASSERT(func != NULL);
-	ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC));
-
-	/*
-	 * TQ_NOQUEUE flag can't be used with non-dynamic task queues.
-	 */
-	ASSERT(! (flags & TQ_NOQUEUE));
-
-	/*
-	 * Enqueue the task to the underlying queue.
-	 */
-	mutex_enter(&tq->tq_lock);
-
-	TASKQ_S_RANDOM_DISPATCH_FAILURE(tq, flags);
-
-	if ((tqe = taskq_ent_alloc(tq, flags)) == NULL) {
-		mutex_exit(&tq->tq_lock);
-		return ((taskqid_t)NULL);
-	}
-	TQ_ENQUEUE(tq, tqe, func, arg);
-	mutex_exit(&tq->tq_lock);
-	return ((taskqid_t)tqe);
-}
-
-/*
- * Wait for all pending tasks to complete.
- * Calling taskq_wait from a task will cause deadlock.
- */
-void
-taskq_wait(taskq_t *tq)
-{
-
-	mutex_enter(&tq->tq_lock);
-	while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0)
-		cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
-	mutex_exit(&tq->tq_lock);
-}
-
-/*
- * Suspend execution of tasks.
- *
- * Tasks in the queue part will be suspended immediately upon return from this
- * function. Pending tasks in the dynamic part will continue to execute, but all
- * new tasks will  be suspended.
- */
-void
-taskq_suspend(taskq_t *tq)
-{
-	rw_enter(&tq->tq_threadlock, RW_WRITER);
-
-	/*
-	 * Mark task queue as being suspended. Needed for taskq_suspended().
-	 */
-	mutex_enter(&tq->tq_lock);
-	ASSERT(!(tq->tq_flags & TASKQ_SUSPENDED));
-	tq->tq_flags |= TASKQ_SUSPENDED;
-	mutex_exit(&tq->tq_lock);
-}
-
-/*
- * returns: 1 if tq is suspended, 0 otherwise.
- */
-int
-taskq_suspended(taskq_t *tq)
-{
-	return ((tq->tq_flags & TASKQ_SUSPENDED) != 0);
-}
-
-/*
- * Resume taskq execution.
- */
-void
-taskq_resume(taskq_t *tq)
-{
-	ASSERT(RW_WRITE_HELD(&tq->tq_threadlock));
-
-	mutex_enter(&tq->tq_lock);
-	ASSERT(tq->tq_flags & TASKQ_SUSPENDED);
-	tq->tq_flags &= ~TASKQ_SUSPENDED;
-	mutex_exit(&tq->tq_lock);
-
-	rw_exit(&tq->tq_threadlock);
-}
-
-
-int
-taskq_member(taskq_t *tq, kthread_t *thread)
-{
-	if (tq->tq_nthreads == 1)
-		return (tq->tq_thread == thread);
-	else {
-		int i, found = 0;
-
-		mutex_enter(&tq->tq_lock);
-		for (i = 0; i < tq->tq_nthreads; i++) {
-			if (tq->tq_threadlist[i] == thread) {
-				found = 1;
-				break;
-			}
-		}
-		mutex_exit(&tq->tq_lock);
-		return (found);
-	}
-}
-
-/*
- * Worker thread for processing task queue.
- */
-static void
-taskq_thread(void *arg)
-{
-	taskq_t *tq = arg;
-	taskq_ent_t *tqe;
-	callb_cpr_t cprinfo;
-	hrtime_t start, end;
-
-	CALLB_CPR_INIT(&cprinfo, &tq->tq_lock, callb_generic_cpr, tq->tq_name);
-
-	mutex_enter(&tq->tq_lock);
-	while (tq->tq_flags & TASKQ_ACTIVE) {
-		if ((tqe = tq->tq_task.tqent_next) == &tq->tq_task) {
-			if (--tq->tq_active == 0)
-				cv_broadcast(&tq->tq_wait_cv);
-			if (tq->tq_flags & TASKQ_CPR_SAFE) {
-				cv_wait(&tq->tq_dispatch_cv, &tq->tq_lock);
-			} else {
-				CALLB_CPR_SAFE_BEGIN(&cprinfo);
-				cv_wait(&tq->tq_dispatch_cv, &tq->tq_lock);
-				CALLB_CPR_SAFE_END(&cprinfo, &tq->tq_lock);
-			}
-			tq->tq_active++;
-			continue;
-		}
-		tqe->tqent_prev->tqent_next = tqe->tqent_next;
-		tqe->tqent_next->tqent_prev = tqe->tqent_prev;
-		mutex_exit(&tq->tq_lock);
-
-		rw_enter(&tq->tq_threadlock, RW_READER);
-		start = gethrtime();
-		DTRACE_PROBE2(taskq__exec__start, taskq_t *, tq,
-		    taskq_ent_t *, tqe);
-		tqe->tqent_func(tqe->tqent_arg);
-		DTRACE_PROBE2(taskq__exec__end, taskq_t *, tq,
-		    taskq_ent_t *, tqe);
-		end = gethrtime();
-		rw_exit(&tq->tq_threadlock);
-
-		mutex_enter(&tq->tq_lock);
-		tq->tq_totaltime += end - start;
-		tq->tq_executed++;
-
-		taskq_ent_free(tq, tqe);
-	}
-	tq->tq_nthreads--;
-	cv_broadcast(&tq->tq_wait_cv);
-	ASSERT(!(tq->tq_flags & TASKQ_CPR_SAFE));
-	CALLB_CPR_EXIT(&cprinfo);
-	thread_exit();
-}
-
-/*
- * Taskq creation. May sleep for memory.
- * Always use automatically generated instances to avoid kstat name space
- * collisions.
- */
-
-taskq_t *
-taskq_create(const char *name, int nthreads, pri_t pri, int minalloc,
-    int maxalloc, uint_t flags)
-{
-	return taskq_create_common(name, 0, nthreads, pri, minalloc,
-	    maxalloc, flags | TASKQ_NOINSTANCE);
-}
-
-static taskq_t *
-taskq_create_common(const char *name, int instance, int nthreads, pri_t pri,
-    int minalloc, int maxalloc, uint_t flags)
-{
-	taskq_t *tq = kmem_cache_alloc(taskq_cache, KM_SLEEP);
-	uint_t ncpus = ((boot_max_ncpus == -1) ? max_ncpus : boot_max_ncpus);
-	uint_t bsize;	/* # of buckets - always power of 2 */
-
-	ASSERT(instance == 0);
-	ASSERT(flags == TASKQ_PREPOPULATE | TASKQ_NOINSTANCE);
-
-	/*
-	 * TASKQ_CPR_SAFE and TASKQ_DYNAMIC flags are mutually exclusive.
-	 */
-	ASSERT((flags & (TASKQ_DYNAMIC | TASKQ_CPR_SAFE)) !=
-	    ((TASKQ_DYNAMIC | TASKQ_CPR_SAFE)));
-
-	ASSERT(tq->tq_buckets == NULL);
-
-	bsize = 1 << (highbit(ncpus) - 1);
-	ASSERT(bsize >= 1);
-	bsize = MIN(bsize, taskq_maxbuckets);
-
-	tq->tq_maxsize = nthreads;
-
-	(void) strncpy(tq->tq_name, name, TASKQ_NAMELEN + 1);
-	tq->tq_name[TASKQ_NAMELEN] = '\0';
-	/* Make sure the name conforms to the rules for C indentifiers */
-	strident_canon(tq->tq_name, TASKQ_NAMELEN);
-
-	tq->tq_flags = flags | TASKQ_ACTIVE;
-	tq->tq_active = nthreads;
-	tq->tq_nthreads = nthreads;
-	tq->tq_minalloc = minalloc;
-	tq->tq_maxalloc = maxalloc;
-	tq->tq_nbuckets = bsize;
-	tq->tq_pri = pri;
-
-	if (flags & TASKQ_PREPOPULATE) {
-		mutex_enter(&tq->tq_lock);
-		while (minalloc-- > 0)
-			taskq_ent_free(tq, taskq_ent_alloc(tq, TQ_SLEEP));
-		mutex_exit(&tq->tq_lock);
-	}
-
-	if (nthreads == 1) {
-		tq->tq_thread = thread_create(NULL, 0, taskq_thread, tq,
-		    0, NULL, TS_RUN, pri);
-	} else {
-		kthread_t **tpp = kmem_alloc(sizeof (kthread_t *) * nthreads,
-		    KM_SLEEP);
-
-		tq->tq_threadlist = tpp;
-
-		mutex_enter(&tq->tq_lock);
-		while (nthreads-- > 0) {
-			*tpp = thread_create(NULL, 0, taskq_thread, tq,
-			    0, NULL, TS_RUN, pri);
-			tpp++;
-		}
-		mutex_exit(&tq->tq_lock);
-	}
-
-	return (tq);
-}
-
-/*
- * taskq_destroy().
- *
- * Assumes: by the time taskq_destroy is called no one will use this task queue
- * in any way and no one will try to dispatch entries in it.
- */
-void
-taskq_destroy(taskq_t *tq)
-{
-	taskq_bucket_t *b = tq->tq_buckets;
-	int bid = 0;
-
-	ASSERT(! (tq->tq_flags & TASKQ_CPR_SAFE));
-
-	/*
-	 * Wait for any pending entries to complete.
-	 */
-	taskq_wait(tq);
-
-	mutex_enter(&tq->tq_lock);
-	ASSERT((tq->tq_task.tqent_next == &tq->tq_task) &&
-	    (tq->tq_active == 0));
-
-	if ((tq->tq_nthreads > 1) && (tq->tq_threadlist != NULL))
-		kmem_free(tq->tq_threadlist, sizeof (kthread_t *) *
-		    tq->tq_nthreads);
-
-	tq->tq_flags &= ~TASKQ_ACTIVE;
-	cv_broadcast(&tq->tq_dispatch_cv);
-	while (tq->tq_nthreads != 0)
-		cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
-
-	tq->tq_minalloc = 0;
-	while (tq->tq_nalloc != 0)
-		taskq_ent_free(tq, taskq_ent_alloc(tq, TQ_SLEEP));
-
-	mutex_exit(&tq->tq_lock);
-
-	/*
-	 * Mark each bucket as closing and wakeup all sleeping threads.
-	 */
-	for (; (b != NULL) && (bid < tq->tq_nbuckets); b++, bid++) {
-		taskq_ent_t *tqe;
-
-		mutex_enter(&b->tqbucket_lock);
-
-		b->tqbucket_flags |= TQBUCKET_CLOSE;
-		/* Wakeup all sleeping threads */
-
-		for (tqe = b->tqbucket_freelist.tqent_next;
-		    tqe != &b->tqbucket_freelist; tqe = tqe->tqent_next)
-			cv_signal(&tqe->tqent_cv);
-
-		ASSERT(b->tqbucket_nalloc == 0);
-
-		/*
-		 * At this point we waited for all pending jobs to complete (in
-		 * both the task queue and the bucket and no new jobs should
-		 * arrive. Wait for all threads to die.
-		 */
-		while (b->tqbucket_nfree > 0)
-			cv_wait(&b->tqbucket_cv, &b->tqbucket_lock);
-		mutex_exit(&b->tqbucket_lock);
-		mutex_destroy(&b->tqbucket_lock);
-		cv_destroy(&b->tqbucket_cv);
-	}
-
-	if (tq->tq_buckets != NULL) {
-		ASSERT(tq->tq_flags & TASKQ_DYNAMIC);
-		kmem_free(tq->tq_buckets,
-		    sizeof (taskq_bucket_t) * tq->tq_nbuckets);
-
-		/* Cleanup fields before returning tq to the cache */
-		tq->tq_buckets = NULL;
-		tq->tq_tcreates = 0;
-		tq->tq_tdeaths = 0;
-	} else {
-		ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC));
-	}
-
-	tq->tq_totaltime = 0;
-	tq->tq_tasks = 0;
-	tq->tq_maxtasks = 0;
-	tq->tq_executed = 0;
-	kmem_cache_free(taskq_cache, tq);
-}
-
-SYSINIT(sol_taskq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, taskq_init, NULL);
-SYSUNINIT(sol_taskq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, taskq_fini, NULL);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr.c b/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr.c
deleted file mode 100644
index b38833afb54..00000000000
--- a/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
-/*	  All Rights Reserved  	*/
-
-/*
- * Portions of this source code were derived from Berkeley 4.3 BSD
- * under license from the Regents of the University of California.
- */
-
-/*
- * xdr.c, generic XDR routines implementation.
- * These are the "generic" xdr routines used to serialize and de-serialize
- * most common data items.  See xdr.h for more info on the interface to
- * xdr.
- */
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#pragma weak xdr_int32_t = xdr_int
-#pragma weak xdr_uint32_t = xdr_u_int
-#pragma weak xdr_int64_t = xdr_longlong_t
-#pragma weak xdr_uint64_t = xdr_u_longlong_t
-
-#if defined(sun)
-#if !defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
-#error "Exactly one of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined"
-#elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
-#error "Only one of _BIG_ENDIAN or _LITTLE_ENDIAN may be defined"
-#endif
-#endif
-
-/*
- * constants specific to the xdr "protocol"
- */
-#define	XDR_FALSE	((int32_t)0)
-#define	XDR_TRUE	((int32_t)1)
-#define	LASTUNSIGNED	((uint_t)0-1)
-
-/*
- * for unit alignment
- */
-static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
-
-/*
- * Free a data structure using XDR
- * Not a filter, but a convenient utility nonetheless
- */
-void
-xdr_free(xdrproc_t proc, char *objp)
-{
-	XDR x;
-
-	x.x_op = XDR_FREE;
-	(*proc)(&x, objp);
-}
-
-/*
- * XDR nothing
- */
-bool_t
-xdr_void(void)
-{
-	return (TRUE);
-}
-
-/*
- * XDR integers
- *
- * PSARC 2003/523 Contract Private Interface
- * xdr_int
- * Changes must be reviewed by Solaris File Sharing
- * Changes must be communicated to contract-2003-523@sun.com
- */
-bool_t
-xdr_int(XDR *xdrs, int *ip)
-{
-	if (xdrs->x_op == XDR_ENCODE)
-		return (XDR_PUTINT32(xdrs, ip));
-
-	if (xdrs->x_op == XDR_DECODE)
-		return (XDR_GETINT32(xdrs, ip));
-
-	if (xdrs->x_op == XDR_FREE)
-		return (TRUE);
-
-	return (FALSE);
-}
-
-/*
- * XDR unsigned integers
- *
- * PSARC 2003/523 Contract Private Interface
- * xdr_u_int
- * Changes must be reviewed by Solaris File Sharing
- * Changes must be communicated to contract-2003-523@sun.com
- */
-bool_t
-xdr_u_int(XDR *xdrs, uint_t *up)
-{
-	if (xdrs->x_op == XDR_ENCODE)
-		return (XDR_PUTINT32(xdrs, (int32_t *)up));
-
-	if (xdrs->x_op == XDR_DECODE)
-		return (XDR_GETINT32(xdrs, (int32_t *)up));
-
-	if (xdrs->x_op == XDR_FREE)
-		return (TRUE);
-
-	return (FALSE);
-}
-
-
-#if defined(_ILP32)
-/*
- * xdr_long and xdr_u_long for binary compatability on ILP32 kernels.
- *
- * No prototypes since new code should not be using these interfaces.
- */
-bool_t
-xdr_long(XDR *xdrs, long *ip)
-{
-	return (xdr_int(xdrs, (int *)ip));
-}
-
-bool_t
-xdr_u_long(XDR *xdrs, unsigned long *up)
-{
-	return (xdr_u_int(xdrs, (uint_t *)up));
-}
-#endif /* _ILP32 */
-
-
-/*
- * XDR long long integers
- */
-bool_t
-xdr_longlong_t(XDR *xdrs, longlong_t *hp)
-{
-	if (xdrs->x_op == XDR_ENCODE) {
-#if BYTE_ORDER == _LITTLE_ENDIAN
-		if (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
-		    BYTES_PER_XDR_UNIT)) == TRUE) {
-			return (XDR_PUTINT32(xdrs, (int32_t *)hp));
-		}
-#else
-		if (XDR_PUTINT32(xdrs, (int32_t *)hp) == TRUE) {
-			return (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
-			    BYTES_PER_XDR_UNIT)));
-		}
-#endif
-		return (FALSE);
-
-	}
-	if (xdrs->x_op == XDR_DECODE) {
-#if BYTE_ORDER == _LITTLE_ENDIAN
-		if (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
-		    BYTES_PER_XDR_UNIT)) == TRUE) {
-			return (XDR_GETINT32(xdrs, (int32_t *)hp));
-		}
-#else
-		if (XDR_GETINT32(xdrs, (int32_t *)hp) == TRUE) {
-			return (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
-			    BYTES_PER_XDR_UNIT)));
-		}
-#endif
-		return (FALSE);
-	}
-	return (TRUE);
-}
-
-/*
- * XDR unsigned long long integers
- */
-bool_t
-xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp)
-{
-
-	if (xdrs->x_op == XDR_ENCODE) {
-#if BYTE_ORDER == _LITTLE_ENDIAN
-		if (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
-		    BYTES_PER_XDR_UNIT)) == TRUE) {
-			return (XDR_PUTINT32(xdrs, (int32_t *)hp));
-		}
-#else
-		if (XDR_PUTINT32(xdrs, (int32_t *)hp) == TRUE) {
-			return (XDR_PUTINT32(xdrs, (int32_t *)((char *)hp +
-			    BYTES_PER_XDR_UNIT)));
-		}
-#endif
-		return (FALSE);
-
-	}
-	if (xdrs->x_op == XDR_DECODE) {
-#if BYTE_ORDER == _LITTLE_ENDIAN
-		if (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
-		    BYTES_PER_XDR_UNIT)) == TRUE) {
-			return (XDR_GETINT32(xdrs, (int32_t *)hp));
-		}
-#else
-		if (XDR_GETINT32(xdrs, (int32_t *)hp) == TRUE) {
-			return (XDR_GETINT32(xdrs, (int32_t *)((char *)hp +
-			    BYTES_PER_XDR_UNIT)));
-		}
-#endif
-		return (FALSE);
-	}
-	return (TRUE);
-}
-
-/*
- * XDR short integers
- */
-bool_t
-xdr_short(XDR *xdrs, short *sp)
-{
-	int32_t l;
-
-	switch (xdrs->x_op) {
-
-	case XDR_ENCODE:
-		l = (int32_t)*sp;
-		return (XDR_PUTINT32(xdrs, &l));
-
-	case XDR_DECODE:
-		if (!XDR_GETINT32(xdrs, &l))
-			return (FALSE);
-		*sp = (short)l;
-		return (TRUE);
-
-	case XDR_FREE:
-		return (TRUE);
-	}
-	return (FALSE);
-}
-
-/*
- * XDR unsigned short integers
- */
-bool_t
-xdr_u_short(XDR *xdrs, ushort_t *usp)
-{
-	uint32_t l;
-
-	switch (xdrs->x_op) {
-
-	case XDR_ENCODE:
-		l = (uint32_t)*usp;
-		return (XDR_PUTINT32(xdrs, (int32_t *)&l));
-
-	case XDR_DECODE:
-		if (!XDR_GETINT32(xdrs, (int32_t *)&l)) {
-			return (FALSE);
-		}
-		*usp = (ushort_t)l;
-		return (TRUE);
-
-	case XDR_FREE:
-		return (TRUE);
-	}
-	return (FALSE);
-}
-
-
-/*
- * XDR a char
- */
-bool_t
-xdr_char(XDR *xdrs, char *cp)
-{
-	int i;
-
-	i = (*cp);
-	if (!xdr_int(xdrs, &i)) {
-		return (FALSE);
-	}
-	*cp = (char)i;
-	return (TRUE);
-}
-
-/*
- * XDR booleans
- *
- * PSARC 2003/523 Contract Private Interface
- * xdr_bool
- * Changes must be reviewed by Solaris File Sharing
- * Changes must be communicated to contract-2003-523@sun.com
- */
-bool_t
-xdr_bool(XDR *xdrs, bool_t *bp)
-{
-	int32_t i32b;
-
-	switch (xdrs->x_op) {
-
-	case XDR_ENCODE:
-		i32b = *bp ? XDR_TRUE : XDR_FALSE;
-		return (XDR_PUTINT32(xdrs, &i32b));
-
-	case XDR_DECODE:
-		if (!XDR_GETINT32(xdrs, &i32b)) {
-			return (FALSE);
-		}
-		*bp = (i32b == XDR_FALSE) ? FALSE : TRUE;
-		return (TRUE);
-
-	case XDR_FREE:
-		return (TRUE);
-	}
-	return (FALSE);
-}
-
-/*
- * XDR enumerations
- *
- * PSARC 2003/523 Contract Private Interface
- * xdr_enum
- * Changes must be reviewed by Solaris File Sharing
- * Changes must be communicated to contract-2003-523@sun.com
- */
-#ifndef lint
-enum sizecheck { SIZEVAL } sizecheckvar;	/* used to find the size of */
-						/* an enum */
-#endif
-bool_t
-xdr_enum(XDR *xdrs, enum_t *ep)
-{
-#ifndef lint
-	/*
-	 * enums are treated as ints
-	 */
-	if (sizeof (sizecheckvar) == sizeof (int32_t)) {
-		return (xdr_int(xdrs, (int32_t *)ep));
-	} else if (sizeof (sizecheckvar) == sizeof (short)) {
-		return (xdr_short(xdrs, (short *)ep));
-	} else {
-		return (FALSE);
-	}
-#else
-	(void) (xdr_short(xdrs, (short *)ep));
-	return (xdr_int(xdrs, (int32_t *)ep));
-#endif
-}
-
-/*
- * XDR opaque data
- * Allows the specification of a fixed size sequence of opaque bytes.
- * cp points to the opaque object and cnt gives the byte length.
- *
- * PSARC 2003/523 Contract Private Interface
- * xdr_opaque
- * Changes must be reviewed by Solaris File Sharing
- * Changes must be communicated to contract-2003-523@sun.com
- */
-bool_t
-xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt)
-{
-	uint_t rndup;
-	static char crud[BYTES_PER_XDR_UNIT];
-
-	/*
-	 * if no data we are done
-	 */
-	if (cnt == 0)
-		return (TRUE);
-
-	/*
-	 * round byte count to full xdr units
-	 */
-	rndup = cnt % BYTES_PER_XDR_UNIT;
-	if (rndup != 0)
-		rndup = BYTES_PER_XDR_UNIT - rndup;
-
-	if (xdrs->x_op == XDR_DECODE) {
-		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
-			return (FALSE);
-		}
-		if (rndup == 0)
-			return (TRUE);
-		return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
-	}
-
-	if (xdrs->x_op == XDR_ENCODE) {
-		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
-			return (FALSE);
-		}
-		if (rndup == 0)
-			return (TRUE);
-		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
-	}
-
-	if (xdrs->x_op == XDR_FREE)
-		return (TRUE);
-
-	return (FALSE);
-}
-
-/*
- * XDR counted bytes
- * *cpp is a pointer to the bytes, *sizep is the count.
- * If *cpp is NULL maxsize bytes are allocated
- *
- * PSARC 2003/523 Contract Private Interface
- * xdr_bytes
- * Changes must be reviewed by Solaris File Sharing
- * Changes must be communicated to contract-2003-523@sun.com
- */
-bool_t
-xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize)
-{
-	char *sp = *cpp;  /* sp is the actual string pointer */
-	uint_t nodesize;
-
-	/*
-	 * first deal with the length since xdr bytes are counted
-	 */
-	if (!xdr_u_int(xdrs, sizep)) {
-		return (FALSE);
-	}
-	nodesize = *sizep;
-	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
-		return (FALSE);
-	}
-
-	/*
-	 * now deal with the actual bytes
-	 */
-	switch (xdrs->x_op) {
-	case XDR_DECODE:
-		if (nodesize == 0)
-			return (TRUE);
-		if (sp == NULL)
-			*cpp = sp = (char *)mem_alloc(nodesize);
-		/* FALLTHROUGH */
-
-	case XDR_ENCODE:
-		return (xdr_opaque(xdrs, sp, nodesize));
-
-	case XDR_FREE:
-		if (sp != NULL) {
-			mem_free(sp, nodesize);
-			*cpp = NULL;
-		}
-		return (TRUE);
-	}
-	return (FALSE);
-}
-
-/*
- * Implemented here due to commonality of the object.
- */
-bool_t
-xdr_netobj(XDR *xdrs, struct netobj *np)
-{
-	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
-}
-
-/*
- * XDR a descriminated union
- * Support routine for discriminated unions.
- * You create an array of xdrdiscrim structures, terminated with
- * an entry with a null procedure pointer.  The routine gets
- * the discriminant value and then searches the array of xdrdiscrims
- * looking for that value.  It calls the procedure given in the xdrdiscrim
- * to handle the discriminant.  If there is no specific routine a default
- * routine may be called.
- * If there is no specific or default routine an error is returned.
- */
-bool_t
-xdr_union(XDR *xdrs, enum_t *dscmp, char *unp,
-	const struct xdr_discrim *choices, const xdrproc_t dfault)
-{
-	enum_t dscm;
-
-	/*
-	 * we deal with the discriminator;  it's an enum
-	 */
-	if (!xdr_enum(xdrs, dscmp)) {
-		return (FALSE);
-	}
-	dscm = *dscmp;
-
-	/*
-	 * search choices for a value that matches the discriminator.
-	 * if we find one, execute the xdr routine for that value.
-	 */
-	for (; choices->proc != NULL_xdrproc_t; choices++) {
-		if (choices->value == dscm)
-			return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
-	}
-
-	/*
-	 * no match - execute the default xdr routine if there is one
-	 */
-	return ((dfault == NULL_xdrproc_t) ? FALSE :
-	    (*dfault)(xdrs, unp, LASTUNSIGNED));
-}
-
-
-/*
- * Non-portable xdr primitives.
- * Care should be taken when moving these routines to new architectures.
- */
-
-
-/*
- * XDR null terminated ASCII strings
- * xdr_string deals with "C strings" - arrays of bytes that are
- * terminated by a NULL character.  The parameter cpp references a
- * pointer to storage; If the pointer is null, then the necessary
- * storage is allocated.  The last parameter is the max allowed length
- * of the string as specified by a protocol.
- */
-bool_t
-xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize)
-{
-	char *sp = *cpp;  /* sp is the actual string pointer */
-	uint_t size;
-	uint_t nodesize;
-
-	/*
-	 * first deal with the length since xdr strings are counted-strings
-	 */
-	switch (xdrs->x_op) {
-	case XDR_FREE:
-		if (sp == NULL)
-			return (TRUE);	/* already free */
-		/* FALLTHROUGH */
-	case XDR_ENCODE:
-		size = (sp != NULL) ? (uint_t)strlen(sp) : 0;
-		break;
-	case XDR_DECODE:
-		break;
-	}
-	if (!xdr_u_int(xdrs, &size)) {
-		return (FALSE);
-	}
-	if (size > maxsize) {
-		return (FALSE);
-	}
-	nodesize = size + 1;
-
-	/*
-	 * now deal with the actual bytes
-	 */
-	switch (xdrs->x_op) {
-	case XDR_DECODE:
-		if (nodesize == 0)
-			return (TRUE);
-		if (sp == NULL)
-			sp = (char *)mem_alloc(nodesize);
-		sp[size] = 0;
-		if (!xdr_opaque(xdrs, sp, size)) {
-			/*
-			 * free up memory if allocated here
-			 */
-			if (*cpp == NULL) {
-				mem_free(sp, nodesize);
-			}
-			return (FALSE);
-		}
-		if (strlen(sp) != size) {
-			if (*cpp == NULL) {
-				mem_free(sp, nodesize);
-			}
-			return (FALSE);
-		}
-		*cpp = sp;
-		return (TRUE);
-
-	case XDR_ENCODE:
-		return (xdr_opaque(xdrs, sp, size));
-
-	case XDR_FREE:
-		mem_free(sp, nodesize);
-		*cpp = NULL;
-		return (TRUE);
-	}
-	return (FALSE);
-}
-
-/*
- * Wrapper for xdr_string that can be called directly from
- * routines like clnt_call
- */
-bool_t
-xdr_wrapstring(XDR *xdrs, char **cpp)
-{
-	if (xdr_string(xdrs, cpp, LASTUNSIGNED))
-		return (TRUE);
-	return (FALSE);
-}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr_array.c b/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr_array.c
deleted file mode 100644
index d37dda6921a..00000000000
--- a/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr_array.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
-/*	  All Rights Reserved  	*/
-
-/*
- * Portions of this source code were derived from Berkeley 4.3 BSD
- * under license from the Regents of the University of California.
- */
-
-/*
- * xdr_array.c, Generic XDR routines impelmentation.
- * These are the "non-trivial" xdr primitives used to serialize and de-serialize
- * arrays.  See xdr.h for more info on the interface to xdr.
- */
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-#define	LASTUNSIGNED	((uint_t)0-1)
-
-/*
- * XDR an array of arbitrary elements
- * *addrp is a pointer to the array, *sizep is the number of elements.
- * If addrp is NULL (*sizep * elsize) bytes are allocated.
- * elsize is the size (in bytes) of each element, and elproc is the
- * xdr procedure to call to handle each element of the array.
- */
-bool_t
-xdr_array(XDR *xdrs, caddr_t *addrp, uint_t *sizep, const uint_t maxsize,
-	const uint_t elsize, const xdrproc_t elproc)
-{
-	uint_t i;
-	caddr_t target = *addrp;
-	uint_t c;  /* the actual element count */
-	bool_t stat = TRUE;
-	uint_t nodesize;
-
-	/* like strings, arrays are really counted arrays */
-	if (!xdr_u_int(xdrs, sizep)) {
-		return (FALSE);
-	}
-	c = *sizep;
-	if ((c > maxsize || LASTUNSIGNED / elsize < c) &&
-	    xdrs->x_op != XDR_FREE) {
-		return (FALSE);
-	}
-	nodesize = c * elsize;
-
-	/*
-	 * if we are deserializing, we may need to allocate an array.
-	 * We also save time by checking for a null array if we are freeing.
-	 */
-	if (target == NULL)
-		switch (xdrs->x_op) {
-		case XDR_DECODE:
-			if (c == 0)
-				return (TRUE);
-			*addrp = target = (char *)mem_alloc(nodesize);
-			bzero(target, nodesize);
-			break;
-
-		case XDR_FREE:
-			return (TRUE);
-
-		case XDR_ENCODE:
-			break;
-		}
-
-	/*
-	 * now we xdr each element of array
-	 */
-	for (i = 0; (i < c) && stat; i++) {
-		stat = (*elproc)(xdrs, target, LASTUNSIGNED);
-		target += elsize;
-	}
-
-	/*
-	 * the array may need freeing
-	 */
-	if (xdrs->x_op == XDR_FREE) {
-		mem_free(*addrp, nodesize);
-		*addrp = NULL;
-	}
-	return (stat);
-}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr_mem.c b/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr_mem.c
deleted file mode 100644
index 32ff32daaa0..00000000000
--- a/sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr_mem.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
-/*	  All Rights Reserved  	*/
-
-/*
- * Portions of this source code were derived from Berkeley 4.3 BSD
- * under license from the Regents of the University of California.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * xdr_mem.c, XDR implementation using memory buffers.
- *
- * If you have some data to be interpreted as external data representation
- * or to be converted to external data representation in a memory buffer,
- * then this is the package for you.
- */
-
-#include 
-#include 
-#include 
-
-#include 
-#include 
-
-static struct xdr_ops *xdrmem_ops(void);
-
-/*
- * The procedure xdrmem_create initializes a stream descriptor for a
- * memory buffer.
- */
-void
-xdrmem_create(XDR *xdrs, caddr_t addr, uint_t size, enum xdr_op op)
-{
-	xdrs->x_op = op;
-	xdrs->x_ops = xdrmem_ops();
-	xdrs->x_private = xdrs->x_base = addr;
-	xdrs->x_handy = size;
-	xdrs->x_public = NULL;
-}
-
-/* ARGSUSED */
-static void
-xdrmem_destroy(XDR *xdrs)
-{
-}
-
-static bool_t
-xdrmem_getint32(XDR *xdrs, int32_t *int32p)
-{
-	if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0)
-		return (FALSE);
-	/* LINTED pointer alignment */
-	*int32p = (int32_t)ntohl((uint32_t)(*((int32_t *)(xdrs->x_private))));
-	xdrs->x_private += sizeof (int32_t);
-	return (TRUE);
-}
-
-static bool_t
-xdrmem_putint32(XDR *xdrs, int32_t *int32p)
-{
-	if ((xdrs->x_handy -= (int)sizeof (int32_t)) < 0)
-		return (FALSE);
-	/* LINTED pointer alignment */
-	*(int32_t *)xdrs->x_private = (int32_t)htonl((uint32_t)(*int32p));
-	xdrs->x_private += sizeof (int32_t);
-	return (TRUE);
-}
-
-static bool_t
-xdrmem_getbytes(XDR *xdrs, caddr_t addr, int len)
-{
-	if ((xdrs->x_handy -= len) < 0)
-		return (FALSE);
-	bcopy(xdrs->x_private, addr, len);
-	xdrs->x_private += len;
-	return (TRUE);
-}
-
-static bool_t
-xdrmem_putbytes(XDR *xdrs, caddr_t addr, int len)
-{
-	if ((xdrs->x_handy -= len) < 0)
-		return (FALSE);
-	bcopy(addr, xdrs->x_private, len);
-	xdrs->x_private += len;
-	return (TRUE);
-}
-
-static uint_t
-xdrmem_getpos(XDR *xdrs)
-{
-	return ((uint_t)((uintptr_t)xdrs->x_private - (uintptr_t)xdrs->x_base));
-}
-
-static bool_t
-xdrmem_setpos(XDR *xdrs, uint_t pos)
-{
-	caddr_t newaddr = xdrs->x_base + pos;
-	caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
-	ptrdiff_t diff;
-
-	if (newaddr > lastaddr)
-		return (FALSE);
-	xdrs->x_private = newaddr;
-	diff = lastaddr - newaddr;
-	xdrs->x_handy = (int)diff;
-	return (TRUE);
-}
-
-static rpc_inline_t *
-xdrmem_inline(XDR *xdrs, int len)
-{
-	rpc_inline_t *buf = NULL;
-
-	if (xdrs->x_handy >= len) {
-		xdrs->x_handy -= len;
-		/* LINTED pointer alignment */
-		buf = (rpc_inline_t *)xdrs->x_private;
-		xdrs->x_private += len;
-	}
-	return (buf);
-}
-
-static bool_t
-xdrmem_control(XDR *xdrs, int request, void *info)
-{
-	xdr_bytesrec *xptr;
-	int32_t *int32p;
-	int len;
-
-	switch (request) {
-
-	case XDR_GET_BYTES_AVAIL:
-		xptr = (xdr_bytesrec *)info;
-		xptr->xc_is_last_record = TRUE;
-		xptr->xc_num_avail = xdrs->x_handy;
-		return (TRUE);
-
-	case XDR_PEEK:
-		/*
-		 * Return the next 4 byte unit in the XDR stream.
-		 */
-		if (xdrs->x_handy < sizeof (int32_t))
-			return (FALSE);
-		int32p = (int32_t *)info;
-		*int32p = (int32_t)ntohl((uint32_t)
-		    (*((int32_t *)(xdrs->x_private))));
-		return (TRUE);
-
-	case XDR_SKIPBYTES:
-		/*
-		 * Skip the next N bytes in the XDR stream.
-		 */
-		int32p = (int32_t *)info;
-		len = RNDUP((int)(*int32p));
-		if ((xdrs->x_handy -= len) < 0)
-			return (FALSE);
-		xdrs->x_private += len;
-		return (TRUE);
-
-	}
-	return (FALSE);
-}
-
-static struct xdr_ops *
-xdrmem_ops(void)
-{
-	static struct xdr_ops ops;
-
-	if (ops.x_getint32 == NULL) {
-		ops.x_getbytes = xdrmem_getbytes;
-		ops.x_putbytes = xdrmem_putbytes;
-		ops.x_getpostn = xdrmem_getpos;
-		ops.x_setpostn = xdrmem_setpos;
-		ops.x_inline = xdrmem_inline;
-		ops.x_destroy = xdrmem_destroy;
-		ops.x_control = xdrmem_control;
-		ops.x_getint32 = xdrmem_getint32;
-		ops.x_putint32 = xdrmem_putint32;
-	}
-	return (&ops);
-}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/rpc/xdr.h b/sys/cddl/contrib/opensolaris/uts/common/rpc/xdr.h
deleted file mode 100644
index 6cb0c6db392..00000000000
--- a/sys/cddl/contrib/opensolaris/uts/common/rpc/xdr.h
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
-/*
- * Portions of this source code were derived from Berkeley
- * 4.3 BSD under license from the Regents of the University of
- * California.
- */
-
-/*
- * xdr.h, External Data Representation Serialization Routines.
- *
- */
-
-#ifndef _RPC_XDR_H
-#define	_RPC_XDR_H
-
-#include 	/* For all ntoh* and hton*() kind of macros */
-#include 	/* For all ntoh* and hton*() kind of macros */
-#ifndef _KERNEL
-#include  /* defines FILE *, used in ANSI C function prototypes */
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * XDR provides a conventional way for converting between C data
- * types and an external bit-string representation.  Library supplied
- * routines provide for the conversion on built-in C data types.  These
- * routines and utility routines defined here are used to help implement
- * a type encode/decode routine for each user-defined type.
- *
- * Each data type provides a single procedure which takes two arguments:
- *
- *	bool_t
- *	xdrproc(xdrs, argresp)
- *		XDR *xdrs;
- *		 *argresp;
- *
- * xdrs is an instance of a XDR handle, to which or from which the data
- * type is to be converted.  argresp is a pointer to the structure to be
- * converted.  The XDR handle contains an operation field which indicates
- * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
- *
- * XDR_DECODE may allocate space if the pointer argresp is null.  This
- * data can be freed with the XDR_FREE operation.
- *
- * We write only one procedure per data type to make it easy
- * to keep the encode and decode procedures for a data type consistent.
- * In many cases the same code performs all operations on a user defined type,
- * because all the hard work is done in the component type routines.
- * decode as a series of calls on the nested data types.
- */
-
-/*
- * Xdr operations.  XDR_ENCODE causes the type to be encoded into the
- * stream.  XDR_DECODE causes the type to be extracted from the stream.
- * XDR_FREE can be used to release the space allocated by an XDR_DECODE
- * request.
- */
-enum xdr_op {
-	XDR_ENCODE = 0,
-	XDR_DECODE = 1,
-	XDR_FREE = 2
-};
-
-/*
- * This is the number of bytes per unit of external data.
- */
-#define	BYTES_PER_XDR_UNIT	(4)
-#define	RNDUP(x)  ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
-		    * BYTES_PER_XDR_UNIT)
-
-/*
- * The XDR handle.
- * Contains operation which is being applied to the stream,
- * an operations vector for the paticular implementation (e.g. see xdr_mem.c),
- * and two private fields for the use of the particular impelementation.
- *
- * PSARC 2003/523 Contract Private Interface
- * XDR
- * Changes must be reviewed by Solaris File Sharing
- * Changes must be communicated to contract-2003-523@sun.com
- */
-typedef struct XDR {
-	enum xdr_op	x_op;	/* operation; fast additional param */
-	struct xdr_ops *x_ops;
-	caddr_t 	x_public; /* users' data */
-	caddr_t		x_private; /* pointer to private data */
-	caddr_t 	x_base;	/* private used for position info */
-	int		x_handy; /* extra private word */
-} XDR;
-
-/*
- * PSARC 2003/523 Contract Private Interface
- * xdr_ops
- * Changes must be reviewed by Solaris File Sharing
- * Changes must be communicated to contract-2003-523@sun.com
- */
-#ifndef __FreeBSD__	
-struct xdr_ops {
-#ifdef __STDC__
-#if !defined(_KERNEL)
-		bool_t	(*x_getlong)(struct XDR *, long *);
-		/* get a long from underlying stream */
-		bool_t	(*x_putlong)(struct XDR *, long *);
-		/* put a long to " */
-#endif /* KERNEL */
-		bool_t	(*x_getbytes)(struct XDR *, caddr_t, int);
-		/* get some bytes from " */
-		bool_t	(*x_putbytes)(struct XDR *, caddr_t, int);
-		/* put some bytes to " */
-		uint_t	(*x_getpostn)(struct XDR *);
-		/* returns bytes off from beginning */
-		bool_t  (*x_setpostn)(struct XDR *, uint_t);
-		/* lets you reposition the stream */
-		rpc_inline_t *(*x_inline)(struct XDR *, int);
-		/* buf quick ptr to buffered data */
-		void	(*x_destroy)(struct XDR *);
-		/* free privates of this xdr_stream */
-		bool_t	(*x_control)(struct XDR *, int, void *);
-#if defined(_LP64) || defined(_KERNEL)
-		bool_t	(*x_getint32)(struct XDR *, int32_t *);
-		/* get a int from underlying stream */
-		bool_t	(*x_putint32)(struct XDR *, int32_t *);
-		/* put an int to " */
-#endif /* _LP64 || _KERNEL */
-#else
-#if !defined(_KERNEL)
-		bool_t	(*x_getlong)();	/* get a long from underlying stream */
-		bool_t	(*x_putlong)();	/* put a long to " */
-#endif /* KERNEL */
-		bool_t	(*x_getbytes)(); /* get some bytes from " */
-		bool_t	(*x_putbytes)(); /* put some bytes to " */
-		uint_t	(*x_getpostn)(); /* returns bytes off from beginning */
-		bool_t  (*x_setpostn)(); /* lets you reposition the stream */
-		rpc_inline_t *(*x_inline)();
-				/* buf quick ptr to buffered data */
-		void	(*x_destroy)();	/* free privates of this xdr_stream */
-		bool_t	(*x_control)();
-#if defined(_LP64) || defined(_KERNEL)
-		bool_t	(*x_getint32)();
-		bool_t	(*x_putint32)();
-#endif /* _LP64 || defined(_KERNEL) */
-#endif
-};
-
-#else /* FreeBSD */
-struct xdr_ops {
-	/* get a long from underlying stream */
-	bool_t	(*x_getint32)(struct XDR *, int32_t *);
-	/* put a long to " */
-	bool_t	(*x_putint32)(struct XDR *, const int32_t *);
-	/* get some bytes from " */
-	bool_t	(*x_getbytes)(struct XDR *, char *, u_int);
-	/* put some bytes to " */
-	bool_t	(*x_putbytes)(struct XDR *, const char *, u_int);
-	/* returns bytes off from beginning */
-	u_int	(*x_getpostn)(struct XDR *);
-	/* lets you reposition the stream */
-	bool_t  (*x_setpostn)(struct XDR *, u_int);
-	/* buf quick ptr to buffered data */
-	int32_t *(*x_inline)(struct XDR *, u_int);
-	/* free privates of this xdr_stream */
-	void	(*x_destroy)(struct XDR *);
-	bool_t	(*x_control)(struct XDR *, int, void *);
-};
-#endif
-	
-/*
- * Operations defined on a XDR handle
- *
- * XDR		*xdrs;
- * long		*longp;
- * caddr_t	 addr;
- * uint_t	 len;
- * uint_t	 pos;
- */
-#if !defined(_KERNEL)
-#define	XDR_GETLONG(xdrs, longp)			\
-	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
-#define	xdr_getlong(xdrs, longp)			\
-	(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
-
-#define	XDR_PUTLONG(xdrs, longp)			\
-	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
-#define	xdr_putlong(xdrs, longp)			\
-	(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
-#endif /* KERNEL */
-
-
-#if !defined(_LP64) && !defined(_KERNEL)
-
-/*
- * For binary compatability on ILP32 we do not change the shape
- * of the XDR structure and the GET/PUTINT32 functions just use
- * the get/putlong vectors which operate on identically-sized
- * units of data.
- */
-
-#define	XDR_GETINT32(xdrs, int32p)			\
-	(*(xdrs)->x_ops->x_getlong)(xdrs, (long *)int32p)
-#define	xdr_getint32(xdrs, int32p)			\
-	(*(xdrs)->x_ops->x_getlong)(xdrs, (long *)int32p)
-
-#define	XDR_PUTINT32(xdrs, int32p)			\
-	(*(xdrs)->x_ops->x_putlong)(xdrs, (long *)int32p)
-#define	xdr_putint32(xdrs, int32p)			\
-	(*(xdrs)->x_ops->x_putlong)(xdrs, (long *)int32p)
-
-#else /* !_LP64 && !_KERNEL */
-
-#define	XDR_GETINT32(xdrs, int32p)			\
-	(*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
-#define	xdr_getint32(xdrs, int32p)			\
-	(*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
-
-#define	XDR_PUTINT32(xdrs, int32p)			\
-	(*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
-#define	xdr_putint32(xdrs, int32p)			\
-	(*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
-
-#endif /* !_LP64 && !_KERNEL */
-
-#define	XDR_GETBYTES(xdrs, addr, len)			\
-	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
-#define	xdr_getbytes(xdrs, addr, len)			\
-	(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
-
-#define	XDR_PUTBYTES(xdrs, addr, len)			\
-	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
-#define	xdr_putbytes(xdrs, addr, len)			\
-	(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
-
-#define	XDR_GETPOS(xdrs)				\
-	(*(xdrs)->x_ops->x_getpostn)(xdrs)
-#define	xdr_getpos(xdrs)				\
-	(*(xdrs)->x_ops->x_getpostn)(xdrs)
-
-#define	XDR_SETPOS(xdrs, pos)				\
-	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
-#define	xdr_setpos(xdrs, pos)				\
-	(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
-
-#define	XDR_INLINE(xdrs, len)				\
-	(*(xdrs)->x_ops->x_inline)(xdrs, len)
-#define	xdr_inline(xdrs, len)				\
-	(*(xdrs)->x_ops->x_inline)(xdrs, len)
-
-#define	XDR_DESTROY(xdrs)				\
-	(*(xdrs)->x_ops->x_destroy)(xdrs)
-#define	xdr_destroy(xdrs)				\
-	(*(xdrs)->x_ops->x_destroy)(xdrs)
-
-#define	XDR_CONTROL(xdrs, req, op)			\
-	(*(xdrs)->x_ops->x_control)(xdrs, req, op)
-#define	xdr_control(xdrs, req, op)			\
-	(*(xdrs)->x_ops->x_control)(xdrs, req, op)
-
-/*
- * Support struct for discriminated unions.
- * You create an array of xdrdiscrim structures, terminated with
- * a entry with a null procedure pointer.  The xdr_union routine gets
- * the discriminant value and then searches the array of structures
- * for a matching value.  If a match is found the associated xdr routine
- * is called to handle that part of the union.  If there is
- * no match, then a default routine may be called.
- * If there is no match and no default routine it is an error.
- */
-
-
-/*
- * A xdrproc_t exists for each data type which is to be encoded or decoded.
- *
- * The second argument to the xdrproc_t is a pointer to an opaque pointer.
- * The opaque pointer generally points to a structure of the data type
- * to be decoded.  If this pointer is 0, then the type routines should
- * allocate dynamic storage of the appropriate size and return it.
- * bool_t	(*xdrproc_t)(XDR *, void *);
- */
-#ifdef __cplusplus
-typedef bool_t (*xdrproc_t)(XDR *, void *);
-#else
-#ifdef __STDC__
-typedef bool_t (*xdrproc_t)(); /* For Backward compatibility */
-#else
-typedef	bool_t (*xdrproc_t)();
-#endif
-#endif
-
-#define	NULL_xdrproc_t ((xdrproc_t)0)
-
-#if defined(_LP64) || defined(_I32LPx)
-#define	xdr_rpcvers(xdrs, versp)	xdr_u_int(xdrs, versp)
-#define	xdr_rpcprog(xdrs, progp)	xdr_u_int(xdrs, progp)
-#define	xdr_rpcproc(xdrs, procp)	xdr_u_int(xdrs, procp)
-#define	xdr_rpcprot(xdrs, protp)	xdr_u_int(xdrs, protp)
-#define	xdr_rpcport(xdrs, portp)	xdr_u_int(xdrs, portp)
-#else
-#define	xdr_rpcvers(xdrs, versp)	xdr_u_long(xdrs, versp)
-#define	xdr_rpcprog(xdrs, progp)	xdr_u_long(xdrs, progp)
-#define	xdr_rpcproc(xdrs, procp)	xdr_u_long(xdrs, procp)
-#define	xdr_rpcprot(xdrs, protp)	xdr_u_long(xdrs, protp)
-#define	xdr_rpcport(xdrs, portp)	xdr_u_long(xdrs, portp)
-#endif
-
-struct xdr_discrim {
-	int	value;
-	xdrproc_t proc;
-};
-
-/*
- * In-line routines for fast encode/decode of primitve data types.
- * Caveat emptor: these use single memory cycles to get the
- * data from the underlying buffer, and will fail to operate
- * properly if the data is not aligned.  The standard way to use these
- * is to say:
- *	if ((buf = XDR_INLINE(xdrs, count)) == NULL)
- *		return (FALSE);
- *	<<< macro calls >>>
- * where ``count'' is the number of bytes of data occupied
- * by the primitive data types.
- *
- * N.B. and frozen for all time: each data type here uses 4 bytes
- * of external representation.
- */
-
-#define	IXDR_GET_INT32(buf)		((int32_t)ntohl((uint32_t)*(buf)++))
-#define	IXDR_PUT_INT32(buf, v)		(*(buf)++ = (int32_t)htonl((uint32_t)v))
-#define	IXDR_GET_U_INT32(buf)		((uint32_t)IXDR_GET_INT32(buf))
-#define	IXDR_PUT_U_INT32(buf, v)	IXDR_PUT_INT32((buf), ((int32_t)(v)))
-
-#if !defined(_KERNEL) && !defined(_LP64)
-
-#define	IXDR_GET_LONG(buf)		((long)ntohl((ulong_t)*(buf)++))
-#define	IXDR_PUT_LONG(buf, v)		(*(buf)++ = (long)htonl((ulong_t)v))
-#define	IXDR_GET_U_LONG(buf)		((ulong_t)IXDR_GET_LONG(buf))
-#define	IXDR_PUT_U_LONG(buf, v)		IXDR_PUT_LONG((buf), ((long)(v)))
-
-#define	IXDR_GET_BOOL(buf)		((bool_t)IXDR_GET_LONG(buf))
-#define	IXDR_GET_ENUM(buf, t)		((t)IXDR_GET_LONG(buf))
-#define	IXDR_GET_SHORT(buf)		((short)IXDR_GET_LONG(buf))
-#define	IXDR_GET_U_SHORT(buf)		((ushort_t)IXDR_GET_LONG(buf))
-
-#define	IXDR_PUT_BOOL(buf, v)		IXDR_PUT_LONG((buf), ((long)(v)))
-#define	IXDR_PUT_ENUM(buf, v)		IXDR_PUT_LONG((buf), ((long)(v)))
-#define	IXDR_PUT_SHORT(buf, v)		IXDR_PUT_LONG((buf), ((long)(v)))
-#define	IXDR_PUT_U_SHORT(buf, v)	IXDR_PUT_LONG((buf), ((long)(v)))
-
-#else
-
-#define	IXDR_GET_BOOL(buf)		((bool_t)IXDR_GET_INT32(buf))
-#define	IXDR_GET_ENUM(buf, t)		((t)IXDR_GET_INT32(buf))
-#define	IXDR_GET_SHORT(buf)		((short)IXDR_GET_INT32(buf))
-#define	IXDR_GET_U_SHORT(buf)		((ushort_t)IXDR_GET_INT32(buf))
-
-#define	IXDR_PUT_BOOL(buf, v)		IXDR_PUT_INT32((buf), ((int)(v)))
-#define	IXDR_PUT_ENUM(buf, v)		IXDR_PUT_INT32((buf), ((int)(v)))
-#define	IXDR_PUT_SHORT(buf, v)		IXDR_PUT_INT32((buf), ((int)(v)))
-#define	IXDR_PUT_U_SHORT(buf, v)	IXDR_PUT_INT32((buf), ((int)(v)))
-
-#endif
-
-#if BYTE_ORDER == _LITTLE_ENDIAN
-#define	IXDR_GET_HYPER(buf, v)	{ \
-			*((int32_t *)(&v)) = ntohl(*(uint32_t *)buf++); \
-			*((int32_t *)(((char *)&v) + BYTES_PER_XDR_UNIT)) \
-			= ntohl(*(uint32_t *)buf++); \
-			}
-#define	IXDR_PUT_HYPER(buf, v)	{ \
-			*(buf)++ = (int32_t)htonl(*(uint32_t *) \
-				((char *)&v)); \
-			*(buf)++ = \
-				(int32_t)htonl(*(uint32_t *)(((char *)&v) \
-				+ BYTES_PER_XDR_UNIT)); \
-			}
-#else
-
-#define	IXDR_GET_HYPER(buf, v)	{ \
-			*((int32_t *)(((char *)&v) + \
-				BYTES_PER_XDR_UNIT)) \
-				= ntohl(*(uint32_t *)buf++); \
-			*((int32_t *)(&v)) = \
-				ntohl(*(uint32_t *)buf++); \
-			}
-
-#define	IXDR_PUT_HYPER(buf, v)	{ \
-			*(buf)++ = \
-				(int32_t)htonl(*(uint32_t *)(((char *)&v) + \
-				BYTES_PER_XDR_UNIT)); \
-			*(buf)++ = \
-				(int32_t)htonl(*(uint32_t *)((char *)&v)); \
-			}
-#endif
-#define	IXDR_GET_U_HYPER(buf, v)	IXDR_GET_HYPER(buf, v)
-#define	IXDR_PUT_U_HYPER(buf, v)	IXDR_PUT_HYPER(buf, v)
-
-
-/*
- * These are the "generic" xdr routines.
- */
-#ifdef __STDC__
-extern bool_t	xdr_void(void);
-extern bool_t	xdr_int(XDR *, int *);
-extern bool_t	xdr_u_int(XDR *, uint_t *);
-extern bool_t	xdr_long(XDR *, long *);
-extern bool_t	xdr_u_long(XDR *, ulong_t *);
-extern bool_t	xdr_short(XDR *, short *);
-extern bool_t	xdr_u_short(XDR *, ushort_t *);
-extern bool_t	xdr_bool(XDR *, bool_t *);
-extern bool_t	xdr_enum(XDR *, enum_t *);
-extern bool_t	xdr_array(XDR *, caddr_t *, uint_t *, const uint_t,
-		    const uint_t, const xdrproc_t);
-extern bool_t	xdr_bytes(XDR *, char **, uint_t *, const uint_t);
-extern bool_t	xdr_opaque(XDR *, caddr_t, const uint_t);
-extern bool_t	xdr_string(XDR *, char **, const uint_t);
-extern bool_t	xdr_union(XDR *, enum_t *, char *,
-		    const struct xdr_discrim *, const xdrproc_t);
-extern unsigned int  xdr_sizeof(xdrproc_t, void *);
-
-extern bool_t   xdr_hyper(XDR *, longlong_t *);
-extern bool_t   xdr_longlong_t(XDR *, longlong_t *);
-extern bool_t   xdr_u_hyper(XDR *, u_longlong_t *);
-extern bool_t   xdr_u_longlong_t(XDR *, u_longlong_t *);
-
-extern bool_t	xdr_char(XDR *, char *);
-extern bool_t	xdr_wrapstring(XDR *, char **);
-extern bool_t	xdr_reference(XDR *, caddr_t *, uint_t, const xdrproc_t);
-extern bool_t	xdr_pointer(XDR *, char **, uint_t, const xdrproc_t);
-extern void	xdr_free(xdrproc_t, char *);
-extern bool_t	xdr_time_t(XDR *, time_t *);
-
-extern bool_t	xdr_int8_t(XDR *, int8_t *);
-extern bool_t	xdr_uint8_t(XDR *, uint8_t *);
-extern bool_t	xdr_int16_t(XDR *, int16_t *);
-extern bool_t	xdr_uint16_t(XDR *, uint16_t *);
-extern bool_t	xdr_int32_t(XDR *, int32_t *);
-extern bool_t	xdr_uint32_t(XDR *, uint32_t *);
-#if defined(_INT64_TYPE)
-extern bool_t	xdr_int64_t(XDR *, int64_t *);
-extern bool_t	xdr_uint64_t(XDR *, uint64_t *);
-#endif
-
-#ifndef _KERNEL
-extern bool_t	xdr_u_char(XDR *, uchar_t *);
-extern bool_t	xdr_vector(XDR *, char *, const uint_t, const uint_t, const
-xdrproc_t);
-extern bool_t	xdr_float(XDR *, float *);
-extern bool_t	xdr_double(XDR *, double *);
-extern bool_t	xdr_quadruple(XDR *, long double *);
-#endif /* !_KERNEL */
-#else
-extern bool_t	xdr_void();
-extern bool_t	xdr_int();
-extern bool_t	xdr_u_int();
-extern bool_t	xdr_long();
-extern bool_t	xdr_u_long();
-extern bool_t	xdr_short();
-extern bool_t	xdr_u_short();
-extern bool_t	xdr_bool();
-extern bool_t	xdr_enum();
-extern bool_t	xdr_array();
-extern bool_t	xdr_bytes();
-extern bool_t	xdr_opaque();
-extern bool_t	xdr_string();
-extern bool_t	xdr_union();
-
-extern bool_t   xdr_hyper();
-extern bool_t   xdr_longlong_t();
-extern bool_t   xdr_u_hyper();
-extern bool_t   xdr_u_longlong_t();
-extern bool_t	xdr_char();
-extern bool_t	xdr_reference();
-extern bool_t	xdr_pointer();
-extern void	xdr_free();
-extern bool_t	xdr_wrapstring();
-extern bool_t	xdr_time_t();
-
-extern bool_t	xdr_int8_t();
-extern bool_t	xdr_uint8_t();
-extern bool_t	xdr_int16_t();
-extern bool_t	xdr_uint16_t();
-extern bool_t	xdr_int32_t();
-extern bool_t	xdr_uint32_t();
-#if defined(_INT64_TYPE)
-extern bool_t	xdr_int64_t();
-extern bool_t	xdr_uint64_t();
-#endif
-
-#ifndef _KERNEL
-extern bool_t	xdr_u_char();
-extern bool_t	xdr_vector();
-extern bool_t	xdr_float();
-extern bool_t	xdr_double();
-extern bool_t   xdr_quadruple();
-#endif /* !_KERNEL */
-#endif
-
-/*
- * Common opaque bytes objects used by many rpc protocols;
- * declared here due to commonality.
- */
-#define	MAX_NETOBJ_SZ 1024
-struct netobj {
-	uint_t	n_len;
-	char	*n_bytes;
-};
-typedef struct netobj netobj;
-
-#ifdef __STDC__
-extern bool_t   xdr_netobj(XDR *, netobj *);
-#else
-extern bool_t   xdr_netobj();
-#endif
-
-/*
- * These are XDR control operators
- */
-
-#define	XDR_GET_BYTES_AVAIL 1
-
-struct xdr_bytesrec {
-	bool_t xc_is_last_record;
-	size_t xc_num_avail;
-};
-
-typedef struct xdr_bytesrec xdr_bytesrec;
-
-/*
- * These are the request arguments to XDR_CONTROL.
- *
- * XDR_PEEK - returns the contents of the next XDR unit on the XDR stream.
- * XDR_SKIPBYTES - skips the next N bytes in the XDR stream.
- * XDR_RDMAGET - for xdr implementation over RDMA, gets private flags from
- *		 the XDR stream being moved over RDMA
- * XDR_RDMANOCHUNK - for xdr implementaion over RDMA, sets private flags in
- *                   the XDR stream moving over RDMA.
- */
-#ifdef _KERNEL
-#define	XDR_PEEK		2
-#define	XDR_SKIPBYTES		3
-#define	XDR_RDMA_GET_FLAGS	4
-#define	XDR_RDMA_SET_FLAGS	5
-#define	XDR_RDMA_ADD_CHUNK	6
-#define	XDR_RDMA_GET_CHUNK_LEN	7
-#define	XDR_RDMA_SET_WLIST	8
-#define	XDR_RDMA_GET_WLIST	9
-#define	XDR_RDMA_GET_WCINFO	10
-#define	XDR_RDMA_GET_RLIST	11
-#endif
-
-/*
- * These are the public routines for the various implementations of
- * xdr streams.
- */
-#ifndef _KERNEL
-#ifdef __STDC__
-extern void   xdrmem_create(XDR *, const caddr_t, const uint_t, const enum
-xdr_op);
-	/* XDR using memory buffers */
-extern void   xdrrec_create(XDR *, const uint_t, const uint_t, const caddr_t,
-int (*) (void *, caddr_t, int), int (*) (void *, caddr_t, int));
-/* XDR pseudo records for tcp */
-extern bool_t xdrrec_endofrecord(XDR *, bool_t);
-/* make end of xdr record */
-extern bool_t xdrrec_skiprecord(XDR *);
-/* move to beginning of next record */
-extern bool_t xdrrec_eof(XDR *);
-extern uint_t xdrrec_readbytes(XDR *, caddr_t, uint_t);
-/* true if no more input */
-#else
-extern void   xdrmem_create();
-extern void   xdrstdio_create();
-extern void   xdrrec_create();
-extern bool_t xdrrec_endofrecord();
-extern bool_t xdrrec_skiprecord();
-extern bool_t xdrrec_eof();
-extern uint_t xdrrec_readbytes();
-#endif
-#else
-
-extern void	xdrmem_create(XDR *, caddr_t, uint_t, enum xdr_op);
-extern struct xdr_ops xdrmblk_ops;
-extern struct xdr_ops xdrrdmablk_ops;
-extern struct xdr_ops xdrrdma_ops;
-
-struct rpc_msg;
-extern bool_t	xdr_callmsg(XDR *, struct rpc_msg *);
-extern bool_t	xdr_replymsg_body(XDR *, struct rpc_msg *);
-extern bool_t	xdr_replymsg_hdr(XDR *, struct rpc_msg *);
-
-#include 
-#ifdef	mem_alloc
-#undef	mem_alloc
-#define	mem_alloc(size)		malloc((size), M_TEMP, M_WAITOK | M_ZERO)
-#endif
-#ifdef	mem_free
-#undef	mem_free
-#define	mem_free(ptr, size)	free((ptr), M_TEMP)
-#endif
-
-#endif /* !_KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* !_RPC_XDR_H */
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/callb.h b/sys/cddl/contrib/opensolaris/uts/common/sys/callb.h
index 54f35ac51ca..2b9ac3f9838 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/callb.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/callb.h
@@ -135,8 +135,6 @@ typedef struct callb_cpr {
 #define	CALLB_CPR_INIT(cp, lockp, func, name)	{			\
 		strlcpy(curthread->td_name, (name),			\
 		    sizeof(curthread->td_name));			\
-		strlcpy(curthread->td_proc->p_comm, (name),		\
-		    sizeof(curthread->td_proc->p_comm));		\
 		bzero((caddr_t)(cp), sizeof (callb_cpr_t));		\
 		(cp)->cc_lockp = lockp;					\
 		(cp)->cc_id = callb_add(func, (void *)(cp),		\
diff --git a/sys/cddl/compat/opensolaris/sys/taskq.h b/sys/cddl/contrib/opensolaris/uts/common/sys/taskq.h
similarity index 83%
rename from sys/cddl/compat/opensolaris/sys/taskq.h
rename to sys/cddl/contrib/opensolaris/uts/common/sys/taskq.h
index 174018a5eea..3878ded5e97 100644
--- a/sys/cddl/compat/opensolaris/sys/taskq.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/taskq.h
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -18,22 +17,18 @@
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
- *
- * $FreeBSD$
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #ifndef	_SYS_TASKQ_H
 #define	_SYS_TASKQ_H
 
-#pragma ident	"@(#)taskq.h	1.5	05/06/08 SMI"
-
-#include 
+#include 
 #include 
-#include 
+#include 
 
 #ifdef	__cplusplus
 extern "C" {
@@ -41,6 +36,11 @@ extern "C" {
 
 #define	TASKQ_NAMELEN	31
 
+struct taskqueue;
+struct taskq {
+	struct taskqueue	*tq_queue;
+};
+
 typedef struct taskq taskq_t;
 typedef uintptr_t taskqid_t;
 typedef void (task_func_t)(void *);
@@ -51,6 +51,7 @@ typedef void (task_func_t)(void *);
 #define	TASKQ_PREPOPULATE	0x0001	/* Prepopulate with threads and data */
 #define	TASKQ_CPR_SAFE		0x0002	/* Use CPR safe protocol */
 #define	TASKQ_DYNAMIC		0x0004	/* Use dynamic thread scheduling */
+#define	TASKQ_THREADS_CPU_PCT	0x0008	/* number of threads as % of ncpu */
 
 /*
  * Flags for taskq_dispatch. TQ_SLEEP/TQ_NOSLEEP should be same as
@@ -65,6 +66,9 @@ typedef void (task_func_t)(void *);
 
 extern taskq_t *system_taskq;
 
+extern void	taskq_init(void);
+extern void	taskq_mp_init(void);
+
 extern taskq_t	*taskq_create(const char *, int, pri_t, int, int, uint_t);
 extern taskq_t	*taskq_create_instance(const char *, int, int, pri_t, int,
     int, uint_t);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h b/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
index a166315160a..a46b7118735 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
@@ -353,6 +353,11 @@ typedef struct caller_context {
 	ulong_t		cc_flags;
 } caller_context_t;
 
+/*
+ * Structure tags for function prototypes, defined elsewhere.
+ */
+struct taskq;
+
 /*
  * Flags for VOP_LOOKUP
  *
@@ -369,6 +374,13 @@ typedef struct caller_context {
  */
 #define	V_RDDIR_ENTFLAGS	0x01	/* request dirent flags */
 
+/*
+ * Public vnode manipulation functions.
+ */
+#ifdef	_KERNEL
+
+void	vn_rele_async(struct vnode *vp, struct taskq *taskq);
+
 /*
  * Extensible vnode attribute (xva) routines:
  * xva_init() initializes an xvattr_t (zero struct, init mapsize, set AT_XATTR)
@@ -377,10 +389,12 @@ typedef struct caller_context {
 void		xva_init(xvattr_t *);
 xoptattr_t	*xva_getxoptattr(xvattr_t *);	/* Get ptr to xoptattr_t */
 
-struct taskq;
-void	vn_rele_async(struct vnode *vp, struct taskq *taskq);
-void	vn_rele_async_fini(void);
-	
+#define	VN_RELE_ASYNC(vp, taskq)	{ \
+	vn_rele_async(vp, taskq); \
+}
+
+#endif	/* _KERNEL */
+
 /*
  * Flags to VOP_SETATTR/VOP_GETATTR.
  */
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
index af8168e909d..46e0b80d270 100644
--- a/sys/compat/ia32/ia32_sysvec.c
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -172,6 +172,21 @@ SYSINIT(oia32, SI_SUB_EXEC, SI_ORDER_ANY,
 	(sysinit_cfunc_t) elf32_insert_brand_entry,
 	&ia32_brand_oinfo);
 
+static Elf32_Brandinfo kia32_brand_info = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_386,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/lib/ld.so.1",
+	.sysvec		= &ia32_freebsd_sysvec,
+	.brand_note	= &elf32_kfreebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
+};
+
+SYSINIT(kia32, SI_SUB_EXEC, SI_ORDER_ANY,
+	(sysinit_cfunc_t) elf32_insert_brand_entry,
+	&kia32_brand_info);
+
 
 void
 elf32_dump_thread(struct thread *td __unused, void *dst __unused,
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index dfa80d5ab61..541db2fc8c7 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -1085,6 +1085,7 @@ linprocfs_donetdev(PFS_FILL_ARGS)
 	    "bytes    packets errs drop fifo frame compressed",
 	    "bytes    packets errs drop fifo frame compressed");
 
+	CURVNET_SET(TD_TO_VNET(curthread));
 	IFNET_RLOCK();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		linux_ifname(ifp, ifname, sizeof ifname);
@@ -1095,6 +1096,7 @@ linprocfs_donetdev(PFS_FILL_ARGS)
 		    0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
 	}
 	IFNET_RUNLOCK();
+	CURVNET_RESTORE();
 
 	return (0);
 }
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 11dc6d5041b..8acc5929258 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -2061,22 +2061,20 @@ linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
 	struct ifnet *ifscan;
 	int ethno;
 
+	IFNET_RLOCK_ASSERT();
+
 	/* Short-circuit non ethernet interfaces */
 	if (!IFP_IS_ETH(ifp))
 		return (strlcpy(buffer, ifp->if_xname, buflen));
 
 	/* Determine the (relative) unit number for ethernet interfaces */
 	ethno = 0;
-	IFNET_RLOCK();
 	TAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
-		if (ifscan == ifp) {
-			IFNET_RUNLOCK();
+		if (ifscan == ifp)
 			return (snprintf(buffer, buflen, "eth%d", ethno));
-		}
 		if (IFP_IS_ETH(ifscan))
 			ethno++;
 	}
-	IFNET_RUNLOCK();
 
 	return (0);
 }
@@ -2106,6 +2104,7 @@ ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
 		return (NULL);
 	index = 0;
 	is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0;
+	CURVNET_SET(TD_TO_VNET(td));
 	IFNET_RLOCK();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		/*
@@ -2119,6 +2118,7 @@ ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
 			break;
 	}
 	IFNET_RUNLOCK();
+	CURVNET_RESTORE();
 	if (ifp != NULL)
 		strlcpy(bsdname, ifp->if_xname, IFNAMSIZ);
 	return (ifp);
@@ -2148,6 +2148,7 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
 
 	max_len = MAXPHYS - 1;
 
+	CURVNET_SET(TD_TO_VNET(td));
 	/* handle the 'request buffer size' case */
 	if (ifc.ifc_buf == PTROUT(NULL)) {
 		ifc.ifc_len = 0;
@@ -2159,11 +2160,14 @@ linux_ifconf(struct thread *td, struct ifconf *uifc)
 			}
 		}
 		error = copyout(&ifc, uifc, sizeof(ifc));
+		CURVNET_RESTORE();
 		return (error);
 	}
 
-	if (ifc.ifc_len <= 0)
+	if (ifc.ifc_len <= 0) {
+		CURVNET_RESTORE();
 		return (EINVAL);
+	}
 
 again:
 	/* Keep track of eth interfaces */
@@ -2177,7 +2181,7 @@ again:
 	valid_len = 0;
 
 	/* Return all AF_INET addresses of all interfaces */
-	IFNET_RLOCK();		/* could sleep XXX */
+	IFNET_RLOCK();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		int addrs = 0;
 
@@ -2225,6 +2229,7 @@ again:
 	memcpy(PTRIN(ifc.ifc_buf), sbuf_data(sb), ifc.ifc_len);
 	error = copyout(&ifc, uifc, sizeof(ifc));
 	sbuf_delete(sb);
+	CURVNET_RESTORE();
 
 	return (error);
 }
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index b448f943a12..ee0b2202367 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1790,6 +1790,7 @@ device		miibus
 #	BCM570x family of controllers, including the 3Com 3c996-T,
 #	the Netgear GA302T, the SysKonnect SK-9D21 and SK-9D41, and
 #	the embedded gigE NICs on Dell PowerEdge 2550 servers.
+# bwi:	Broadcom BCM430* and BCM431* family of wireless adapters.
 # cas:	Sun Cassini/Cassini+ and National Semiconductor DP83065 Saturn
 # cm:	Arcnet SMC COM90c26 / SMC COM90c56
 #	(and SMC COM90c66 in '56 compatibility mode) adapters.
@@ -1959,6 +1960,7 @@ device		wb		# Winbond W89C840F
 device		xl		# 3Com 3c90x (``Boomerang'', ``Cyclone'')
 
 # PCI Ethernet NICs.
+device		bwi		# Broadcom BCM430* BCM431*
 device		de		# DEC/Intel DC21x4x (``Tulip'')
 device		em		# Intel Pro/1000 Gigabit Ethernet
 device		igb		# Intel Pro/1000 PCIE Gigabit Ethernet
diff --git a/sys/conf/files b/sys/conf/files
index e5f2ac8cc83..cb5e4dc8d87 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -91,8 +91,8 @@ pccarddevs.h			standard				   \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"pccarddevs.h"
 teken_state.h		optional sc					   \
-	dependency	"$S/dev/syscons/teken/gensequences $S/dev/syscons/teken/sequences" \
-	compile-with	"${AWK} -f $S/dev/syscons/teken/gensequences $S/dev/syscons/teken/sequences > teken_state.h" \
+	dependency	"$S/teken/gensequences $S/teken/sequences" \
+	compile-with	"${AWK} -f $S/teken/gensequences $S/teken/sequences > teken_state.h" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"teken_state.h"
 usbdevs.h			optional usb				   \
@@ -845,8 +845,10 @@ dev/drm/r128_irq.c		optional r128drm
 dev/drm/r128_state.c		optional r128drm \
 	compile-with "${NORMAL_C} -finline-limit=13500"
 dev/drm/r300_cmdbuf.c		optional radeondrm
+dev/drm/r600_blit.c		optional radeondrm
 dev/drm/r600_cp.c		optional radeondrm
 dev/drm/radeon_cp.c		optional radeondrm
+dev/drm/radeon_cs.c		optional radeondrm
 dev/drm/radeon_drv.c		optional radeondrm
 dev/drm/radeon_irq.c		optional radeondrm
 dev/drm/radeon_mem.c		optional radeondrm
@@ -1296,6 +1298,7 @@ dev/ppc/ppc_puc.c		optional ppc puc
 dev/pst/pst-iop.c		optional pst
 dev/pst/pst-pci.c		optional pst pci
 dev/pst/pst-raid.c		optional pst
+dev/pty/pty.c			optional pty
 dev/puc/puc.c			optional puc
 dev/puc/puc_cfg.c		optional puc
 dev/puc/puc_pccard.c		optional puc pccard
@@ -2058,7 +2061,6 @@ kern/tty_info.c			standard
 kern/tty_inq.c			standard
 kern/tty_outq.c			standard
 kern/tty_pts.c			standard
-kern/tty_pty.c			optional pty
 kern/tty_tty.c			standard
 kern/tty_ttydisc.c		standard
 kern/uipc_accf.c		optional inet
@@ -2615,6 +2617,7 @@ security/mac_portacl/mac_portacl.c optional mac_portacl
 security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids
 security/mac_stub/mac_stub.c	optional mac_stub
 security/mac_test/mac_test.c	optional mac_test
+teken/teken.c			optional sc
 ufs/ffs/ffs_alloc.c		optional ffs
 ufs/ffs/ffs_balloc.c		optional ffs
 ufs/ffs/ffs_inode.c		optional ffs
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index be1aff5801d..efd76c06946 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -219,7 +219,6 @@ dev/syscons/apm/apm_saver.c	optional	apm_saver apm
 dev/syscons/scterm-teken.c	optional	sc
 dev/syscons/scvgarndr.c		optional	sc vga
 dev/syscons/scvtb.c		optional	sc
-dev/syscons/teken/teken.c	optional sc
 dev/uart/uart_cpu_amd64.c	optional	uart
 dev/wpi/if_wpi.c		optional	wpi
 isa/atrtc.c			standard
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 88bd1f148f7..17cd70e6538 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -220,7 +220,6 @@ dev/syscons/scterm-teken.c	optional sc
 dev/syscons/scvesactl.c		optional sc vga vesa
 dev/syscons/scvgarndr.c		optional sc vga
 dev/syscons/scvtb.c		optional sc
-dev/syscons/teken/teken.c	optional sc
 dev/uart/uart_cpu_i386.c	optional uart
 dev/acpica/acpi_if.m		standard
 dev/acpi_support/acpi_wmi_if.m	standard
diff --git a/sys/conf/files.ia64 b/sys/conf/files.ia64
index 706d64efce8..864be05c93a 100644
--- a/sys/conf/files.ia64
+++ b/sys/conf/files.ia64
@@ -60,7 +60,6 @@ dev/kbd/kbd.c			optional	atkbd | sc | ukbd | usb2_input_kbd
 dev/syscons/scterm-teken.c	optional	sc
 dev/syscons/scvgarndr.c		optional	sc vga
 dev/syscons/scvtb.c		optional	sc
-dev/syscons/teken/teken.c	optional sc
 dev/uart/uart_cpu_ia64.c	optional	uart
 dev/acpica/acpi_if.m		standard
 ia64/acpica/OsdEnvironment.c	optional	acpi
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 8a19155f335..c263ab53f3a 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -48,7 +48,6 @@ dev/sound/macio/tumbler.c	optional	snd_ai2s iicbus powermac
 dev/syscons/scgfbrndr.c		optional	sc
 dev/syscons/scterm-teken.c	optional	sc
 dev/syscons/scvtb.c		optional	sc
-dev/syscons/teken/teken.c	optional sc
 dev/tsec/if_tsec.c		optional	tsec
 dev/tsec/if_tsec_ocp.c		optional	tsec mpc85xx
 dev/uart/uart_bus_ocp.c		optional	uart mpc85xx
diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64
index 53077bbf237..ef6efa63e1e 100644
--- a/sys/conf/files.sparc64
+++ b/sys/conf/files.sparc64
@@ -57,7 +57,6 @@ dev/sound/sbus/cs4231.c		optional	snd_audiocs ebus | \
 dev/syscons/scgfbrndr.c		optional	sc
 dev/syscons/scterm-teken.c	optional	sc
 dev/syscons/scvtb.c		optional	sc
-dev/syscons/teken/teken.c	optional sc
 dev/uart/uart_cpu_sparc64.c	optional	uart
 dev/uart/uart_kbd_sun.c		optional	uart sc
 kern/syscalls.c			optional	ktr
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index f56d20ebbf4..49e99fd3d6f 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -31,8 +31,8 @@
 # $FreeBSD$
 
 TYPE="FreeBSD"
-REVISION="8.0"
-BRANCH="BETA2"
+REVISION="9.0"
+BRANCH="CURRENT"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
 	BRANCH=${BRANCH_OVERRIDE}
 fi
@@ -87,29 +87,25 @@ touch version
 v=`cat version` u=${USER:-root} d=`pwd` h=${HOSTNAME:-`hostname`} t=`date`
 i=`${MAKE:-make} -V KERN_IDENT`
 
-for dir in /bin /usr/bin /usr/local/bin; do
-	if [ -x "${dir}/svnversion" ]; then
-		svnversion=${dir}/svnversion
-		SRCDIR=${d##*obj}
-		if [ -n "$MACHINE" ]; then
-			SRCDIR=${SRCDIR##/$MACHINE}
+case "$d" in
+*/sys/*)
+	for dir in /bin /usr/bin /usr/local/bin; do
+		if [ -x "${dir}/svnversion" ]; then
+			svnversion=${dir}/svnversion
+			SRCDIR=${d##*obj}
+			if [ -n "$MACHINE" ]; then
+				SRCDIR=${SRCDIR##/$MACHINE}
+			fi
+			SRCDIR=${SRCDIR%%/sys/*}
+			break
 		fi
-		SRCDIR=${SRCDIR%%/sys/*}
-		break
-	fi
-done
+	done
 
-if [ -n "$svnversion" -a -d "${SRCDIR}/.svn" ] ; then
-	# If we are called from the kernel build, limit
-	# the scope of svnversion to sys/ .
-	if [ -e "${SRCDIR}/sys/conf/newvers.sh" ] ; then
-		svn=" r`cd $SRCDIR/sys && $svnversion`"
-	else
-		svn=" r`cd $SRCDIR && $svnversion`"
+	if [ -n "$svnversion" -a -d "${SRCDIR}/sys/.svn" ] ; then
+		svn=" r`cd ${SRCDIR}/sys && $svnversion`"
 	fi
-else
-	svn=""
-fi
+	;;
+esac
 
 cat << EOF > vers.c
 $COPYRIGHT
diff --git a/sys/conf/options b/sys/conf/options
index 41c80b5434c..22484e34ab0 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -672,7 +672,6 @@ ISAPNP			opt_isa.h
 DEV_BPF			opt_bpf.h
 DEV_MCA			opt_mca.h
 DEV_CARP		opt_carp.h
-DEV_PTY			opt_tty.h
 DEV_SPLASH		opt_splash.h
 
 # EISA support
@@ -821,8 +820,9 @@ TDMA_TXRATE_QUARTER_DEFAULT	opt_tdma.h
 TDMA_TXRATE_11NA_DEFAULT	opt_tdma.h
 TDMA_TXRATE_11NG_DEFAULT	opt_tdma.h
 
-# Virtualize the network stack
+# Network stack virtualization options
 VIMAGE			opt_global.h
+VNET_DEBUG		opt_global.h
 
 # Common Flash Interface (CFI) options
 CFI_SUPPORT_STRATAFLASH	opt_cfi.h
diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64
index 5247921eb8a..beb97ed7d1e 100644
--- a/sys/conf/options.amd64
+++ b/sys/conf/options.amd64
@@ -52,7 +52,6 @@ PSM_DEBUG		opt_psm.h
 DEV_ATPIC		opt_atpic.h
 
 # Debugging
-STOP_NMI		opt_cpu.h
 KDTRACE_FRAME		opt_kdtrace.h
 
 # BPF just-in-time compiler
diff --git a/sys/conf/options.arm b/sys/conf/options.arm
index a3fb7602f40..b3cc09731c8 100644
--- a/sys/conf/options.arm
+++ b/sys/conf/options.arm
@@ -24,6 +24,7 @@ KERNVIRTADDR		opt_global.h
 LOADERRAMADDR		opt_global.h
 PHYSADDR		opt_global.h
 PHYSMEM_SIZE		opt_global.h
+MII_ADDR_BASE		opt_global.h
 SKYEYE_WORKAROUNDS	opt_global.h
 SOC_MV_DISCOVERY	opt_global.h
 SOC_MV_KIRKWOOD		opt_global.h
diff --git a/sys/conf/options.i386 b/sys/conf/options.i386
index 45a1637fe9e..cd2ab98dafc 100644
--- a/sys/conf/options.i386
+++ b/sys/conf/options.i386
@@ -110,7 +110,6 @@ ASR_COMPAT		opt_asr.h
 
 # Debugging
 NPX_DEBUG		opt_npx.h
-STOP_NMI		opt_cpu.h
 
 # BPF just-in-time compiler
 BPF_JITTER		opt_bpf.h
diff --git a/sys/conf/options.pc98 b/sys/conf/options.pc98
index 837169b6ff5..dca3d694ae7 100644
--- a/sys/conf/options.pc98
+++ b/sys/conf/options.pc98
@@ -95,7 +95,6 @@ DEV_NPX			opt_npx.h
 
 # Debugging
 NPX_DEBUG		opt_npx.h
-STOP_NMI		opt_cpu.h
 AGP_DEBUG		opt_agp.h
 
 # BPF just-in-time compiler
diff --git a/sys/contrib/altq/altq/altq_subr.c b/sys/contrib/altq/altq/altq_subr.c
index 32107e57d36..edacc0d4b1e 100644
--- a/sys/contrib/altq/altq/altq_subr.c
+++ b/sys/contrib/altq/altq/altq_subr.c
@@ -462,8 +462,8 @@ tbr_timeout(arg)
 	s = splimp();
 #endif
 #if defined(__FreeBSD__) && (__FreeBSD_version >= 500000)
-	IFNET_RLOCK();
-	VNET_LIST_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
+	VNET_LIST_RLOCK_NOSLEEP();
 	VNET_FOREACH(vnet_iter) {
 		CURVNET_SET(vnet_iter);
 #endif
@@ -480,8 +480,8 @@ tbr_timeout(arg)
 #if defined(__FreeBSD__) && (__FreeBSD_version >= 500000)
 		CURVNET_RESTORE();
 	}
-	VNET_LIST_RUNLOCK();
-	IFNET_RUNLOCK();
+	VNET_LIST_RUNLOCK_NOSLEEP();
+	IFNET_RUNLOCK_NOSLEEP();
 #endif
 	splx(s);
 	if (active > 0)
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 591ea36b801..e8031ac7dfe 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -971,6 +971,9 @@ void
 pf_purge_thread(void *v)
 {
 	int nloops = 0, s;
+#ifdef __FreeBSD__
+	int locked;
+#endif
 
 	for (;;) {
 		tsleep(pf_purge_thread, PWAIT, "pftm", 1 * hz);
@@ -978,14 +981,19 @@ pf_purge_thread(void *v)
 #ifdef __FreeBSD__
 		sx_slock(&pf_consistency_lock);
 		PF_LOCK();
+		locked = 0;
 
 		if (pf_end_threads) {
-			pf_purge_expired_states(pf_status.states);
+			PF_UNLOCK();
+			sx_sunlock(&pf_consistency_lock);
+			sx_xlock(&pf_consistency_lock);
+			PF_LOCK();
+			pf_purge_expired_states(pf_status.states, 1);
 			pf_purge_expired_fragments();
-			pf_purge_expired_src_nodes(0);
+			pf_purge_expired_src_nodes(1);
 			pf_end_threads++;
 
-			sx_sunlock(&pf_consistency_lock);
+			sx_xunlock(&pf_consistency_lock);
 			PF_UNLOCK();
 			wakeup(pf_purge_thread);
 			kproc_exit(0);
@@ -994,20 +1002,44 @@ pf_purge_thread(void *v)
 		s = splsoftnet();
 
 		/* process a fraction of the state table every second */
+#ifdef __FreeBSD__
+		if(!pf_purge_expired_states(1 + (pf_status.states
+		    / pf_default_rule.timeout[PFTM_INTERVAL]), 0)) {
+			PF_UNLOCK();
+			sx_sunlock(&pf_consistency_lock);
+			sx_xlock(&pf_consistency_lock);
+			PF_LOCK();
+			locked = 1;
+
+			pf_purge_expired_states(1 + (pf_status.states
+			    / pf_default_rule.timeout[PFTM_INTERVAL]), 1);
+		}
+#else
 		pf_purge_expired_states(1 + (pf_status.states
 		    / pf_default_rule.timeout[PFTM_INTERVAL]));
+#endif
 
 		/* purge other expired types every PFTM_INTERVAL seconds */
 		if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) {
 			pf_purge_expired_fragments();
-			pf_purge_expired_src_nodes(0);
+			if (!pf_purge_expired_src_nodes(locked)) {
+				PF_UNLOCK();
+				sx_sunlock(&pf_consistency_lock);
+				sx_xlock(&pf_consistency_lock);
+				PF_LOCK();
+				locked = 1;
+				pf_purge_expired_src_nodes(1);
+			}
 			nloops = 0;
 		}
 
 		splx(s);
 #ifdef __FreeBSD__
 		PF_UNLOCK();
-		sx_sunlock(&pf_consistency_lock);
+		if (locked)
+			sx_xunlock(&pf_consistency_lock);
+		else
+			sx_sunlock(&pf_consistency_lock);
 #endif
 	}
 }
@@ -1056,8 +1088,13 @@ pf_state_expires(const struct pf_state *state)
 	return (state->expire + timeout);
 }
 
+#ifdef __FreeBSD__
+int
+pf_purge_expired_src_nodes(int waslocked)
+#else
 void
 pf_purge_expired_src_nodes(int waslocked)
+#endif
 {
 	 struct pf_src_node		*cur, *next;
 	 int				 locked = waslocked;
@@ -1068,12 +1105,8 @@ pf_purge_expired_src_nodes(int waslocked)
 		 if (cur->states <= 0 && cur->expire <= time_second) {
 			 if (! locked) {
 #ifdef __FreeBSD__
-				 if (!sx_try_upgrade(&pf_consistency_lock)) {
-					 PF_UNLOCK();
-					 sx_sunlock(&pf_consistency_lock);
-					 sx_xlock(&pf_consistency_lock);
-					 PF_LOCK();
-				 }
+				 if (!sx_try_upgrade(&pf_consistency_lock))
+				 	return (0);
 #else
 				 rw_enter_write(&pf_consistency_lock);
 #endif
@@ -1100,6 +1133,10 @@ pf_purge_expired_src_nodes(int waslocked)
 #else
 		rw_exit_write(&pf_consistency_lock);
 #endif
+
+#ifdef __FreeBSD__
+	return (1);
+#endif
 }
 
 void
@@ -1202,12 +1239,21 @@ pf_free_state(struct pf_state *cur)
 	pf_status.states--;
 }
 
+#ifdef __FreeBSD__
+int
+pf_purge_expired_states(u_int32_t maxcheck, int waslocked)
+#else
 void
 pf_purge_expired_states(u_int32_t maxcheck)
+#endif
 {
 	static struct pf_state	*cur = NULL;
 	struct pf_state		*next;
+#ifdef __FreeBSD__
+	int 			 locked = waslocked;
+#else
 	int 			 locked = 0;
+#endif
 
 	while (maxcheck--) {
 		/* wrap to start of list when we hit the end */
@@ -1224,12 +1270,8 @@ pf_purge_expired_states(u_int32_t maxcheck)
 			/* free unlinked state */
 			if (! locked) {
 #ifdef __FreeBSD__
-				 if (!sx_try_upgrade(&pf_consistency_lock)) {
-					 PF_UNLOCK();
-					 sx_sunlock(&pf_consistency_lock);
-					 sx_xlock(&pf_consistency_lock);
-					 PF_LOCK();
-				 }
+				 if (!sx_try_upgrade(&pf_consistency_lock))
+				 	return (0);
 #else
 				rw_enter_write(&pf_consistency_lock);
 #endif
@@ -1241,12 +1283,8 @@ pf_purge_expired_states(u_int32_t maxcheck)
 			pf_unlink_state(cur);
 			if (! locked) {
 #ifdef __FreeBSD__
-				 if (!sx_try_upgrade(&pf_consistency_lock)) {
-					 PF_UNLOCK();
-					 sx_sunlock(&pf_consistency_lock);
-					 sx_xlock(&pf_consistency_lock);
-					 PF_LOCK();
-				 }
+				 if (!sx_try_upgrade(&pf_consistency_lock))
+				 	return (0);
 #else
 				rw_enter_write(&pf_consistency_lock);
 #endif
@@ -1257,10 +1295,13 @@ pf_purge_expired_states(u_int32_t maxcheck)
 		cur = next;
 	}
 
-	if (locked)
 #ifdef __FreeBSD__
+	if (!waslocked && locked)
 		sx_downgrade(&pf_consistency_lock);
+
+	return (1);
 #else
+	if (locked)
 		rw_exit_write(&pf_consistency_lock);
 #endif
 }
diff --git a/sys/contrib/pf/net/pf_if.c b/sys/contrib/pf/net/pf_if.c
index a78a5452532..156fb22a731 100644
--- a/sys/contrib/pf/net/pf_if.c
+++ b/sys/contrib/pf/net/pf_if.c
@@ -663,7 +663,7 @@ pfi_address_add(struct sockaddr *sa, int af, int net)
 			    "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
 			return;
 		}
-		memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer));
+		memcpy(p, pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer));
 		/* no need to zero buffer */
 		free(pfi_buffer, PFI_MTYPE);
 		pfi_buffer = p;
diff --git a/sys/contrib/pf/net/pfvar.h b/sys/contrib/pf/net/pfvar.h
index 2c176db0299..32e721c5733 100644
--- a/sys/contrib/pf/net/pfvar.h
+++ b/sys/contrib/pf/net/pfvar.h
@@ -1593,8 +1593,13 @@ extern struct pool		 pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
 extern struct pool		 pf_state_scrub_pl;
 #endif
 extern void			 pf_purge_thread(void *);
+#ifdef __FreeBSD__
+extern int			 pf_purge_expired_src_nodes(int);
+extern int			 pf_purge_expired_states(u_int32_t, int);
+#else
 extern void			 pf_purge_expired_src_nodes(int);
 extern void			 pf_purge_expired_states(u_int32_t);
+#endif
 extern void			 pf_unlink_state(struct pf_state *);
 extern void			 pf_free_state(struct pf_state *);
 extern int			 pf_insert_state(struct pfi_kif *,
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
index c576a3584e5..f3d931aaf06 100644
--- a/sys/dev/aac/aac.c
+++ b/sys/dev/aac/aac.c
@@ -3270,10 +3270,10 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
 			while (co != NULL) {
 				if (co->co_found == 0) {
 					mtx_unlock(&sc->aac_io_lock);
-					newbus_xlock();
+					mtx_lock(&Giant);
 					device_delete_child(sc->aac_dev,
 							    co->co_disk);
-					newbus_xunlock();
+					mtx_unlock(&Giant);
 					mtx_lock(&sc->aac_io_lock);
 					co_next = TAILQ_NEXT(co, co_link);
 					mtx_lock(&sc->aac_container_lock);
@@ -3291,9 +3291,9 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
 			/* Attach the newly created containers */
 			if (added) {
 				mtx_unlock(&sc->aac_io_lock);
-				newbus_xlock();
+				mtx_lock(&Giant);
 				bus_generic_attach(sc->aac_dev);
-				newbus_xunlock();
+				mtx_unlock(&Giant);
 				mtx_lock(&sc->aac_io_lock);
 			}
 
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index c3e4e521379..a2e58833d25 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -675,6 +675,8 @@ acpi_suspend(device_t dev)
     device_t child, *devlist;
     int error, i, numdevs, pstate;
 
+    GIANT_REQUIRED;
+
     /* First give child devices a chance to suspend. */
     error = bus_generic_suspend(dev);
     if (error)
@@ -717,6 +719,8 @@ acpi_resume(device_t dev)
     int i, numdevs, error;
     device_t child, *devlist;
 
+    GIANT_REQUIRED;
+
     /*
      * Put all devices in D0 before resuming them.  Call _S0D on each one
      * since some systems expect this.
@@ -741,6 +745,8 @@ static int
 acpi_shutdown(device_t dev)
 {
 
+    GIANT_REQUIRED;
+
     /* Allow children to shutdown first. */
     bus_generic_shutdown(dev);
 
@@ -1008,14 +1014,27 @@ acpi_hint_device_unit(device_t acdev, device_t child, const char *name,
 	    continue;
 
 	/*
-	 * Check for matching resources.  We must have at least one,
-	 * and all resources specified have to match.
+	 * Check for matching resources.  We must have at least one match.
+	 * Since I/O and memory resources cannot be shared, if we get a
+	 * match on either of those, ignore any mismatches in IRQs or DRQs.
 	 *
 	 * XXX: We may want to revisit this to be more lenient and wire
 	 * as long as it gets one match.
 	 */
 	matches = 0;
 	if (resource_long_value(name, unit, "port", &value) == 0) {
+	    /*
+	     * Floppy drive controllers are notorious for having a
+	     * wide variety of resources not all of which include the
+	     * first port that is specified by the hint (typically
+	     * 0x3f0) (see the comment above fdc_isa_alloc_resources()
+	     * in fdc_isa.c).  However, they do all seem to include
+	     * port + 2 (e.g. 0x3f2) so for a floppy device, look for
+	     * 'value + 2' in the port resources instead of the hint
+	     * value.
+	     */
+	    if (strcmp(name, "fdc") == 0)
+		value += 2;
 	    if (acpi_match_resource_hint(child, SYS_RES_IOPORT, value))
 		matches++;
 	    else
@@ -1027,6 +1046,8 @@ acpi_hint_device_unit(device_t acdev, device_t child, const char *name,
 	    else
 		continue;
 	}
+	if (matches > 0)
+	    goto matched;
 	if (resource_long_value(name, unit, "irq", &value) == 0) {
 	    if (acpi_match_resource_hint(child, SYS_RES_IRQ, value))
 		matches++;
@@ -1040,6 +1061,7 @@ acpi_hint_device_unit(device_t acdev, device_t child, const char *name,
 		continue;
 	}
 
+    matched:
 	if (matches > 0) {
 	    /* We have a winner! */
 	    *unitp = unit;
@@ -2528,7 +2550,11 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
     thread_unlock(curthread);
 #endif
 
-    newbus_xlock();
+    /*
+     * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE
+     * drivers need this.
+     */
+    mtx_lock(&Giant);
 
     slp_state = ACPI_SS_NONE;
 
@@ -2601,7 +2627,7 @@ backout:
     if (slp_state >= ACPI_SS_SLEPT)
 	acpi_enable_fixed_events(sc);
 
-    newbus_xunlock();
+    mtx_unlock(&Giant);
 
 #ifdef SMP
     thread_lock(curthread);
diff --git a/sys/dev/acpica/acpi_battery.c b/sys/dev/acpica/acpi_battery.c
index 1ec1413d226..dd2b3fa2080 100644
--- a/sys/dev/acpica/acpi_battery.c
+++ b/sys/dev/acpica/acpi_battery.c
@@ -329,7 +329,6 @@ acpi_battery_find_dev(u_int logical_unit)
 
     dev = NULL;
     found_unit = 0;
-    newbus_slock();
     batt_dc = devclass_find("battery");
     maxunit = devclass_get_maxunit(batt_dc);
     for (i = 0; i < maxunit; i++) {
@@ -341,7 +340,6 @@ acpi_battery_find_dev(u_int logical_unit)
 	found_unit++;
 	dev = NULL;
     }
-    newbus_sunlock();
 
     return (dev);
 }
@@ -371,17 +369,13 @@ acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg)
      */
     switch (cmd) {
     case ACPIIO_BATT_GET_UNITS:
-	newbus_slock();
 	*(int *)addr = acpi_battery_get_units();
-	newbus_sunlock();
 	error = 0;
 	break;
     case ACPIIO_BATT_GET_BATTINFO:
 	if (dev != NULL || unit == ACPI_BATTERY_ALL_UNITS) {
 	    bzero(&ioctl_arg->battinfo, sizeof(ioctl_arg->battinfo));
-	    newbus_slock();
 	    error = acpi_battery_get_battinfo(dev, &ioctl_arg->battinfo);
-	    newbus_sunlock();
 	}
 	break;
     case ACPIIO_BATT_GET_BIF:
@@ -422,11 +416,6 @@ acpi_battery_sysctl(SYSCTL_HANDLER_ARGS)
 {
     int val, error;
 
-    /*
-     * Tolerate a race here because newbus lock can't be acquired before
-     * acpi_battery_get_battinfo() as it can create a LOR with the sysctl
-     * lock.
-     */
     acpi_battery_get_battinfo(NULL, &acpi_battery_battinfo);
     val = *(u_int *)oidp->oid_arg1;
     error = sysctl_handle_int(oidp, &val, 0, req);
@@ -438,10 +427,6 @@ acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS)
 {
     int count, error;
 
-    /*
-     * Tolerate a race here in order to avoid a LOR between sysctl lock
-     * and newbus lock.
-     */
     count = acpi_battery_get_units();
     error = sysctl_handle_int(oidp, &count, 0, req);
     return (error);
diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c
index 37134e23bf9..5d8ad535998 100644
--- a/sys/dev/acpica/acpi_cpu.c
+++ b/sys/dev/acpica/acpi_cpu.c
@@ -732,9 +732,7 @@ acpi_cpu_startup(void *arg)
     int i;
 
     /* Get set of CPU devices */
-    newbus_slock();
     devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices);
-    newbus_sunlock();
 
     /*
      * Setup any quirks that might necessary now that we have probed
diff --git a/sys/dev/acpica/acpi_dock.c b/sys/dev/acpica/acpi_dock.c
index 95b9faec157..b7d2e3e444a 100644
--- a/sys/dev/acpica/acpi_dock.c
+++ b/sys/dev/acpica/acpi_dock.c
@@ -188,12 +188,12 @@ acpi_dock_attach_later(void *context)
 
 	dev = (device_t)context;
 
-	newbus_xlock();
 	if (!device_is_enabled(dev))
 		device_enable(dev);
 
+	mtx_lock(&Giant);
 	device_probe_and_attach(dev);
-	newbus_xunlock();
+	mtx_unlock(&Giant);
 }
 
 static ACPI_STATUS
@@ -299,11 +299,11 @@ acpi_dock_eject_child(ACPI_HANDLE handle, UINT32 level, void *context,
 	    "ejecting device for %s\n", acpi_name(handle));
 
 	dev = acpi_get_device(handle);
-	newbus_xlock();
 	if (dev != NULL && device_is_attached(dev)) {
+		mtx_lock(&Giant);
 		device_detach(dev);
+		mtx_unlock(&Giant);
 	}
-	newbus_xunlock();
 
 	acpi_SetInteger(handle, "_EJ0", 0);
 out:
diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c
index 1e58d529fd0..962fdb7e938 100644
--- a/sys/dev/acpica/acpi_thermal.c
+++ b/sys/dev/acpica/acpi_thermal.c
@@ -936,8 +936,6 @@ acpi_tz_thread(void *arg)
     sc = NULL;
 
     for (;;) {
-	newbus_slock();
-
 	/* If the number of devices has changed, re-evaluate. */
 	if (devclass_get_count(acpi_tz_devclass) != devcount) {
 	    if (devs != NULL) {
@@ -950,7 +948,6 @@ acpi_tz_thread(void *arg)
 	    for (i = 0; i < devcount; i++)
 		sc[i] = device_get_softc(devs[i]);
 	}
-	newbus_sunlock();
 
 	/* Check for temperature events and act on them. */
 	for (i = 0; i < devcount; i++) {
diff --git a/sys/dev/adb/adb_bus.c b/sys/dev/adb/adb_bus.c
index c4a9c96ae9e..faab048b52c 100644
--- a/sys/dev/adb/adb_bus.c
+++ b/sys/dev/adb/adb_bus.c
@@ -113,7 +113,6 @@ adb_bus_enumerate(void *xdev)
 	uint8_t i, next_free;
 	uint16_t r3;
 
-	newbus_xlock();
 	sc->sc_dev = dev;
 	sc->parent = device_get_parent(dev);
 
@@ -188,7 +187,6 @@ adb_bus_enumerate(void *xdev)
 	}
 
 	bus_generic_attach(dev);
-	newbus_xunlock();
 
 	config_intrhook_disestablish(&sc->enum_hook);
 }
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 389648adf8e..273c276bd2a 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -63,6 +63,7 @@ static int ahci_suspend(device_t dev);
 static int ahci_resume(device_t dev);
 static int ahci_ch_suspend(device_t dev);
 static int ahci_ch_resume(device_t dev);
+static void ahci_ch_pm(void *arg);
 static void ahci_ch_intr_locked(void *data);
 static void ahci_ch_intr(void *data);
 static int ahci_ctlr_reset(device_t dev);
@@ -121,9 +122,11 @@ ahci_attach(device_t dev)
 	struct ahci_controller *ctlr = device_get_softc(dev);
 	device_t child;
 	int	error, unit, speed;
-	u_int32_t version, caps;
+	u_int32_t version;
 
 	ctlr->dev = dev;
+	resource_int_value(device_get_name(dev),
+	    device_get_unit(dev), "ccc", &ctlr->ccc);
 	/* if we have a memory BAR(5) we are likely on an AHCI part */
 	ctlr->r_rid = PCIR_BAR(5);
 	if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -160,41 +163,49 @@ ahci_attach(device_t dev)
 	}
 	/* Announce HW capabilities. */
 	version = ATA_INL(ctlr->r_mem, AHCI_VS);
-	caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
-	speed = (caps & AHCI_CAP_ISS) >> AHCI_CAP_ISS_SHIFT;
+	ctlr->caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
+	if (version >= 0x00010020)
+		ctlr->caps2 = ATA_INL(ctlr->r_mem, AHCI_CAP2);
+	speed = (ctlr->caps & AHCI_CAP_ISS) >> AHCI_CAP_ISS_SHIFT;
 	device_printf(dev,
 		    "AHCI v%x.%02x with %d %sGbps ports, Port Multiplier %s\n",
 		    ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f),
 		    ((version >> 4) & 0xf0) + (version & 0x0f),
-		    (caps & AHCI_CAP_NPMASK) + 1,
+		    (ctlr->caps & AHCI_CAP_NPMASK) + 1,
 		    ((speed == 1) ? "1.5":((speed == 2) ? "3":
 		    ((speed == 3) ? "6":"?"))),
-		    (caps & AHCI_CAP_SPM) ?
+		    (ctlr->caps & AHCI_CAP_SPM) ?
 		    "supported" : "not supported");
 	if (bootverbose) {
 		device_printf(dev, "Caps:%s%s%s%s%s%s%s%s %sGbps",
-		    (caps & AHCI_CAP_64BIT) ? " 64bit":"",
-		    (caps & AHCI_CAP_SNCQ) ? " NCQ":"",
-		    (caps & AHCI_CAP_SSNTF) ? " SNTF":"",
-		    (caps & AHCI_CAP_SMPS) ? " MPS":"",
-		    (caps & AHCI_CAP_SSS) ? " SS":"",
-		    (caps & AHCI_CAP_SALP) ? " ALP":"",
-		    (caps & AHCI_CAP_SAL) ? " AL":"",
-		    (caps & AHCI_CAP_SCLO) ? " CLO":"",
+		    (ctlr->caps & AHCI_CAP_64BIT) ? " 64bit":"",
+		    (ctlr->caps & AHCI_CAP_SNCQ) ? " NCQ":"",
+		    (ctlr->caps & AHCI_CAP_SSNTF) ? " SNTF":"",
+		    (ctlr->caps & AHCI_CAP_SMPS) ? " MPS":"",
+		    (ctlr->caps & AHCI_CAP_SSS) ? " SS":"",
+		    (ctlr->caps & AHCI_CAP_SALP) ? " ALP":"",
+		    (ctlr->caps & AHCI_CAP_SAL) ? " AL":"",
+		    (ctlr->caps & AHCI_CAP_SCLO) ? " CLO":"",
 		    ((speed == 1) ? "1.5":((speed == 2) ? "3":
 		    ((speed == 3) ? "6":"?"))));
 		printf("%s%s%s%s%s%s %dcmd%s%s%s %dports\n",
-		    (caps & AHCI_CAP_SAM) ? " AM":"",
-		    (caps & AHCI_CAP_SPM) ? " PM":"",
-		    (caps & AHCI_CAP_FBSS) ? " FBS":"",
-		    (caps & AHCI_CAP_PMD) ? " PMD":"",
-		    (caps & AHCI_CAP_SSC) ? " SSC":"",
-		    (caps & AHCI_CAP_PSC) ? " PSC":"",
-		    ((caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1,
-		    (caps & AHCI_CAP_CCCS) ? " CCC":"",
-		    (caps & AHCI_CAP_EMS) ? " EM":"",
-		    (caps & AHCI_CAP_SXS) ? " eSATA":"",
-		    (caps & AHCI_CAP_NPMASK) + 1);
+		    (ctlr->caps & AHCI_CAP_SAM) ? " AM":"",
+		    (ctlr->caps & AHCI_CAP_SPM) ? " PM":"",
+		    (ctlr->caps & AHCI_CAP_FBSS) ? " FBS":"",
+		    (ctlr->caps & AHCI_CAP_PMD) ? " PMD":"",
+		    (ctlr->caps & AHCI_CAP_SSC) ? " SSC":"",
+		    (ctlr->caps & AHCI_CAP_PSC) ? " PSC":"",
+		    ((ctlr->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1,
+		    (ctlr->caps & AHCI_CAP_CCCS) ? " CCC":"",
+		    (ctlr->caps & AHCI_CAP_EMS) ? " EM":"",
+		    (ctlr->caps & AHCI_CAP_SXS) ? " eSATA":"",
+		    (ctlr->caps & AHCI_CAP_NPMASK) + 1);
+	}
+	if (bootverbose && version >= 0x00010020) {
+		device_printf(dev, "Caps2:%s%s%s\n",
+		    (ctlr->caps2 & AHCI_CAP2_APST) ? " APST":"",
+		    (ctlr->caps2 & AHCI_CAP2_NVMP) ? " NVMP":"",
+		    (ctlr->caps2 & AHCI_CAP2_BOH) ? " BOH":"");
 	}
 	/* Attach all channels on this controller */
 	for (unit = 0; unit < ctlr->channels; unit++) {
@@ -266,6 +277,21 @@ ahci_ctlr_reset(device_t dev)
 	ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE);
 	/* Clear interrupts */
 	ATA_OUTL(ctlr->r_mem, AHCI_IS, ATA_INL(ctlr->r_mem, AHCI_IS));
+	/* Configure CCC */
+	if (ctlr->ccc) {
+		ATA_OUTL(ctlr->r_mem, AHCI_CCCP, ATA_INL(ctlr->r_mem, AHCI_PI));
+		ATA_OUTL(ctlr->r_mem, AHCI_CCCC,
+		    (ctlr->ccc << AHCI_CCCC_TV_SHIFT) |
+		    (4 << AHCI_CCCC_CC_SHIFT) |
+		    AHCI_CCCC_EN);
+		ctlr->cccv = (ATA_INL(ctlr->r_mem, AHCI_CCCC) &
+		    AHCI_CCCC_INT_MASK) >> AHCI_CCCC_INT_SHIFT;
+		if (bootverbose) {
+			device_printf(dev,
+			    "CCC with %dms/4cmd enabled on vector %d\n",
+			    ctlr->ccc, ctlr->cccv);
+		}
+	}
 	/* Enable AHCI interrupts */
 	ATA_OUTL(ctlr->r_mem, AHCI_GHC,
 	    ATA_INL(ctlr->r_mem, AHCI_GHC) | AHCI_GHC_IE);
@@ -326,7 +352,8 @@ ahci_setup_interrupt(device_t dev)
 	for (i = 0; i < ctlr->numirqs; i++) {
 		ctlr->irqs[i].ctlr = ctlr;
 		ctlr->irqs[i].r_irq_rid = i + (msi ? 1 : 0);
-		if (ctlr->numirqs == 1 || i >= ctlr->channels)
+		if (ctlr->numirqs == 1 || i >= ctlr->channels ||
+		    (ctlr->ccc && i == ctlr->cccv))
 			ctlr->irqs[i].mode = AHCI_IRQ_MODE_ALL;
 		else if (i == ctlr->numirqs - 1)
 			ctlr->irqs[i].mode = AHCI_IRQ_MODE_AFTER;
@@ -360,11 +387,16 @@ ahci_intr(void *data)
 	void *arg;
 	int unit;
 
-	is = ATA_INL(ctlr->r_mem, AHCI_IS);
-	if (irq->mode == AHCI_IRQ_MODE_ALL)
+	if (irq->mode == AHCI_IRQ_MODE_ALL) {
 		unit = 0;
-	else	/* AHCI_IRQ_MODE_AFTER */
+		if (ctlr->ccc)
+			is = ctlr->ichannels;
+		else
+			is = ATA_INL(ctlr->r_mem, AHCI_IS);
+	} else {	/* AHCI_IRQ_MODE_AFTER */
 		unit = irq->r_irq_rid - 1;
+		is = ATA_INL(ctlr->r_mem, AHCI_IS);
+	}
 	for (; unit < ctlr->channels; unit++) {
 		if ((is & (1 << unit)) != 0 &&
 		    (arg = ctlr->interrupt[unit].argument)) {
@@ -523,10 +555,14 @@ ahci_ch_attach(device_t dev)
 
 	ch->dev = dev;
 	ch->unit = (intptr_t)device_get_ivars(dev);
-	ch->caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
+	ch->caps = ctlr->caps;
+	ch->caps2 = ctlr->caps2;
 	ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1,
+	mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF);
 	resource_int_value(device_get_name(dev),
 	    device_get_unit(dev), "pm_level", &ch->pm_level);
+	if (ch->pm_level > 3)
+		callout_init_mtx(&ch->pm_timer, &ch->mtx, 0);
 	/* Limit speed for my onboard JMicron external port.
 	 * It is not eSATA really. */
 	if (pci_get_devid(ctlr->dev) == 0x2363197b &&
@@ -536,7 +572,6 @@ ahci_ch_attach(device_t dev)
 		ch->sata_rev = 1;
 	resource_int_value(device_get_name(dev),
 	    device_get_unit(dev), "sata_rev", &ch->sata_rev);
-	mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF);
 	rid = ch->unit;
 	if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
 	    &rid, RF_ACTIVE)))
@@ -584,6 +619,11 @@ ahci_ch_attach(device_t dev)
 		error = ENXIO;
 		goto err3;
 	}
+	if (ch->pm_level > 3) {
+		callout_reset(&ch->pm_timer,
+		    (ch->pm_level == 4) ? hz / 1000 : hz / 8,
+		    ahci_ch_pm, dev);
+	}
 	mtx_unlock(&ch->mtx);
 	return (0);
 
@@ -610,6 +650,8 @@ ahci_ch_detach(device_t dev)
 	cam_sim_free(ch->sim, /*free_devq*/TRUE);
 	mtx_unlock(&ch->mtx);
 
+	if (ch->pm_level > 3)
+		callout_drain(&ch->pm_timer);
 	bus_teardown_intr(dev, ch->r_irq, ch->ih);
 	bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
 
@@ -661,7 +703,7 @@ ahci_ch_resume(device_t dev)
 	/* Activate the channel and power/spin up device */
 	ATA_OUTL(ch->r_mem, AHCI_P_CMD,
 	     (AHCI_P_CMD_ACTIVE | AHCI_P_CMD_POD | AHCI_P_CMD_SUD |
-	     ((ch->pm_level > 1) ? AHCI_P_CMD_ALPE : 0) |
+	     ((ch->pm_level == 2 || ch->pm_level == 3) ? AHCI_P_CMD_ALPE : 0) |
 	     ((ch->pm_level > 2) ? AHCI_P_CMD_ASP : 0 )));
 	ahci_start_fr(dev);
 	ahci_start(dev);
@@ -815,6 +857,7 @@ ahci_slotsfree(device_t dev)
 	for (i = 0; i < ch->numslots; i++) {
 		struct ahci_slot *slot = &ch->slot[i];
 
+		callout_drain(&slot->timeout);
 		if (slot->dma.data_map) {
 			bus_dmamap_destroy(ch->dma.data_tag, slot->dma.data_map);
 			slot->dma.data_map = NULL;
@@ -847,6 +890,27 @@ ahci_phy_check_events(device_t dev)
 	}
 }
 
+static void
+ahci_notify_events(device_t dev, u_int32_t status)
+{
+	struct ahci_channel *ch = device_get_softc(dev);
+	struct cam_path *dpath;
+	int i;
+
+	ATA_OUTL(ch->r_mem, AHCI_P_SNTF, status);
+	if (bootverbose)
+		device_printf(dev, "SNTF 0x%04x\n", status);
+	for (i = 0; i < 16; i++) {
+		if ((status & (1 << i)) == 0)
+			continue;
+		if (xpt_create_path(&dpath, NULL,
+		    xpt_path_path_id(ch->path), i, 0) == CAM_REQ_CMP) {
+			xpt_async(AC_SCSI_AEN, dpath, NULL);
+			xpt_free_path(dpath);
+		}
+	}
+}
+
 static void
 ahci_ch_intr_locked(void *data)
 {
@@ -858,21 +922,42 @@ ahci_ch_intr_locked(void *data)
 	mtx_unlock(&ch->mtx);
 }
 
+static void
+ahci_ch_pm(void *arg)
+{
+	device_t dev = (device_t)arg;
+	struct ahci_channel *ch = device_get_softc(dev);
+	uint32_t work;
+
+	if (ch->numrslots != 0)
+		return;
+	work = ATA_INL(ch->r_mem, AHCI_P_CMD);
+	if (ch->pm_level == 4)
+		work |= AHCI_P_CMD_PARTIAL;
+	else
+		work |= AHCI_P_CMD_SLUMBER;
+	ATA_OUTL(ch->r_mem, AHCI_P_CMD, work);
+}
+
 static void
 ahci_ch_intr(void *data)
 {
 	device_t dev = (device_t)data;
 	struct ahci_channel *ch = device_get_softc(dev);
-	uint32_t istatus, cstatus, sstatus, ok, err;
+	uint32_t istatus, sstatus, cstatus, sntf = 0, ok, err;
 	enum ahci_err_type et;
 	int i, ccs, ncq_err = 0;
 
 	/* Read and clear interrupt statuses. */
 	istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
+	if (istatus == 0)
+		return;
 	ATA_OUTL(ch->r_mem, AHCI_P_IS, istatus);
 	/* Read command statuses. */
-	cstatus = ATA_INL(ch->r_mem, AHCI_P_CI);
 	sstatus = ATA_INL(ch->r_mem, AHCI_P_SACT);
+	cstatus = ATA_INL(ch->r_mem, AHCI_P_CI);
+	if ((istatus & AHCI_P_IX_SDB) && (ch->caps & AHCI_CAP_SSNTF))
+		sntf = ATA_INL(ch->r_mem, AHCI_P_SNTF);
 	/* Process PHY events */
 	if (istatus & (AHCI_P_IX_PRC | AHCI_P_IX_PC))
 		ahci_phy_check_events(dev);
@@ -884,17 +969,16 @@ ahci_ch_intr(void *data)
 //    ATA_INL(ch->r_mem, AHCI_P_SERR));
 		ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
 		    >> AHCI_P_CMD_CCS_SHIFT;
+		err = ch->rslots & (cstatus | sstatus);
 		/* Kick controller into sane state */
 		ahci_stop(dev);
 		ahci_start(dev);
-		ok = ch->rslots & ~(cstatus | sstatus);
-		err = ch->rslots & (cstatus | sstatus);
 	} else {
 		ccs = 0;
-		ok = ch->rslots & ~(cstatus | sstatus);
 		err = 0;
 	}
 	/* Complete all successfull commands. */
+	ok = ch->rslots & ~(cstatus | sstatus);
 	for (i = 0; i < ch->numslots; i++) {
 		if ((ok >> i) & 1)
 			ahci_end_transaction(&ch->slot[i], AHCI_ERR_NONE);
@@ -936,6 +1020,9 @@ ahci_ch_intr(void *data)
 		if (ncq_err)
 			ahci_issue_read_log(dev);
 	}
+	/* Process NOTIFY events */
+	if (sntf)
+		ahci_notify_events(dev, sntf);
 }
 
 /* Must be called with channel locked. */
@@ -980,19 +1067,18 @@ ahci_begin_transaction(device_t dev, union ccb *ccb)
 
 	/* Choose empty slot. */
 	tag = ch->lastslot;
-	do {
-		tag++;
-		if (tag >= ch->numslots)
+	while (ch->slot[tag].state != AHCI_SLOT_EMPTY) {
+		if (++tag >= ch->numslots)
 			tag = 0;
-		if (ch->slot[tag].state == AHCI_SLOT_EMPTY)
-			break;
-	} while (tag != ch->lastslot);
-	if (ch->slot[tag].state != AHCI_SLOT_EMPTY)
-		device_printf(ch->dev, "ALL SLOTS BUSY!\n");
+		KASSERT(tag != ch->lastslot, ("ahci: ALL SLOTS BUSY!"));
+	}
 	ch->lastslot = tag;
 	/* Occupy chosen slot. */
 	slot = &ch->slot[tag];
 	slot->ccb = ccb;
+	/* Stop PM timer. */
+	if (ch->numrslots == 0 && ch->pm_level > 3)
+		callout_stop(&ch->pm_timer);
 	/* Update channel stats. */
 	ch->numrslots++;
 	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
@@ -1162,6 +1248,10 @@ ahci_timeout(struct ahci_slot *slot)
 	struct ahci_channel *ch = device_get_softc(dev);
 	int i;
 
+	/* Check for stale timeout. */
+	if (slot->state != AHCI_SLOT_RUNNING)
+		return;
+
 	device_printf(dev, "Timeout on slot %d\n", slot->slot);
 	/* Kick controller into sane state. */
 	ahci_stop(ch->dev);
@@ -1194,8 +1284,6 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
 	struct ahci_channel *ch = device_get_softc(dev);
 	union ccb *ccb = slot->ccb;
 
-	/* Cancel command execution timeout */
-	callout_stop(&slot->timeout);
 	bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
 	    BUS_DMASYNC_POSTWRITE);
 	/* Read result registers to the result struct
@@ -1302,6 +1390,11 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
 		ahci_begin_transaction(dev, fccb);
 		xpt_release_simq(ch->sim, TRUE);
 	}
+	/* Start PM timer. */
+	if (ch->numrslots == 0 && ch->pm_level > 3) {
+		callout_schedule(&ch->pm_timer,
+		    (ch->pm_level == 4) ? hz / 1000 : hz / 8);
+	}
 }
 
 static void
@@ -1516,6 +1609,7 @@ static void
 ahci_reset(device_t dev)
 {
 	struct ahci_channel *ch = device_get_softc(dev);
+	struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev));
 	int i;
 
 	if (bootverbose)
@@ -1562,10 +1656,10 @@ ahci_reset(device_t dev)
 	     (AHCI_P_IX_CPD | AHCI_P_IX_TFE | AHCI_P_IX_HBF |
 	      AHCI_P_IX_HBD | AHCI_P_IX_IF | AHCI_P_IX_OF |
 	      ((ch->pm_level == 0) ? AHCI_P_IX_PRC | AHCI_P_IX_PC : 0) |
-	      AHCI_P_IX_DP | AHCI_P_IX_UF | AHCI_P_IX_SDB |
-	      AHCI_P_IX_DS | AHCI_P_IX_PS | AHCI_P_IX_DHR));
+	      AHCI_P_IX_DP | AHCI_P_IX_UF | (ctlr->ccc ? 0 : AHCI_P_IX_SDB) |
+	      AHCI_P_IX_DS | AHCI_P_IX_PS | (ctlr->ccc ? 0 : AHCI_P_IX_DHR)));
 	if (bootverbose)
-		device_printf(dev, "AHCI reset done: devices=%08x\n", ch->devices);
+		device_printf(dev, "AHCI reset done: device found\n");
 	/* Tell the XPT about the event */
 	xpt_async(AC_BUS_RESET, ch->path, NULL);
 }
@@ -1632,6 +1726,13 @@ ahci_sata_connect(struct ahci_channel *ch)
 		    ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
 		    ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE))
 			break;
+		if ((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_OFFLINE) {
+			if (bootverbose) {
+				device_printf(ch->dev, "SATA offline status=%08x\n",
+				    status);
+			}
+			return (0);
+		}
 		DELAY(1000);
 	}
 	if (timeout >= 100) {
@@ -1664,9 +1765,6 @@ ahci_sata_phy_reset(device_t dev, int quick)
 
 	if (bootverbose)
 		device_printf(dev, "hardware reset ...\n");
-	ATA_OUTL(ch->r_mem, AHCI_P_SCTL, ATA_SC_IPM_DIS_PARTIAL |
-	    ATA_SC_IPM_DIS_SLUMBER | ATA_SC_DET_RESET);
-	DELAY(50000);
 	if (ch->sata_rev == 1)
 		val = ATA_SC_SPD_SPEED_GEN1;
 	else if (ch->sata_rev == 2)
@@ -1675,10 +1773,14 @@ ahci_sata_phy_reset(device_t dev, int quick)
 		val = ATA_SC_SPD_SPEED_GEN3;
 	else
 		val = 0;
+	ATA_OUTL(ch->r_mem, AHCI_P_SCTL,
+	    ATA_SC_DET_RESET | val |
+	    ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER);
+	DELAY(5000);
 	ATA_OUTL(ch->r_mem, AHCI_P_SCTL,
 	    ATA_SC_DET_IDLE | val | ((ch->pm_level > 0) ? 0 :
 	    (ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)));
-	DELAY(50000);
+	DELAY(5000);
 	return (ahci_sata_connect(ch));
 }
 
@@ -1739,9 +1841,9 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
 		uint32_t status;
 
 		cts->protocol = PROTO_ATA;
-		cts->protocol_version = SCSI_REV_2;
+		cts->protocol_version = PROTO_VERSION_UNSPECIFIED;
 		cts->transport = XPORT_SATA;
-		cts->transport_version = 2;
+		cts->transport_version = XPORT_VERSION_UNSPECIFIED;
 		cts->proto_specific.valid = 0;
 		cts->xport_specific.sata.valid = 0;
 		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
@@ -1834,10 +1936,13 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
 		cpi->unit_number = cam_sim_unit(sim);
 		cpi->transport = XPORT_SATA;
-		cpi->transport_version = 2;
+		cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
 		cpi->protocol = PROTO_ATA;
-		cpi->protocol_version = SCSI_REV_2;
+		cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
 		cpi->maxio = MAXPHYS;
+		/* ATI SB600 can't handle 256 sectors with FPDMA (NCQ). */
+		if (pci_get_devid(device_get_parent(dev)) == 0x43801002)
+			cpi->maxio = min(cpi->maxio, 128 * 512);
 		cpi->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 		break;
diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h
index dadbd84f255..9b5726ac805 100644
--- a/sys/dev/ahci/ahci.h
+++ b/sys/dev/ahci/ahci.h
@@ -176,6 +176,21 @@
 #define AHCI_PI                     0x0c
 #define AHCI_VS                     0x10
 
+#define AHCI_CCCC                   0x14
+#define		AHCI_CCCC_TV_MASK	0xffff0000
+#define		AHCI_CCCC_TV_SHIFT	16
+#define		AHCI_CCCC_CC_MASK	0x0000ff00
+#define		AHCI_CCCC_CC_SHIFT	8
+#define		AHCI_CCCC_INT_MASK	0x000000f8
+#define		AHCI_CCCC_INT_SHIFT	3
+#define		AHCI_CCCC_EN		0x00000001
+#define AHCI_CCCP                   0x18
+
+#define AHCI_CAP2                   0x24
+#define		AHCI_CAP2_BOH	0x00000001
+#define		AHCI_CAP2_NVMP	0x00000002
+#define		AHCI_CAP2_APST	0x00000004
+
 #define AHCI_OFFSET                 0x100
 #define AHCI_STEP                   0x80
 
@@ -336,6 +351,7 @@ struct ahci_channel {
 	struct cam_sim		*sim;
 	struct cam_path		*path;
 	uint32_t		caps;		/* Controller capabilities */
+	uint32_t		caps2;		/* Controller capabilities */
 	int			numslots;	/* Number of present slots */
 	int			pm_level;	/* power management level */
 	int			sata_rev;	/* Maximum allowed SATA generation */
@@ -353,6 +369,7 @@ struct ahci_channel {
 	int			lastslot;	/* Last used slot */
 	int			taggedtarget;	/* Last tagged target */
 	union ccb		*frozen;	/* Frozen command */
+	struct callout		pm_timer;	/* Power management events */
 };
 
 /* structure describing a AHCI controller */
@@ -371,9 +388,13 @@ struct ahci_controller {
 #define	AHCI_IRQ_MODE_AFTER	1
 #define	AHCI_IRQ_MODE_ONE	2
 	} irqs[16];
+	uint32_t		caps;		/* Controller capabilities */
+	uint32_t		caps2;		/* Controller capabilities */
 	int			numirqs;
 	int			channels;
 	int			ichannels;
+	int			ccc;		/* CCC timeout */
+	int			cccv;		/* CCC vector */
 	struct {
 		void			(*function)(void *);
 		void			*argument;
diff --git a/sys/dev/alc/if_alc.c b/sys/dev/alc/if_alc.c
index f3483b7747c..a53af779b03 100644
--- a/sys/dev/alc/if_alc.c
+++ b/sys/dev/alc/if_alc.c
@@ -858,7 +858,8 @@ alc_detach(device_t dev)
 			sc->alc_intrhand[i] = NULL;
 		}
 	}
-	alc_phy_down(sc);
+	if (sc->alc_res[0] != NULL)
+		alc_phy_down(sc);
 	bus_release_resources(dev, sc->alc_irq_spec, sc->alc_irq);
 	if ((sc->alc_flags & (ALC_FLAG_MSI | ALC_FLAG_MSIX)) != 0)
 		pci_release_msi(dev);
diff --git a/sys/dev/amdtemp/amdtemp.c b/sys/dev/amdtemp/amdtemp.c
index ba7436aa57d..fdf087533c5 100644
--- a/sys/dev/amdtemp/amdtemp.c
+++ b/sys/dev/amdtemp/amdtemp.c
@@ -269,7 +269,6 @@ amdtemp_intrhook(void *arg)
 	/*
 	 * dev.cpu.N.temperature.
 	 */
-	newbus_xlock();
 	nexus = device_find_child(root_bus, "nexus", 0);
 	acpi = device_find_child(nexus, "acpi", 0);
 
@@ -286,7 +285,6 @@ amdtemp_intrhook(void *arg)
 			    "Max of sensor 0 / 1");
 		}
 	}
-	newbus_xunlock();
 	config_intrhook_disestablish(&sc->sc_ich);
 }
 
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index 688b2df63ad..2061fcc801f 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -90,10 +90,6 @@ __FBSDID("$FreeBSD$");
 
 SYSCTL_NODE(_hw, OID_AUTO, amr, CTLFLAG_RD, 0, "AMR driver parameters");
 
-/*
- * In order to get rid of Giant, amr_state should be protected by
- * a proper softc lock for the cdev operations.
- */
 static d_open_t         amr_open;
 static d_close_t        amr_close;
 static d_ioctl_t        amr_ioctl;
@@ -316,11 +312,9 @@ amr_startup(void *arg)
 	config_intrhook_disestablish(&sc->amr_ich);
     sc->amr_ich.ich_func = NULL;
 
-    newbus_xlock();
     /* get up-to-date drive information */
     if (amr_query_controller(sc)) {
 	device_printf(sc->amr_dev, "can't scan controller for drives\n");
-	newbus_xunlock();
 	return;
     }
 
@@ -353,7 +347,6 @@ amr_startup(void *arg)
 
     /* interrupts will be enabled before we do anything more */
     sc->amr_state |= AMR_STATE_INTEN;
-    newbus_xunlock();
 
     /*
      * Start the timeout routine.
@@ -441,11 +434,7 @@ static int
 amr_open(struct cdev *dev, int flags, int fmt, struct thread *td)
 {
     int			unit = dev2unit(dev);
-    struct amr_softc	*sc;
-
-    newbus_slock();
-    sc = devclass_get_softc(devclass_find("amr"), unit);
-    newbus_sunlock();
+    struct amr_softc	*sc = devclass_get_softc(devclass_find("amr"), unit);
 
     debug_called(1);
 
@@ -501,11 +490,7 @@ static int
 amr_close(struct cdev *dev, int flags, int fmt, struct thread *td)
 {
     int			unit = dev2unit(dev);
-    struct amr_softc	*sc;
-
-    newbus_slock();
-    sc = devclass_get_softc(devclass_find("amr"), unit);
-    newbus_sunlock();
+    struct amr_softc	*sc = devclass_get_softc(devclass_find("amr"), unit);
 
     debug_called(1);
 
@@ -522,7 +507,6 @@ amr_rescan_drives(struct cdev *dev)
     struct amr_softc	*sc = (struct amr_softc *)dev->si_drv1;
     int			i, error = 0;
 
-    newbus_xlock();
     sc->amr_state |= AMR_STATE_REMAP_LD;
     while (sc->amr_busyslots) {
 	device_printf(sc->amr_dev, "idle controller\n");
@@ -546,7 +530,6 @@ amr_rescan_drives(struct cdev *dev)
 	     sc->amr_drive[i].al_disk = 0;
 	}
     }
-    newbus_xunlock();
 
 shutdown_out:
     amr_startup(sc);
@@ -822,9 +805,7 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct threa
 	    struct amr_linux_ioctl	ali;
 	    int				adapter, error;
 
-	    newbus_slock();
 	    devclass = devclass_find("amr");
-	    newbus_sunlock();
 	    if (devclass == NULL)
 		return (ENOENT);
 
diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c
index b13f6ddc254..7f7f0314014 100644
--- a/sys/dev/asmc/asmc.c
+++ b/sys/dev/asmc/asmc.c
@@ -419,7 +419,8 @@ asmc_attach(device_t dev)
 
 		SYSCTL_ADD_PROC(sysctlctx,
 		    SYSCTL_CHILDREN(sc->sc_light_tree),
-		    OID_AUTO, "control", CTLTYPE_INT | CTLFLAG_RW,
+		    OID_AUTO, "control",
+		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
 		    dev, 0, model->smc_light_control, "I",
 		    "Keyboard backlight brightness control");
 	}
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 6696f0cff0c..1460a2117d4 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 static  d_ioctl_t       ata_ioctl;
 static struct cdevsw ata_cdevsw = {
 	.d_version =    D_VERSION,
+	.d_flags =      D_NEEDGIANT, /* we need this as newbus isn't mpsafe */
 	.d_ioctl =      ata_ioctl,
 	.d_name =       "ata",
 };
@@ -203,9 +204,7 @@ ata_conn_event(void *context, int dummy)
 {
     device_t dev = (device_t)context;
 
-    newbus_xlock();
     ata_reinit(dev);
-    newbus_xunlock();
 }
 
 int
@@ -247,6 +246,7 @@ ata_reinit(device_t dev)
 
     /* reinit the children and delete any that fails */
     if (!device_get_children(dev, &children, &nchildren)) {
+	mtx_lock(&Giant);       /* newbus suckage it needs Giant */
 	for (i = 0; i < nchildren; i++) {
 	    /* did any children go missing ? */
 	    if (children[i] && device_is_attached(children[i]) &&
@@ -269,6 +269,7 @@ ata_reinit(device_t dev)
 	    }
 	}
 	free(children, M_TEMP);
+	mtx_unlock(&Giant);     /* newbus suckage dealt with, release Giant */
     }
 
     /* if we still have a good request put it on the queue again */
@@ -394,7 +395,6 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
     int *value = (int *)data;
     int i, nchildren, error = ENOTTY;
 
-    newbus_xlock();
     switch (cmd) {
     case IOCATAGMAXCHANNEL:
 	/* In case we have channel 0..n this will return n+1. */
@@ -405,40 +405,32 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
     case IOCATAREINIT:
 	if (*value >= devclass_get_maxunit(ata_devclass) ||
 	    !(device = devclass_get_device(ata_devclass, *value)) ||
-	    !device_is_attached(device)) {
-            newbus_xunlock();
+	    !device_is_attached(device))
 	    return ENXIO;
-	}
 	error = ata_reinit(device);
 	break;
 
     case IOCATAATTACH:
 	if (*value >= devclass_get_maxunit(ata_devclass) ||
 	    !(device = devclass_get_device(ata_devclass, *value)) ||
-	    !device_is_attached(device)) {
-            newbus_xunlock();
+	    !device_is_attached(device))
 	    return ENXIO;
-	}
 	error = DEVICE_ATTACH(device);
 	break;
 
     case IOCATADETACH:
 	if (*value >= devclass_get_maxunit(ata_devclass) ||
 	    !(device = devclass_get_device(ata_devclass, *value)) ||
-	    !device_is_attached(device)) {
-            newbus_xunlock();
+	    !device_is_attached(device))
 	    return ENXIO;
-	}
 	error = DEVICE_DETACH(device);
 	break;
 
     case IOCATADEVICES:
 	if (devices->channel >= devclass_get_maxunit(ata_devclass) ||
 	    !(device = devclass_get_device(ata_devclass, devices->channel)) ||
-	    !device_is_attached(device)) {
-            newbus_xunlock();
+	    !device_is_attached(device))
 	    return ENXIO;
-	}
 	bzero(devices->name[0], 32);
 	bzero(&devices->params[0], sizeof(struct ata_params));
 	bzero(devices->name[1], 32);
@@ -473,7 +465,6 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
 	if (ata_raid_ioctl_func)
 	    error = ata_raid_ioctl_func(cmd, data);
     }
-    newbus_xunlock();
     return error;
 }
 
@@ -581,7 +572,7 @@ ata_boot_attach(void)
     struct ata_channel *ch;
     int ctlr;
 
-    newbus_xlock();
+    mtx_lock(&Giant);       /* newbus suckage it needs Giant */
 
     /* kick of probe and attach on all channels */
     for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) {
@@ -596,7 +587,8 @@ ata_boot_attach(void)
 	free(ata_delayed_attach, M_TEMP);
 	ata_delayed_attach = NULL;
     }
-    newbus_xunlock();
+
+    mtx_unlock(&Giant);     /* newbus suckage dealt with, release Giant */
 }
 
 
@@ -725,6 +717,7 @@ ata_identify(device_t dev)
     if (bootverbose)
 	device_printf(dev, "Identifying devices: %08x\n", ch->devices);
 
+    mtx_lock(&Giant);
     /* Skip existing devices. */
     if (!device_get_children(dev, &children, &nchildren)) {
 	for (i = 0; i < nchildren; i++) {
@@ -736,8 +729,10 @@ ata_identify(device_t dev)
     /* Create new devices. */
     if (bootverbose)
 	device_printf(dev, "New devices: %08x\n", n);
-    if (n == 0)
+    if (n == 0) {
+	mtx_unlock(&Giant);
 	return (0);
+    }
     for (i = 0; i < ATA_PM; ++i) {
 	if (n & (((ATA_ATA_MASTER | ATA_ATAPI_MASTER) << i))) {
 	    int unit = -1;
@@ -780,6 +775,7 @@ ata_identify(device_t dev)
     }
     bus_generic_probe(dev);
     bus_generic_attach(dev);
+    mtx_unlock(&Giant);
     return 0;
 }
 
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index 15b9edc30b2..c699a05f52e 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -136,8 +136,8 @@ ad_attach(device_t dev)
     if ((atadev->param.support.command2 & ATA_SUPPORT_CFA) ||
 	atadev->param.config == ATA_PROTO_CFA)
 	adp->disk->d_flags = DISKFLAG_CANDELETE;
-    snprintf(adp->disk->d_ident, sizeof(adp->disk->d_ident), "ad:%s",
-	atadev->param.serial);
+    strlcpy(adp->disk->d_ident, atadev->param.serial,
+	sizeof(adp->disk->d_ident));
     disk_create(adp->disk, DISK_VERSION);
     device_add_child(dev, "subdisk", device_get_unit(dev));
     ad_firmware_geom_adjust(dev, adp->disk);
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index afc35506b57..770b13f0e3c 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -272,10 +272,10 @@ ata_dmaload(struct ata_request *request, void *addr, int *entries)
 		      "FAILURE - zero length DMA transfer attempted\n");
 	return EIO;
     }
-    if (((uintptr_t)(request->data) & (ch->dma.alignment - 1)) ||
-	(request->bytecount & (ch->dma.alignment - 1))) {
+    if (request->bytecount & (ch->dma.alignment - 1)) {
 	device_printf(request->dev,
-		      "FAILURE - non aligned DMA transfer attempted\n");
+		      "FAILURE - odd-sized DMA transfer attempt %d %% %d\n",
+		      request->bytecount, ch->dma.alignment);
 	return EIO;
     }
     if (request->bytecount > ch->dma.max_iosize) {
diff --git a/sys/dev/ath/ah_osdep.c b/sys/dev/ath/ah_osdep.c
index 7ba7817188d..6b11b212fea 100644
--- a/sys/dev/ath/ah_osdep.c
+++ b/sys/dev/ath/ah_osdep.c
@@ -110,7 +110,7 @@ ath_hal_malloc(size_t size)
 void
 ath_hal_free(void* p)
 {
-	return free(p, M_ATH_HAL);
+	free(p, M_ATH_HAL);
 }
 
 void
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v3.c b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
index 20adb3119f3..89a23c9f9fd 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v3.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
@@ -1759,7 +1759,7 @@ legacyEepromDetach(struct ath_hal *ah)
 	HAL_EEPROM *ee = AH_PRIVATE(ah)->ah_eeprom;
 
         if (ee->ee_version >= AR_EEPROM_VER4_0 && ee->ee_eepMap == 1)
-		return freeEepromRawPowerCalInfo5112(ah, ee);
+		freeEepromRawPowerCalInfo5112(ah, ee);
 	ath_hal_free(ee);
 	AH_PRIVATE(ah)->ah_eeprom = AH_NULL;
 }
diff --git a/sys/dev/ath/ath_hal/ah_regdomain.c b/sys/dev/ath/ath_hal/ah_regdomain.c
index 814b9ab335d..fd138a48735 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain.c
+++ b/sys/dev/ath/ath_hal/ah_regdomain.c
@@ -573,7 +573,7 @@ static COUNTRY_CODE_TO_ENUM_RD allCountries[] = {
 	{ CTRY_SWITZERLAND, ETSI1_WORLD },
 	{ CTRY_SYRIA,       NULL1_WORLD },
 	{ CTRY_TAIWAN,      APL3_FCCA },
-	{ CTRY_THAILAND,    NULL1_WORLD },
+	{ CTRY_THAILAND,    FCC3_WORLD },
 	{ CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD },
 	{ CTRY_TUNISIA,     ETSI3_WORLD },
 	{ CTRY_TURKEY,      ETSI3_WORLD },
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index a789f5ea298..b6fbaf857d6 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -1236,7 +1236,16 @@ ath_resume(struct ath_softc *sc)
 	if (sc->sc_resume_up) {
 		if (ic->ic_opmode == IEEE80211_M_STA) {
 			ath_init(sc);
-			ieee80211_beacon_miss(ic);
+			/*
+			 * Program the beacon registers using the last rx'd
+			 * beacon frame and enable sync on the next beacon
+			 * we see.  This should handle the case where we
+			 * wakeup and find the same AP and also the case where
+			 * we wakeup and need to roam.  For the latter we
+			 * should get bmiss events that trigger a roam.
+			 */
+			ath_beacon_config(sc, NULL);
+			sc->sc_syncbeacon = 1;
 		} else
 			ieee80211_resume_all(ic);
 	}
@@ -1443,7 +1452,7 @@ ath_hal_gethangstate(struct ath_hal *ah, uint32_t mask, uint32_t *hangs)
 	uint32_t rsize;
 	void *sp;
 
-	if (!ath_hal_getdiagstate(ah, 32, &mask, sizeof(&mask), &sp, &rsize))
+	if (!ath_hal_getdiagstate(ah, 32, &mask, sizeof(mask), &sp, &rsize))
 		return 0;
 	KASSERT(rsize == sizeof(uint32_t), ("resultsize %u", rsize));
 	*hangs = *(uint32_t *)sp;
diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c
index 1fbdee76e25..93c9acb7a9c 100644
--- a/sys/dev/atkbdc/psm.c
+++ b/sys/dev/atkbdc/psm.c
@@ -1488,9 +1488,7 @@ psmopen(struct cdev *dev, int flag, int fmt, struct thread *td)
 	if (sc->state & PSM_OPEN)
 		return (EBUSY);
 
-	newbus_xlock();
 	device_busy(devclass_get_device(psm_devclass, unit));
-	newbus_xunlock();
 
 	/* Initialize state */
 	sc->mode.level = sc->dflt_mode.level;
@@ -1645,9 +1643,7 @@ psmclose(struct cdev *dev, int flag, int fmt, struct thread *td)
 	/* close is almost always successful */
 	sc->state &= ~PSM_OPEN;
 	kbdc_lock(sc->kbdc, FALSE);
-	newbus_xlock();
 	device_unbusy(devclass_get_device(psm_devclass, unit));
-	newbus_xunlock();
 	return (0);
 }
 
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 4528762a02d..db65ec2caad 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -3055,12 +3055,14 @@ bge_rxeof(struct bge_softc *sc)
 {
 	struct ifnet *ifp;
 	int rx_npkts = 0, stdcnt = 0, jumbocnt = 0;
+	uint16_t rx_prod, rx_cons;
 
 	BGE_LOCK_ASSERT(sc);
+	rx_cons = sc->bge_rx_saved_considx;
+	rx_prod = sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx;
 
 	/* Nothing to do. */
-	if (sc->bge_rx_saved_considx ==
-	    sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx)
+	if (rx_cons == rx_prod)
 		return (rx_npkts);
 
 	ifp = sc->bge_ifp;
@@ -3073,8 +3075,7 @@ bge_rxeof(struct bge_softc *sc)
 		bus_dmamap_sync(sc->bge_cdata.bge_rx_jumbo_ring_tag,
 		    sc->bge_cdata.bge_rx_jumbo_ring_map, BUS_DMASYNC_POSTREAD);
 
-	while (sc->bge_rx_saved_considx !=
-	    sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx) {
+	while (rx_cons != rx_prod) {
 		struct bge_rx_bd	*cur_rx;
 		uint32_t		rxidx;
 		struct mbuf		*m = NULL;
@@ -3089,11 +3090,10 @@ bge_rxeof(struct bge_softc *sc)
 		}
 #endif
 
-		cur_rx =
-	    &sc->bge_ldata.bge_rx_return_ring[sc->bge_rx_saved_considx];
+		cur_rx = &sc->bge_ldata.bge_rx_return_ring[rx_cons];
 
 		rxidx = cur_rx->bge_idx;
-		BGE_INC(sc->bge_rx_saved_considx, sc->bge_return_ring_cnt);
+		BGE_INC(rx_cons, sc->bge_return_ring_cnt);
 
 		if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING &&
 		    cur_rx->bge_flags & BGE_RXBDFLAG_VLAN_TAG) {
@@ -3207,6 +3207,7 @@ bge_rxeof(struct bge_softc *sc)
 		bus_dmamap_sync(sc->bge_cdata.bge_rx_jumbo_ring_tag,
 		    sc->bge_cdata.bge_rx_jumbo_ring_map, BUS_DMASYNC_PREWRITE);
 
+	sc->bge_rx_saved_considx = rx_cons;
 	bge_writembx(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
 	if (stdcnt)
 		bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
diff --git a/sys/dev/bktr/bktr_os.c b/sys/dev/bktr/bktr_os.c
index 1fd458cd3c1..327c4bbdb95 100644
--- a/sys/dev/bktr/bktr_os.c
+++ b/sys/dev/bktr/bktr_os.c
@@ -597,9 +597,7 @@ bktr_open( struct cdev *dev, int flags, int fmt, struct thread *td )
 		return( ENXIO );	
 
 	/* Record that the device is now busy */
-	newbus_xlock();
 	device_busy(devclass_get_device(bktr_devclass, unit)); 
-	newbus_xunlock();
 
 
 	if (bt848_card != -1) {
@@ -670,11 +668,8 @@ bktr_open( struct cdev *dev, int flags, int fmt, struct thread *td )
 	}
 
 	/* If there was an error opening the device, undo the busy status */
-	if (result != 0) {
-		newbus_xlock();
+	if (result != 0)
 		device_unbusy(devclass_get_device(bktr_devclass, unit)); 
-		newbus_xunlock();
-	}
 	return( result );
 }
 
@@ -694,7 +689,6 @@ bktr_close( struct cdev *dev, int flags, int fmt, struct thread *td )
 	/* Get the device data */
 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
 	if (bktr == NULL) {
-
 		/* the device is no longer valid/functioning */
 		return (ENXIO);
 	}
@@ -711,11 +705,10 @@ bktr_close( struct cdev *dev, int flags, int fmt, struct thread *td )
 		break;
 	default:
 		return (ENXIO);
+		break;
 	}
 
-	newbus_xlock();
 	device_unbusy(devclass_get_device(bktr_devclass, unit)); 
-	newbus_xunlock();
 	return( result );
 }
 
diff --git a/sys/dev/coretemp/coretemp.c b/sys/dev/coretemp/coretemp.c
index d639eec59fd..0226c8f1cd4 100644
--- a/sys/dev/coretemp/coretemp.c
+++ b/sys/dev/coretemp/coretemp.c
@@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#define	TZ_ZEROC	2732
+
 struct coretemp_softc {
 	device_t	sc_dev;
 	int		sc_tjmax;
@@ -193,8 +195,8 @@ coretemp_attach(device_t dev)
 	    SYSCTL_CHILDREN(device_get_sysctl_tree(pdev)),
 	    OID_AUTO, "temperature",
 	    CTLTYPE_INT | CTLFLAG_RD,
-	    dev, 0, coretemp_get_temp_sysctl, "I",
-	    "Current temperature in degC");
+	    dev, 0, coretemp_get_temp_sysctl, "IK",
+	    "Current temperature");
 
 	return (0);
 }
@@ -283,7 +285,7 @@ coretemp_get_temp_sysctl(SYSCTL_HANDLER_ARGS)
 	device_t dev = (device_t) arg1;
 	int temp;
 
-	temp = coretemp_get_temp(dev);
+	temp = coretemp_get_temp(dev) * 10 + TZ_ZEROC;
 
 	return (sysctl_handle_int(oidp, &temp, 0, req));
 }
diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c
index 21ce96d6ab0..596609b89d9 100644
--- a/sys/dev/cxgb/cxgb_main.c
+++ b/sys/dev/cxgb/cxgb_main.c
@@ -1456,7 +1456,10 @@ setup_rss(adapter_t *adap)
 		rspq_map[i] = nq[0] ? i % nq[0] : 0;
 		rspq_map[i + RSS_TABLE_SIZE / 2] = nq[1] ? i % nq[1] + nq[0] : 0;
 	}
+
 	/* Calculate the reverse RSS map table */
+	for (i = 0; i < SGE_QSETS; ++i)
+		adap->rrss_map[i] = 0xff;
 	for (i = 0; i < RSS_TABLE_SIZE; ++i)
 		if (adap->rrss_map[rspq_map[i]] == 0xff)
 			adap->rrss_map[rspq_map[i]] = i;
diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h
index e630f861d57..cad2cee623a 100644
--- a/sys/dev/drm/drmP.h
+++ b/sys/dev/drm/drmP.h
@@ -148,6 +148,8 @@ MALLOC_DECLARE(DRM_MEM_CTXBITMAP);
 MALLOC_DECLARE(DRM_MEM_SGLISTS);
 MALLOC_DECLARE(DRM_MEM_DRAWABLE);
 
+SYSCTL_DECL(_hw_drm);
+
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
 
 				/* Internal types and structures */
@@ -416,7 +418,6 @@ struct drm_file {
 	struct drm_device *dev;
 	int		  authenticated;
 	int		  master;
-	int		  minor;
 	pid_t		  pid;
 	uid_t		  uid;
 	drm_magic_t	  magic;
diff --git a/sys/dev/drm/drm_bufs.c b/sys/dev/drm/drm_bufs.c
index 647dee96345..bd31b0ae31a 100644
--- a/sys/dev/drm/drm_bufs.c
+++ b/sys/dev/drm/drm_bufs.c
@@ -45,27 +45,35 @@ __FBSDID("$FreeBSD$");
  */
 static int drm_alloc_resource(struct drm_device *dev, int resource)
 {
+	struct resource *res;
+	int rid;
+
+	DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+
 	if (resource >= DRM_MAX_PCI_RESOURCE) {
 		DRM_ERROR("Resource %d too large\n", resource);
 		return 1;
 	}
 
-	DRM_UNLOCK();
 	if (dev->pcir[resource] != NULL) {
-		DRM_LOCK();
 		return 0;
 	}
 
-	dev->pcirid[resource] = PCIR_BAR(resource);
-	dev->pcir[resource] = bus_alloc_resource_any(dev->device,
-	    SYS_RES_MEMORY, &dev->pcirid[resource], RF_SHAREABLE);
+	DRM_UNLOCK();
+	rid = PCIR_BAR(resource);
+	res = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &rid,
+	    RF_SHAREABLE);
 	DRM_LOCK();
-
-	if (dev->pcir[resource] == NULL) {
+	if (res == NULL) {
 		DRM_ERROR("Couldn't find resource 0x%x\n", resource);
 		return 1;
 	}
 
+	if (dev->pcir[resource] == NULL) {
+		dev->pcirid[resource] = rid;
+		dev->pcir[resource] = res;
+	}
+
 	return 0;
 }
 
diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c
index e12f8cdfa92..c690c34dfa3 100644
--- a/sys/dev/drm/drm_drv.c
+++ b/sys/dev/drm/drm_drv.c
@@ -53,9 +53,6 @@ static void drm_unload(struct drm_device *dev);
 static drm_pci_id_list_t *drm_find_description(int vendor, int device,
     drm_pci_id_list_t *idlist);
 
-#define DRIVER_SOFTC(unit) \
-	((struct drm_device *)devclass_get_softc(drm_devclass, unit))
-
 MODULE_VERSION(drm, 1);
 MODULE_DEPEND(drm, agp, 1, 1, 1);
 MODULE_DEPEND(drm, pci, 1, 1, 1);
@@ -136,6 +133,9 @@ static struct cdevsw drm_cdevsw = {
 
 static int drm_msi = 1;	/* Enable by default. */
 TUNABLE_INT("hw.drm.msi", &drm_msi);
+SYSCTL_NODE(_hw, OID_AUTO, drm, CTLFLAG_RW, NULL, "DRM device");
+SYSCTL_INT(_hw_drm, OID_AUTO, msi, CTLFLAG_RDTUN, &drm_msi, 1,
+    "Enable MSI interrupts for drm devices");
 
 static struct drm_msi_blacklist_entry drm_msi_blacklist[] = {
 	{0x8086, 0x2772}, /* Intel i945G	*/ \
@@ -210,11 +210,12 @@ int drm_attach(device_t kdev, drm_pci_id_list_t *idlist)
 	dev->device = kdev;
 #endif
 	dev->devnode = make_dev(&drm_cdevsw,
-			unit,
+			0,
 			DRM_DEV_UID,
 			DRM_DEV_GID,
 			DRM_DEV_MODE,
 			"dri/card%d", unit);
+	dev->devnode->si_drv1 = dev;
 
 #if __FreeBSD_version >= 700053
 	dev->pci_domain = pci_get_domain(dev->device);
@@ -606,7 +607,7 @@ int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
 	struct drm_device *dev = NULL;
 	int retcode = 0;
 
-	dev = DRIVER_SOFTC(dev2unit(kdev));
+	dev = kdev->si_drv1;
 
 	DRM_DEBUG("open_count = %d\n", dev->open_count);
 
@@ -614,13 +615,11 @@ int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
 
 	if (!retcode) {
 		atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
-		newbus_xlock();
 		DRM_LOCK();
 		device_busy(dev->device);
 		if (!dev->open_count++)
 			retcode = drm_firstopen(dev);
 		DRM_UNLOCK();
-		newbus_xunlock();
 	}
 
 	return retcode;
@@ -634,11 +633,6 @@ void drm_close(void *data)
 
 	DRM_DEBUG("open_count = %d\n", dev->open_count);
 
-	/*
-	 * We require to lock newbus here for handling device_unbusy() and
-	 * avoid a LOR with DRM_LOCK.
-	 */
-	newbus_xlock();
 	DRM_LOCK();
 
 	if (dev->driver->preclose != NULL)
@@ -715,7 +709,6 @@ void drm_close(void *data)
 	}
 
 	DRM_UNLOCK();
-	newbus_xunlock();
 }
 
 /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm.
diff --git a/sys/dev/drm/drm_fops.c b/sys/dev/drm/drm_fops.c
index f766928d651..3f743e04ca9 100644
--- a/sys/dev/drm/drm_fops.c
+++ b/sys/dev/drm/drm_fops.c
@@ -44,14 +44,13 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
 		    struct drm_device *dev)
 {
 	struct drm_file *priv;
-	int m = dev2unit(kdev);
 	int retcode;
 
 	if (flags & O_EXCL)
 		return EBUSY; /* No exclusive opens */
 	dev->flags = flags;
 
-	DRM_DEBUG("pid = %d, minor = %d\n", DRM_CURRENTPID, m);
+	DRM_DEBUG("pid = %d, device = %s\n", DRM_CURRENTPID, devtoname(kdev));
 
 	priv = malloc(sizeof(*priv), DRM_MEM_FILES, M_NOWAIT | M_ZERO);
 	if (priv == NULL) {
@@ -68,7 +67,6 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
 	priv->dev		= dev;
 	priv->uid		= p->td_ucred->cr_svuid;
 	priv->pid		= p->td_proc->p_pid;
-	priv->minor		= m;
 	priv->ioctl_count 	= 0;
 
 	/* for compatibility root is always authenticated */
diff --git a/sys/dev/drm/drm_pciids.h b/sys/dev/drm/drm_pciids.h
index 4562e5f722e..3b2347ed5b6 100644
--- a/sys/dev/drm/drm_pciids.h
+++ b/sys/dev/drm/drm_pciids.h
@@ -259,9 +259,12 @@
 	{0x1002, 0x940F, CHIP_R600|RADEON_NEW_MEMMAP, "ATI FireGL V7600"}, \
 	{0x1002, 0x94A0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon HD 4830"}, \
 	{0x1002, 0x94A1, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon HD 4850"}, \
+	{0x1002, 0x94A3, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI FirePro M7740"}, \
 	{0x1002, 0x94B1, CHIP_RV740|RADEON_NEW_MEMMAP, "ATI RV740"}, \
 	{0x1002, 0x94B3, CHIP_RV740|RADEON_NEW_MEMMAP, "ATI Radeon HD 4770"}, \
+	{0x1002, 0x94B4, CHIP_RV740|RADEON_NEW_MEMMAP, "ATI Radeon HD 4700 Series"}, \
 	{0x1002, 0x94B5, CHIP_RV740|RADEON_NEW_MEMMAP, "ATI Radeon HD 4770"}, \
+	{0x1002, 0x94B9, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI FirePro M5750"}, \
 	{0x1002, 0x94C0, CHIP_RV610|RADEON_NEW_MEMMAP, "RV610"}, \
 	{0x1002, 0x94C1, CHIP_RV610|RADEON_NEW_MEMMAP, "Radeon HD 2400 XT"}, \
 	{0x1002, 0x94C3, CHIP_RV610|RADEON_NEW_MEMMAP, "Radeon HD 2400 Pro"}, \
@@ -327,6 +330,11 @@
 	{0x1002, 0x9614, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon 3300 Graphics"}, \
 	{0x1002, 0x9615, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon 3200 Graphics"}, \
 	{0x1002, 0x9616, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon 3000 Graphics"}, \
+	{0x1002, 0x9710, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon HD 4200"}, \
+	{0x1002, 0x9711, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon 4100"}, \
+	{0x1002, 0x9712, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Mobility Radeon HD 4200"}, \
+	{0x1002, 0x9713, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Mobility Radeon 4100"}, \
+	{0x1002, 0x9714, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI RS880"}, \
 	{0x1002, 0x9440, CHIP_RV770|RADEON_NEW_MEMMAP, "ATI Radeon 4800 Series"}, \
 	{0x1002, 0x9441, CHIP_RV770|RADEON_NEW_MEMMAP, "ATI Radeon 4870 X2"}, \
 	{0x1002, 0x9442, CHIP_RV770|RADEON_NEW_MEMMAP, "ATI Radeon 4800 Series"}, \
@@ -350,6 +358,7 @@
 	{0x1002, 0x9487, CHIP_RV730|RADEON_NEW_MEMMAP, "ATI Radeon RV730 (AGP)"}, \
 	{0x1002, 0x948F, CHIP_RV730|RADEON_NEW_MEMMAP, "ATI Radeon RV730 (AGP)"}, \
 	{0x1002, 0x9490, CHIP_RV730|RADEON_NEW_MEMMAP, "ATI Radeon HD 4670"}, \
+	{0x1002, 0x9495, CHIP_RV730|RADEON_NEW_MEMMAP, "ATI Radeon HD 4600 Series"}, \
 	{0x1002, 0x9498, CHIP_RV730|RADEON_NEW_MEMMAP, "ATI Radeon HD 4650"}, \
 	{0x1002, 0x9480, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon HD 4650"}, \
 	{0x1002, 0x9488, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon HD 4670"}, \
@@ -366,6 +375,7 @@
 	{0x1002, 0x9552, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon 4300 Series"}, \
 	{0x1002, 0x9553, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon 4500 Series"}, \
 	{0x1002, 0x9555, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon 4500 Series"}, \
+	{0x1002, 0x9557, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI FirePro RG220"}, \
 	{0, 0, 0, NULL}
 
 #define r128_PCI_IDS \
diff --git a/sys/dev/drm/drm_sysctl.c b/sys/dev/drm/drm_sysctl.c
index 0d59d485a99..cc332833fd6 100644
--- a/sys/dev/drm/drm_sysctl.c
+++ b/sys/dev/drm/drm_sysctl.c
@@ -298,12 +298,13 @@ static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
 
 	DRM_UNLOCK();
 
-	DRM_SYSCTL_PRINT("\na dev	pid    uid	magic	  ioctls\n");
+	DRM_SYSCTL_PRINT(
+	    "\na dev            pid   uid      magic     ioctls\n");
 	for (i = 0; i < privcount; i++) {
 		priv = &tempprivs[i];
-		DRM_SYSCTL_PRINT("%c %3d %5d %5d %10u %10lu\n",
+		DRM_SYSCTL_PRINT("%c %-12s %5d %5d %10u %10lu\n",
 			       priv->authenticated ? 'y' : 'n',
-			       priv->minor,
+			       devtoname(priv->dev->devnode),
 			       priv->pid,
 			       priv->uid,
 			       priv->magic,
diff --git a/sys/dev/drm/r600_cp.c b/sys/dev/drm/r600_cp.c
index 64e98ce41e6..2a4a6bd873c 100644
--- a/sys/dev/drm/r600_cp.c
+++ b/sys/dev/drm/r600_cp.c
@@ -318,7 +318,8 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
 		pfp = RV670_pfp_microcode;
 		break;
 	case CHIP_RS780:
-		DRM_INFO("Loading RS780 Microcode\n");
+	case CHIP_RS880:
+		DRM_INFO("Loading RS780/RS880 Microcode\n");
 		cp  = RS780_cp_microcode;
 		pfp = RS780_pfp_microcode;
 		break;
@@ -722,6 +723,7 @@ static void r600_gfx_init(struct drm_device *dev,
 		break;
 	case CHIP_RV610:
 	case CHIP_RS780:
+	case CHIP_RS880:
 	case CHIP_RV620:
 		dev_priv->r600_max_pipes = 1;
 		dev_priv->r600_max_tile_pipes = 1;
@@ -856,7 +858,8 @@ static void r600_gfx_init(struct drm_device *dev,
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
 		RADEON_WRITE(R600_DB_DEBUG, R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE);
 	else
 		RADEON_WRITE(R600_DB_DEBUG, 0);
@@ -874,7 +877,8 @@ static void r600_gfx_init(struct drm_device *dev,
 	sq_ms_fifo_sizes = RADEON_READ(R600_SQ_MS_FIFO_SIZES);
 	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
 		sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(0xa) |
 				    R600_FETCH_FIFO_HIWATER(0xa) |
 				    R600_DONE_FIFO_HIWATER(0xe0) |
@@ -917,7 +921,8 @@ static void r600_gfx_init(struct drm_device *dev,
 					    R600_NUM_ES_STACK_ENTRIES(0));
 	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
 		/* no vertex cache */
 		sq_config &= ~R600_VC_ENABLE;
 
@@ -974,7 +979,8 @@ static void r600_gfx_init(struct drm_device *dev,
 
 	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
 		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_TC_ONLY));
 	else
 		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_VC_AND_TC));
@@ -1017,6 +1023,7 @@ static void r600_gfx_init(struct drm_device *dev,
 		break;
 	case CHIP_RV610:
 	case CHIP_RS780:
+	case CHIP_RS880:
 	case CHIP_RV620:
 		gs_prim_buffer_depth = 32;
 		break;
@@ -1062,6 +1069,7 @@ static void r600_gfx_init(struct drm_device *dev,
 	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
 	case CHIP_RV610:
 	case CHIP_RS780:
+	case CHIP_RS880:
 	case CHIP_RV620:
 		tc_cntl = R600_TC_L2_SIZE(8);
 		break;
@@ -1835,6 +1843,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
 	 */
 	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
 
+	dev_priv->do_boxes = 0;
 	dev_priv->cp_mode = init->cp_mode;
 
 	/* We don't support anything other than bus-mastering ring mode,
@@ -2092,6 +2101,8 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
 	r600_do_engine_reset(dev);
 	r600_test_writeback(dev_priv);
 
+	r600_cs_init(dev);
+
 	return 0;
 }
 
@@ -2224,3 +2235,135 @@ int r600_cp_dispatch_indirect(struct drm_device *dev,
 
 	return 0;
 }
+
+void r600_cp_dispatch_swap(struct drm_device * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int nbox = sarea_priv->nbox;
+	struct drm_clip_rect *pbox = sarea_priv->boxes;
+	int i, cpp, src_pitch, dst_pitch;
+	uint64_t src, dst;
+	RING_LOCALS;
+	DRM_DEBUG("\n");
+
+	if (dev_priv->color_fmt == RADEON_COLOR_FORMAT_ARGB8888)
+		cpp = 4;
+	else
+		cpp = 2;
+
+	if (dev_priv->sarea_priv->pfCurrentPage == 0) {
+		src_pitch = dev_priv->back_pitch;
+		dst_pitch = dev_priv->front_pitch;
+		src = dev_priv->back_offset + dev_priv->fb_location;
+		dst = dev_priv->front_offset + dev_priv->fb_location;
+	} else {
+		src_pitch = dev_priv->front_pitch;
+		dst_pitch = dev_priv->back_pitch;
+		src = dev_priv->front_offset + dev_priv->fb_location;
+		dst = dev_priv->back_offset + dev_priv->fb_location;
+	}
+
+	if (r600_prepare_blit_copy(dev)) {
+		DRM_ERROR("unable to allocate vertex buffer for swap buffer\n");
+		return;
+	}
+	for (i = 0; i < nbox; i++) {
+		int x = pbox[i].x1;
+		int y = pbox[i].y1;
+		int w = pbox[i].x2 - x;
+		int h = pbox[i].y2 - y;
+
+		DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h);
+
+		r600_blit_swap(dev,
+			       src, dst,
+			       x, y, x, y, w, h,
+			       src_pitch, dst_pitch, cpp);
+	}
+	r600_done_blit_copy(dev);
+
+	/* Increment the frame counter.  The client-side 3D driver must
+	 * throttle the framerate by waiting for this value before
+	 * performing the swapbuffer ioctl.
+	 */
+	dev_priv->sarea_priv->last_frame++;
+
+	BEGIN_RING(3);
+	R600_FRAME_AGE(dev_priv->sarea_priv->last_frame);
+	ADVANCE_RING();
+}
+
+int r600_cp_dispatch_texture(struct drm_device * dev,
+			     struct drm_file *file_priv,
+			     drm_radeon_texture_t * tex,
+			     drm_radeon_tex_image_t * image)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	struct drm_buf *buf;
+	u32 *buffer;
+	const u8 __user *data;
+	int size, pass_size;
+	u64 src_offset, dst_offset;
+
+	if (!radeon_check_offset(dev_priv, tex->offset)) {
+		DRM_ERROR("Invalid destination offset\n");
+		return -EINVAL;
+	}
+
+	/* this might fail for zero-sized uploads - are those illegal? */
+	if (!radeon_check_offset(dev_priv, tex->offset + tex->height * tex->pitch - 1)) {
+		DRM_ERROR("Invalid final destination offset\n");
+		return -EINVAL;
+	}
+
+	size = tex->height * tex->pitch;
+
+	if (size == 0)
+		return 0;
+
+	dst_offset = tex->offset;
+
+	r600_prepare_blit_copy(dev);
+	do {
+		data = (const u8 __user *)image->data;
+		pass_size = size;
+
+		buf = radeon_freelist_get(dev);
+		if (!buf) {
+			DRM_DEBUG("EAGAIN\n");
+			if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
+				return -EFAULT;
+			return -EAGAIN;
+		}
+
+		if (pass_size > buf->total)
+			pass_size = buf->total;
+
+		/* Dispatch the indirect buffer.
+		 */
+		buffer =
+		    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+
+		if (DRM_COPY_FROM_USER(buffer, data, pass_size)) {
+			DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size);
+			return -EFAULT;
+		}
+
+		buf->file_priv = file_priv;
+		buf->used = pass_size;
+		src_offset = dev_priv->gart_buffers_offset + buf->offset;
+
+		r600_blit_copy(dev, src_offset, dst_offset, pass_size);
+
+		radeon_cp_discard_buffer(dev, buf);
+
+		/* Update the input parameters for next time */
+		image->data = (const u8 __user *)image->data + pass_size;
+		dst_offset += pass_size;
+		size -= pass_size;
+	} while (size > 0);
+	r600_done_blit_copy(dev);
+
+	return 0;
+}
diff --git a/sys/dev/drm/radeon_cp.c b/sys/dev/drm/radeon_cp.c
index 3d8cf9dfecc..734fafa445f 100644
--- a/sys/dev/drm/radeon_cp.c
+++ b/sys/dev/drm/radeon_cp.c
@@ -408,6 +408,15 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
 {
 	uint32_t gb_tile_config, gb_pipe_sel = 0;
 
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) {
+		uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2);
+		if ((z_pipe_sel & 3) == 3)
+			dev_priv->num_z_pipes = 2;
+		else
+			dev_priv->num_z_pipes = 1;
+	} else
+		dev_priv->num_z_pipes = 1;
+
 	/* RS4xx/RS6xx/R4xx/R5xx */
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
 		gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
@@ -2060,6 +2069,8 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
 	else
 		dev_priv->flags |= RADEON_IS_PCI;
 
+	mtx_init(&dev_priv->cs.cs_mutex, "cs_mtx", NULL, MTX_DEF);
+
 	ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
 			 drm_get_resource_len(dev, 2), _DRM_REGISTERS,
 			 _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio);
@@ -2112,6 +2123,8 @@ int radeon_driver_unload(struct drm_device *dev)
 
 	drm_rmmap(dev, dev_priv->mmio);
 
+	mtx_destroy(&dev_priv->cs.cs_mutex);
+
 	drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
 
 	dev->dev_private = NULL;
@@ -2126,9 +2139,9 @@ void radeon_commit_ring(drm_radeon_private_t *dev_priv)
 
 	/* check if the ring is padded out to 16-dword alignment */
 
-	tail_aligned = dev_priv->ring.tail & 0xf;
+	tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN - 1);
 	if (tail_aligned) {
-		int num_p2 = 16 - tail_aligned;
+		int num_p2 = RADEON_RING_ALIGN - tail_aligned;
 
 		ring = dev_priv->ring.start;
 		/* pad with some CP_PACKET2 */
diff --git a/sys/dev/drm/radeon_drm.h b/sys/dev/drm/radeon_drm.h
index 70d3aaa6fc5..11f2fcb8d8a 100644
--- a/sys/dev/drm/radeon_drm.h
+++ b/sys/dev/drm/radeon_drm.h
@@ -497,6 +497,8 @@ typedef struct {
 #define DRM_RADEON_SURF_ALLOC 0x1a
 #define DRM_RADEON_SURF_FREE  0x1b
 
+#define DRM_RADEON_CS         0x26
+
 #define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
 #define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
 #define DRM_IOCTL_RADEON_CP_STOP    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t)
@@ -524,6 +526,7 @@ typedef struct {
 #define DRM_IOCTL_RADEON_SETPARAM   DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t)
 #define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
 #define DRM_IOCTL_RADEON_SURF_FREE  DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
+#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs)
 
 typedef struct drm_radeon_init {
 	enum {
@@ -685,6 +688,8 @@ typedef struct drm_radeon_indirect {
 #define RADEON_PARAM_VBLANK_CRTC           13   /* VBLANK CRTC */
 #define RADEON_PARAM_FB_LOCATION           14   /* FB location */
 #define RADEON_PARAM_NUM_GB_PIPES          15   /* num GB pipes */
+#define RADEON_PARAM_DEVICE_ID             16
+#define RADEON_PARAM_NUM_Z_PIPES           17   /* num Z pipes */
 
 typedef struct drm_radeon_getparam {
 	int param;
@@ -755,4 +760,23 @@ typedef struct drm_radeon_surface_free {
 #define	DRM_RADEON_VBLANK_CRTC1		1
 #define	DRM_RADEON_VBLANK_CRTC2		2
 
+/* New interface which obsolete all previous interface.
+ */
+#define RADEON_CHUNK_ID_RELOCS 0x01
+#define RADEON_CHUNK_ID_IB     0x02
+#define RADEON_CHUNK_ID_OLD 0xff
+
+struct drm_radeon_cs_chunk {
+	uint32_t chunk_id;
+	uint32_t length_dw;
+	uint64_t chunk_data;
+};
+
+struct drm_radeon_cs {
+	uint32_t        num_chunks;
+	uint32_t        cs_id;
+	uint64_t        chunks; /* this points to uint64_t * which point to
+				   cs chunks */
+};
+
 #endif
diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h
index ae1166f023b..a1cd48bc20d 100644
--- a/sys/dev/drm/radeon_drv.h
+++ b/sys/dev/drm/radeon_drv.h
@@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
 
 #define DRIVER_NAME		"radeon"
 #define DRIVER_DESC		"ATI Radeon"
-#define DRIVER_DATE		"20080528"
+#define DRIVER_DATE		"20080613"
 
 /* Interface history:
  *
@@ -102,9 +102,11 @@ __FBSDID("$FreeBSD$");
  * 1.27- Add support for IGP GART
  * 1.28- Add support for VBL on CRTC2
  * 1.29- R500 3D cmd buffer support
+ * 1.30- Add support for occlusion queries
+ * 1.31- Add support for num Z pipes from GET_PARAM
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		29
+#define DRIVER_MINOR		31
 #define DRIVER_PATCHLEVEL	0
 
 /*
@@ -145,6 +147,7 @@ enum radeon_family {
 	CHIP_RV635,
 	CHIP_RV670,
 	CHIP_RS780,
+	CHIP_RS880,
 	CHIP_RV770,
 	CHIP_RV740,
 	CHIP_RV730,
@@ -235,6 +238,46 @@ struct radeon_virt_surface {
 #define PCIGART_FILE_PRIV	((void *) -1L)
 };
 
+struct drm_radeon_kernel_chunk {
+	uint32_t chunk_id;
+	uint32_t length_dw;
+	uint32_t __user *chunk_data;
+	uint32_t *kdata;
+};
+
+struct drm_radeon_cs_parser {
+	struct drm_device *dev;
+	struct drm_file *file_priv;
+	uint32_t num_chunks;
+	struct drm_radeon_kernel_chunk *chunks;
+	int ib_index;
+	int reloc_index;
+	uint32_t card_offset;
+	void *ib;
+};
+
+/* command submission struct */
+struct drm_radeon_cs_priv {
+	struct mtx cs_mutex;
+	uint32_t id_wcnt;
+	uint32_t id_scnt;
+	uint32_t id_last_wcnt;
+	uint32_t id_last_scnt;
+
+	int (*parse)(struct drm_radeon_cs_parser *parser);
+	void (*id_emit)(struct drm_radeon_cs_parser *parser, uint32_t *id);
+	uint32_t (*id_last_get)(struct drm_device *dev);
+	/* this ib handling callback are for hidding memory manager drm
+	 * from memory manager less drm, free have to emit ib discard
+	 * sequence into the ring */
+	int (*ib_get)(struct drm_radeon_cs_parser *parser);
+	uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib);
+	void (*ib_free)(struct drm_radeon_cs_parser *parser, int error);
+	/* do a relocation either MM or non-MM */
+	int (*relocate)(struct drm_radeon_cs_parser *parser,
+			uint32_t *reloc, uint64_t *offset);
+};
+
 #define RADEON_FLUSH_EMITED	(1 << 0)
 #define RADEON_PURGE_EMITED	(1 << 1)
 
@@ -327,6 +370,7 @@ typedef struct drm_radeon_private {
 	unsigned long fb_aper_offset;
 
 	int num_gb_pipes;
+	int num_z_pipes;
 	int track_flush;
 	drm_local_map_t *mmio;
 
@@ -348,6 +392,12 @@ typedef struct drm_radeon_private {
 	int r700_sc_prim_fifo_size;
 	int r700_sc_hiz_tile_fifo_size;
 	int r700_sc_earlyz_tile_fifo_fize;
+	/* r6xx/r7xx drm blit vertex buffer */
+	struct drm_buf *blit_vb;
+
+	/* CS */
+	struct drm_radeon_cs_priv cs;
+	struct drm_buf *cs_buf;
 
 } drm_radeon_private_t;
 
@@ -378,10 +428,10 @@ extern void radeon_set_ring_head(drm_radeon_private_t *dev_priv, u32 val);
 static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv,
 					  u64 off)
 {
-	u32 fb_start = dev_priv->fb_location;
-	u32 fb_end = fb_start + dev_priv->fb_size - 1;
-	u32 gart_start = dev_priv->gart_vm_start;
-	u32 gart_end = gart_start + dev_priv->gart_size - 1;
+	u64 fb_start = dev_priv->fb_location;
+	u64 fb_end = fb_start + dev_priv->fb_size - 1;
+	u64 gart_start = dev_priv->gart_vm_start;
+	u64 gart_end = gart_start + dev_priv->gart_size - 1;
 
 	return ((off >= fb_start && off <= fb_end) ||
 		(off >= gart_start && off <= gart_end));
@@ -475,6 +525,33 @@ extern int r600_cp_dispatch_indirect(struct drm_device *dev,
 				     struct drm_buf *buf, int start, int end);
 extern int r600_page_table_init(struct drm_device *dev);
 extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info);
+extern void r600_cp_dispatch_swap(struct drm_device * dev);
+extern int r600_cp_dispatch_texture(struct drm_device * dev,
+				    struct drm_file *file_priv,
+				    drm_radeon_texture_t * tex,
+				    drm_radeon_tex_image_t * image);
+
+/* r600_blit.c */
+extern int
+r600_prepare_blit_copy(struct drm_device *dev);
+extern void
+r600_done_blit_copy(struct drm_device *dev);
+extern void
+r600_blit_copy(struct drm_device *dev,
+	       uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
+	       int size_bytes);
+extern void
+r600_blit_swap(struct drm_device *dev,
+	       uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
+	       int sx, int sy, int dx, int dy,
+	       int w, int h, int src_pitch, int dst_pitch, int cpp);
+
+/* radeon_state.c */
+extern void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf);
+
+/* radeon_cs.c */
+extern int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv);
+extern int r600_cs_init(struct drm_device *dev);
 
 /* Flags for stats.boxes
  */
@@ -684,6 +761,7 @@ extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pciga
 
 /* pipe config regs */
 #define R400_GB_PIPE_SELECT             0x402c
+#define RV530_GB_PIPE_SELECT2           0x4124
 #define R500_DYN_SCLK_PWMEM_PIPE        0x000d /* PLL */
 #define R300_GB_TILE_CONFIG             0x4018
 #       define R300_ENABLE_TILING       (1 << 0)
@@ -1826,26 +1904,38 @@ do {									\
  */
 
 #define RADEON_WAIT_UNTIL_2D_IDLE() do {				\
-	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)        \
+		OUT_RING( CP_PACKET0( R600_WAIT_UNTIL, 0 ) );           \
+	else                                                            \
+		OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );         \
 	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
 		   RADEON_WAIT_HOST_IDLECLEAN) );			\
 } while (0)
 
 #define RADEON_WAIT_UNTIL_3D_IDLE() do {				\
-	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)        \
+		OUT_RING( CP_PACKET0( R600_WAIT_UNTIL, 0 ) );           \
+	else                                                            \
+		OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );         \
 	OUT_RING( (RADEON_WAIT_3D_IDLECLEAN |				\
 		   RADEON_WAIT_HOST_IDLECLEAN) );			\
 } while (0)
 
 #define RADEON_WAIT_UNTIL_IDLE() do {					\
-	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)        \
+		OUT_RING( CP_PACKET0( R600_WAIT_UNTIL, 0 ) );           \
+	else                                                            \
+		OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );         \
 	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
 		   RADEON_WAIT_3D_IDLECLEAN |				\
 		   RADEON_WAIT_HOST_IDLECLEAN) );			\
 } while (0)
 
 #define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do {				\
-	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)        \
+		OUT_RING( CP_PACKET0( R600_WAIT_UNTIL, 0 ) );           \
+	else                                                            \
+		OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );         \
 	OUT_RING( RADEON_WAIT_CRTC_PFLIP );				\
 } while (0)
 
@@ -1960,14 +2050,17 @@ do {								\
 
 #define RING_LOCALS	int write, _nr, _align_nr; unsigned int mask; u32 *ring;
 
+#define RADEON_RING_ALIGN 16
+
 #define BEGIN_RING( n ) do {						\
 	if ( RADEON_VERBOSE ) {						\
 		DRM_INFO( "BEGIN_RING( %d )\n", (n));			\
 	}								\
-	_align_nr = (n + 0xf) & ~0xf;					\
-	if (dev_priv->ring.space <= (_align_nr * sizeof(u32))) {	\
-                COMMIT_RING();						\
-		radeon_wait_ring( dev_priv, _align_nr * sizeof(u32));	\
+	_align_nr = RADEON_RING_ALIGN - ((dev_priv->ring.tail + n) & (RADEON_RING_ALIGN - 1)); \
+	_align_nr += n;							\
+	if ( dev_priv->ring.space <= (_align_nr) * sizeof(u32) ) {	\
+		COMMIT_RING();						\
+		radeon_wait_ring( dev_priv, (_align_nr) * sizeof(u32) ); \
 	}								\
 	_nr = n; dev_priv->ring.space -= (n) * sizeof(u32);		\
 	ring = dev_priv->ring.start;					\
diff --git a/sys/dev/drm/radeon_state.c b/sys/dev/drm/radeon_state.c
index 39dcd61315f..e032b8f811e 100644
--- a/sys/dev/drm/radeon_state.c
+++ b/sys/dev/drm/radeon_state.c
@@ -1541,7 +1541,7 @@ static void radeon_cp_dispatch_vertex(struct drm_device * dev,
 	} while (i < nbox);
 }
 
-static void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_buf *buf)
+void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_buf *buf)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -2202,7 +2202,10 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
 	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
 		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
 
-	radeon_cp_dispatch_swap(dev);
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
+		r600_cp_dispatch_swap(dev);
+	else
+		radeon_cp_dispatch_swap(dev);
 	sarea_priv->ctx_owner = 0;
 
 	COMMIT_RING();
@@ -2399,7 +2402,10 @@ static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file
 	RING_SPACE_TEST_WITH_RETURN(dev_priv);
 	VB_AGE_TEST_WITH_RETURN(dev_priv);
 
-	ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image);
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
+		ret = r600_cp_dispatch_texture(dev, file_priv, tex, &image);
+	else
+		ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image);
 
 	return ret;
 }
@@ -3072,6 +3078,9 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
 	case RADEON_PARAM_NUM_GB_PIPES:
 		value = dev_priv->num_gb_pipes;
 		break;
+	case RADEON_PARAM_NUM_Z_PIPES:
+		value = dev_priv->num_z_pipes;
+		break;
 	default:
 		DRM_DEBUG("Invalid parameter %d\n", param->param);
 		return -EINVAL;
@@ -3156,6 +3165,14 @@ void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
 void radeon_driver_lastclose(struct drm_device *dev)
 {
 	radeon_surfaces_release(PCIGART_FILE_PRIV, dev->dev_private);
+	if (dev->dev_private) {
+		drm_radeon_private_t *dev_priv = dev->dev_private;
+
+		if (dev_priv->sarea_priv &&
+		    dev_priv->sarea_priv->pfCurrentPage != 0)
+			radeon_cp_dispatch_flip(dev);
+	}
+
 	radeon_do_release(dev);
 }
 
@@ -3216,7 +3233,8 @@ struct drm_ioctl_desc radeon_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH)
+	DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH)
 };
 
 int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index d1fe7aaa3cb..1def87631db 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -1204,7 +1204,8 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 				em_init_locked(adapter);
 				EM_CORE_UNLOCK(adapter);
 			}
-			arp_ifinit(ifp, ifa);
+			if (!(ifp->if_flags & IFF_NOARP))
+				arp_ifinit(ifp, ifa);
 		} else
 #endif
 			error = ether_ioctl(ifp, command, data);
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index ee19b944e77..4124fa14b92 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -952,7 +952,8 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 				igb_init_locked(adapter);
 				IGB_CORE_UNLOCK(adapter);
 			}
-			arp_ifinit(ifp, ifa);
+			if (!(ifp->if_flags & IFF_NOARP))
+				arp_ifinit(ifp, ifa);
 		} else
 #endif
 			error = ether_ioctl(ifp, command, data);
diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
index f5fd475f85a..c5b516c783e 100644
--- a/sys/dev/ep/if_ep.c
+++ b/sys/dev/ep/if_ep.c
@@ -665,14 +665,13 @@ rescan:
 #ifdef EP_LOCAL_STATS
 						sc->tx_underrun++;
 #endif
-					} else {
-						if (status & TXS_JABBER);
-						else
-							++ifp->if_collisions;
-							/* TXS_MAX_COLLISION
-							 * we shouldn't get
-							 * here
-							 */
+					}
+					if (status & TXS_MAX_COLLISION) {
+						/*
+						 * TXS_MAX_COLLISION we
+						 * shouldn't get here
+						 */
+						++ifp->if_collisions;
 					}
 					++ifp->if_oerrors;
 					CSR_WRITE_2(sc, EP_COMMAND, TX_ENABLE);
diff --git a/sys/dev/hptrr/hptrr_osm_bsd.c b/sys/dev/hptrr/hptrr_osm_bsd.c
index 3872cde0d16..eae952e1228 100644
--- a/sys/dev/hptrr/hptrr_osm_bsd.c
+++ b/sys/dev/hptrr/hptrr_osm_bsd.c
@@ -814,6 +814,10 @@ static void hpt_action(struct cam_sim *sim, union ccb *ccb)
 		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
 		strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+		cpi->transport = XPORT_SPI;
+		cpi->transport_version = 2;
+		cpi->protocol = PROTO_SCSI;
+		cpi->protocol_version = SCSI_REV_2;
 		cpi->ccb_h.status = CAM_REQ_CMP;
 		break;
 	}
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
index 214e42cb4b0..d4f065b6024 100644
--- a/sys/dev/hwpmc/hwpmc_core.c
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -32,10 +32,13 @@
 __FBSDID("$FreeBSD$");
 
 #include 
+#include 
 #include 
 #include 
 #include 
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -1179,6 +1182,29 @@ static struct iap_event_descr iap_events[] = {
     IAPDESCR(DBH_01H, 0xDB, 0x01, IAP_F_FM | IAP_F_I7),
     IAPDESCR(E4H_01H, 0xE4, 0x01, IAP_F_FM | IAP_F_I7),
     IAPDESCR(E5H_01H, 0xE5, 0x01, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(E6H_01H, 0xE6, 0x01, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(E6H_02H, 0xE6, 0x02, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(E8H_01H, 0xE8, 0x01, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(E8H_02H, 0xE8, 0x02, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(E8H_03H, 0xE8, 0x03, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F0H_01H, 0xF0, 0x01, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F0H_02H, 0xF0, 0x02, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F0H_04H, 0xF0, 0x04, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F0H_08H, 0xF0, 0x08, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F0H_10H, 0xF0, 0x10, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F0H_20H, 0xF0, 0x20, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F0H_40H, 0xF0, 0x40, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F0H_80H, 0xF0, 0x80, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F1H_02H, 0xF1, 0x02, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F1H_04H, 0xF1, 0x04, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F1H_07H, 0xF1, 0x07, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F2H_01H, 0xF2, 0x01, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F2H_02H, 0xF2, 0x02, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F2H_04H, 0xF2, 0x04, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F2H_08H, 0xF2, 0x08, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F2H_0FH, 0xF2, 0x0F, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F3H_01H, 0xF3, 0x01, IAP_F_FM | IAP_F_I7),
+    IAPDESCR(F3H_02H, 0xF3, 0x02, IAP_F_FM | IAP_F_I7),
     IAPDESCR(F3H_04H, 0xF3, 0x04, IAP_F_FM | IAP_F_I7),
     IAPDESCR(F3H_08H, 0xF3, 0x08, IAP_F_FM | IAP_F_I7),
     IAPDESCR(F3H_10H, 0xF3, 0x10, IAP_F_FM | IAP_F_I7),
@@ -1771,7 +1797,7 @@ core_intr(int cpu, struct trapframe *tf)
 	}
 
 	if (found_interrupt)
-		pmc_x86_lapic_enable_pmc_interrupt();
+		lapic_reenable_pmc();
 
 	atomic_add_int(found_interrupt ? &pmc_stats.pm_intr_processed :
 	    &pmc_stats.pm_intr_ignored, 1);
@@ -1895,7 +1921,7 @@ core2_intr(int cpu, struct trapframe *tf)
 	    (uintmax_t) rdmsr(IA_GLOBAL_OVF_CTRL));
 
 	if (found_interrupt)
-		pmc_x86_lapic_enable_pmc_interrupt();
+		lapic_reenable_pmc();
 
 	atomic_add_int(found_interrupt ? &pmc_stats.pm_intr_processed :
 	    &pmc_stats.pm_intr_ignored, 1);
diff --git a/sys/dev/hwpmc/hwpmc_piv.c b/sys/dev/hwpmc/hwpmc_piv.c
index 565be88cfee..8ee851828b1 100644
--- a/sys/dev/hwpmc/hwpmc_piv.c
+++ b/sys/dev/hwpmc/hwpmc_piv.c
@@ -32,6 +32,7 @@
 __FBSDID("$FreeBSD$");
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -39,6 +40,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -1537,7 +1540,7 @@ p4_intr(int cpu, struct trapframe *tf)
 	 */
 
 	if (did_interrupt)
-		pmc_x86_lapic_enable_pmc_interrupt();
+		lapic_reenable_pmc();
 
 	atomic_add_int(did_interrupt ? &pmc_stats.pm_intr_processed :
 	    &pmc_stats.pm_intr_ignored, 1);
diff --git a/sys/dev/hwpmc/hwpmc_ppro.c b/sys/dev/hwpmc/hwpmc_ppro.c
index 909bfe24897..8da185bf6ab 100644
--- a/sys/dev/hwpmc/hwpmc_ppro.c
+++ b/sys/dev/hwpmc/hwpmc_ppro.c
@@ -32,6 +32,7 @@
 __FBSDID("$FreeBSD$");
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -39,6 +40,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -718,7 +721,7 @@ p6_intr(int cpu, struct trapframe *tf)
 	 * unmasked after a PMC interrupt.
 	 */
 	if (retval)
-		pmc_x86_lapic_enable_pmc_interrupt();
+		lapic_reenable_pmc();
 
 	atomic_add_int(retval ? &pmc_stats.pm_intr_processed :
 	    &pmc_stats.pm_intr_ignored, 1);
diff --git a/sys/dev/hwpmc/hwpmc_x86.c b/sys/dev/hwpmc/hwpmc_x86.c
index b48a6b06424..09d04bb713e 100644
--- a/sys/dev/hwpmc/hwpmc_x86.c
+++ b/sys/dev/hwpmc/hwpmc_x86.c
@@ -39,7 +39,8 @@ __FBSDID("$FreeBSD$");
 
 #include 
 #include 
-#include 
+#include 
+#include 
 #include 
 #include 
 
@@ -47,18 +48,6 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-extern volatile lapic_t *lapic;
-
-void
-pmc_x86_lapic_enable_pmc_interrupt(void)
-{
-	uint32_t value;
-
-	value =  lapic->lvt_pcint;
-	value &= ~APIC_LVT_M;
-	lapic->lvt_pcint = value;
-}
-
 /*
  * Attempt to walk a user call stack using a too-simple algorithm.
  * In the general case we need unwind information associated with
@@ -252,16 +241,15 @@ pmc_md_initialize()
 	struct pmc_mdep *md;
 
 	/* determine the CPU kind */
-	md = NULL;
 	if (cpu_vendor_id == CPU_VENDOR_AMD)
 		md = pmc_amd_initialize();
 	else if (cpu_vendor_id == CPU_VENDOR_INTEL)
 		md = pmc_intel_initialize();
 	else
-		KASSERT(0, ("[x86,%d] Unknown vendor", __LINE__));
+		return (NULL);
 
 	/* disallow sampling if we do not have an LAPIC */
-	if (md != NULL && lapic == NULL)
+	if (!lapic_enable_pmc())
 		for (i = 1; i < md->pmd_nclass; i++)
 			md->pmd_classdep[i].pcd_caps &= ~PMC_CAP_INTERRUPT;
 
@@ -271,6 +259,8 @@ pmc_md_initialize()
 void
 pmc_md_finalize(struct pmc_mdep *md)
 {
+
+	lapic_disable_pmc();
 	if (cpu_vendor_id == CPU_VENDOR_AMD)
 		pmc_amd_finalize(md);
 	else if (cpu_vendor_id == CPU_VENDOR_INTEL)
diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h
index 05078afc8f1..e7bc3497af2 100644
--- a/sys/dev/hwpmc/pmc_events.h
+++ b/sys/dev/hwpmc/pmc_events.h
@@ -29,8 +29,18 @@
 #ifndef _DEV_HWPMC_PMC_EVENTS_H_
 #define	_DEV_HWPMC_PMC_EVENTS_H_
 
-/*
- * PMC event codes.
+/* 
+ * Note: Documentation on adding events can be found both in
+ * the source tree at src/share/doc/papers/hwpmc/hwpmc.ms
+ * as well as on-line at:
+ *
+ * http://wiki.freebsd.org/PmcTools/PmcHardwareHowTo
+ *
+ * Please refer to those resources before you attempt to modify
+ * this file or the hwpmc driver/subsystem.
+ */
+
+/* * PMC event codes.
  *
  * __PMC_EV(CLASS, SYMBOLIC-NAME)
  *
@@ -973,7 +983,30 @@ __PMC_EV(IAP, EVENT_FDH_04H)			\
 __PMC_EV(IAP, EVENT_FDH_08H)			\
 __PMC_EV(IAP, EVENT_FDH_10H)			\
 __PMC_EV(IAP, EVENT_FDH_20H)			\
-__PMC_EV(IAP, EVENT_FDH_40H)
+__PMC_EV(IAP, EVENT_FDH_40H)			\
+__PMC_EV(IAP, EVENT_E6H_02H)			\
+__PMC_EV(IAP, EVENT_E8H_01H)			\
+__PMC_EV(IAP, EVENT_E8H_02H)			\
+__PMC_EV(IAP, EVENT_E8H_03H)			\
+__PMC_EV(IAP, EVENT_F0H_01H)			\
+__PMC_EV(IAP, EVENT_F0H_02H)			\
+__PMC_EV(IAP, EVENT_F0H_04H)			\
+__PMC_EV(IAP, EVENT_F0H_08H)			\
+__PMC_EV(IAP, EVENT_F0H_10H)			\
+__PMC_EV(IAP, EVENT_F0H_20H)			\
+__PMC_EV(IAP, EVENT_F0H_40H)			\
+__PMC_EV(IAP, EVENT_F0H_80H)			\
+__PMC_EV(IAP, EVENT_F1H_02H)			\
+__PMC_EV(IAP, EVENT_F1H_04H)			\
+__PMC_EV(IAP, EVENT_F1H_07H)			\
+__PMC_EV(IAP, EVENT_F2H_01H)			\
+__PMC_EV(IAP, EVENT_F2H_02H)			\
+__PMC_EV(IAP, EVENT_F2H_04H)			\
+__PMC_EV(IAP, EVENT_F2H_08H)			\
+__PMC_EV(IAP, EVENT_F2H_0FH)			\
+__PMC_EV(IAP, EVENT_F3H_01H)			\
+__PMC_EV(IAP, EVENT_F3H_02H)			
+
 
 #define	PMC_EV_IAP_FIRST	PMC_EV_IAP_EVENT_02H_81H
 #define	PMC_EV_IAP_LAST		PMC_EV_IAP_EVENT_FDH_40H
@@ -1894,6 +1927,29 @@ __PMC_EV_ALIAS("UOP_UNFUSION",				IAP_EVENT_DBH_01H) \
 __PMC_EV_ALIAS("BR_INST_DECODED",			IAP_EVENT_E0H_01H) \
 __PMC_EV_ALIAS("BOGUS_BR",				IAP_EVENT_E4H_01H) \
 __PMC_EV_ALIAS("BPU_MISSED_CALL_RET",			IAP_EVENT_E5H_01H) \
+__PMC_EV_ALIAS("BACLEAR.CLEAR",				IAP_EVENT_E6H_01H) \
+__PMC_EV_ALIAS("BACLEAR.BAD_TARGET",			IAP_EVENT_E6H_02H) \
+__PMC_EV_ALIAS("BPU_CLEARS.EARLY",			IAP_EVENT_E8H_01H) \
+__PMC_EV_ALIAS("BPU_CLEARS.LATE",			IAP_EVENT_E8H_02H) \
+__PMC_EV_ALIAS("BPU_CLEARS.ANY",			IAP_EVENT_E8H_03H) \
+__PMC_EV_ALIAS("L2_TRANSACTIONS.LOAD",			IAP_EVENT_F0H_01H) \
+__PMC_EV_ALIAS("L2_TRANSACTIONS.RFO",			IAP_EVENT_F0H_02H) \
+__PMC_EV_ALIAS("L2_TRANSACTIONS.IFETCH",		IAP_EVENT_F0H_04H) \
+__PMC_EV_ALIAS("L2_TRANSACTIONS.PREFETCH",		IAP_EVENT_F0H_08H) \
+__PMC_EV_ALIAS("L2_TRANSACTIONS.L1D_WB",		IAP_EVENT_F0H_10H) \
+__PMC_EV_ALIAS("L2_TRANSACTIONS.FILL",			IAP_EVENT_F0H_20H) \
+__PMC_EV_ALIAS("L2_TRANSACTIONS.WB",			IAP_EVENT_F0H_40H) \
+__PMC_EV_ALIAS("L2_TRANSACTIONS.ANY",			IAP_EVENT_F0H_80H) \
+__PMC_EV_ALIAS("L2_LINES_IN.S_STATE",			IAP_EVENT_F1H_02H) \
+__PMC_EV_ALIAS("L2_LINES_IN.E_STATE",			IAP_EVENT_F1H_04H) \
+__PMC_EV_ALIAS("L2_LINES_IN.ANY",			IAP_EVENT_F1H_07H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.DEMAND_CLEAN",		IAP_EVENT_F2H_01H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.DEMAND_DIRTY",		IAP_EVENT_F2H_02H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.PREFETCH_CLEAN",		IAP_EVENT_F2H_04H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.PREFETCH_DIRTY",		IAP_EVENT_F2H_08H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.ANY",			IAP_EVENT_F2H_0FH) \
+__PMC_EV_ALIAS("L2_HW_PREFETCH.HIT",			IAP_EVENT_F3H_01H) \
+__PMC_EV_ALIAS("L2_HW_PREFETCH.ALLOC",			IAP_EVENT_F3H_02H) \
 __PMC_EV_ALIAS("L2_HW_PREFETCH.DATA_TRIGGER",		IAP_EVENT_F3H_04H) \
 __PMC_EV_ALIAS("L2_HW_PREFETCH.CODE_TRIGGER",		IAP_EVENT_F3H_08H) \
 __PMC_EV_ALIAS("L2_HW_PREFETCH.DCA_TRIGGER",		IAP_EVENT_F3H_10H) \
diff --git a/sys/dev/ips/ips_pci.c b/sys/dev/ips/ips_pci.c
index 70e7d3be068..9ccaf373b3e 100644
--- a/sys/dev/ips/ips_pci.c
+++ b/sys/dev/ips/ips_pci.c
@@ -173,12 +173,10 @@ ips_intrhook(void *arg)
 	struct ips_softc *sc = (struct ips_softc *)arg;
 
 	config_intrhook_disestablish(&sc->ips_ich);
-	newbus_xlock();
 	if (ips_adapter_init(sc))
 		ips_pci_free(sc);
 	else
 		sc->configured = 1;
-	newbus_xunlock();
 }
 
 static int ips_pci_free(ips_softc_t *sc)
diff --git a/sys/dev/iscsi/initiator/isc_cam.c b/sys/dev/iscsi/initiator/isc_cam.c
index fbd5b3d406f..0d8782351c8 100644
--- a/sys/dev/iscsi/initiator/isc_cam.c
+++ b/sys/dev/iscsi/initiator/isc_cam.c
@@ -190,6 +190,8 @@ _inq(struct cam_sim *sim, union ccb *ccb, int maxluns)
      strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
      strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
      cpi->unit_number = cam_sim_unit(sim);
+     cpi->transport = XPORT_ISCSI;
+     cpi->transport_version = 0;
      cpi->ccb_h.status = CAM_REQ_CMP;
 }
 
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index b6f172b664e..3d20b097e58 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -5280,6 +5280,10 @@ isp_default_wwn(ispsoftc_t * isp, int chan, int isactive, int iswwnn)
 			return (seed);
 		}
 		seed = iswwnn ? FCPARAM(isp, chan)->isp_wwnn_nvram : FCPARAM(isp, chan)->isp_wwpn_nvram;
+		if (seed) {
+			return (seed);
+		}
+		return (0x400000007F000009ull);
 	} else {
 		seed = iswwnn ? fc->def_wwnn : fc->def_wwpn;
 	}
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index bd95bdf0a9f..008ded88c11 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -46,7 +46,7 @@ int             ixgbe_display_debug_stats = 0;
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixgbe_driver_version[] = "1.8.8";
+char ixgbe_driver_version[] = "1.8.9";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -245,6 +245,15 @@ TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
 static int ixgbe_enable_msix = 1;
 TUNABLE_INT("hw.ixgbe.enable_msix", &ixgbe_enable_msix);
 
+/*
+ * Header split has seemed to be beneficial in
+ * all circumstances tested, so its on by default
+ * however this variable will allow it to be disabled
+ * for some debug purposes.
+ */
+static bool ixgbe_header_split = TRUE;
+TUNABLE_INT("hw.ixgbe.hdr_split", &ixgbe_header_split);
+
 /*
  * Number of Queues, should normally
  * be left at 0, it then autoconfigures to
@@ -454,7 +463,6 @@ ixgbe_attach(device_t dev)
 	*/
 	if (nmbclusters > 0 ) {
 		int s;
-		/* Calculate the total RX mbuf needs */
 		s = (ixgbe_rxd * adapter->num_queues) * ixgbe_total_ports;
 		if (s > nmbclusters) {
 			device_printf(dev, "RX Descriptors exceed "
@@ -751,7 +759,8 @@ ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
         struct mbuf     *next;
         int             err = 0;
 
-	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+	if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) ||
+	    (!adapter->link_active)) {
 		err = drbr_enqueue(ifp, txr->br, m);
 		return (err);
 	}
@@ -1459,8 +1468,7 @@ ixgbe_msix_link(void *arg)
                 	device_printf(adapter->dev, "\nCRITICAL: ECC ERROR!! "
 			    "Please Reboot!!\n");
 			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
-		}
-		if (reg_eicr & IXGBE_EICR_GPI_SDP1) {
+		} else if (reg_eicr & IXGBE_EICR_GPI_SDP1) {
                 	/* Clear the interrupt */
                 	IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
 			taskqueue_enqueue(adapter->tq, &adapter->msf_task);
@@ -1883,7 +1891,11 @@ ixgbe_set_multi(struct adapter *adapter)
 	
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl);
 
+#if __FreeBSD_version < 800000
+	IF_ADDR_LOCK(ifp);
+#else
 	if_maddr_rlock(ifp);
+#endif
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1892,7 +1904,11 @@ ixgbe_set_multi(struct adapter *adapter)
 		    IXGBE_ETH_LENGTH_OF_ADDRESS);
 		mcnt++;
 	}
+#if __FreeBSD_version < 800000
+	IF_ADDR_UNLOCK(ifp);
+#else
 	if_maddr_runlock(ifp);
+#endif
 
 	update_ptr = mta;
 	ixgbe_update_mc_addr_list(&adapter->hw,
@@ -3534,7 +3550,10 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr)
 	rxr->next_to_check = 0;
 	rxr->last_cleaned = 0;
 	rxr->lro_enabled = FALSE;
-	rxr->hdr_split = FALSE;
+
+	/* Use header split if configured */
+	if (ixgbe_header_split)
+		rxr->hdr_split = TRUE;
 
 	bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -3553,7 +3572,6 @@ ixgbe_setup_receive_ring(struct rx_ring *rxr)
 		}
 		INIT_DEBUGOUT("RX LRO Initialized\n");
 		rxr->lro_enabled = TRUE;
-		rxr->hdr_split = TRUE;
 		lro->ifp = adapter->ifp;
 	}
 
@@ -4457,24 +4475,42 @@ ixgbe_update_stats_counters(struct adapter *adapter)
 	struct ifnet   *ifp = adapter->ifp;;
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32  missed_rx = 0, bprc, lxon, lxoff, total;
+	u64  total_missed_rx = 0;
 
 	adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
 
 	for (int i = 0; i < 8; i++) {
-		int mp;
-		mp = IXGBE_READ_REG(hw, IXGBE_MPC(i));
-		missed_rx += mp;
-        	adapter->stats.mpc[i] += mp;
-		adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+		/* missed_rx tallies misses for the gprc workaround */
+		missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(i));
+        	adapter->stats.mpc[i] += missed_rx;
+		/* Running comprehensive total for stats display */
+		total_missed_rx += adapter->stats.mpc[i];
+		if (hw->mac.type == ixgbe_mac_82598EB)
+			adapter->stats.rnbc[i] +=
+			    IXGBE_READ_REG(hw, IXGBE_RNBC(i));
 	}
 
 	/* Hardware workaround, gprc counts missed packets */
 	adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
 	adapter->stats.gprc -= missed_rx;
 
-	adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
-	adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
-	adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
+	if (hw->mac.type == ixgbe_mac_82599EB) {
+		adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCL);
+		IXGBE_READ_REG(hw, IXGBE_GORCH); /* clears register */
+		adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL);
+		IXGBE_READ_REG(hw, IXGBE_GOTCH); /* clears register */
+		adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORL);
+		IXGBE_READ_REG(hw, IXGBE_TORH); /* clears register */
+		adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
+		adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+	} else {
+		adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
+		adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+		/* 82598 only has a counter in the high register */
+		adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
+		adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
+		adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
+	}
 
 	/*
 	 * Workaround: mprc hardware is incorrectly counting
@@ -4494,9 +4530,6 @@ ixgbe_update_stats_counters(struct adapter *adapter)
 	adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
 	adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
 
-	adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
-	adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
-
 	lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
 	adapter->stats.lxontxc += lxon;
 	lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
@@ -4532,7 +4565,7 @@ ixgbe_update_stats_counters(struct adapter *adapter)
 	ifp->if_collisions = 0;
 
 	/* Rx Errors */
-	ifp->if_ierrors = missed_rx + adapter->stats.crcerrs +
+	ifp->if_ierrors = total_missed_rx + adapter->stats.crcerrs +
 		adapter->stats.rlec;
 }
 
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index 0ae585e892d..eb18ffe4ce3 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -1327,11 +1327,11 @@ mfi_add_ld_complete(struct mfi_command *cm)
 	mfi_release_command(cm);
 
 	mtx_unlock(&sc->mfi_io_lock);
-	newbus_xlock();
+	mtx_lock(&Giant);
 	if ((child = device_add_child(sc->mfi_dev, "mfid", -1)) == NULL) {
 		device_printf(sc->mfi_dev, "Failed to add logical disk\n");
 		free(ld_info, M_MFIBUF);
-		newbus_xunlock();
+		mtx_unlock(&Giant);
 		mtx_lock(&sc->mfi_io_lock);
 		return;
 	}
@@ -1339,7 +1339,7 @@ mfi_add_ld_complete(struct mfi_command *cm)
 	device_set_ivars(child, ld_info);
 	device_set_desc(child, "MFI Logical Disk");
 	bus_generic_attach(sc->mfi_dev);
-	newbus_xunlock();
+	mtx_unlock(&Giant);
 	mtx_lock(&sc->mfi_io_lock);
 }
 
@@ -1805,9 +1805,9 @@ mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm)
 		KASSERT(ld != NULL, ("volume dissappeared"));
 		if (cm->cm_frame->header.cmd_status == MFI_STAT_OK) {
 			mtx_unlock(&sc->mfi_io_lock);
-			newbus_xlock();
+			mtx_lock(&Giant);
 			device_delete_child(sc->mfi_dev, ld->ld_dev);
-			newbus_xunlock();
+			mtx_unlock(&Giant);
 			mtx_lock(&sc->mfi_io_lock);
 		} else
 			mfi_disk_enable(ld);
@@ -1815,11 +1815,11 @@ mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm)
 	case MFI_DCMD_CFG_CLEAR:
 		if (cm->cm_frame->header.cmd_status == MFI_STAT_OK) {
 			mtx_unlock(&sc->mfi_io_lock);
-			newbus_xlock();
+			mtx_lock(&Giant);
 			TAILQ_FOREACH_SAFE(ld, &sc->mfi_ld_tqh, ld_link, ldn) {
 				device_delete_child(sc->mfi_dev, ld->ld_dev);
 			}
-			newbus_xunlock();
+			mtx_unlock(&Giant);
 			mtx_lock(&sc->mfi_io_lock);
 		} else {
 			TAILQ_FOREACH(ld, &sc->mfi_ld_tqh, ld_link)
@@ -1985,9 +1985,7 @@ mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td
 
 		adapter = ioc->mfi_adapter_no;
 		if (device_get_unit(sc->mfi_dev) == 0 && adapter != 0) {
-			newbus_slock();
 			devclass = devclass_find("mfi");
-			newbus_sunlock();
 			sc = devclass_get_softc(devclass, adapter);
 		}
 		mtx_lock(&sc->mfi_io_lock);
@@ -2175,9 +2173,7 @@ out:
 			struct mfi_linux_ioc_packet l_ioc;
 			int adapter;
 
-			newbus_slock();
 			devclass = devclass_find("mfi");
-			newbus_sunlock();
 			if (devclass == NULL)
 				return (ENOENT);
 
@@ -2198,9 +2194,7 @@ out:
 			struct mfi_linux_ioc_aen l_aen;
 			int adapter;
 
-			newbus_slock();
 			devclass = devclass_find("mfi");
-			newbus_sunlock();
 			if (devclass == NULL)
 				return (ENOENT);
 
diff --git a/sys/dev/mfi/mfi_ioctl.h b/sys/dev/mfi/mfi_ioctl.h
index 22973d7f3d2..48e9c7f7ba2 100644
--- a/sys/dev/mfi/mfi_ioctl.h
+++ b/sys/dev/mfi/mfi_ioctl.h
@@ -27,6 +27,8 @@
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
+
 #if defined(__amd64__) /* Assume amd64 wants 32 bit Linux */
 struct iovec32 {
 	u_int32_t	iov_base;
diff --git a/sys/dev/mfi/mfireg.h b/sys/dev/mfi/mfireg.h
index be56b481079..17ab4b3b5cf 100644
--- a/sys/dev/mfi/mfireg.h
+++ b/sys/dev/mfi/mfireg.h
@@ -89,7 +89,7 @@ __FBSDID("$FreeBSD$");
 #define MFI_ODCR0	0xa0 		/* outbound doorbell clear register0  */
 #define MFI_OSP0	0xb0 		/* outbound scratch pad0  */
 #define MFI_1078_EIM	0x80000004 	/* 1078 enable intrrupt mask  */
-#define MFI_RMI		0x2 		/* reply message interrupt  */
+#define MFI_RMI		0x2 		/* reply message interrupt  */       
 #define MFI_1078_RM	0x80000000 	/* reply 1078 message interrupt  */
 #define MFI_ODC		0x4 		/* outbound doorbell change interrupt */
 
@@ -151,15 +151,41 @@ typedef enum {
 	MFI_DCMD_CTRL_EVENT_GETINFO =	0x01040100,
 	MFI_DCMD_CTRL_EVENT_GET =	0x01040300,
 	MFI_DCMD_CTRL_EVENT_WAIT =	0x01040500,
+	MFI_DCMD_PR_GET_STATUS =	0x01070100,
+	MFI_DCMD_PR_GET_PROPERTIES =	0x01070200,
+	MFI_DCMD_PR_SET_PROPERTIES =	0x01070300,
+	MFI_DCMD_PR_START =		0x01070400,
+	MFI_DCMD_PR_STOP =		0x01070500,
+	MFI_DCMD_TIME_SECS_GET =	0x01080201,
+	MFI_DCMD_FLASH_FW_OPEN =	0x010f0100,
+	MFI_DCMD_FLASH_FW_DOWNLOAD =	0x010f0200,
+	MFI_DCMD_FLASH_FW_FLASH =	0x010f0300,
+	MFI_DCMD_FLASH_FW_CLOSE =	0x010f0400,
+	MFI_DCMD_PD_GET_LIST =		0x02010000,
+	MFI_DCMD_PD_GET_INFO = 		0x02020000,
+	MFI_DCMD_PD_STATE_SET =		0x02030100,
+	MFI_DCMD_PD_REBUILD_START =	0x02040100,
+	MFI_DCMD_PD_REBUILD_ABORT =	0x02040200,
+	MFI_DCMD_PD_CLEAR_START =	0x02050100,
+	MFI_DCMD_PD_CLEAR_ABORT =	0x02050200,
+	MFI_DCMD_PD_GET_PROGRESS =	0x02060000,
+	MFI_DCMD_PD_LOCATE_START =	0x02070100,
+	MFI_DCMD_PD_LOCATE_STOP =	0x02070200,
 	MFI_DCMD_LD_GET_LIST =		0x03010000,
 	MFI_DCMD_LD_GET_INFO =		0x03020000,
 	MFI_DCMD_LD_GET_PROP =		0x03030000,
 	MFI_DCMD_LD_SET_PROP =		0x03040000,
+	MFI_DCMD_LD_INIT_START =	0x03060100,
 	MFI_DCMD_LD_DELETE =		0x03090000,
 	MFI_DCMD_CFG_READ =		0x04010000,
 	MFI_DCMD_CFG_ADD =		0x04020000,
 	MFI_DCMD_CFG_CLEAR =		0x04030000,
+	MFI_DCMD_CFG_MAKE_SPARE =	0x04040000,
+	MFI_DCMD_CFG_REMOVE_SPARE =	0x04050000,	
 	MFI_DCMD_CFG_FOREIGN_IMPORT =	0x04060400,
+	MFI_DCMD_BBU_GET_STATUS =	0x05010000,
+	MFI_DCMD_BBU_GET_CAPACITY_INFO =0x05020000,
+	MFI_DCMD_BBU_GET_DESIGN_INFO =	0x05030000,
 	MFI_DCMD_CLUSTER =		0x08000000,
 	MFI_DCMD_CLUSTER_RESET_ALL =	0x08010100,
 	MFI_DCMD_CLUSTER_RESET_LD =	0x08010200
@@ -245,6 +271,9 @@ typedef enum {
 	MFI_STAT_RESERVATION_IN_PROGRESS,
 	MFI_STAT_I2C_ERRORS_DETECTED,
 	MFI_STAT_PCI_ERRORS_DETECTED,
+	MFI_STAT_DIAG_FAILED,
+	MFI_STAT_BOOT_MSG_PENDING,
+	MFI_STAT_FOREIGN_CONFIG_INCOMPLETE,
 	MFI_STAT_INVALID_STATUS =	0xFF
 } mfi_status_t;
 
@@ -303,6 +332,17 @@ typedef enum {
 	MR_LD_CACHE_ALLOW_WRITE_CACHE =	0x20,
 	MR_LD_CACHE_ALLOW_READ_CACHE =	0x40
 } mfi_ld_cache;
+#define	MR_LD_CACHE_MASK	0x7f
+
+#define	MR_LD_CACHE_POLICY_READ_AHEAD_NONE		0
+#define	MR_LD_CACHE_POLICY_READ_AHEAD_ALWAYS		MR_LD_CACHE_READ_AHEAD
+#define	MR_LD_CACHE_POLICY_READ_AHEAD_ADAPTIVE		\
+	(MR_LD_CACHE_READ_AHEAD | MR_LD_CACHE_READ_ADAPTIVE)
+#define	MR_LD_CACHE_POLICY_WRITE_THROUGH		0
+#define	MR_LD_CACHE_POLICY_WRITE_BACK			MR_LD_CACHE_WRITE_BACK
+#define	MR_LD_CACHE_POLICY_IO_CACHED			\
+	(MR_LD_CACHE_ALLOW_WRITE_CACHE | MR_LD_CACHE_ALLOW_READ_CACHE)
+#define	MR_LD_CACHE_POLICY_IO_DIRECT			0
 
 typedef enum {
 	MR_PD_CACHE_UNCHANGED  =	0,
@@ -320,6 +360,7 @@ typedef enum {
 #define MFI_DEFAULT_ID		-1
 #define MFI_MAX_LUN		8
 #define MFI_MAX_LD		64
+#define	MFI_MAX_PD		256
 
 #define MFI_FRAME_SIZE		64
 #define MFI_MBOX_SIZE		12
@@ -866,12 +907,10 @@ union mfi_pd_ddf_type {
 } __packed;
 
 struct mfi_pd_progress {
-	struct {
-		uint32_t		rbld	: 1;
-		uint32_t		patrol	: 1;
-		uint32_t		clear	: 1;
-		uint32_t		reserved: 29;
-	} active;
+	uint32_t			active;
+#define	MFI_PD_PROGRESS_REBUILD	(1<<0)
+#define	MFI_PD_PROGRESS_PATROL	(1<<1)
+#define	MFI_PD_PROGRESS_CLEAR	(1<<2)
 	struct mfi_progress		rbld;
 	struct mfi_progress		patrol;
 	struct mfi_progress		clear;
@@ -890,8 +929,8 @@ struct mfi_pd_info {
 	uint32_t			other_err_count;
 	uint32_t			pred_fail_count;
 	uint32_t			last_pred_fail_event_seq_num;
-	uint16_t			fw_state;
-	uint8_t				disable_for_removal;
+	uint16_t			fw_state;	/* MFI_PD_STATE_* */
+	uint8_t				disabled_for_removal;
 	uint8_t				link_speed;
 	union mfi_pd_ddf_type		state;
 	struct {
@@ -918,7 +957,7 @@ struct mfi_pd_address {
 	uint16_t		encl_device_id;
 	uint8_t			encl_index;
 	uint8_t			slot_number;
-	uint8_t			scsi_dev_type;
+	uint8_t			scsi_dev_type;	/* 0 = disk */
 	uint8_t			connect_port_bitmap;
 	uint64_t		sas_addr[2];
 } __packed;
@@ -926,12 +965,19 @@ struct mfi_pd_address {
 struct mfi_pd_list {
 	uint32_t		size;
 	uint32_t		count;
-	uint8_t			data;
-	/*
-	struct mfi_pd_address	addr[];
-	*/
+	struct mfi_pd_address	addr[0];
 } __packed;
 
+enum mfi_pd_state {
+	MFI_PD_STATE_UNCONFIGURED_GOOD = 0x00,
+	MFI_PD_STATE_UNCONFIGURED_BAD = 0x01,
+	MFI_PD_STATE_HOT_SPARE = 0x02,
+	MFI_PD_STATE_OFFLINE = 0x10,
+	MFI_PD_STATE_FAILED = 0x11,
+	MFI_PD_STATE_REBUILD = 0x14,
+	MFI_PD_STATE_ONLINE = 0x18
+};
+
 union mfi_ld_ref {
 	struct {
 		uint8_t		target_id;
@@ -986,6 +1032,9 @@ struct mfi_ld_params {
 	uint8_t			span_depth;
 	uint8_t			state;
 	uint8_t			init_state;
+#define	MFI_LD_PARAMS_INIT_NO		0
+#define	MFI_LD_PARAMS_INIT_QUICK	1
+#define	MFI_LD_PARAMS_INIT_FULL		2
 	uint8_t			is_consistent;
 	uint8_t			reserved[23];
 } __packed;
@@ -995,7 +1044,7 @@ struct mfi_ld_progress {
 #define	MFI_LD_PROGRESS_CC	(1<<0)
 #define	MFI_LD_PROGRESS_BGI	(1<<1)
 #define	MFI_LD_PROGRESS_FGI	(1<<2)
-#define	MFI_LD_PORGRESS_RECON	(1<<3)
+#define	MFI_LD_PROGRESS_RECON	(1<<3)
 	struct mfi_progress	cc;
 	struct mfi_progress	bgi;
 	struct mfi_progress	fgi;
@@ -1028,26 +1077,18 @@ struct mfi_ld_info {
 	uint8_t			reserved2[16];
 } __packed;
 
-union mfi_spare_type {
-	struct {
-		uint8_t		is_dedicate		:1;
-		uint8_t		is_revertable		:1;
-		uint8_t		is_encl_affinity	:1;
-		uint8_t		reserved		:5;
-	} v;
-	uint8_t		type;
-} __packed;
-
 #define MAX_ARRAYS 16
 struct mfi_spare {
 	union mfi_pd_ref	ref;
-	union mfi_spare_type	spare_type;
+	uint8_t			spare_type;
+#define	MFI_SPARE_DEDICATED	(1 << 0)
+#define	MFI_SPARE_REVERTIBLE	(1 << 1)
+#define	MFI_SPARE_ENCL_AFFINITY	(1 << 2)
 	uint8_t			reserved[2];
 	uint8_t			array_count;
-	uint16_t		array_refd[MAX_ARRAYS];
+	uint16_t		array_ref[MAX_ARRAYS];
 } __packed;
 
-#define MAX_ROW_SIZE 32
 struct mfi_array {
 	uint64_t			size;
 	uint8_t				num_drives;
@@ -1055,13 +1096,13 @@ struct mfi_array {
 	uint16_t			array_ref;
 	uint8_t				pad[20];
 	struct {
-		union mfi_pd_ref	ref;
-		uint16_t		fw_state;
+		union mfi_pd_ref	ref;	/* 0xffff == missing drive */
+		uint16_t		fw_state;	/* MFI_PD_STATE_* */
 		struct {
 			uint8_t		pd;
 			uint8_t		slot;
 		} encl;
-	} pd[MAX_ROW_SIZE];
+	} pd[0];
 } __packed;
 
 struct mfi_config_data {
@@ -1073,14 +1114,118 @@ struct mfi_config_data {
 	uint16_t		spares_count;
 	uint16_t		spares_size;
 	uint8_t			reserved[16];
-	uint8_t			data;
-	/*
-	struct mfi_array	array[];
-	struct mfi_ld_config	ld[];
-	struct mfi_spare	spare[];
-	*/
+	struct mfi_array	array[0];
+	struct mfi_ld_config	ld[0];
+	struct mfi_spare	spare[0];
 } __packed;
 
+struct mfi_bbu_capacity_info {
+	uint16_t		relative_charge;
+	uint16_t		absolute_charge;
+	uint16_t		remaining_capacity;
+	uint16_t		full_charge_capacity;
+	uint16_t		run_time_to_empty;
+	uint16_t		average_time_to_empty;
+	uint16_t		average_time_to_full;
+	uint16_t		cycle_count;
+	uint16_t		max_error;
+	uint16_t		remaining_capacity_alarm;
+	uint16_t		remaining_time_alarm;
+	uint8_t			reserved[26];
+} __packed;
+
+struct mfi_bbu_design_info {
+	uint32_t		mfg_date;
+	uint16_t		design_capacity;
+	uint16_t		design_voltage;
+	uint16_t		spec_info;
+	uint16_t		serial_number;
+	uint16_t		pack_stat_config;
+	uint8_t			mfg_name[12];
+	uint8_t			device_name[8];
+	uint8_t			device_chemistry[8];
+	uint8_t			mfg_data[8];
+	uint8_t			reserved[17];
+} __packed;
+
+struct mfi_ibbu_state {
+	uint16_t		gas_guage_status;
+	uint16_t		relative_charge;
+	uint16_t		charger_system_state;
+	uint16_t		charger_system_ctrl;
+	uint16_t		charging_current;
+	uint16_t		absolute_charge;
+	uint16_t		max_error;
+	uint8_t			reserved[18];
+} __packed;
+
+struct mfi_bbu_state {
+	uint16_t		gas_guage_status;
+	uint16_t		relative_charge;
+	uint16_t		charger_status;
+	uint16_t		remaining_capacity;
+	uint16_t		full_charge_capacity;
+	uint8_t			is_SOH_good;
+	uint8_t			reserved[21];
+} __packed;
+
+union mfi_bbu_status_detail {
+	struct mfi_ibbu_state	ibbu;
+	struct mfi_bbu_state	bbu;
+};
+
+struct mfi_bbu_status {
+	uint8_t			battery_type;
+#define	MFI_BBU_TYPE_NONE	0
+#define	MFI_BBU_TYPE_IBBU	1
+#define	MFI_BBU_TYPE_BBU	2	
+	uint8_t			reserved;
+	uint16_t		voltage;
+	int16_t			current;
+	uint16_t		temperature;
+	uint32_t		fw_status;
+#define	MFI_BBU_STATE_PACK_MISSING	(1 << 0)
+#define	MFI_BBU_STATE_VOLTAGE_LOW	(1 << 1)
+#define	MFI_BBU_STATE_TEMPERATURE_HIGH	(1 << 2)
+#define	MFI_BBU_STATE_CHARGE_ACTIVE	(1 << 0)
+#define	MFI_BBU_STATE_DISCHARGE_ACTIVE	(1 << 0)
+	uint8_t			pad[20];
+	union mfi_bbu_status_detail detail;
+} __packed;
+
+enum mfi_pr_state {
+	MFI_PR_STATE_STOPPED = 0,
+	MFI_PR_STATE_READY = 1,
+	MFI_PR_STATE_ACTIVE = 2,
+	MFI_PR_STATE_ABORTED = 0xff
+};
+
+struct mfi_pr_status {
+	uint32_t		num_iteration;
+	uint8_t			state;
+	uint8_t			num_pd_done;
+	uint8_t			reserved[10];
+};
+
+enum mfi_pr_opmode {
+	MFI_PR_OPMODE_AUTO = 0,
+	MFI_PR_OPMODE_MANUAL = 1,
+	MFI_PR_OPMODE_DISABLED = 2
+};
+
+struct mfi_pr_properties {
+	uint8_t			op_mode;
+	uint8_t			max_pd;
+	uint8_t			reserved;
+	uint8_t			exclude_ld_count;
+	uint16_t		excluded_ld[MFI_MAX_LD];
+	uint8_t			cur_pd_map[MFI_MAX_PD / 8];
+	uint8_t			last_pd_map[MFI_MAX_PD / 8];
+	uint32_t		next_exec;
+	uint32_t		exec_freq;
+	uint32_t		clear_freq;
+};
+
 #define MFI_SCSI_MAX_TARGETS	128
 #define MFI_SCSI_MAX_LUNS	8
 #define MFI_SCSI_INITIATOR_ID	255
diff --git a/sys/dev/mge/if_mge.c b/sys/dev/mge/if_mge.c
index ff505e98637..0188ae3b79f 100644
--- a/sys/dev/mge/if_mge.c
+++ b/sys/dev/mge/if_mge.c
@@ -69,7 +69,9 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-#define	MV_PHY_ADDR_BASE	8
+#ifndef MII_ADDR_BASE
+#define MII_ADDR_BASE 8
+#endif
 
 #include 
 #include 
@@ -1264,14 +1266,15 @@ mge_miibus_readreg(device_t dev, int phy, int reg)
 
 	/*
 	 * We assume static PHY address <=> device unit mapping:
-	 * PHY Address = MV_PHY_ADDR_BASE + devce unit.
+	 * PHY Address = MII_ADDR_BASE + devce unit.
 	 * This is true for most Marvell boards.
 	 * 
 	 * Code below grants proper PHY detection on each device
 	 * unit.
 	 */
 
-	if ((MV_PHY_ADDR_BASE + device_get_unit(dev)) != phy)
+	
+	if ((MII_ADDR_BASE + device_get_unit(dev)) != phy)
 		return (0);
 
 	MGE_WRITE(sc_mge0, MGE_REG_SMI, 0x1fffffff &
@@ -1292,7 +1295,7 @@ mge_miibus_writereg(device_t dev, int phy, int reg, int value)
 {
 	uint32_t retries;
 
-	if ((MV_PHY_ADDR_BASE + device_get_unit(dev)) != phy)
+	if ((MII_ADDR_BASE + device_get_unit(dev)) != phy)
 		return (0);
 
 	MGE_WRITE(sc_mge0, MGE_REG_SMI, 0x1fffffff &
diff --git a/sys/dev/mii/e1000phy.c b/sys/dev/mii/e1000phy.c
index f0d159bbaca..4f2fa66f6e8 100644
--- a/sys/dev/mii/e1000phy.c
+++ b/sys/dev/mii/e1000phy.c
@@ -240,13 +240,11 @@ e1000phy_reset(struct mii_softc *sc)
 
 		if (esc->mii_model == MII_MODEL_MARVELL_E1116 ||
 		    esc->mii_model == MII_MODEL_MARVELL_E1149) {
-			page = PHY_READ(sc, E1000_EADR);
-			/* Select page 2, MAC specific control register. */
 			PHY_WRITE(sc, E1000_EADR, 2);
 			reg = PHY_READ(sc, E1000_SCR);
 			reg |= E1000_SCR_RGMII_POWER_UP;
 			PHY_WRITE(sc, E1000_SCR, reg);
-			PHY_WRITE(sc, E1000_EADR, page);
+			PHY_WRITE(sc, E1000_EADR, 0);
 		}
 	}
 
diff --git a/sys/dev/mlx/mlx.c b/sys/dev/mlx/mlx.c
index 9e74f624573..6087216901f 100644
--- a/sys/dev/mlx/mlx.c
+++ b/sys/dev/mlx/mlx.c
@@ -772,9 +772,7 @@ mlx_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct threa
 	 * Scan the controller to see whether new drives have appeared.
 	 */
     case MLX_RESCAN_DRIVES:
-	newbus_xlock();
 	mlx_startup(sc);
-	newbus_xunlock();
 	return(0);
 
 	/*
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index 0fd424dbaf4..68726675f81 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -1496,9 +1496,7 @@ mmc_delayed_attach(void *xsc)
 {
 	struct mmc_softc *sc = xsc;
 	
-	newbus_xlock();
 	mmc_scan(sc);
-	newbus_xunlock();
 	config_intrhook_disestablish(&sc->config_intrhook);
 }
 
diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c
index c320cdb49c3..991bc792e1a 100644
--- a/sys/dev/mwl/if_mwl.c
+++ b/sys/dev/mwl/if_mwl.c
@@ -1738,6 +1738,10 @@ mwl_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
 		 * WEP keys when the sta reaches AUTH state.
 		 */
 		macaddr = vap->iv_bss->ni_bssid;
+		if ((k->wk_flags & IEEE80211_KEY_GROUP) == 0) {
+			/* XXX plumb to local sta db too for static key wep */
+			mwl_hal_keyset(hvap, &hk, vap->iv_myaddr);
+		}
 	} else if (vap->iv_opmode == IEEE80211_M_WDS &&
 	    vap->iv_state != IEEE80211_S_RUN) {
 		/*
diff --git a/sys/dev/null/null.c b/sys/dev/null/null.c
index 0b94eb7aa86..0f1d118b730 100644
--- a/sys/dev/null/null.c
+++ b/sys/dev/null/null.c
@@ -49,9 +49,6 @@ static d_write_t null_write;
 static d_ioctl_t null_ioctl;
 static d_read_t zero_read;
 
-#define NULL_MINOR	2
-#define ZERO_MINOR	12
-
 static struct cdevsw null_cdevsw = {
 	.d_version =	D_VERSION,
 	.d_read =	(d_read_t *)nullop,
@@ -115,10 +112,10 @@ null_modevent(module_t mod __unused, int type, void *data __unused)
 		if (bootverbose)
 			printf("null: \n");
 		zbuf = (void *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK | M_ZERO);
-		null_dev = make_dev(&null_cdevsw, NULL_MINOR, UID_ROOT,
-			GID_WHEEL, 0666, "null");
-		zero_dev = make_dev(&zero_cdevsw, ZERO_MINOR, UID_ROOT,
-			GID_WHEEL, 0666, "zero");
+		null_dev = make_dev(&null_cdevsw, 0, UID_ROOT, GID_WHEEL,
+			0666, "null");
+		zero_dev = make_dev(&zero_cdevsw, 0, UID_ROOT, GID_WHEEL,
+			0666, "zero");
 		break;
 
 	case MOD_UNLOAD:
diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c
index f60118528ff..a0585b00b8e 100644
--- a/sys/dev/pccbb/pccbb.c
+++ b/sys/dev/pccbb/pccbb.c
@@ -464,7 +464,14 @@ cbb_event_thread(void *arg)
 	sc->flags |= CBB_KTHREAD_RUNNING;
 	while ((sc->flags & CBB_KTHREAD_DONE) == 0) {
 		mtx_unlock(&sc->mtx);
-		newbus_xlock();
+		/*
+		 * We take out Giant here because we need it deep,
+		 * down in the bowels of the vm system for mapping the
+		 * memory we need to read the CIS.  In addition, since
+		 * we are adding/deleting devices from the dev tree,
+		 * and that code isn't MP safe, we have to hold Giant.
+		 */
+		mtx_lock(&Giant);
 		status = cbb_get(sc, CBB_SOCKET_STATE);
 		DPRINTF(("Status is 0x%x\n", status));
 		if (!CBB_CARD_PRESENT(status)) {
@@ -490,7 +497,7 @@ cbb_event_thread(void *arg)
 			not_a_card = 0;		/* We know card type */
 			cbb_insert(sc);
 		}
-		newbus_xunlock();
+		mtx_unlock(&Giant);
 
 		/*
 		 * First time through we need to tell mountroot that we're
diff --git a/sys/dev/ppbus/vpo.c b/sys/dev/ppbus/vpo.c
index f63ff49e374..40091787a4f 100644
--- a/sys/dev/ppbus/vpo.c
+++ b/sys/dev/ppbus/vpo.c
@@ -427,6 +427,8 @@ vpo_action(struct cam_sim *sim, union ccb *ccb)
 		strncpy(cpi->hba_vid, "Iomega", HBA_IDLEN);
 		strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN);
 		cpi->unit_number = sim->unit_number;
+		cpi->transport = XPORT_PPB;
+		cpi->transport_version = 0;
 
 		cpi->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
diff --git a/sys/dev/pst/pst-iop.c b/sys/dev/pst/pst-iop.c
index 3fa37fdbfd3..d4e83f01ecb 100644
--- a/sys/dev/pst/pst-iop.c
+++ b/sys/dev/pst/pst-iop.c
@@ -152,9 +152,7 @@ iop_attach(void *arg)
 	    break;
 
 	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
-	    newbus_xlock();
 	    pst_add_raid(sc, &sc->lct[i]);
-	    newbus_xunlock();
 	    break;
 	}
     }
diff --git a/sys/kern/tty_pty.c b/sys/dev/pty/pty.c
similarity index 77%
rename from sys/kern/tty_pty.c
rename to sys/dev/pty/pty.c
index 3bb5b476523..c24396a69ca 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/dev/pty/pty.c
@@ -35,8 +35,10 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -45,12 +47,15 @@ __FBSDID("$FreeBSD$");
  * the pts(4) driver. We just call into pts(4) to create the actual PTY.
  * To make sure we don't use the same PTY multiple times, we abuse
  * si_drv1 inside the cdev to mark whether the PTY is in use.
+ *
+ * It also implements a /dev/ptmx device node, which is useful for Linux
+ * binary emulation.
  */
 
-static unsigned int pty_warningcnt = 10;
+static unsigned int pty_warningcnt = 1;
 SYSCTL_UINT(_kern, OID_AUTO, tty_pty_warningcnt, CTLFLAG_RW,
 	&pty_warningcnt, 0,
-	"Warnings that will be triggered upon PTY allocation");
+	"Warnings that will be triggered upon legacy PTY allocation");
 
 static int
 ptydev_fdopen(struct cdev *dev, int fflags, struct thread *td, struct file *fp)
@@ -74,7 +79,7 @@ ptydev_fdopen(struct cdev *dev, int fflags, struct thread *td, struct file *fp)
 	/* Raise a warning when a legacy PTY has been allocated. */
 	if (pty_warningcnt > 0) {
 		pty_warningcnt--;
-		printf("pid %d (%s) is using legacy pty devices%s\n", 
+		log(LOG_INFO, "pid %d (%s) is using legacy pty devices%s\n", 
 		    td->td_proc->p_pid, td->td_name,
 		    pty_warningcnt ? "" : " - not logging anymore");
 	}
@@ -116,11 +121,39 @@ pty_clone(void *arg, struct ucred *cr, char *name, int namelen,
 	    NULL, UID_ROOT, GID_WHEEL, 0666, "%s", name);
 }
 
-static void
-pty_init(void *unused)
+static int
+ptmx_fdopen(struct cdev *dev __unused, int fflags, struct thread *td,
+    struct file *fp)
 {
 
-	EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
+	return (pts_alloc(fflags & (FREAD|FWRITE), td, fp));
 }
 
-SYSINIT(pty, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, pty_init, NULL);
+static struct cdevsw ptmx_cdevsw = {
+	.d_version	= D_VERSION,
+	.d_fdopen	= ptmx_fdopen,
+	.d_name		= "ptmx",
+};
+
+static int
+pty_modevent(module_t mod, int type, void *data)
+{
+
+        switch(type) {
+        case MOD_LOAD: 
+		EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
+		make_dev(&ptmx_cdevsw, 0, UID_ROOT, GID_WHEEL, 0666, "ptmx");
+		break;
+	case MOD_SHUTDOWN:
+		break;
+	case MOD_UNLOAD:
+		/* XXX: No unloading support yet. */
+		return (EBUSY);
+	default:
+		return (EOPNOTSUPP);
+	}
+
+	return (0);
+}
+
+DEV_MODULE(pty, pty_modevent, NULL);
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 0fc2e899b3d..5a5790d0c25 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -174,8 +174,8 @@ static struct rl_type re_devs[] = {
 	{ RT_VENDORID, RT_DEVICEID_8101E, 0,
 	    "RealTek 8101E/8102E/8102EL PCIe 10/100baseTX" },
 	{ RT_VENDORID, RT_DEVICEID_8168, 0,
-	    "RealTek 8168/8168B/8168C/8168CP/8168D/8111B/8111C/8111CP PCIe "
-	    "Gigabit Ethernet" },
+	    "RealTek 8168/8168B/8168C/8168CP/8168D/8168DP/"
+	    "8111B/8111C/8111CP/8111DP PCIe Gigabit Ethernet" },
 	{ RT_VENDORID, RT_DEVICEID_8169, 0,
 	    "RealTek 8169/8169S/8169SB(L)/8110S/8110SB(L) Gigabit Ethernet" },
 	{ RT_VENDORID, RT_DEVICEID_8169SC, 0,
@@ -217,7 +217,8 @@ static struct rl_hwrev re_hwrevs[] = {
 	{ RL_HWREV_8168C, RL_8169, "8168C/8111C"},
 	{ RL_HWREV_8168C_SPIN2, RL_8169, "8168C/8111C"},
 	{ RL_HWREV_8168CP, RL_8169, "8168CP/8111CP"},
-	{ RL_HWREV_8168D, RL_8169, "8168D"},
+	{ RL_HWREV_8168D, RL_8169, "8168D/8111D"},
+	{ RL_HWREV_8168DP, RL_8169, "8168DP/8111DP"},
 	{ 0, 0, NULL }
 };
 
@@ -1282,6 +1283,7 @@ re_attach(device_t dev)
 		/* FALLTHROUGH */
 	case RL_HWREV_8168CP:
 	case RL_HWREV_8168D:
+	case RL_HWREV_8168DP:
 		sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
 		    RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
 		    RL_FLAG_AUTOPAD;
diff --git a/sys/dev/rp/rp.c b/sys/dev/rp/rp.c
index 45f59d37304..520ca80f930 100644
--- a/sys/dev/rp/rp.c
+++ b/sys/dev/rp/rp.c
@@ -903,9 +903,7 @@ rpopen(struct tty *tp)
 		rp_callout_handle = timeout(rp_do_poll, 
 					    (void *)NULL, POLL_INTERVAL);
 
-	newbus_xlock();
 	device_busy(rp->rp_ctlp->dev);
-	newbus_xunlock();
 	return(0);
 }
 
@@ -916,9 +914,7 @@ rpclose(struct tty *tp)
 
 	rp = tty_softc(tp);
 	rphardclose(tp);
-	newbus_xlock();
 	device_unbusy(rp->rp_ctlp->dev);
-	newbus_xunlock();
 }
 
 static void
diff --git a/sys/dev/rp/rp_pci.c b/sys/dev/rp/rp_pci.c
index e8a1c68cf5a..cbd55167801 100644
--- a/sys/dev/rp/rp_pci.c
+++ b/sys/dev/rp/rp_pci.c
@@ -225,11 +225,7 @@ rp_pcidetach(device_t dev)
 {
 	CONTROLLER_t	*ctlp;
 
-	if (device_get_state(dev) == DS_BUSY)
-		return (EBUSY);
-
 	ctlp = device_get_softc(dev);
-
 	rp_pcireleaseresource(ctlp);
 
 	return (0);
@@ -240,11 +236,7 @@ rp_pcishutdown(device_t dev)
 {
 	CONTROLLER_t	*ctlp;
 
-	if (device_get_state(dev) == DS_BUSY)
-		return (EBUSY);
-
 	ctlp = device_get_softc(dev);
-
 	rp_pcireleaseresource(ctlp);
 
 	return (0);
diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c
index 92b8b70bb27..31002ebcfce 100644
--- a/sys/dev/siis/siis.c
+++ b/sys/dev/siis/siis.c
@@ -646,6 +646,30 @@ siis_slotsfree(device_t dev)
 	}
 }
 
+static void
+siis_notify_events(device_t dev)
+{
+	struct siis_channel *ch = device_get_softc(dev);
+	struct cam_path *dpath;
+	u_int32_t status;
+	int i;
+
+	status = ATA_INL(ch->r_mem, SIIS_P_SNTF);
+	ATA_OUTL(ch->r_mem, SIIS_P_SNTF, status);
+	if (bootverbose)
+		device_printf(dev, "SNTF 0x%04x\n", status);
+	for (i = 0; i < 16; i++) {
+		if ((status & (1 << i)) == 0)
+			continue;
+		if (xpt_create_path(&dpath, NULL,
+		    xpt_path_path_id(ch->path), i, 0) == CAM_REQ_CMP) {
+			xpt_async(AC_SCSI_AEN, dpath, NULL);
+			xpt_free_path(dpath);
+		}
+	}
+
+}
+
 static void
 siis_phy_check_events(device_t dev)
 {
@@ -707,6 +731,9 @@ siis_ch_intr(void *data)
 	/* Process PHY events */
 	if (istatus & SIIS_P_IX_PHYRDYCHG)
 		siis_phy_check_events(dev);
+	/* Process NOTIFY events */
+	if (istatus & SIIS_P_IX_SDBN)
+		siis_notify_events(dev);
 	/* Process command errors */
 	if (istatus & SIIS_P_IX_COMMERR) {
 		estatus = ATA_INL(ch->r_mem, SIIS_P_CMDERR);
@@ -1267,7 +1294,6 @@ siis_reset(device_t dev)
 		/* XXX; Commands in loading state. */
 		siis_end_transaction(&ch->slot[i], SIIS_ERR_INNOCENT);
 	}
-	ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PME);
 	/* Reset and reconnect PHY, */
 	if (!siis_sata_phy_reset(dev)) {
 		ch->devices = 0;
@@ -1461,9 +1487,9 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
 		uint32_t status;
 
 		cts->protocol = PROTO_ATA;
-		cts->protocol_version = SCSI_REV_2;
+		cts->protocol_version = PROTO_VERSION_UNSPECIFIED;
 		cts->transport = XPORT_SATA;
-		cts->transport_version = 2;
+		cts->transport_version = XPORT_VERSION_UNSPECIFIED;
 		cts->proto_specific.valid = 0;
 		cts->xport_specific.sata.valid = 0;
 		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
@@ -1548,9 +1574,9 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
 		cpi->unit_number = cam_sim_unit(sim);
 		cpi->transport = XPORT_SATA;
-		cpi->transport_version = 2;
+		cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
 		cpi->protocol = PROTO_ATA;
-		cpi->protocol_version = SCSI_REV_2;
+		cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
 		cpi->ccb_h.status = CAM_REQ_CMP;
 		cpi->maxio = MAXPHYS;
 		xpt_done(ccb);
diff --git a/sys/dev/snp/snp.c b/sys/dev/snp/snp.c
index fcc70a5d84f..37d996563f9 100644
--- a/sys/dev/snp/snp.c
+++ b/sys/dev/snp/snp.c
@@ -192,7 +192,7 @@ snp_write(struct cdev *dev, struct uio *uio, int flag)
 {
 	struct snp_softc *ss;
 	struct tty *tp;
-	int error, len, i;
+	int error, len;
 	char in[SNP_INPUT_BUFSIZE];
 
 	error = devfs_get_cdevpriv((void **)&ss);
@@ -223,14 +223,9 @@ snp_write(struct cdev *dev, struct uio *uio, int flag)
 		 * because we shouldn't bail out when we're running
 		 * close to the watermarks.
 		 */
-		if (ttydisc_can_bypass(tp)) {
-			ttydisc_rint_bypass(tp, in, len);
-		} else {
-			for (i = 0; i < len; i++)
-				ttydisc_rint(tp, in[i], 0);
-		}
-
+		ttydisc_rint_simple(tp, in, len);
 		ttydisc_rint_done(tp);
+
 		tty_unlock(tp);
 	}
 
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index bf99d54ea1f..4eda8be81a4 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -1520,7 +1520,7 @@ hdac_get_capabilities(struct hdac_softc *sc)
 	sc->num_iss = HDAC_GCAP_ISS(gcap);
 	sc->num_oss = HDAC_GCAP_OSS(gcap);
 	sc->num_bss = HDAC_GCAP_BSS(gcap);
-
+	sc->num_sdo = HDAC_GCAP_NSDO(gcap);
 	sc->support_64bit = HDA_FLAG_MATCH(gcap, HDAC_GCAP_64OK);
 
 	corbsize = HDAC_READ_1(&sc->mem, HDAC_CORBSIZE);
@@ -1555,11 +1555,12 @@ hdac_get_capabilities(struct hdac_softc *sc)
 		return (ENXIO);
 	}
 
-	HDA_BOOTHVERBOSE(
-		device_printf(sc->dev, "    CORB size: %d\n", sc->corb_size);
-		device_printf(sc->dev, "    RIRB size: %d\n", sc->rirb_size);
-		device_printf(sc->dev, "      Streams: ISS=%d OSS=%d BSS=%d\n",
-		    sc->num_iss, sc->num_oss, sc->num_bss);
+	HDA_BOOTVERBOSE(
+		device_printf(sc->dev, "Caps: OSS %d, ISS %d, BSS %d, "
+		    "NSDO %d%s, CORB %d, RIRB %d\n",
+		    sc->num_oss, sc->num_iss, sc->num_bss, 1 << sc->num_sdo,
+		    sc->support_64bit ? ", 64bit" : "",
+		    sc->corb_size, sc->rirb_size);
 	);
 
 	return (0);
@@ -7435,7 +7436,6 @@ hdac_attach2(void *arg)
 		    quirks_on, quirks_off);
 	);
 
-	newbus_xlock();
 	hdac_lock(sc);
 
 	/* Remove ourselves from the config hooks */
@@ -7675,7 +7675,6 @@ hdac_attach2(void *arg)
 	    SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO,
 	    "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev),
 	    sysctl_hdac_pindump, "I", "Dump pin states/data");
-	newbus_xunlock();
 }
 
 /****************************************************************************
diff --git a/sys/dev/sound/pci/hda/hdac_private.h b/sys/dev/sound/pci/hda/hdac_private.h
index bd329675b3c..2369a9a8d1d 100644
--- a/sys/dev/sound/pci/hda/hdac_private.h
+++ b/sys/dev/sound/pci/hda/hdac_private.h
@@ -339,6 +339,7 @@ struct hdac_softc {
 	int		num_iss;
 	int		num_oss;
 	int		num_bss;
+	int		num_sdo;
 	int		support_64bit;
 	int		streamcnt;
 
diff --git a/sys/dev/sound/pci/hda/hdac_reg.h b/sys/dev/sound/pci/hda/hdac_reg.h
index 969471023d3..813af7221a6 100644
--- a/sys/dev/sound/pci/hda/hdac_reg.h
+++ b/sys/dev/sound/pci/hda/hdac_reg.h
@@ -136,6 +136,8 @@
 	(((gcap) & HDAC_GCAP_ISS_MASK) >> HDAC_GCAP_ISS_SHIFT)
 #define HDAC_GCAP_OSS(gcap)						\
 	(((gcap) & HDAC_GCAP_OSS_MASK) >> HDAC_GCAP_OSS_SHIFT)
+#define HDAC_GCAP_NSDO(gcap)						\
+	(((gcap) & HDAC_GCAP_NSDO_MASK) >> HDAC_GCAP_NSDO_SHIFT)
 
 /* GCTL - Global Control */
 #define HDAC_GCTL_CRST			0x00000001
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index fe63e0d38b5..f5d47406391 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -2958,7 +2958,7 @@ uaudio_mixer_get(struct usb_device *udev, uint8_t what,
 	USETW(req.wIndex, mc->wIndex);
 	USETW(req.wLength, len);
 
-	err = usbd_do_request(udev, &Giant, &req, data);
+	err = usbd_do_request(udev, NULL, &req, data);
 	if (err) {
 		DPRINTF("err=%s\n", usbd_errstr(err));
 		return (0);
@@ -3081,7 +3081,7 @@ uaudio_set_speed(struct usb_device *udev, uint8_t endpt, uint32_t speed)
 	data[1] = speed >> 8;
 	data[2] = speed >> 16;
 
-	return (usbd_do_request(udev, &Giant, &req, data));
+	return (usbd_do_request(udev, NULL, &req, data));
 }
 
 static int
diff --git a/sys/dev/syscons/scterm-teken.c b/sys/dev/syscons/scterm-teken.c
index 36cfbb5d35f..133d6220805 100644
--- a/sys/dev/syscons/scterm-teken.c
+++ b/sys/dev/syscons/scterm-teken.c
@@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$");
 
 #include 
 
-#include 
+#include 
 
 static void scteken_revattr(unsigned char, teken_attr_t *);
 static unsigned int scteken_attr(const teken_attr_t *);
@@ -300,12 +300,20 @@ static unsigned int
 scteken_attr(const teken_attr_t *a)
 {
 	unsigned int attr = 0;
+	teken_color_t fg, bg;
 
+	if (a->ta_format & TF_REVERSE) {
+		fg = a->ta_bgcolor;
+		bg = a->ta_fgcolor;
+	} else {
+		fg = a->ta_fgcolor;
+		bg = a->ta_bgcolor;
+	}
 	if (a->ta_format & TF_BOLD)
-		attr |= fgcolors_bold[a->ta_fgcolor];
+		attr |= fgcolors_bold[fg];
 	else
-		attr |= fgcolors_normal[a->ta_fgcolor];
-	attr |= bgcolors[a->ta_bgcolor];
+		attr |= fgcolors_normal[fg];
+	attr |= bgcolors[bg];
 
 #ifdef FG_UNDERLINE
 	if (a->ta_format & TF_UNDERLINE)
diff --git a/sys/dev/syscons/scvgarndr.c b/sys/dev/syscons/scvgarndr.c
index 1ab41d2e5e4..fd823ce434b 100644
--- a/sys/dev/syscons/scvgarndr.c
+++ b/sys/dev/syscons/scvgarndr.c
@@ -193,6 +193,8 @@ static u_short mouse_or_mask[16] = {
 		case 15:						\
 			writew(pos, vga_palette15[color]);		\
 			break;						\
+		case 8:							\
+			writeb(pos, (uint8_t)color);			\
 		}
 	
 static uint32_t vga_palette32[16] = {
@@ -215,6 +217,7 @@ static uint16_t vga_palette15[16] = {
 #ifndef SC_NO_CUTPASTE
 static uint32_t mouse_buf32[256];
 static uint16_t mouse_buf16[256];
+static uint8_t  mouse_buf8[256];
 #endif
 #endif
 
@@ -498,7 +501,9 @@ vga_rndrinit(scr_stat *scp)
 		scp->rndr->draw_cursor = vga_pxlcursor_planar;
 		scp->rndr->blink_cursor = vga_pxlblink_planar;
 		scp->rndr->draw_mouse = vga_pxlmouse_planar;
-	} else if (scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_DIRECT) {
+	} else
+	if (scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_DIRECT ||
+	    scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_PACKED) {
 		scp->rndr->clear = vga_pxlclear_direct;
 		scp->rndr->draw_border = vga_pxlborder_direct;
 		scp->rndr->draw = vga_vgadraw_direct;
@@ -1148,6 +1153,7 @@ vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
 	int i, j;
 	uint32_t *u32;
 	uint16_t *u16;
+	uint8_t  *u8;
 	int bpp;
 
 	if (!on)
@@ -1179,6 +1185,10 @@ vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
 				u16 = (uint16_t*)(p + j * pixel_size);
 				writew(u16, mouse_buf16[i * 16 + j]);
 				break;
+			case 8:
+				u8 = (uint8_t*)(p + j * pixel_size);
+				writeb(u8, mouse_buf8[i * 16 + j]);
+				break;
 			}
 		}
 
@@ -1214,6 +1224,14 @@ vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
 				else if (mouse_and_mask[i] & (1 << (15 - j)))
 					writew(u16, 0);
 				break;
+			case 8:
+				u8 = (uint8_t*)(p + j * pixel_size);
+				mouse_buf8[i * 16 + j] = *u8;
+				if (mouse_or_mask[i] & (1 << (15 - j)))
+					writeb(u8, 15);
+				else if (mouse_and_mask[i] & (1 << (15 - j)))
+					writeb(u8, 0);
+				break;
 			}
 		}
 
diff --git a/sys/dev/syscons/scvidctl.c b/sys/dev/syscons/scvidctl.c
index 045f79f25e7..d481e066430 100644
--- a/sys/dev/syscons/scvidctl.c
+++ b/sys/dev/syscons/scvidctl.c
@@ -391,6 +391,10 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
 	    (info.vi_depth != 15) && (info.vi_depth != 16) &&
 	    (info.vi_depth != 24) && (info.vi_depth != 32))
 	    return ENODEV;
+    } else if (info.vi_mem_model == V_INFO_MM_PACKED) {
+	if (!(info.vi_flags & V_INFO_LINEAR) &&
+	    (info.vi_depth != 8))
+	    return ENODEV;
     } else
 	return ENODEV;
 
diff --git a/sys/dev/twe/twe.c b/sys/dev/twe/twe.c
index 2641fae5e85..59b5027adac 100644
--- a/sys/dev/twe/twe.c
+++ b/sys/dev/twe/twe.c
@@ -294,10 +294,8 @@ twe_init(struct twe_softc *sc)
     /*
      * Scan for drives
      */
-    newbus_xlock();
     for (i = 0; i < TWE_MAX_UNITS; i++)
 	twe_add_unit(sc, i);
-    newbus_xunlock();
 
     /*
      * Initialise connection with controller.
@@ -623,15 +621,11 @@ twe_ioctl(struct twe_softc *sc, int ioctlcmd, void *addr)
 	break;
 
     case TWEIO_ADD_UNIT:
-	newbus_xlock();
 	error = twe_add_unit(sc, td->td_unit);
-	newbus_xunlock();
 	break;
 
     case TWEIO_DEL_UNIT:
-	newbus_xlock();
 	error = twe_del_unit(sc, td->td_unit);
-	newbus_xunlock();
 	break;
 
 	/* XXX implement ATA PASSTHROUGH */
diff --git a/sys/dev/txp/if_txp.c b/sys/dev/txp/if_txp.c
index 619b3f71ee6..9396f4d9ecb 100644
--- a/sys/dev/txp/if_txp.c
+++ b/sys/dev/txp/if_txp.c
@@ -1389,7 +1389,8 @@ txp_alloc_rings(struct txp_softc *sc)
 
 	/* High priority rx ring. */
 	error = txp_dma_alloc(sc, "hi priority rx ring",
-	    &sc->sc_cdata.txp_rxhiring_tag, sizeof(struct txp_rx_desc), 0,
+	    &sc->sc_cdata.txp_rxhiring_tag,
+	    roundup(sizeof(struct txp_rx_desc), 16), 0,
 	    &sc->sc_cdata.txp_rxhiring_map, (void **)&sc->sc_ldata.txp_rxhiring,
 	    sizeof(struct txp_rx_desc) * RX_ENTRIES,
 	    &sc->sc_ldata.txp_rxhiring_paddr);
@@ -1409,7 +1410,8 @@ txp_alloc_rings(struct txp_softc *sc)
 
 	/* Low priority rx ring. */
 	error = txp_dma_alloc(sc, "low priority rx ring",
-	    &sc->sc_cdata.txp_rxloring_tag, sizeof(struct txp_rx_desc), 0,
+	    &sc->sc_cdata.txp_rxloring_tag,
+	    roundup(sizeof(struct txp_rx_desc), 16), 0,
 	    &sc->sc_cdata.txp_rxloring_map, (void **)&sc->sc_ldata.txp_rxloring,
 	    sizeof(struct txp_rx_desc) * RX_ENTRIES,
 	    &sc->sc_ldata.txp_rxloring_paddr);
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index f6776f01a4c..a9254443590 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -67,7 +67,6 @@ static device_attach_t usb_attach;
 static device_detach_t usb_detach;
 
 static void	usb_attach_sub(device_t, struct usb_bus *);
-static void	usb_post_init(void *);
 
 /* static variables */
 
@@ -84,8 +83,6 @@ TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
 SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RDTUN, &usb_no_boot_wait, 0,
     "No device enumerate waiting at boot.");
 
-static uint8_t usb_post_init_called = 0;
-
 static devclass_t usb_devclass;
 
 static device_method_t usb_methods[] = {
@@ -142,10 +139,8 @@ usb_attach(device_t dev)
 		bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
 	}
 
-	if (usb_post_init_called) {
-		usb_attach_sub(dev, bus);
-		usb_needs_explore(bus, 1);
-	}
+	usb_attach_sub(dev, bus);
+
 	return (0);			/* return success */
 }
 
@@ -224,6 +219,15 @@ usb_bus_explore(struct usb_proc_msg *pm)
 			/* avoid zero, hence that is memory default */
 			bus->driver_added_refcount = 1;
 		}
+
+		/*
+		 * The following three lines of code are only here to
+		 * recover from DDB:
+		 */
+		usb_proc_rewakeup(&bus->control_xfer_proc);
+		usb_proc_rewakeup(&bus->giant_callback_proc);
+		usb_proc_rewakeup(&bus->non_giant_callback_proc);
+
 		USB_BUS_UNLOCK(bus);
 
 		/*
@@ -260,10 +264,10 @@ usb_bus_detach(struct usb_proc_msg *pm)
 	device_set_softc(dev, NULL);
 	USB_BUS_UNLOCK(bus);
 
-	newbus_xlock();
-
 	/* detach children first */
+	mtx_lock(&Giant);
 	bus_generic_detach(dev);
+	mtx_unlock(&Giant);
 
 	/*
 	 * Free USB Root device, but not any sub-devices, hence they
@@ -272,7 +276,6 @@ usb_bus_detach(struct usb_proc_msg *pm)
 	usb_free_device(udev,
 	    USB_UNCFG_FLAG_FREE_EP0);
 
-	newbus_xunlock();
 	USB_BUS_LOCK(bus);
 	/* clear bdev variable last */
 	bus->bdev = NULL;
@@ -288,6 +291,12 @@ usb_power_wdog(void *arg)
 	usb_callout_reset(&bus->power_wdog,
 	    4 * hz, usb_power_wdog, arg);
 
+	/*
+	 * The following line of code is only here to recover from
+	 * DDB:
+	 */
+	usb_proc_rewakeup(&bus->explore_proc);	/* recover from DDB */
+
 	USB_BUS_UNLOCK(bus);
 
 	usb_bus_power_update(bus);
@@ -341,7 +350,6 @@ usb_bus_attach(struct usb_proc_msg *pm)
 	}
 
 	USB_BUS_UNLOCK(bus);
-	newbus_xlock();
 
 	/* default power_mask value */
 	bus->hw_power_state =
@@ -374,7 +382,6 @@ usb_bus_attach(struct usb_proc_msg *pm)
 		err = USB_ERR_NOMEM;
 	}
 
-	newbus_xunlock();
 	USB_BUS_LOCK(bus);
 
 	if (err) {
@@ -392,17 +399,18 @@ usb_bus_attach(struct usb_proc_msg *pm)
 /*------------------------------------------------------------------------*
  *	usb_attach_sub
  *
- * This function creates a thread which runs the USB attach code. It
- * is factored out, hence it can be called at two different places in
- * time. During bootup this function is called from
- * "usb_post_init". During hot-plug it is called directly from the
- * "usb_attach()" method.
+ * This function creates a thread which runs the USB attach code.
  *------------------------------------------------------------------------*/
 static void
 usb_attach_sub(device_t dev, struct usb_bus *bus)
 {
 	const char *pname = device_get_nameunit(dev);
 
+	mtx_lock(&Giant);
+	if (usb_devclass_ptr == NULL)
+		usb_devclass_ptr = devclass_find("usbus");
+	mtx_unlock(&Giant);
+
 	/* Initialise USB process messages */
 	bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore;
 	bus->explore_msg[0].bus = bus;
@@ -445,52 +453,12 @@ usb_attach_sub(device_t dev, struct usb_bus *bus)
 			/* ignore */
 		}
 		USB_BUS_UNLOCK(bus);
+
+		/* Do initial explore */
+		usb_needs_explore(bus, 1);
 	}
 }
 
-/*------------------------------------------------------------------------*
- *	usb_post_init
- *
- * This function is called to attach all USB busses that were found
- * during bootup.
- *------------------------------------------------------------------------*/
-static void
-usb_post_init(void *arg)
-{
-	struct usb_bus *bus;
-	devclass_t dc;
-	device_t dev;
-	int max;
-	int n;
-
-	newbus_xlock();
-
-	usb_devclass_ptr = devclass_find("usbus");
-
-	dc = usb_devclass_ptr;
-	if (dc) {
-		max = devclass_get_maxunit(dc) + 1;
-		for (n = 0; n != max; n++) {
-			dev = devclass_get_device(dc, n);
-			if (dev && device_is_attached(dev)) {
-				bus = device_get_ivars(dev);
-				if (bus)
-					usb_attach_sub(dev, bus);
-			}
-		}
-	} else {
-		DPRINTFN(0, "no devclass\n");
-	}
-	usb_post_init_called = 1;
-
-	/* explore all USB busses in parallell */
-
-	usb_needs_explore_all();
-
-	newbus_xunlock();
-}
-
-SYSINIT(usb_post_init, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, usb_post_init, NULL);
 SYSUNINIT(usb_bus_unload, SI_SUB_KLD, SI_ORDER_ANY, usb_bus_unload, NULL);
 
 /*------------------------------------------------------------------------*
diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
index 2170b370016..5816079b3f6 100644
--- a/sys/dev/usb/input/ukbd.c
+++ b/sys/dev/usb/input/ukbd.c
@@ -96,10 +96,14 @@ __FBSDID("$FreeBSD$");
 
 #if USB_DEBUG
 static int ukbd_debug = 0;
+static int ukbd_no_leds = 0;
 
 SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW, 0, "USB ukbd");
 SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, debug, CTLFLAG_RW,
     &ukbd_debug, 0, "Debug level");
+SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, no_leds, CTLFLAG_RW,
+    &ukbd_no_leds, 0, "Disables setting of keyboard leds");
+
 #endif
 
 #define	UPROTO_BOOT_KEYBOARD 1
@@ -165,6 +169,7 @@ struct ukbd_softc {
 #define	UKBD_FLAG_APPLE_EJECT	0x0040
 #define	UKBD_FLAG_APPLE_FN	0x0080
 #define	UKBD_FLAG_APPLE_SWAP	0x0100
+#define	UKBD_FLAG_TIMER_RUNNING	0x0200
 
 	int32_t	sc_mode;		/* input mode (K_XLATE,K_RAW,K_CODE) */
 	int32_t	sc_state;		/* shift/lock key state */
@@ -279,6 +284,25 @@ static device_attach_t ukbd_attach;
 static device_detach_t ukbd_detach;
 static device_resume_t ukbd_resume;
 
+static uint8_t
+ukbd_any_key_pressed(struct ukbd_softc *sc)
+{
+	uint8_t i;
+	uint8_t j;
+
+	for (j = i = 0; i < UKBD_NKEYCODE; i++)
+		j |= sc->sc_odata.keycode[i];
+
+	return (j ? 1 : 0);
+}
+
+static void
+ukbd_start_timer(struct ukbd_softc *sc)
+{
+	sc->sc_flags |= UKBD_FLAG_TIMER_RUNNING;
+	usb_callout_reset(&sc->sc_callout, hz / 40, &ukbd_timeout, sc);
+}
+
 static void
 ukbd_put_key(struct ukbd_softc *sc, uint32_t key)
 {
@@ -308,11 +332,15 @@ ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait)
 
 		usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER);
 
-		DELAY(1000);	/* delay 1 ms */
+		/* Delay-optimised support for repetition of keys */
 
-		sc->sc_time_ms++;
+		if (ukbd_any_key_pressed(sc)) {
+			/* a key is pressed - need timekeeping */
+			DELAY(1000);
 
-		/* support repetition of keys: */
+			/* 1 millisecond has passed */
+			sc->sc_time_ms += 1;
+		}
 
 		ukbd_interrupt(sc);
 
@@ -470,7 +498,11 @@ ukbd_timeout(void *arg)
 	}
 	ukbd_interrupt(sc);
 
-	usb_callout_reset(&sc->sc_callout, hz / 40, &ukbd_timeout, sc);
+	if (ukbd_any_key_pressed(sc)) {
+		ukbd_start_timer(sc);
+	} else {
+		sc->sc_flags &= ~UKBD_FLAG_TIMER_RUNNING;
+	}
 }
 
 static uint8_t
@@ -582,6 +614,12 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error)
 			}
 
 			ukbd_interrupt(sc);
+
+			if (!(sc->sc_flags & UKBD_FLAG_TIMER_RUNNING)) {
+				if (ukbd_any_key_pressed(sc)) {
+					ukbd_start_timer(sc);
+				}
+			}
 		}
 	case USB_ST_SETUP:
 tr_setup:
@@ -613,6 +651,11 @@ ukbd_set_leds_callback(struct usb_xfer *xfer, usb_error_t error)
 	uint8_t buf[2];
 	struct ukbd_softc *sc = usbd_xfer_softc(xfer);
 
+#if USB_DEBUG
+	if (ukbd_no_leds)
+		return;
+#endif
+
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
 	case USB_ST_SETUP:
@@ -647,11 +690,11 @@ ukbd_set_leds_callback(struct usb_xfer *xfer, usb_error_t error)
 			usbd_xfer_set_frames(xfer, 2);
 			usbd_transfer_submit(xfer);
 		}
-		return;
+		break;
 
 	default:			/* Error */
 		DPRINTFN(0, "error=%s\n", usbd_errstr(error));
-		return;
+		break;
 	}
 }
 
@@ -745,8 +788,6 @@ ukbd_attach(device_t dev)
 	uint16_t n;
 	uint16_t hid_len;
 
-	mtx_lock(&Giant);
-
 	kbd_init_struct(kbd, UKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0);
 
 	kbd->kb_data = (void *)sc;
@@ -831,7 +872,7 @@ ukbd_attach(device_t dev)
 	}
 
 	/* ignore if SETIDLE fails, hence it is not crucial */
-	err = usbd_req_set_idle(sc->sc_udev, &Giant, sc->sc_iface_index, 0, 0);
+	err = usbd_req_set_idle(sc->sc_udev, NULL, sc->sc_iface_index, 0, 0);
 
 	ukbd_ioctl(kbd, KDSETLED, (caddr_t)&sc->sc_state);
 
@@ -854,14 +895,14 @@ ukbd_attach(device_t dev)
 	if (bootverbose) {
 		genkbd_diag(kbd, bootverbose);
 	}
+	/* lock keyboard mutex */
+
+	mtx_lock(&Giant);
 
 	/* start the keyboard */
 
 	usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
 
-	/* start the timer */
-
-	ukbd_timeout(sc);
 	mtx_unlock(&Giant);
 	return (0);			/* success */
 
@@ -876,8 +917,6 @@ ukbd_detach(device_t dev)
 	struct ukbd_softc *sc = device_get_softc(dev);
 	int error;
 
-	mtx_lock(&Giant);
-
 	DPRINTF("\n");
 
 	if (sc->sc_flags & UKBD_FLAG_POLLING) {
@@ -913,8 +952,6 @@ ukbd_detach(device_t dev)
 
 	usb_callout_drain(&sc->sc_callout);
 
-	mtx_unlock(&Giant);
-
 	DPRINTF("%s: disconnected\n",
 	    device_get_nameunit(dev));
 
@@ -926,9 +963,7 @@ ukbd_resume(device_t dev)
 {
 	struct ukbd_softc *sc = device_get_softc(dev);
 
-	mtx_lock(&Giant);
 	ukbd_clear_state(&sc->sc_kbd);
-	mtx_unlock(&Giant);
 
 	return (0);
 }
@@ -944,7 +979,6 @@ ukbd_configure(int flags)
 static int
 ukbd__probe(int unit, void *arg, int flags)
 {
-	mtx_assert(&Giant, MA_OWNED);
 	return (ENXIO);
 }
 
@@ -952,7 +986,6 @@ ukbd__probe(int unit, void *arg, int flags)
 static int
 ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
 {
-	mtx_assert(&Giant, MA_OWNED);
 	return (ENXIO);
 }
 
@@ -960,7 +993,6 @@ ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
 static int
 ukbd_test_if(keyboard_t *kbd)
 {
-	mtx_assert(&Giant, MA_OWNED);
 	return (0);
 }
 
@@ -968,7 +1000,6 @@ ukbd_test_if(keyboard_t *kbd)
 static int
 ukbd_term(keyboard_t *kbd)
 {
-	mtx_assert(&Giant, MA_OWNED);
 	return (ENXIO);
 }
 
@@ -976,7 +1007,6 @@ ukbd_term(keyboard_t *kbd)
 static int
 ukbd_intr(keyboard_t *kbd, void *arg)
 {
-	mtx_assert(&Giant, MA_OWNED);
 	return (0);
 }
 
@@ -984,7 +1014,6 @@ ukbd_intr(keyboard_t *kbd, void *arg)
 static int
 ukbd_lock(keyboard_t *kbd, int lock)
 {
-	mtx_assert(&Giant, MA_OWNED);
 	return (1);
 }
 
@@ -1003,7 +1032,6 @@ ukbd_enable(keyboard_t *kbd)
 		mtx_unlock(&Giant);
 		return (retval);
 	}
-	mtx_assert(&Giant, MA_OWNED);
 	KBD_ACTIVATE(kbd);
 	return (0);
 }
@@ -1020,7 +1048,6 @@ ukbd_disable(keyboard_t *kbd)
 		mtx_unlock(&Giant);
 		return (retval);
 	}
-	mtx_assert(&Giant, MA_OWNED);
 	KBD_DEACTIVATE(kbd);
 	return (0);
 }
@@ -1049,7 +1076,6 @@ ukbd_check(keyboard_t *kbd)
 		if (!mtx_owned(&Giant))
 			return (0);
 	}
-	mtx_assert(&Giant, MA_OWNED);
 
 #ifdef UKBD_EMULATE_ATSCANCODE
 	if (sc->sc_buffered_char[0]) {
@@ -1085,7 +1111,6 @@ ukbd_check_char(keyboard_t *kbd)
 		if (!mtx_owned(&Giant))
 			return (0);
 	}
-	mtx_assert(&Giant, MA_OWNED);
 
 	if ((sc->sc_composed_char > 0) &&
 	    (!(sc->sc_flags & UKBD_FLAG_COMPOSE))) {
@@ -1124,7 +1149,6 @@ ukbd_read(keyboard_t *kbd, int wait)
 		if (!mtx_owned(&Giant))
 			return (-1);
 	}
-	mtx_assert(&Giant, MA_OWNED);
 
 #ifdef UKBD_EMULATE_ATSCANCODE
 	if (sc->sc_buffered_char[0]) {
@@ -1189,7 +1213,6 @@ ukbd_read_char(keyboard_t *kbd, int wait)
 		if (!mtx_owned(&Giant))
 			return (NOKEY);
 	}
-	mtx_assert(&Giant, MA_OWNED);
 
 next_code:
 
@@ -1392,7 +1415,6 @@ ukbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
 		 */
 		return (EINVAL);
 	}
-	mtx_assert(&Giant, MA_OWNED);
 
 	switch (cmd) {
 	case KDGKBMODE:		/* get keyboard mode */
@@ -1526,7 +1548,6 @@ ukbd_clear_state(keyboard_t *kbd)
 	if (!mtx_owned(&Giant)) {
 		return;			/* XXX */
 	}
-	mtx_assert(&Giant, MA_OWNED);
 
 	sc->sc_flags &= ~(UKBD_FLAG_COMPOSE | UKBD_FLAG_POLLING);
 	sc->sc_state &= LOCK_MASK;	/* preserve locking key state */
@@ -1546,7 +1567,6 @@ ukbd_clear_state(keyboard_t *kbd)
 static int
 ukbd_get_state(keyboard_t *kbd, void *buf, size_t len)
 {
-	mtx_assert(&Giant, MA_OWNED);
 	return (len == 0) ? 1 : -1;
 }
 
@@ -1554,7 +1574,6 @@ ukbd_get_state(keyboard_t *kbd, void *buf, size_t len)
 static int
 ukbd_set_state(keyboard_t *kbd, void *buf, size_t len)
 {
-	mtx_assert(&Giant, MA_OWNED);
 	return (EINVAL);
 }
 
@@ -1571,7 +1590,6 @@ ukbd_poll(keyboard_t *kbd, int on)
 		mtx_unlock(&Giant);
 		return (retval);
 	}
-	mtx_assert(&Giant, MA_OWNED);
 
 	if (on) {
 		sc->sc_flags |= UKBD_FLAG_POLLING;
diff --git a/sys/dev/usb/misc/ufm.c b/sys/dev/usb/misc/ufm.c
index c10166a5bf0..136182a1c3e 100644
--- a/sys/dev/usb/misc/ufm.c
+++ b/sys/dev/usb/misc/ufm.c
@@ -86,11 +86,9 @@ static device_attach_t ufm_attach;
 static device_detach_t ufm_detach;
 
 static usb_fifo_ioctl_t ufm_ioctl;
-static usb_fifo_open_t ufm_open;
 
 static struct usb_fifo_methods ufm_fifo_methods = {
 	.f_ioctl = &ufm_ioctl,
-	.f_open = &ufm_open,
 	.basename[0] = "ufm",
 };
 
@@ -178,15 +176,6 @@ ufm_detach(device_t dev)
 	return (0);
 }
 
-static int
-ufm_open(struct usb_fifo *dev, int fflags)
-{
-	if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) {
-		return (EACCES);
-	}
-	return (0);
-}
-
 static int
 ufm_do_req(struct ufm_softc *sc, uint8_t request,
     uint16_t value, uint16_t index, uint8_t *retbuf)
@@ -315,6 +304,10 @@ ufm_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
 	struct ufm_softc *sc = usb_fifo_softc(fifo);
 	int error = 0;
 
+	if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) {
+		return (EACCES);
+	}
+
 	switch (cmd) {
 	case FM_SET_FREQ:
 		error = ufm_set_freq(sc, addr);
diff --git a/sys/dev/usb/net/if_aue.c b/sys/dev/usb/net/if_aue.c
index 142780f5613..1a2ce70b5ae 100644
--- a/sys/dev/usb/net/if_aue.c
+++ b/sys/dev/usb/net/if_aue.c
@@ -484,7 +484,7 @@ aue_miibus_writereg(device_t dev, int phy, int reg, int data)
 	}
 
 	if (i == AUE_TIMEOUT)
-		device_printf(sc->sc_ue.ue_dev, "MII read timed out\n");
+		device_printf(sc->sc_ue.ue_dev, "MII write timed out\n");
 
 	if (!locked)
 		AUE_UNLOCK(sc);
@@ -603,11 +603,14 @@ aue_reset(struct aue_softc *sc)
 	 * to set the GPIO pins high so that the PHY(s) will
 	 * be enabled.
 	 *
-	 * Note: We force all of the GPIO pins low first, *then*
-	 * enable the ones we want.
+	 * NOTE: We used to force all of the GPIO pins low first and then
+	 * enable the ones we want. This has been changed to better
+	 * match the ADMtek's reference design to avoid setting the
+	 * power-down configuration line of the PHY at the same time
+	 * it is reset.
 	 */
-	aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0);
-	aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0|AUE_GPIO_SEL1);
+	aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_SEL0|AUE_GPIO_SEL1);
+	aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_SEL0|AUE_GPIO_SEL1|AUE_GPIO_OUT0);
 
 	if (sc->sc_flags & AUE_FLAG_LSYS) {
 		/* Grrr. LinkSys has to be different from everyone else. */
diff --git a/sys/dev/usb/net/if_cdce.c b/sys/dev/usb/net/if_cdce.c
index 352fcec1f5a..52ea2069311 100644
--- a/sys/dev/usb/net/if_cdce.c
+++ b/sys/dev/usb/net/if_cdce.c
@@ -197,9 +197,6 @@ static const struct usb_ether_methods cdce_ue_methods = {
 };
 
 static const struct usb_device_id cdce_devs[] = {
-	{USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)},
-	{USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)},
-
 	{USB_VPI(USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632, CDCE_FLAG_NO_UNION)},
 	{USB_VPI(USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250, CDCE_FLAG_NO_UNION)},
 	{USB_VPI(USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX, CDCE_FLAG_NO_UNION)},
@@ -213,6 +210,9 @@ static const struct usb_device_id cdce_devs[] = {
 	{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
 	{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
 	{USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)},
+
+	{USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)},
+	{USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)},
 };
 
 static int
diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c
index 427137a92f2..6cf446016e7 100644
--- a/sys/dev/usb/net/usb_ethernet.c
+++ b/sys/dev/usb/net/usb_ethernet.c
@@ -221,10 +221,10 @@ ue_attach_post_task(struct usb_proc_msg *_task)
 
 	if (ue->ue_methods->ue_mii_upd != NULL && 
 	    ue->ue_methods->ue_mii_sts != NULL) {
-		newbus_xlock();
+		mtx_lock(&Giant);	/* device_xxx() depends on this */
 		error = mii_phy_probe(ue->ue_dev, &ue->ue_miibus,
 		    ue_ifmedia_upd, ue->ue_methods->ue_mii_sts);
-		newbus_xunlock();
+		mtx_unlock(&Giant);
 		if (error) {
 			device_printf(ue->ue_dev, "MII without any PHY\n");
 			goto error;
@@ -279,12 +279,9 @@ uether_ifdetach(struct usb_ether *ue)
 
 		/* detach miibus */
 		if (ue->ue_miibus != NULL) {
-
-			/*
-			 * It is up to the callers to provide the correct
-			 * newbus locking.
-			 */
+			mtx_lock(&Giant);	/* device_xxx() depends on this */
 			device_delete_child(ue->ue_dev, ue->ue_miibus);
+			mtx_unlock(&Giant);
 		}
 
 		/* detach ethernet */
diff --git a/sys/dev/usb/serial/uipaq.c b/sys/dev/usb/serial/uipaq.c
index 79fe21e5c2c..89a4cd254ab 100644
--- a/sys/dev/usb/serial/uipaq.c
+++ b/sys/dev/usb/serial/uipaq.c
@@ -1103,6 +1103,10 @@ uipaq_probe(device_t dev)
 	if (uaa->info.bIfaceIndex != UIPAQ_IFACE_INDEX) {
 		return (ENXIO);
 	}
+	if (uaa->info.bInterfaceClass == UICLASS_IAD) {
+		DPRINTF("IAD detected - not UIPAQ serial device\n");
+		return (ENXIO);
+	}
 	return (usbd_lookup_id_by_uaa(uipaq_devs, sizeof(uipaq_devs), uaa));
 }
 
diff --git a/sys/dev/usb/serial/uvisor.c b/sys/dev/usb/serial/uvisor.c
index c7175e31a63..3f1624bcbf4 100644
--- a/sys/dev/usb/serial/uvisor.c
+++ b/sys/dev/usb/serial/uvisor.c
@@ -95,7 +95,15 @@ SYSCTL_INT(_hw_usb_uvisor, OID_AUTO, debug, CTLFLAG_RW,
 
 #define	UVISOR_CONFIG_INDEX	0
 #define	UVISOR_IFACE_INDEX	0
-#define	UVISOR_BUFSIZE       1024	/* bytes */
+
+/*
+ * The following buffer sizes are hardcoded due to the way the Palm
+ * firmware works. It looks like the device is not short terminating
+ * the data transferred.
+ */
+#define	UVISORIBUFSIZE	       0	/* Use wMaxPacketSize */
+#define	UVISOROBUFSIZE	       32	/* bytes */
+#define	UVISOROFRAMES	       32	/* units */
 
 /* From the Linux driver */
 /*
@@ -208,7 +216,8 @@ static const struct usb_config uvisor_config[UVISOR_N_TRANSFER] = {
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
-		.bufsize = UVISOR_BUFSIZE,	/* bytes */
+		.bufsize = UVISOROBUFSIZE * UVISOROFRAMES,
+		.frames = UVISOROFRAMES,
 		.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
 		.callback = &uvisor_write_callback,
 	},
@@ -217,7 +226,7 @@ static const struct usb_config uvisor_config[UVISOR_N_TRANSFER] = {
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
-		.bufsize = UVISOR_BUFSIZE,	/* bytes */
+		.bufsize = UVISORIBUFSIZE,
 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
 		.callback = &uvisor_read_callback,
 	},
@@ -270,7 +279,7 @@ static const struct usb_device_id uvisor_devs[] = {
 	{USB_VPI(USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE31, UVISOR_FLAG_PALM4)},
 	{USB_VPI(USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_I500, UVISOR_FLAG_PALM4)},
 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40, 0)},
-	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41, UVISOR_FLAG_PALM4)},
+	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41, 0)},
 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_S360, UVISOR_FLAG_PALM4)},
 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_NX60, UVISOR_FLAG_PALM4)},
 	{USB_VPI(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_35, UVISOR_FLAG_PALM35)},
@@ -375,7 +384,6 @@ uvisor_init(struct uvisor_softc *sc, struct usb_device *udev, struct usb_config
 	struct uvisor_connection_info coninfo;
 	struct uvisor_palm_connection_info pconinfo;
 	uint16_t actlen;
-	uWord wAvail;
 	uint8_t buffer[256];
 
 	if (sc->sc_flag & UVISOR_FLAG_VISOR) {
@@ -496,6 +504,9 @@ uvisor_init(struct uvisor_softc *sc, struct usb_device *udev, struct usb_config
 			goto done;
 		}
 	}
+#if 0
+	uWord wAvail;
+
 	DPRINTF("getting available bytes\n");
 	req.bmRequestType = UT_READ_VENDOR_ENDPOINT;
 	req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE;
@@ -507,6 +518,7 @@ uvisor_init(struct uvisor_softc *sc, struct usb_device *udev, struct usb_config
 		goto done;
 	}
 	DPRINTF("avail=%d\n", UGETW(wAvail));
+#endif
 
 	DPRINTF("done\n");
 done:
@@ -579,19 +591,31 @@ uvisor_write_callback(struct usb_xfer *xfer, usb_error_t error)
 	struct uvisor_softc *sc = usbd_xfer_softc(xfer);
 	struct usb_page_cache *pc;
 	uint32_t actlen;
+	uint8_t x;
 
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_SETUP:
 	case USB_ST_TRANSFERRED:
 tr_setup:
-		pc = usbd_xfer_get_frame(xfer, 0);
-		if (ucom_get_data(&sc->sc_ucom, pc, 0,
-		    UVISOR_BUFSIZE, &actlen)) {
+		for (x = 0; x != UVISOROFRAMES; x++) {
 
-			usbd_xfer_set_frame_len(xfer, 0, actlen);
+			usbd_xfer_set_frame_offset(xfer, 
+			    x * UVISOROBUFSIZE, x);
+
+			pc = usbd_xfer_get_frame(xfer, x);
+			if (ucom_get_data(&sc->sc_ucom, pc, 0,
+			    UVISOROBUFSIZE, &actlen)) {
+				usbd_xfer_set_frame_len(xfer, x, actlen);
+			} else {
+				break;
+			}
+		}
+		/* check for data */
+		if (x != 0) {
+			usbd_xfer_set_frames(xfer, x);
 			usbd_transfer_submit(xfer);
 		}
-		return;
+		break;
 
 	default:			/* Error */
 		if (error != USB_ERR_CANCELLED) {
@@ -599,7 +623,7 @@ tr_setup:
 			usbd_xfer_set_stall(xfer);
 			goto tr_setup;
 		}
-		return;
+		break;
 	}
 }
 
diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
index 2e412d98ca3..23893e48c48 100644
--- a/sys/dev/usb/storage/umass.c
+++ b/sys/dev/usb/storage/umass.c
@@ -124,6 +124,7 @@ __FBSDID("$FreeBSD$");
 
 #include 
 #include 
+#include 
 #include "usbdevs.h"
 
 #include 
@@ -412,6 +413,10 @@ static const struct umass_devdescr umass_devdescr[] = {
 		UMASS_PROTO_DEFAULT,
 		NO_SYNCHRONIZE_CACHE
 	},
+	{USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_SDCR_6335, RID_WILDCARD,
+		UMASS_PROTO_DEFAULT,
+		NO_TEST_UNIT_READY | NO_SYNCHRONIZE_CACHE
+	},
 	{USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_AU6390, RID_WILDCARD,
 		UMASS_PROTO_DEFAULT,
 		NO_SYNCHRONIZE_CACHE
@@ -733,6 +738,10 @@ static const struct umass_devdescr umass_devdescr[] = {
 		UMASS_PROTO_UFI,
 		NO_QUIRKS
 	},
+	{ USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_SPE3030CC, RID_WILDCARD,
+		UMASS_PROTO_DEFAULT,
+		NO_SYNCHRONIZE_CACHE
+	},
 	{USB_VENDOR_PLEXTOR, USB_PRODUCT_PLEXTOR_40_12_40U, RID_WILDCARD,
 		UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 		NO_TEST_UNIT_READY
@@ -893,6 +902,10 @@ static const struct umass_devdescr umass_devdescr[] = {
 		UMASS_PROTO_UFI | UMASS_PROTO_CBI,
 		NO_QUIRKS
 	},
+	{USB_VENDOR_TECLAST, USB_PRODUCT_TECLAST_TLC300, RID_WILDCARD,
+		UMASS_PROTO_DEFAULT,
+		NO_TEST_UNIT_READY | NO_SYNCHRONIZE_CACHE
+	},
 	{USB_VENDOR_TREK, USB_PRODUCT_TREK_MEMKEY, RID_WILDCARD,
 		UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 		NO_INQUIRY
@@ -965,6 +978,10 @@ static const struct umass_devdescr umass_devdescr[] = {
 		UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 		NO_SYNCHRONIZE_CACHE
 	},
+	{USB_VENDOR_ASUS, USB_PRODUCT_ASUS_GMSC, RID_WILDCARD,
+		UMASS_PROTO_DEFAULT,
+		NO_SYNCHRONIZE_CACHE
+	},
 	{VID_EOT, PID_EOT, RID_EOT, 0, 0}
 };
 
@@ -2961,6 +2978,28 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
 
 				if (sc->sc_transfer.cmd_data[0] == INQUIRY) {
 
+					/*
+					 * Umass devices don't generally report their serial numbers
+					 * in the usual SCSI way.  Emulate it here.
+					 */
+					if ((sc->sc_transfer.cmd_data[1] & SI_EVPD) &&
+					    sc->sc_transfer.cmd_data[2] == SVPD_UNIT_SERIAL_NUMBER &&
+					    sc->sc_udev != NULL &&
+					    sc->sc_udev->serial != NULL &&
+					    sc->sc_udev->serial[0] != '\0') {
+						struct scsi_vpd_unit_serial_number *vpd_serial;
+
+						vpd_serial = (struct scsi_vpd_unit_serial_number *)ccb->csio.data_ptr;
+						vpd_serial->length = strlen(sc->sc_udev->serial);
+						if (vpd_serial->length > sizeof(vpd_serial->serial_num))
+							vpd_serial->length = sizeof(vpd_serial->serial_num);
+						memcpy(vpd_serial->serial_num, sc->sc_udev->serial, vpd_serial->length);
+						ccb->csio.scsi_status = SCSI_STATUS_OK;
+						ccb->ccb_h.status = CAM_REQ_CMP;
+						xpt_done(ccb);
+						goto done;
+					}
+
 					/*
 					 * Handle EVPD inquiry for broken devices first
 					 * NO_INQUIRY also implies NO_INQUIRY_EVPD
@@ -3177,6 +3216,29 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
 			maxsector = scsi_4btoul(rcap->addr) - 1;
 			scsi_ulto4b(maxsector, rcap->addr);
 		}
+		/*
+		 * We have to add SVPD_UNIT_SERIAL_NUMBER to the list
+		 * of pages supported by the device - otherwise, CAM
+		 * will never ask us for the serial number if the
+		 * device cannot handle that by itself.
+		 */
+		if (ccb->ccb_h.func_code == XPT_SCSI_IO &&
+		    sc->sc_transfer.cmd_data[0] == INQUIRY &&
+		    (sc->sc_transfer.cmd_data[1] & SI_EVPD) &&
+		    sc->sc_transfer.cmd_data[2] == SVPD_SUPPORTED_PAGE_LIST &&
+		    sc->sc_udev != NULL &&
+		    sc->sc_udev->serial != NULL &&
+		    sc->sc_udev->serial[0] != '\0') {
+			struct ccb_scsiio *csio;
+			struct scsi_vpd_supported_page_list *page_list;
+
+			csio = &ccb->csio;
+			page_list = (struct scsi_vpd_supported_page_list *)csio->data_ptr;
+			if (page_list->length + 1 < SVPD_SUPPORTED_PAGES_SIZE) {
+				page_list->list[page_list->length] = SVPD_UNIT_SERIAL_NUMBER;
+				page_list->length++;
+			}
+		}
 		xpt_done(ccb);
 		break;
 
diff --git a/sys/dev/usb/storage/urio.c b/sys/dev/usb/storage/urio.c
index 6bb2e889e40..403c4c2b216 100644
--- a/sys/dev/usb/storage/urio.c
+++ b/sys/dev/usb/storage/urio.c
@@ -390,9 +390,6 @@ urio_open(struct usb_fifo *fifo, int fflags)
 {
 	struct urio_softc *sc = usb_fifo_softc(fifo);
 
-	if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) {
-		return (EACCES);
-	}
 	if (fflags & FREAD) {
 		/* clear stall first */
 		mtx_lock(&sc->sc_mtx);
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index 68c3caf6a05..119839831c1 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -484,6 +484,8 @@ typedef struct usb_interface_assoc_descriptor usb_interface_assoc_descriptor_t;
 #define	UISUBCLASS_RF			0x01
 #define	UIPROTO_BLUETOOTH		0x01
 
+#define	UICLASS_IAD		0xEF	/* Interface Association Descriptor */
+
 #define	UICLASS_APPL_SPEC	0xfe
 #define	UISUBCLASS_FIRMWARE_DOWNLOAD	1
 #define	UISUBCLASS_IRDA			2
diff --git a/sys/dev/usb/usb_busdma.c b/sys/dev/usb/usb_busdma.c
index e5d6ed7951e..177b94faceb 100644
--- a/sys/dev/usb/usb_busdma.c
+++ b/sys/dev/usb/usb_busdma.c
@@ -679,8 +679,14 @@ usb_pc_cpu_invalidate(struct usb_page_cache *pc)
 		/* nothing has been loaded into this page cache! */
 		return;
 	}
-	bus_dmamap_sync(pc->tag, pc->map,
-	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+
+	/*
+	 * TODO: We currently do XXX_POSTREAD and XXX_PREREAD at the
+	 * same time, but in the future we should try to isolate the
+	 * different cases to optimise the code. --HPS
+	 */
+	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_POSTREAD);
+	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREREAD);
 }
 
 /*------------------------------------------------------------------------*
@@ -693,8 +699,7 @@ usb_pc_cpu_flush(struct usb_page_cache *pc)
 		/* nothing has been loaded into this page cache! */
 		return;
 	}
-	bus_dmamap_sync(pc->tag, pc->map,
-	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREWRITE);
 }
 
 /*------------------------------------------------------------------------*
diff --git a/sys/dev/usb/usb_compat_linux.c b/sys/dev/usb/usb_compat_linux.c
index 00fc86bdc98..604ac4d8845 100644
--- a/sys/dev/usb/usb_compat_linux.c
+++ b/sys/dev/usb/usb_compat_linux.c
@@ -215,12 +215,14 @@ usb_linux_probe(device_t dev)
 	if (uaa->usb_mode != USB_MODE_HOST) {
 		return (ENXIO);
 	}
+	mtx_lock(&Giant);
 	LIST_FOREACH(udrv, &usb_linux_driver_list, linux_driver_list) {
 		if (usb_linux_lookup_id(udrv->id_table, uaa)) {
 			err = 0;
 			break;
 		}
 	}
+	mtx_unlock(&Giant);
 
 	return (err);
 }
@@ -237,7 +239,9 @@ usb_linux_get_usb_driver(struct usb_linux_softc *sc)
 {
 	struct usb_driver *udrv;
 
+	mtx_lock(&Giant);
 	udrv = sc->sc_udrv;
+	mtx_unlock(&Giant);
 	return (udrv);
 }
 
@@ -256,11 +260,13 @@ usb_linux_attach(device_t dev)
 	struct usb_driver *udrv;
 	const struct usb_device_id *id = NULL;
 
+	mtx_lock(&Giant);
 	LIST_FOREACH(udrv, &usb_linux_driver_list, linux_driver_list) {
 		id = usb_linux_lookup_id(udrv->id_table, uaa);
 		if (id)
 			break;
 	}
+	mtx_unlock(&Giant);
 
 	if (id == NULL) {
 		return (ENXIO);
@@ -281,7 +287,9 @@ usb_linux_attach(device_t dev)
 			return (ENXIO);
 		}
 	}
+	mtx_lock(&Giant);
 	LIST_INSERT_HEAD(&usb_linux_attached_list, sc, sc_attached_list);
+	mtx_unlock(&Giant);
 
 	/* success */
 	return (0);
@@ -299,12 +307,14 @@ usb_linux_detach(device_t dev)
 	struct usb_linux_softc *sc = device_get_softc(dev);
 	struct usb_driver *udrv = NULL;
 
+	mtx_lock(&Giant);
 	if (sc->sc_attached_list.le_prev) {
 		LIST_REMOVE(sc, sc_attached_list);
 		sc->sc_attached_list.le_prev = NULL;
 		udrv = sc->sc_udrv;
 		sc->sc_udrv = NULL;
 	}
+	mtx_unlock(&Giant);
 
 	if (udrv && udrv->disconnect) {
 		(udrv->disconnect) (sc->sc_ui);
@@ -464,10 +474,13 @@ usb_unlink_bsd(struct usb_xfer *xfer,
 	if (!usbd_transfer_pending(xfer))
 		return;
 	if (xfer->priv_fifo == (void *)urb) {
-		if (drain)
+		if (drain) {
+			mtx_unlock(&Giant);
 			usbd_transfer_drain(xfer);
-		else
+			mtx_lock(&Giant);
+		} else {
 			usbd_transfer_stop(xfer);
+		}
 		usbd_transfer_start(xfer);
 	}
 }
@@ -1135,9 +1148,9 @@ usb_linux_register(void *arg)
 {
 	struct usb_driver *drv = arg;
 
-	newbus_xlock();
+	mtx_lock(&Giant);
 	LIST_INSERT_HEAD(&usb_linux_driver_list, drv, linux_driver_list);
-	newbus_xunlock();
+	mtx_unlock(&Giant);
 
 	usb_needs_explore_all();
 }
@@ -1159,16 +1172,16 @@ usb_linux_deregister(void *arg)
 	struct usb_linux_softc *sc;
 
 repeat:
-	newbus_xlock();
+	mtx_lock(&Giant);
 	LIST_FOREACH(sc, &usb_linux_attached_list, sc_attached_list) {
 		if (sc->sc_udrv == drv) {
+			mtx_unlock(&Giant);
 			device_detach(sc->sc_fbsd_dev);
-			newbus_xunlock();
 			goto repeat;
 		}
 	}
 	LIST_REMOVE(drv, linux_driver_list);
-	newbus_xunlock();
+	mtx_unlock(&Giant);
 }
 
 /*------------------------------------------------------------------------*
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index b7c6553db75..c828b24057f 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -217,7 +217,7 @@ usb_ref_device(struct usb_cdev_privdata *cpd,
 		 * We need to grab the sx-lock before grabbing the
 		 * FIFO refs to avoid deadlock at detach!
 		 */
-		sx_xlock(cpd->udev->default_sx + 1);
+		usbd_enum_lock(cpd->udev);
 
 		mtx_lock(&usb_ref_lock);
 
@@ -275,14 +275,12 @@ usb_ref_device(struct usb_cdev_privdata *cpd,
 	}
 	mtx_unlock(&usb_ref_lock);
 
-	if (crd->is_uref) {
-		mtx_lock(&Giant);	/* XXX */
-	}
 	return (0);
 
 error:
 	if (crd->is_uref) {
-		sx_unlock(cpd->udev->default_sx + 1);
+		usbd_enum_unlock(cpd->udev);
+
 		if (--(cpd->udev->refcount) == 0) {
 			cv_signal(cpd->udev->default_cv + 1);
 		}
@@ -334,10 +332,9 @@ usb_unref_device(struct usb_cdev_privdata *cpd,
 
 	DPRINTFN(2, "cpd=%p is_uref=%d\n", cpd, crd->is_uref);
 
-	if (crd->is_uref) {
-		mtx_unlock(&Giant);	/* XXX */
-		sx_unlock(cpd->udev->default_sx + 1);
-	}
+	if (crd->is_uref)
+		usbd_enum_unlock(cpd->udev);
+
 	mtx_lock(&usb_ref_lock);
 	if (crd->is_read) {
 		if (--(crd->rxfifo->refcount) == 0) {
@@ -1040,16 +1037,11 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
 	 * Performance optimisation: We try to check for IOCTL's that
 	 * don't need the USB reference first. Then we grab the USB
 	 * reference if we need it!
-	 * Note that some ioctl_post handlers would need to run with the
-	 * newbus lock held.  It cannot be acquired later because it can
-	 * introduce a LOR, so acquire it here.
 	 */
-	newbus_xlock();
 	err = usb_ref_device(cpd, &refs, 0 /* no uref */ );
-	if (err) {
-		newbus_xunlock();
+	if (err)
 		return (ENXIO);
-	}
+
 	fflags = cpd->fflags;
 
 	f = NULL;			/* set default value */
@@ -1081,7 +1073,6 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
 	}
 done:
 	usb_unref_device(cpd, &refs);
-	newbus_xunlock();
 	return (err);
 }
 
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 2d34017ba33..635a9b1528d 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -402,11 +402,11 @@ usb_unconfigure(struct usb_device *udev, uint8_t flag)
 	uint8_t do_unlock;
 
 	/* automatic locking */
-	if (sx_xlocked(udev->default_sx + 1)) {
+	if (usbd_enum_is_locked(udev)) {
 		do_unlock = 0;
 	} else {
 		do_unlock = 1;
-		sx_xlock(udev->default_sx + 1);
+		usbd_enum_lock(udev);
 	}
 
 	/* detach all interface drivers */
@@ -442,9 +442,8 @@ usb_unconfigure(struct usb_device *udev, uint8_t flag)
 	udev->curr_config_no = USB_UNCONFIG_NO;
 	udev->curr_config_index = USB_UNCONFIG_INDEX;
 
-	if (do_unlock) {
-		sx_unlock(udev->default_sx + 1);
-	}
+	if (do_unlock)
+		usbd_enum_unlock(udev);
 }
 
 /*------------------------------------------------------------------------*
@@ -472,11 +471,11 @@ usbd_set_config_index(struct usb_device *udev, uint8_t index)
 	DPRINTFN(6, "udev=%p index=%d\n", udev, index);
 
 	/* automatic locking */
-	if (sx_xlocked(udev->default_sx + 1)) {
+	if (usbd_enum_is_locked(udev)) {
 		do_unlock = 0;
 	} else {
 		do_unlock = 1;
-		sx_xlock(udev->default_sx + 1);
+		usbd_enum_lock(udev);
 	}
 
 	usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_SUBDEV);
@@ -585,9 +584,8 @@ done:
 	if (err) {
 		usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_SUBDEV);
 	}
-	if (do_unlock) {
-		sx_unlock(udev->default_sx + 1);
-	}
+	if (do_unlock)
+		usbd_enum_unlock(udev);
 	return (err);
 }
 
@@ -823,11 +821,11 @@ usbd_set_alt_interface_index(struct usb_device *udev,
 	uint8_t do_unlock;
 
 	/* automatic locking */
-	if (sx_xlocked(udev->default_sx + 1)) {
+	if (usbd_enum_is_locked(udev)) {
 		do_unlock = 0;
 	} else {
 		do_unlock = 1;
-		sx_xlock(udev->default_sx + 1);
+		usbd_enum_lock(udev);
 	}
 	if (iface == NULL) {
 		err = USB_ERR_INVAL;
@@ -863,9 +861,9 @@ usbd_set_alt_interface_index(struct usb_device *udev,
 	    iface->idesc->bAlternateSetting);
 
 done:
-	if (do_unlock) {
-		sx_unlock(udev->default_sx + 1);
-	}
+	if (do_unlock)
+		usbd_enum_unlock(udev);
+
 	return (err);
 }
 
@@ -1230,11 +1228,11 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index)
 		return (USB_ERR_INVAL);
 	}
 	/* automatic locking */
-	if (sx_xlocked(udev->default_sx + 1)) {
+	if (usbd_enum_is_locked(udev)) {
 		do_unlock = 0;
 	} else {
 		do_unlock = 1;
-		sx_xlock(udev->default_sx + 1);
+		usbd_enum_lock(udev);
 	}
 
 	if (udev->curr_config_index == USB_UNCONFIG_INDEX) {
@@ -1315,9 +1313,9 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index)
 		}
 	}
 done:
-	if (do_unlock) {
-		sx_unlock(udev->default_sx + 1);
-	}
+	if (do_unlock)
+		usbd_enum_unlock(udev);
+
 	return (0);
 }
 
@@ -1779,7 +1777,8 @@ repeat_set_config:
 			}
 		} else if (usb_test_huawei_autoinst_p(udev, &uaa) == 0) {
 			DPRINTFN(0, "Found Huawei auto-install disk!\n");
-			err = USB_ERR_STALLED;	/* fake an error */
+			/* leave device unconfigured */
+			usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_SUBDEV);
 		}
 	} else {
 		err = 0;		/* set success */
@@ -1902,15 +1901,18 @@ static void
 usb_cdev_free(struct usb_device *udev)
 {
 	struct usb_fs_privdata* pd;
+	struct cdev* pcdev;
 
 	DPRINTFN(2, "Freeing device nodes\n");
 
 	while ((pd = LIST_FIRST(&udev->pd_list)) != NULL) {
 		KASSERT(pd->cdev->si_drv1 == pd, ("privdata corrupt"));
 
-		destroy_dev_sched_cb(pd->cdev, usb_cdev_cleanup, pd);
+		pcdev = pd->cdev;
 		pd->cdev = NULL;
 		LIST_REMOVE(pd, pd_next);
+		if (pcdev != NULL)
+			destroy_dev_sched_cb(pcdev, usb_cdev_cleanup, pd);
 	}
 }
 
@@ -2448,3 +2450,37 @@ usbd_device_attached(struct usb_device *udev)
 {
 	return (udev->state > USB_STATE_DETACHED);
 }
+
+/* The following function locks enumerating the given USB device. */
+
+void
+usbd_enum_lock(struct usb_device *udev)
+{
+	sx_xlock(udev->default_sx + 1);
+	/* 
+	 * NEWBUS LOCK NOTE: We should check if any parent SX locks
+	 * are locked before locking Giant. Else the lock can be
+	 * locked multiple times.
+	 */
+	mtx_lock(&Giant);
+}
+
+/* The following function unlocks enumerating the given USB device. */
+
+void
+usbd_enum_unlock(struct usb_device *udev)
+{
+	mtx_unlock(&Giant);
+	sx_xunlock(udev->default_sx + 1);
+}
+
+/*
+ * The following function checks the enumerating lock for the given
+ * USB device.
+ */
+
+uint8_t
+usbd_enum_is_locked(struct usb_device *udev)
+{
+	return (sx_xlocked(udev->default_sx + 1));
+}
diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h
index d601c146a21..682e2007e6e 100644
--- a/sys/dev/usb/usb_device.h
+++ b/sys/dev/usb/usb_device.h
@@ -211,5 +211,8 @@ uint8_t	usb_peer_can_wakeup(struct usb_device *udev);
 struct usb_endpoint *usb_endpoint_foreach(struct usb_device *udev, struct usb_endpoint *ep);
 void	usb_set_device_state(struct usb_device *udev,
 	    enum usb_dev_state state);
+void	usbd_enum_lock(struct usb_device *);
+void	usbd_enum_unlock(struct usb_device *);
+uint8_t usbd_enum_is_locked(struct usb_device *);
 
 #endif					/* _USB_DEVICE_H_ */
diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c
index 2bc3eefd210..92bf8329eb8 100644
--- a/sys/dev/usb/usb_handle_request.c
+++ b/sys/dev/usb/usb_handle_request.c
@@ -152,8 +152,8 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
 	 * attach:
 	 */
 	USB_XFER_UNLOCK(xfer);
-	newbus_xlock();
-	sx_xlock(udev->default_sx + 1);
+
+	usbd_enum_lock(udev);
 
 	if (conf_no == USB_UNCONFIG_NO) {
 		conf_no = USB_UNCONFIG_INDEX;
@@ -176,8 +176,7 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
 		goto done;
 	}
 done:
-	sx_unlock(udev->default_sx + 1);
-	newbus_xunlock();
+	usbd_enum_unlock(udev);
 	USB_XFER_LOCK(xfer);
 	return (err);
 }
@@ -190,19 +189,19 @@ usb_check_alt_setting(struct usb_device *udev,
 	usb_error_t err = 0;
 
 	/* automatic locking */
-	if (sx_xlocked(udev->default_sx + 1)) {
+	if (usbd_enum_is_locked(udev)) {
 		do_unlock = 0;
 	} else {
 		do_unlock = 1;
-		sx_xlock(udev->default_sx + 1);
+		usbd_enum_lock(udev);
 	}
 
 	if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc))
 		err = USB_ERR_INVAL;
 
-	if (do_unlock) {
-		sx_unlock(udev->default_sx + 1);
-	}
+	if (do_unlock)
+		usbd_enum_unlock(udev);
+
 	return (err);
 }
 
@@ -236,8 +235,8 @@ usb_handle_iface_request(struct usb_xfer *xfer,
 	 * attach:
 	 */
 	USB_XFER_UNLOCK(xfer);
-	newbus_xlock();
-	sx_xlock(udev->default_sx + 1);
+
+	usbd_enum_lock(udev);
 
 	error = ENXIO;
 
@@ -353,20 +352,17 @@ tr_repeat:
 		goto tr_stalled;
 	}
 tr_valid:
-	sx_unlock(udev->default_sx + 1);
-	newbus_xunlock();
+	usbd_enum_unlock(udev);
 	USB_XFER_LOCK(xfer);
 	return (0);
 
 tr_short:
-	sx_unlock(udev->default_sx + 1);
-	newbus_xunlock();
+	usbd_enum_unlock(udev);
 	USB_XFER_LOCK(xfer);
 	return (USB_ERR_SHORT_XFER);
 
 tr_stalled:
-	sx_unlock(udev->default_sx + 1);
-	newbus_xunlock();
+	usbd_enum_unlock(udev);
 	USB_XFER_LOCK(xfer);
 	return (USB_ERR_STALLED);
 }
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index a09be96b8e4..2c81d97d126 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -96,6 +96,7 @@ struct uhub_current_state {
 struct uhub_softc {
 	struct uhub_current_state sc_st;/* current state */
 	device_t sc_dev;		/* base device */
+	struct mtx sc_mtx;		/* our mutex */
 	struct usb_device *sc_udev;	/* USB device */
 	struct usb_xfer *sc_xfer[UHUB_N_TRANSFER];	/* interrupt xfer */
 	uint8_t	sc_flags;
@@ -234,10 +235,8 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up)
 
 	if (child->driver_added_refcount != refcount) {
 		child->driver_added_refcount = refcount;
-		newbus_xlock();
 		err = usb_probe_and_attach(child,
 		    USB_IFACE_INDEX_ANY);
-		newbus_xunlock();
 		if (err) {
 			goto done;
 		}
@@ -320,11 +319,9 @@ repeat:
 	/* detach any existing devices */
 
 	if (child) {
-		newbus_xlock();
 		usb_free_device(child,
 		    USB_UNCFG_FLAG_FREE_SUBDEV |
 		    USB_UNCFG_FLAG_FREE_EP0);
-		newbus_xunlock();
 		child = NULL;
 	}
 	/* get fresh status */
@@ -432,10 +429,8 @@ repeat:
 		mode = USB_MODE_HOST;
 
 	/* need to create a new child */
-	newbus_xlock();
 	child = usb_alloc_device(sc->sc_dev, udev->bus, udev,
 	    udev->depth + 1, portno - 1, portno, speed, mode);
-	newbus_xunlock();
 	if (child == NULL) {
 		DPRINTFN(0, "could not allocate new device!\n");
 		goto error;
@@ -444,11 +439,9 @@ repeat:
 
 error:
 	if (child) {
-		newbus_xlock();
 		usb_free_device(child,
 		    USB_UNCFG_FLAG_FREE_SUBDEV |
 		    USB_UNCFG_FLAG_FREE_EP0);
-		newbus_xunlock();
 		child = NULL;
 	}
 	if (err == 0) {
@@ -698,6 +691,8 @@ uhub_attach(device_t dev)
 	sc->sc_udev = udev;
 	sc->sc_dev = dev;
 
+	mtx_init(&sc->sc_mtx, "USB HUB mutex", NULL, MTX_DEF);
+
 	snprintf(sc->sc_name, sizeof(sc->sc_name), "%s",
 	    device_get_nameunit(dev));
 
@@ -781,7 +776,7 @@ uhub_attach(device_t dev)
 	} else {
 		/* normal HUB */
 		err = usbd_transfer_setup(udev, &iface_index, sc->sc_xfer,
-		    uhub_config, UHUB_N_TRANSFER, sc, &Giant);
+		    uhub_config, UHUB_N_TRANSFER, sc, &sc->sc_mtx);
 	}
 	if (err) {
 		DPRINTFN(0, "cannot setup interrupt transfer, "
@@ -857,9 +852,9 @@ uhub_attach(device_t dev)
 	/* Start the interrupt endpoint, if any */
 
 	if (sc->sc_xfer[0] != NULL) {
-		USB_XFER_LOCK(sc->sc_xfer[0]);
+		mtx_lock(&sc->sc_mtx);
 		usbd_transfer_start(sc->sc_xfer[0]);
-		USB_XFER_UNLOCK(sc->sc_xfer[0]);
+		mtx_unlock(&sc->sc_mtx);
 	}
 
 	/* Enable automatic power save on all USB HUBs */
@@ -875,6 +870,9 @@ error:
 		free(udev->hub, M_USBDEV);
 		udev->hub = NULL;
 	}
+
+	mtx_destroy(&sc->sc_mtx);
+
 	return (ENXIO);
 }
 
@@ -915,6 +913,9 @@ uhub_detach(device_t dev)
 
 	free(hub, M_USBDEV);
 	sc->sc_udev->hub = NULL;
+
+	mtx_destroy(&sc->sc_mtx);
+
 	return (0);
 }
 
@@ -987,6 +988,7 @@ uhub_child_location_string(device_t parent, device_t child,
 	struct usb_hub *hub = sc->sc_udev->hub;
 	struct hub_result res;
 
+	mtx_lock(&Giant);
 	uhub_find_iface_index(hub, child, &res);
 	if (!res.udev) {
 		DPRINTF("device not on hub\n");
@@ -998,6 +1000,7 @@ uhub_child_location_string(device_t parent, device_t child,
 	snprintf(buf, buflen, "port=%u interface=%u",
 	    res.portno, res.iface_index);
 done:
+	mtx_unlock(&Giant);
 
 	return (0);
 }
@@ -1011,6 +1014,7 @@ uhub_child_pnpinfo_string(device_t parent, device_t child,
 	struct usb_interface *iface;
 	struct hub_result res;
 
+	mtx_lock(&Giant);
 	uhub_find_iface_index(hub, child, &res);
 	if (!res.udev) {
 		DPRINTF("device not on hub\n");
@@ -1041,6 +1045,7 @@ uhub_child_pnpinfo_string(device_t parent, device_t child,
 		goto done;
 	}
 done:
+	mtx_unlock(&Giant);
 
 	return (0);
 }
@@ -1778,13 +1783,13 @@ usb_dev_resume_peer(struct usb_device *udev)
 		/* always update hardware power! */
 		(bus->methods->set_hw_power) (bus);
 	}
-	newbus_xlock();
-	sx_xlock(udev->default_sx + 1);
+
+	usbd_enum_lock(udev);
 
 	/* notify all sub-devices about resume */
 	err = usb_suspend_resume(udev, 0);
-	sx_unlock(udev->default_sx + 1);
-	newbus_xunlock();
+
+	usbd_enum_unlock(udev);
 
 	/* check if peer has wakeup capability */
 	if (usb_peer_can_wakeup(udev)) {
@@ -1850,13 +1855,12 @@ repeat:
 		}
 	}
 
-	newbus_xlock();
-	sx_xlock(udev->default_sx + 1);
+	usbd_enum_lock(udev);
 
 	/* notify all sub-devices about suspend */
 	err = usb_suspend_resume(udev, 1);
-	sx_unlock(udev->default_sx + 1);
-	newbus_xunlock();
+
+	usbd_enum_unlock(udev);
 
 	if (usb_peer_can_wakeup(udev)) {
 		/* allow device to do remote wakeup */
diff --git a/sys/dev/usb/usb_process.c b/sys/dev/usb/usb_process.c
index eb79f166508..eb503fd18c4 100644
--- a/sys/dev/usb/usb_process.c
+++ b/sys/dev/usb/usb_process.c
@@ -63,10 +63,13 @@
 #endif
 
 #if (__FreeBSD_version >= 800000)
+static struct proc *usbproc;
+static int usb_pcount;
 #define	USB_THREAD_CREATE(f, s, p, ...) \
-		kproc_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__)
-#define	USB_THREAD_SUSPEND(p)   kproc_suspend(p,0)
-#define	USB_THREAD_EXIT(err)	kproc_exit(err)
+		kproc_kthread_add((f), (s), &usbproc, (p), RFHIGHPID, \
+		    0, "usb", __VA_ARGS__)
+#define	USB_THREAD_SUSPEND(p)   kthread_suspend(p,0)
+#define	USB_THREAD_EXIT(err)	kthread_exit()
 #else
 #define	USB_THREAD_CREATE(f, s, p, ...) \
 		kthread_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__)
@@ -181,6 +184,11 @@ usb_process(void *arg)
 	up->up_ptr = NULL;
 	cv_signal(&up->up_cv);
 	mtx_unlock(up->up_mtx);
+#if (__FreeBSD_version >= 800000)
+	/* Clear the proc pointer if this is the last thread. */
+	if (--usb_pcount == 0)
+		usbproc = NULL;
+#endif
 
 	USB_THREAD_EXIT(0);
 }
@@ -207,8 +215,8 @@ usb_proc_create(struct usb_process *up, struct mtx *p_mtx,
 
 	TAILQ_INIT(&up->up_qhead);
 
-	cv_init(&up->up_cv, "wmsg");
-	cv_init(&up->up_drain, "dmsg");
+	cv_init(&up->up_cv, "-");
+	cv_init(&up->up_drain, "usbdrain");
 
 	if (USB_THREAD_CREATE(&usb_process, up,
 	    &up->up_ptr, pmesg)) {
@@ -216,6 +224,9 @@ usb_proc_create(struct usb_process *up, struct mtx *p_mtx,
 		up->up_ptr = NULL;
 		goto error;
 	}
+#if (__FreeBSD_version >= 800000)
+	usb_pcount++;
+#endif
 	return (0);
 
 error:
@@ -446,3 +457,29 @@ usb_proc_drain(struct usb_process *up)
 	}
 	mtx_unlock(up->up_mtx);
 }
+
+/*------------------------------------------------------------------------*
+ *	usb_proc_rewakeup
+ *
+ * This function is called to re-wakeup the the given USB
+ * process. This usually happens after that the USB system has been in
+ * polling mode, like during a panic. This function must be called
+ * having "up->up_mtx" locked.
+ *------------------------------------------------------------------------*/
+void
+usb_proc_rewakeup(struct usb_process *up)
+{
+	/* check if not initialised */
+	if (up->up_mtx == NULL)
+		return;
+	/* check if gone */
+	if (up->up_gone)
+		return;
+
+	mtx_assert(up->up_mtx, MA_OWNED);
+
+	if (up->up_msleep == 0) {
+		/* re-wakeup */
+		cv_signal(&up->up_cv);
+	}
+}
diff --git a/sys/dev/usb/usb_process.h b/sys/dev/usb/usb_process.h
index c717dc1522b..b4159af1bbd 100644
--- a/sys/dev/usb/usb_process.h
+++ b/sys/dev/usb/usb_process.h
@@ -49,7 +49,11 @@ struct usb_process {
 	struct cv up_cv;
 	struct cv up_drain;
 
+#if (__FreeBSD_version >= 800000)
+	struct thread *up_ptr;
+#else
 	struct proc *up_ptr;
+#endif
 	struct thread *up_curtd;
 	struct mtx *up_mtx;
 
@@ -71,5 +75,6 @@ void	usb_proc_drain(struct usb_process *up);
 void	usb_proc_mwait(struct usb_process *up, void *pm0, void *pm1);
 void	usb_proc_free(struct usb_process *up);
 void   *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1);
+void	usb_proc_rewakeup(struct usb_process *up);
 
 #endif					/* _USB_PROCESS_H_ */
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 3c466fb72d3..8daf475a4b8 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -2907,13 +2907,9 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
 		}
 
 		/* Make sure cv_signal() and cv_broadcast() is not called */
-		udev->bus->control_xfer_proc.up_dsleep = 0;
 		udev->bus->control_xfer_proc.up_msleep = 0;
-		udev->bus->explore_proc.up_dsleep = 0;
 		udev->bus->explore_proc.up_msleep = 0;
-		udev->bus->giant_callback_proc.up_dsleep = 0;
 		udev->bus->giant_callback_proc.up_msleep = 0;
-		udev->bus->non_giant_callback_proc.up_dsleep = 0;
 		udev->bus->non_giant_callback_proc.up_msleep = 0;
 
 		/* poll USB hardware */
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 288750c935e..3cb6a3ae82a 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -360,6 +360,7 @@ vendor SMC		0x0707	Standard Microsystems
 vendor PUTERCOM		0x0708	Putercom
 vendor MCT		0x0711	MCT
 vendor IMATION		0x0718	Imation
+vendor TECLAST		0x071b	Teclast
 vendor SONYERICSSON	0x0731	Sony Ericsson
 vendor EICON		0x0734	Eicon Networks
 vendor SYNTECH		0x0745	Syntech Information
@@ -585,6 +586,7 @@ vendor NETGEAR3		0x1385	Netgear
 vendor BALTECH		0x13ad	Baltech
 vendor CISCOLINKSYS	0x13b1	Cisco-Linksys
 vendor SHARK		0x13d2	Shark
+vendor EMTEC		0x13fe	Emtec
 vendor NOVATEL		0x1410	Novatel Wireless
 vendor MERLIN		0x1416	Merlin
 vendor WISTRONNEWEB	0x1435	Wistron NeWeb
@@ -820,6 +822,7 @@ product AKS USBHASP		0x0001	USB-HASP 0.06
 /* Alcor Micro, Inc. products */
 product ALCOR2 KBD_HUB		0x2802	Kbd Hub
 
+product ALCOR SDCR_6335		0x6335	SD/MMC Card Reader
 product ALCOR TRANSCEND		0x6387	Transcend JetFlash Drive
 product ALCOR MA_KBD_HUB	0x9213	MacAlly Kbd Hub
 product ALCOR AU9814		0x9215	AU9814 Hub
@@ -861,6 +864,12 @@ product APC UPS			0x0002	Uninterruptible Power Supply
 
 /* Apple Computer products */
 product APPLE EXT_KBD		0x020c	Apple Extended USB Keyboard
+product APPLE KBD_TP_ANSI	0x0223	Apple Internal Keyboard/Trackpad (Wellspring/ANSI)
+product APPLE KBD_TP_ISO	0x0224	Apple Internal Keyboard/Trackpad (Wellspring/ISO)
+product APPLE KBD_TP_JIS	0x0225	Apple Internal Keyboard/Trackpad (Wellspring/JIS)
+product APPLE KBD_TP_ANSI2	0x0230	Apple Internal Keyboard/Trackpad (Wellspring2/ANSI)
+product APPLE KBD_TP_ISO2	0x0231	Apple Internal Keyboard/Trackpad (Wellspring2/ISO)
+product APPLE KBD_TP_JIS2	0x0232	Apple Internal Keyboard/Trackpad (Wellspring2/JIS)
 product APPLE OPTMOUSE		0x0302	Optical mouse
 product APPLE MIGHTYMOUSE	0x0304	Mighty Mouse
 product APPLE EXT_KBD_HUB	0x1003	Hub in Apple Extended USB Keyboard
@@ -902,6 +911,7 @@ product ASUS RT2573_1		0x1723	RT2573
 product ASUS RT2573_2		0x1724	RT2573
 product ASUS LCM		0x1726	LCM display
 product ASUS P535		0x420f	ASUS P535 PDA
+product	ASUS GMSC		0x422f	ASUS Generic Mass Storage
 
 /* ATen products */
 product ATEN UC1284		0x2001	Parallel printer
@@ -1971,6 +1981,7 @@ product PHILIPS HUB		0x0201	hub
 product PHILIPS PCA646VC	0x0303	PCA646VC PC Camera
 product PHILIPS PCVC680K	0x0308	PCVC680K Vesta Pro PC Camera
 product PHILIPS DSS150		0x0471	DSS 150 Digital Speaker System
+product PHILIPS SPE3030CC	0x083a	USB 2.0 External Disk
 product PHILIPS SNU5600		0x1236	SNU5600
 product PHILIPS UM10016		0x1552	ISP 1581 Hi-Speed USB MPEG2 Encoder Reference Kit
 product PHILIPS DIVAUSB		0x1801	DIVA USB mp3 player
@@ -2345,6 +2356,9 @@ product SUN KBD_HUB		0x100e	Kbd Hub
 /* Super Top products */
 product	SUPERTOP IDE		0x6600	USB-IDE
 
+/* Teclast products */
+product TECLAST TLC300		0x3203	USB Media Player
+
 /* Supra products */
 product DIAMOND2 SUPRAEXPRESS56K 0x07da	Supra Express 56K modem
 product DIAMOND2 SUPRA2890	0x0b4a	SupraMax 2890 56K Modem
diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c
index 8714645450e..c04c3985b5b 100644
--- a/sys/dev/usb/wlan/if_upgt.c
+++ b/sys/dev/usb/wlan/if_upgt.c
@@ -465,7 +465,6 @@ upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:
-		newbus_xlock();
 		if (ifp->if_flags & IFF_UP) {
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 				if ((ifp->if_flags ^ sc->sc_if_flags) &
@@ -482,7 +481,6 @@ upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 		sc->sc_if_flags = ifp->if_flags;
 		if (startall)
 			ieee80211_start_all(ic);
-		newbus_xunlock();
 		break;
 	case SIOCGIFMEDIA:
 		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c
index 9bdb6eaaf16..493c5fad16a 100644
--- a/sys/dev/usb/wlan/if_zyd.c
+++ b/sys/dev/usb/wlan/if_zyd.c
@@ -2547,7 +2547,7 @@ zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
 
 	bits = (rate == 11) ? (totlen * 16) + 10 :
 	    ((rate == 22) ? (totlen * 8) + 10 : (totlen * 8));
-	desc->plcp_length = bits / ratediv[phy];
+	desc->plcp_length = htole16(bits / ratediv[phy]);
 	desc->plcp_service = 0;
 	if (rate == 22 && (bits % 11) > 0 && (bits % 11) <= 3)
 		desc->plcp_service |= ZYD_PLCP_LENGEXT;
diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c
index 535b1e078bc..259f2f6c041 100644
--- a/sys/dev/xen/blkback/blkback.c
+++ b/sys/dev/xen/blkback/blkback.c
@@ -1156,7 +1156,7 @@ vbd_add_dev(struct xenbus_device *xdev)
 	devclass_t dc;
 	int err = 0;
 
-	newbus_xlock();
+	mtx_lock(&Giant);
 
 	/* We will add a vbd device as a child of nexus0 (for now) */
 	if (!(dc = devclass_find("nexus")) ||
@@ -1183,7 +1183,7 @@ vbd_add_dev(struct xenbus_device *xdev)
 
  done:
 
-	newbus_xunlock();
+	mtx_unlock(&Giant);
 
 	return err;
 }
diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c
index f73c81239f4..8487e8e35f4 100644
--- a/sys/dev/xen/blkfront/blkfront.c
+++ b/sys/dev/xen/blkfront/blkfront.c
@@ -16,7 +16,9 @@
  */
 
 /*
- * XenoBSD block device driver
+ * XenBSD block device driver
+ *
+ * Copyright (c) 2009 Frank Suchomel, Citrix
  */
 
 #include 
@@ -122,6 +124,10 @@ static int blkif_ioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct
 static int blkif_queue_request(struct bio *bp);
 static void xb_strategy(struct bio *bp);
 
+// In order to quiesce the device during kernel dumps, outstanding requests to
+// DOM0 for disk reads/writes need to be accounted for.
+static	int	blkif_queued_requests;
+static	int	xb_dump(void *, void *, vm_offset_t, off_t, size_t);
 
 
 /* XXX move to xb_vbd.c when VBD update support is added */
@@ -231,6 +237,7 @@ xlvbd_add(device_t dev, blkif_sector_t capacity,
 	sc->xb_disk->d_close = blkif_close;
 	sc->xb_disk->d_ioctl = blkif_ioctl;
 	sc->xb_disk->d_strategy = xb_strategy;
+	sc->xb_disk->d_dump = xb_dump;
 	sc->xb_disk->d_name = name;
 	sc->xb_disk->d_drv1 = sc;
 	sc->xb_disk->d_sectorsize = sector_size;
@@ -286,9 +293,10 @@ xb_strategy(struct bio *bp)
 	 * Place it in the queue of disk activities for this disk
 	 */
 	mtx_lock(&blkif_io_lock);
-	bioq_disksort(&sc->xb_bioq, bp);
 
+	bioq_disksort(&sc->xb_bioq, bp);
 	xb_startio(sc);
+
 	mtx_unlock(&blkif_io_lock);
 	return;
 
@@ -301,6 +309,81 @@ xb_strategy(struct bio *bp)
 	return;
 }
 
+static void xb_quiesce(struct blkfront_info *info);
+// Quiesce the disk writes for a dump file before allowing the next buffer.
+static void
+xb_quiesce(struct blkfront_info *info)
+{
+	int		mtd;
+
+	// While there are outstanding requests
+	while (blkif_queued_requests) {
+		RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, mtd);
+		if (mtd) {
+			// Recieved request completions, update queue.
+			blkif_int(info);
+		}
+		if (blkif_queued_requests) {
+			// Still pending requests, wait for the disk i/o to complete
+			HYPERVISOR_block();
+		}
+	}
+}
+
+// Some bio structures for dumping core
+#define DUMP_BIO_NO 16				// 16 * 4KB = 64KB dump block
+static	struct bio		xb_dump_bp[DUMP_BIO_NO];
+
+// Kernel dump function for a paravirtualized disk device
+static int
+xb_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
+        size_t length)
+{
+			int				 sbp;
+  			int			     mbp;
+			size_t			 chunk;
+	struct	disk   			*dp = arg;
+	struct	xb_softc		*sc = (struct xb_softc *) dp->d_drv1;
+	        int	    		 rc = 0;
+
+	xb_quiesce(sc->xb_info);		// All quiet on the western front.
+	if (length > 0) {
+		// If this lock is held, then this module is failing, and a successful
+		// kernel dump is highly unlikely anyway.
+		mtx_lock(&blkif_io_lock);
+		// Split the 64KB block into 16 4KB blocks
+		for (sbp=0; length>0 && sbp PAGE_SIZE ? PAGE_SIZE : length;
+			xb_dump_bp[sbp].bio_disk   = dp;
+			xb_dump_bp[sbp].bio_pblkno = offset / dp->d_sectorsize;
+			xb_dump_bp[sbp].bio_bcount = chunk;
+			xb_dump_bp[sbp].bio_resid  = chunk;
+			xb_dump_bp[sbp].bio_data   = virtual;
+			xb_dump_bp[sbp].bio_cmd    = BIO_WRITE;
+			xb_dump_bp[sbp].bio_done   = NULL;
+
+			bioq_disksort(&sc->xb_bioq, &xb_dump_bp[sbp]);
+
+			length -= chunk;
+			offset += chunk;
+			virtual = (char *) virtual + chunk;
+		}
+		// Tell DOM0 to do the I/O
+		xb_startio(sc);
+		mtx_unlock(&blkif_io_lock);
+
+		// Must wait for the completion: the dump routine reuses the same
+		//                               16 x 4KB buffer space.
+		xb_quiesce(sc->xb_info);	// All quite on the eastern front
+		// If there were any errors, bail out...
+		for (mbp=0; mbp RING_SIZE", nfree));
 	info->shadow_free = info->shadow[nfree].req.id;
 	info->shadow[nfree].req.id = 0x0fffffee; /* debug */
+	atomic_add_int(&blkif_queued_requests, 1);
 	return nfree;
 }
 
@@ -655,6 +739,7 @@ ADD_ID_TO_FREELIST(struct blkfront_info *info, unsigned long id)
 	info->shadow[id].req.id  = info->shadow_free;
 	info->shadow[id].request = 0;
 	info->shadow_free = id;
+	atomic_subtract_int(&blkif_queued_requests, 1);
 }
 
 static inline void 
diff --git a/sys/dev/xen/console/console.c b/sys/dev/xen/console/console.c
index 68bb0aecf85..df5c3ee5907 100644
--- a/sys/dev/xen/console/console.c
+++ b/sys/dev/xen/console/console.c
@@ -45,17 +45,15 @@ static int xc_mute;
 static void xcons_force_flush(void);
 static void xencons_priv_interrupt(void *);
 
-static cn_probe_t       xccnprobe;
-static cn_init_t        xccninit;
-static cn_getc_t        xccngetc;
-static cn_putc_t        xccnputc;
-static cn_putc_t        xccnputc_dom0;
-static cn_checkc_t      xccncheckc;
+static cn_probe_t       xc_cnprobe;
+static cn_init_t        xc_cninit;
+static cn_term_t        xc_cnterm;
+static cn_getc_t        xc_cngetc;
+static cn_putc_t        xc_cnputc;
 
 #define XC_POLLTIME 	(hz/10)
 
-CONS_DRIVER(xc, xccnprobe, xccninit, NULL, xccngetc, 
-	    xccncheckc, xccnputc, NULL);
+CONSOLE_DRIVER(xc);
 
 static int xen_console_up;
 static boolean_t xc_start_needed;
@@ -105,7 +103,7 @@ static struct ttydevsw xc_ttydevsw = {
 };
 
 static void
-xccnprobe(struct consdev *cp)
+xc_cnprobe(struct consdev *cp)
 {
 	cp->cn_pri = CN_REMOTE;
 	sprintf(cp->cn_name, "%s0", driver_name);
@@ -113,37 +111,19 @@ xccnprobe(struct consdev *cp)
 
 
 static void
-xccninit(struct consdev *cp)
+xc_cninit(struct consdev *cp)
 { 
 	CN_LOCK_INIT(cn_mtx,"XCONS LOCK");
 
 }
-int
-xccngetc(struct consdev *dev)
-{
-	int c;
-	if (xc_mute)
-	    	return 0;
-	do {
-		if ((c = xccncheckc(dev)) == -1) {
-#ifdef KDB
-			if (!kdb_active)
-#endif
-				/*
-				 * Polling without sleeping in Xen
-				 * doesn't work well.  Sleeping gives
-				 * other things like clock a chance to
-				 * run
-				 */
-				tsleep(&cn_mtx, PWAIT | PCATCH,
-				    "console sleep", XC_POLLTIME);
-		}
-	} while(c == -1);
-	return c;
+
+static void
+xc_cnterm(struct consdev *cp)
+{ 
 }
 
-int
-xccncheckc(struct consdev *dev)
+static int
+xc_cngetc(struct consdev *dev)
 {
 	int ret = (xc_mute ? 0 : -1);
 
@@ -162,17 +142,27 @@ xccncheckc(struct consdev *dev)
 }
 
 static void
-xccnputc(struct consdev *dev, int c)
+xc_cnputc_domu(struct consdev *dev, int c)
 {
 	xcons_putc(c);
 }
 
 static void
-xccnputc_dom0(struct consdev *dev, int c)
+xc_cnputc_dom0(struct consdev *dev, int c)
 {
 	HYPERVISOR_console_io(CONSOLEIO_write, 1, (char *)&c);
 }
 
+static void
+xc_cnputc(struct consdev *dev, int c)
+{
+
+	if (xen_start_info->flags & SIF_INITDOMAIN)
+		xc_cnputc_dom0(dev, c);
+	else
+		xc_cnputc_domu(dev, c);
+}
+
 extern int db_active;
 static boolean_t
 xcons_putc(int c)
@@ -226,10 +216,6 @@ xc_attach(device_t dev)
 {
 	int error;
 
-	if (xen_start_info->flags & SIF_INITDOMAIN) {
-		xc_consdev.cn_putc = xccnputc_dom0;
-	} 
-
 	xccons = tty_alloc(&xc_ttydevsw, NULL);
 	tty_makedev(xccons, NULL, "xc%r", 0);
 
@@ -388,7 +374,7 @@ xc_timeout(void *v)
 	tp = (struct tty *)v;
 
 	tty_lock(tp);
-	while ((c = xccncheckc(NULL)) != -1)
+	while ((c = xc_cngetc(NULL)) != -1)
 		ttydisc_rint(tp, c, 0);
 
 	if (xc_start_needed) {
diff --git a/sys/dev/xen/netback/netback.c b/sys/dev/xen/netback/netback.c
index cabc4ab7241..a6111e265f5 100644
--- a/sys/dev/xen/netback/netback.c
+++ b/sys/dev/xen/netback/netback.c
@@ -1388,7 +1388,7 @@ vif_add_dev(struct xenbus_device *xdev)
 	devclass_t dc;
 	int err = 0;
 
-	newbus_xlock();
+	mtx_lock(&Giant);
 
 	/* We will add a vif device as a child of nexus0 (for now) */
 	if (!(dc = devclass_find("nexus")) ||
@@ -1415,7 +1415,7 @@ vif_add_dev(struct xenbus_device *xdev)
 
  done:
 
-	newbus_xunlock();
+	mtx_unlock(&Giant);
 
 	return err;
 }
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index 25436c70f45..5668f751d96 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -193,6 +193,9 @@ fifo_open(ap)
 			goto fail2;
 		fip->fi_writesock = wso;
 		error = soconnect2(wso, rso);
+		/* Close the direction we do not use, so we can get POLLHUP. */
+		if (error == 0)
+			error = soshutdown(rso, SHUT_WR);
 		if (error) {
 			(void)soclose(wso);
 fail2:
diff --git a/sys/fs/nfsclient/nfs_clsubs.c b/sys/fs/nfsclient/nfs_clsubs.c
index 7ae2860f380..a217a21513a 100644
--- a/sys/fs/nfsclient/nfs_clsubs.c
+++ b/sys/fs/nfsclient/nfs_clsubs.c
@@ -129,28 +129,25 @@ int
 ncl_upgrade_vnlock(struct vnode *vp)
 {
 	int old_lock;
-	
- 	if ((old_lock = VOP_ISLOCKED(vp)) != LK_EXCLUSIVE) {
- 		if (old_lock == LK_SHARED) {
- 			/* Upgrade to exclusive lock, this might block */
- 			vn_lock(vp, LK_UPGRADE | LK_RETRY);
- 		} else {
- 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- 		}
+
+	ASSERT_VOP_LOCKED(vp, "ncl_upgrade_vnlock");
+	old_lock = VOP_ISLOCKED(vp);
+	if (old_lock != LK_EXCLUSIVE) {
+		KASSERT(old_lock == LK_SHARED,
+		    ("ncl_upgrade_vnlock: wrong old_lock %d", old_lock));
+		/* Upgrade to exclusive lock, this might block */
+		vn_lock(vp, LK_UPGRADE | LK_RETRY);
   	}
-	return old_lock;
+	return (old_lock);
 }
 
 void
 ncl_downgrade_vnlock(struct vnode *vp, int old_lock)
 {
 	if (old_lock != LK_EXCLUSIVE) {
- 		if (old_lock == LK_SHARED) {
- 			/* Downgrade from exclusive lock, this might block */
- 			vn_lock(vp, LK_DOWNGRADE);
- 		} else {
- 			VOP_UNLOCK(vp, 0);
- 		}
+		KASSERT(old_lock == LK_SHARED, ("wrong old_lock %d", old_lock));
+		/* Downgrade from exclusive lock. */
+		vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
   	}
 }
 
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 219c62e8c2f..5dc3a593458 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -1405,8 +1405,8 @@ again:
 	}
 	mtx_unlock(&dnp->n_mtx);
 
-	CURVNET_SET(P_TO_VNET(&proc0));
 #ifdef INET
+	CURVNET_SET(CRED_TO_VNET(cnp->cn_cred));
 	IN_IFADDR_RLOCK();
 	if (!TAILQ_EMPTY(&V_in_ifaddrhead))
 		cverf.lval[0] = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr.s_addr;
@@ -1415,9 +1415,9 @@ again:
 		cverf.lval[0] = create_verf;
 #ifdef INET
 	IN_IFADDR_RUNLOCK();
+	CURVNET_RESTORE();
 #endif
 	cverf.lval[1] = ++create_verf;
-	CURVNET_RESTORE();
 	error = nfsrpc_create(dvp, cnp->cn_nameptr, cnp->cn_namelen,
 	    vap, cverf, fmode, cnp->cn_cred, cnp->cn_thread, &dnfsva, &nfsva,
 	    &nfhp, &attrflag, &dattrflag, NULL);
diff --git a/sys/fs/pseudofs/pseudofs_vncache.c b/sys/fs/pseudofs/pseudofs_vncache.c
index 31458707b58..035f2c79dd7 100644
--- a/sys/fs/pseudofs/pseudofs_vncache.c
+++ b/sys/fs/pseudofs/pseudofs_vncache.c
@@ -193,6 +193,7 @@ retry:
 	vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
 	error = insmntque(*vpp, mp);
 	if (error != 0) {
+		free(pvd, M_PFSVNCACHE);
 		*vpp = NULLVP;
 		return (error);
 	}
@@ -245,11 +246,13 @@ pfs_vncache_free(struct vnode *vp)
 	KASSERT(pvd != NULL, ("pfs_vncache_free(): no vnode data\n"));
 	if (pvd->pvd_next)
 		pvd->pvd_next->pvd_prev = pvd->pvd_prev;
-	if (pvd->pvd_prev)
+	if (pvd->pvd_prev) {
 		pvd->pvd_prev->pvd_next = pvd->pvd_next;
-	else if (pfs_vncache == pvd)
+		--pfs_vncache_entries;
+	} else if (pfs_vncache == pvd) {
 		pfs_vncache = pvd->pvd_next;
-	--pfs_vncache_entries;
+		--pfs_vncache_entries;
+	}
 	mtx_unlock(&pfs_vncache_mutex);
 
 	free(pvd, M_PFSVNCACHE);
diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index e03749b97c1..34ca500c985 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -339,7 +339,6 @@ pfs_getextattr(struct vop_getextattr_args *va)
 	if (proc != NULL)
 		PROC_UNLOCK(proc);
 
-	pfs_unlock(pn);
 	PFS_RETURN (error);
 }
 
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index b40dea07fcb..8b560abe37b 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -371,14 +371,14 @@ g_dev_strategy(struct bio *bp)
 	cp = dev->si_drv2;
 	KASSERT(cp->acr || cp->acw,
 	    ("Consumer with zero access count in g_dev_strategy"));
-
+#ifdef INVARIANTS
 	if ((bp->bio_offset % cp->provider->sectorsize) != 0 ||
 	    (bp->bio_bcount % cp->provider->sectorsize) != 0) {
 		bp->bio_resid = bp->bio_bcount;
 		biofinish(bp, NULL, EINVAL);
 		return;
 	}
-
+#endif
 	for (;;) {
 		/*
 		 * XXX: This is not an ideal solution, but I belive it to
diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c
index 20998bdd417..4cf3196d406 100644
--- a/sys/geom/geom_disk.c
+++ b/sys/geom/geom_disk.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -400,39 +401,25 @@ g_disk_destroy(void *ptr, int flag)
 }
 
 /*
- * We only allow [a-zA-Z0-9-_@#%.:] characters, the rest is converted to 'x'.
+ * We only allow printable characters in disk ident,
+ * the rest is converted to 'x'.
  */
 static void
 g_disk_ident_adjust(char *ident, size_t size)
 {
-	char newid[DISK_IDENT_SIZE], tmp[4];
-	size_t len;
-	char *p;
+	char *p, tmp[4], newid[DISK_IDENT_SIZE];
 
-	bzero(newid, sizeof(newid));
-	len = 0;
-	for (p = ident; *p != '\0' && len < sizeof(newid) - 1; p++) {
-		switch (*p) {
-		default:
-			if ((*p < 'a' || *p > 'z') &&
-			    (*p < 'A' || *p > 'Z') &&
-			    (*p < '0' || *p > '9')) {
-				snprintf(tmp, sizeof(tmp), "x%02hhx", *p);
-				strlcat(newid, tmp, sizeof(newid));
-				len += 3;
-				break;
-			}
-			/* FALLTHROUGH */
-		case '-':
-		case '_':
-		case '@':
-		case '#':
-		case '%':
-		case '.':
-		case ':':
-			newid[len++] = *p;
-			break;
+	newid[0] = '\0';
+	for (p = ident; *p != '\0'; p++) {
+		if (isprint(*p)) {
+			tmp[0] = *p;
+			tmp[1] = '\0';
+		} else {
+			snprintf(tmp, sizeof(tmp), "x%02hhx",
+			    *(unsigned char *)p);
 		}
+		if (strlcat(newid, tmp, sizeof(newid)) >= sizeof(newid))
+			break;
 	}
 	bzero(ident, size);
 	strlcpy(ident, newid, size);
diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c
index 61ca41c97ea..c95840a1a3b 100644
--- a/sys/geom/geom_io.c
+++ b/sys/geom/geom_io.c
@@ -567,7 +567,7 @@ g_io_schedule_down(struct thread *tp __unused)
 		if (bp == NULL) {
 			CTR0(KTR_GEOM, "g_down going to sleep");
 			msleep(&g_wait_down, &g_bio_run_down.bio_queue_lock,
-			    PRIBIO | PDROP, "-", hz/10);
+			    PRIBIO | PDROP, "-", 0);
 			continue;
 		}
 		CTR0(KTR_GEOM, "g_down has work to do");
@@ -672,7 +672,7 @@ g_io_schedule_up(struct thread *tp __unused)
 		}
 		CTR0(KTR_GEOM, "g_up going to sleep");
 		msleep(&g_wait_up, &g_bio_run_up.bio_queue_lock,
-		    PRIBIO | PDROP, "-", hz/10);
+		    PRIBIO | PDROP, "-", 0);
 	}
 }
 
diff --git a/sys/geom/geom_vfs.c b/sys/geom/geom_vfs.c
index a35cc2c7ba1..9d01f40c0f7 100644
--- a/sys/geom/geom_vfs.c
+++ b/sys/geom/geom_vfs.c
@@ -134,12 +134,10 @@ static void
 g_vfs_orphan(struct g_consumer *cp)
 {
 	struct g_geom *gp;
-	struct bufobj *bo;
 
 	g_topology_assert();
 
 	gp = cp->geom;
-	bo = gp->softc;
 	g_trace(G_T_TOPOLOGY, "g_vfs_orphan(%p(%s))", cp, gp->name);
 	if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
 		g_access(cp, -cp->acr, -cp->acw, -cp->ace);
diff --git a/sys/geom/mirror/g_mirror_ctl.c b/sys/geom/mirror/g_mirror_ctl.c
index 27e58ceb31c..4524a90d8dd 100644
--- a/sys/geom/mirror/g_mirror_ctl.c
+++ b/sys/geom/mirror/g_mirror_ctl.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004-2006 Pawel Jakub Dawidek 
+ * Copyright (c) 2004-2009 Pawel Jakub Dawidek 
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -93,19 +93,19 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp)
 {
 	struct g_mirror_softc *sc;
 	struct g_mirror_disk *disk;
-	const char *name, *balancep;
-	intmax_t *slicep;
+	const char *name, *balancep, *prov;
+	intmax_t *slicep, *priority;
 	uint32_t slice;
 	uint8_t balance;
 	int *autosync, *noautosync, *failsync, *nofailsync, *hardcode, *dynamic;
-	int *nargs, do_sync = 0, dirty = 1;
+	int *nargs, do_sync = 0, dirty = 1, do_priority = 0;
 
 	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
 	if (nargs == NULL) {
 		gctl_error(req, "No '%s' argument.", "nargs");
 		return;
 	}
-	if (*nargs != 1) {
+	if (*nargs != 1 && *nargs != 2) {
 		gctl_error(req, "Invalid number of arguments.");
 		return;
 	}
@@ -149,6 +149,29 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp)
 		gctl_error(req, "No '%s' argument.", "dynamic");
 		return;
 	}
+	priority = gctl_get_paraml(req, "priority", sizeof(*priority));
+	if (priority == NULL) {
+		gctl_error(req, "No '%s' argument.", "priority");
+		return;
+	}
+	if (*priority < -1 || *priority > 255) {
+		gctl_error(req, "Priority range is 0 to 255, %jd given",
+		    *priority);
+		return;
+	}
+	/* 
+	 * Since we have a priority, we also need a provider now.
+	 * Note: be WARNS safe, by always assigning prov and only throw an
+	 * error if *priority != -1.
+	 */
+	prov = gctl_get_asciiparam(req, "arg1");
+	if (*priority > -1) {
+		if (prov == NULL) {
+			gctl_error(req, "Priority needs a disk name");
+			return;
+		}
+		do_priority = 1;
+	}
 	if (*autosync && *noautosync) {
 		gctl_error(req, "'%s' and '%s' specified.", "autosync",
 		    "noautosync");
@@ -189,19 +212,32 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp)
 		slice = sc->sc_slice;
 	else
 		slice = *slicep;
-	if (g_mirror_ndisks(sc, -1) < sc->sc_ndisks) {
+	/* Enforce usage() of -p not allowing any other options. */
+	if (do_priority && (*autosync || *noautosync || *failsync ||
+	    *nofailsync || *hardcode || *dynamic || *slicep != -1 ||
+	    strcmp(balancep, "none") != 0)) {
 		sx_xunlock(&sc->sc_lock);
-		gctl_error(req, "Not all disks connected. Try 'forget' command "
-		    "first.");
+		gctl_error(req, "only -p accepted when setting priority");
 		return;
 	}
 	if (sc->sc_balance == balance && sc->sc_slice == slice && !*autosync &&
 	    !*noautosync && !*failsync && !*nofailsync && !*hardcode &&
-	    !*dynamic) {
+	    !*dynamic && !do_priority) {
 		sx_xunlock(&sc->sc_lock);
 		gctl_error(req, "Nothing has changed.");
 		return;
 	}
+	if ((!do_priority && *nargs != 1) || (do_priority && *nargs != 2)) {
+		sx_xunlock(&sc->sc_lock);
+		gctl_error(req, "Invalid number of arguments.");
+		return;
+	}
+	if (g_mirror_ndisks(sc, -1) < sc->sc_ndisks) {
+		sx_xunlock(&sc->sc_lock);
+		gctl_error(req, "Not all disks connected. Try 'forget' command "
+		    "first.");
+		return;
+	}
 	sc->sc_balance = balance;
 	sc->sc_slice = slice;
 	if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_NOAUTOSYNC) != 0) {
@@ -223,6 +259,23 @@ g_mirror_ctl_configure(struct gctl_req *req, struct g_class *mp)
 		}
 	}
 	LIST_FOREACH(disk, &sc->sc_disks, d_next) {
+		/*
+		 * Handle priority first, since we only need one disk, do one
+		 * operation on it and then we're done. No need to check other
+		 * flags, as usage doesn't allow it.
+		 */
+		if (do_priority) {
+			if (strcmp(disk->d_name, prov) == 0) {
+				if (disk->d_priority == *priority)
+					gctl_error(req, "Nothing has changed.");
+				else {
+					disk->d_priority = *priority;
+					g_mirror_update_metadata(disk);
+				}
+				break;
+			}
+			continue;
+		}
 		if (do_sync) {
 			if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING)
 				disk->d_flags &= ~G_MIRROR_DISK_FLAG_FORCE_SYNC;
diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c
index ca442bdc6a4..d24edb6f585 100644
--- a/sys/geom/multipath/g_multipath.c
+++ b/sys/geom/multipath/g_multipath.c
@@ -198,6 +198,7 @@ g_multipath_done_error(struct bio *bp)
 		if (sc->cp_active == NULL) {
 			printf("GEOM_MULTIPATH: out of providers for %s\n",
 			    sc->sc_name);
+			g_topology_unlock();
 			return;
 		} else {
 			printf("GEOM_MULTIPATH: %s now active path in %s\n",
@@ -294,10 +295,6 @@ g_multipath_create(struct g_class *mp, struct g_multipath_metadata *md)
 	}
 
 	sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
-	if (sc == NULL) {
-		goto fail;
-	}
-
 	gp->softc = sc;
 	gp->start = g_multipath_start;
 	gp->orphan = g_multipath_orphan;
diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index cfbd897f749..61f9c7aa257 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -409,9 +409,9 @@ g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp)
 	last = (pp->mediasize / pp->sectorsize) - 1;
 
 	le16enc(table->mbr + DOSMAGICOFFSET, DOSMAGIC);
-	table->mbr[DOSPARTOFF + 1] = 0xff;		/* shd */
-	table->mbr[DOSPARTOFF + 2] = 0xff;		/* ssect */
-	table->mbr[DOSPARTOFF + 3] = 0xff;		/* scyl */
+	table->mbr[DOSPARTOFF + 1] = 0x01;		/* shd */
+	table->mbr[DOSPARTOFF + 2] = 0x01;		/* ssect */
+	table->mbr[DOSPARTOFF + 3] = 0x00;		/* scyl */
 	table->mbr[DOSPARTOFF + 4] = 0xee;		/* typ */
 	table->mbr[DOSPARTOFF + 5] = 0xff;		/* ehd */
 	table->mbr[DOSPARTOFF + 6] = 0xff;		/* esect */
diff --git a/sys/geom/stripe/g_stripe.c b/sys/geom/stripe/g_stripe.c
index 88b0cad0483..17e258ce67b 100644
--- a/sys/geom/stripe/g_stripe.c
+++ b/sys/geom/stripe/g_stripe.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
 #include 
 
 
-#define	MAX_IO_SIZE	(DFLTPHYS * 2)
 static MALLOC_DEFINE(M_STRIPE, "stripe_data", "GEOM_STRIPE Data");
 
 static uma_zone_t g_stripe_zone;
@@ -87,7 +86,7 @@ g_sysctl_stripe_fast(SYSCTL_HANDLER_ARGS)
 }
 SYSCTL_PROC(_kern_geom_stripe, OID_AUTO, fast, CTLTYPE_INT | CTLFLAG_RW,
     NULL, 0, g_sysctl_stripe_fast, "I", "Fast, but memory-consuming, mode");
-static u_int g_stripe_maxmem = MAX_IO_SIZE * 100;
+static u_int g_stripe_maxmem = MAXPHYS * 100;
 TUNABLE_INT("kern.geom.stripe.maxmem", &g_stripe_maxmem);
 SYSCTL_UINT(_kern_geom_stripe, OID_AUTO, maxmem, CTLFLAG_RD, &g_stripe_maxmem,
     0, "Maximum memory that can be allocated in \"fast\" mode (in bytes)");
@@ -125,10 +124,10 @@ static void
 g_stripe_init(struct g_class *mp __unused)
 {
 
-	g_stripe_zone = uma_zcreate("g_stripe_zone", MAX_IO_SIZE, NULL, NULL,
+	g_stripe_zone = uma_zcreate("g_stripe_zone", MAXPHYS, NULL, NULL,
 	    NULL, NULL, 0, 0);
-	g_stripe_maxmem -= g_stripe_maxmem % MAX_IO_SIZE;
-	uma_zone_set_max(g_stripe_zone, g_stripe_maxmem / MAX_IO_SIZE);
+	g_stripe_maxmem -= g_stripe_maxmem % MAXPHYS;
+	uma_zone_set_max(g_stripe_zone, g_stripe_maxmem / MAXPHYS);
 }
 
 static void
@@ -613,14 +612,14 @@ g_stripe_start(struct bio *bp)
 	 * Do use "fast" mode when:
 	 * 1. "Fast" mode is ON.
 	 * and
-	 * 2. Request size is less than or equal to MAX_IO_SIZE (128kB),
+	 * 2. Request size is less than or equal to MAXPHYS,
 	 *    which should always be true.
 	 * and
 	 * 3. Request size is bigger than stripesize * ndisks. If it isn't,
 	 *    there will be no need to send more than one I/O request to
 	 *    a provider, so there is nothing to optmize.
 	 */
-	if (g_stripe_fast && bp->bio_length <= MAX_IO_SIZE &&
+	if (g_stripe_fast && bp->bio_length <= MAXPHYS &&
 	    bp->bio_length >= stripesize * sc->sc_ndisks) {
 		fast = 1;
 	}
diff --git a/sys/i386/acpica/acpi_machdep.c b/sys/i386/acpica/acpi_machdep.c
index 456867123b1..e26cce9a729 100644
--- a/sys/i386/acpica/acpi_machdep.c
+++ b/sys/i386/acpica/acpi_machdep.c
@@ -164,7 +164,6 @@ acpi_capm_get_info(apm_info_t aip)
 	else
 		aip->ai_acline = acline;	/* on/off */
 
-	newbus_slock();
 	if (acpi_battery_get_battinfo(NULL, &batt) != 0) {
 		aip->ai_batt_stat = APM_UNKNOWN;
 		aip->ai_batt_life = APM_UNKNOWN;
@@ -176,7 +175,6 @@ acpi_capm_get_info(apm_info_t aip)
 		aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60;
 		aip->ai_batteries = acpi_battery_get_units();
 	}
-	newbus_sunlock();
 
 	return (0);
 }
@@ -192,7 +190,6 @@ acpi_capm_get_pwstatus(apm_pwstatus_t app)
 	    (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL))
 		return (1);
 
-	newbus_slock();
 	if (app->ap_device == PMDV_ALLDEV)
 		error = acpi_battery_get_battinfo(NULL, &batt);
 	else {
@@ -203,7 +200,6 @@ acpi_capm_get_pwstatus(apm_pwstatus_t app)
 		else
 			error = ENXIO;
 	}
-	newbus_sunlock();
 	if (error)
 		return (1);
 
@@ -287,9 +283,7 @@ apmopen(struct cdev *dev, int flag, int fmt, struct thread *td)
 	struct	acpi_softc *acpi_sc;
 	struct 	apm_clone_data *clone;
 
-	newbus_slock();
 	acpi_sc = devclass_get_softc(devclass_find("acpi"), 0);
-	newbus_sunlock();
 	clone = apm_create_clone(dev, acpi_sc);
 	dev->si_drv1 = clone;
 
diff --git a/sys/i386/bios/smapi.c b/sys/i386/bios/smapi.c
index 74cf612182a..e572664e2ac 100644
--- a/sys/i386/bios/smapi.c
+++ b/sys/i386/bios/smapi.c
@@ -288,12 +288,10 @@ smapi_modevent (module_t mod, int what, void *arg)
 	case MOD_LOAD:
 		break;
 	case MOD_UNLOAD:
-		newbus_xlock();
 		devclass_get_devices(smapi_devclass, &devs, &count);
 		for (i = 0; i < count; i++) {
 			device_delete_child(device_get_parent(devs[i]), devs[i]);
 		}
-		newbus_xunlock();
 		break;
 	default:
 		break;
diff --git a/sys/i386/bios/smbios.c b/sys/i386/bios/smbios.c
index 37a3b2cd092..f38d9857399 100644
--- a/sys/i386/bios/smbios.c
+++ b/sys/i386/bios/smbios.c
@@ -230,12 +230,10 @@ smbios_modevent (mod, what, arg)
 	case MOD_LOAD:
 		break;
 	case MOD_UNLOAD:
-		newbus_xlock();
 		devclass_get_devices(smbios_devclass, &devs, &count);
 		for (i = 0; i < count; i++) {
 			device_delete_child(device_get_parent(devs[i]), devs[i]);
 		}
-		newbus_xunlock();
 		break;
 	default:
 		break;
diff --git a/sys/i386/bios/vpd.c b/sys/i386/bios/vpd.c
index f816121260f..246b76d3570 100644
--- a/sys/i386/bios/vpd.c
+++ b/sys/i386/bios/vpd.c
@@ -248,12 +248,10 @@ vpd_modevent (mod, what, arg)
 	case MOD_LOAD:
 		break;
 	case MOD_UNLOAD:
-		newbus_xlock();
 		devclass_get_devices(vpd_devclass, &devs, &count);
 		for (i = 0; i < count; i++) {
 			device_delete_child(device_get_parent(devs[i]), devs[i]);
 		}
-		newbus_xunlock();
 		break;
 	default:
 		break;
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index 02f5a36ddab..ef958af9a14 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -70,7 +70,6 @@ options 	P1003_1B_SEMAPHORES	# POSIX-style semaphores
 options 	_KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
 options 	PRINTF_BUFR_SIZE=128	# Prevent printf output being interspersed.
 options 	KBD_INSTALL_CDEV	# install a CDEV entry in /dev
-options 	STOP_NMI		# Stop CPUS using NMI instead of IPI
 options 	HWPMC_HOOKS		# Necessary kernel hooks for hwpmc(4)
 options 	AUDIT			# Security event auditing
 options 	MAC			# TrustedBSD MAC Framework
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index f442e2455e1..f772b25584d 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -49,7 +49,6 @@ options 	MP_WATCHDOG
 
 # Debugging options.
 #
-options 	STOP_NMI		# Stop CPUS using NMI instead of IPI
 options 	COUNT_XINVLTLB_HITS	# Counters for TLB events
 options 	COUNT_IPIS		# Per-CPU IPI interrupt counters
 
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
index b68a73ec3e6..abfe147769b 100644
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -108,6 +108,22 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
 	(sysinit_cfunc_t) elf32_insert_brand_entry,
 	&freebsd_brand_oinfo);
 
+static Elf32_Brandinfo kfreebsd_brand_info = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_386,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/lib/ld.so.1",
+	.sysvec		= &elf32_freebsd_sysvec,
+	.interp_newpath	= NULL,
+	.brand_note	= &elf32_kfreebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
+};
+
+SYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY,
+	(sysinit_cfunc_t) elf32_insert_brand_entry,
+	&kfreebsd_brand_info);
+
 
 void
 elf32_dump_thread(struct thread *td __unused, void *dst __unused,
diff --git a/sys/i386/i386/local_apic.c b/sys/i386/i386/local_apic.c
index 6b350e29794..9b1d1b3173e 100644
--- a/sys/i386/i386/local_apic.c
+++ b/sys/i386/i386/local_apic.c
@@ -123,7 +123,7 @@ static struct lvt lvts[LVT_MAX + 1] = {
 	{ 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 },	/* LINT1: NMI */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_TIMER_INT },	/* Timer */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_ERROR_INT },	/* Error */
-	{ 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 },	/* PMC */
+	{ 1, 1, 1, 1, APIC_LVT_DM_NMI, 0 },	/* PMC */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_THERMAL_INT },	/* Thermal */
 };
 
@@ -307,11 +307,9 @@ lapic_setup(int boot)
 	lapic->lvt_lint0 = lvt_mode(la, LVT_LINT0, lapic->lvt_lint0);
 	lapic->lvt_lint1 = lvt_mode(la, LVT_LINT1, lapic->lvt_lint1);
 
-#ifdef	HWPMC_HOOKS
 	/* Program the PMC LVT entry if present. */
 	if (maxlvt >= LVT_PMC)
 		lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
-#endif
 
 	/* Program timer LVT and setup handler. */
 	lapic->lvt_timer = lvt_mode(la, LVT_TIMER, lapic->lvt_timer);
@@ -334,6 +332,88 @@ lapic_setup(int boot)
 	intr_restore(eflags);
 }
 
+void
+lapic_reenable_pmc(void)
+{
+#ifdef HWPMC_HOOKS
+	uint32_t value;
+
+	value =  lapic->lvt_pcint;
+	value &= ~APIC_LVT_M;
+	lapic->lvt_pcint = value;
+#endif
+}
+
+#ifdef HWPMC_HOOKS
+static void
+lapic_update_pmc(void *dummy)
+{
+	struct lapic *la;
+
+	la = &lapics[lapic_id()];
+	lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
+}
+#endif
+
+int
+lapic_enable_pmc(void)
+{
+#ifdef HWPMC_HOOKS
+	u_int32_t maxlvt;
+
+	/* Fail if the local APIC is not present. */
+	if (lapic == NULL)
+		return (0);
+
+	/* Fail if the PMC LVT is not present. */
+	maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
+	if (maxlvt < LVT_PMC)
+		return (0);
+
+	lvts[LVT_PMC].lvt_masked = 0;
+
+#ifdef SMP
+	/*
+	 * If hwpmc was loaded at boot time then the APs may not be
+	 * started yet.  In that case, don't forward the request to
+	 * them as they will program the lvt when they start.
+	 */
+	if (smp_started)
+		smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL);
+	else
+#endif
+		lapic_update_pmc(NULL);
+	return (1);
+#else
+	return (0);
+#endif
+}
+
+void
+lapic_disable_pmc(void)
+{
+#ifdef HWPMC_HOOKS
+	u_int32_t maxlvt;
+
+	/* Fail if the local APIC is not present. */
+	if (lapic == NULL)
+		return;
+
+	/* Fail if the PMC LVT is not present. */
+	maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT;
+	if (maxlvt < LVT_PMC)
+		return;
+
+	lvts[LVT_PMC].lvt_masked = 1;
+
+#ifdef SMP
+	/* The APs should always be started when hwpmc is unloaded. */
+	KASSERT(mp_ncpus == 1 || smp_started, ("hwpmc unloaded too early"));
+#endif
+	smp_rendezvous(NULL, lapic_update_pmc, NULL, NULL);
+#endif
+}
+
 /*
  * Called by cpu_initclocks() on the BSP to setup the local APIC timer so
  * that it can drive hardclock, statclock, and profclock.  This function
@@ -914,18 +994,21 @@ apic_free_vector(u_int apic_id, u_int vector, u_int irq)
 	 * we don't lose an interrupt delivery race.
 	 */
 	td = curthread;
-	thread_lock(td);
-	if (sched_is_bound(td))
-		panic("apic_free_vector: Thread already bound.\n");
-	sched_bind(td, apic_cpuid(apic_id));
-	thread_unlock(td);
+	if (!rebooting) {
+		thread_lock(td);
+		if (sched_is_bound(td))
+			panic("apic_free_vector: Thread already bound.\n");
+		sched_bind(td, apic_cpuid(apic_id));
+		thread_unlock(td);
+	}
 	mtx_lock_spin(&icu_lock);
 	lapics[apic_id].la_ioint_irqs[vector - APIC_IO_INTS] = -1;
 	mtx_unlock_spin(&icu_lock);
-	thread_lock(td);
-	sched_unbind(td);
-	thread_unlock(td);
-
+	if (!rebooting) {
+		thread_lock(td);
+		sched_unbind(td);
+		thread_unlock(td);
+	}
 }
 
 /* Map an IDT vector (APIC) to an IRQ (interrupt source). */
@@ -1248,8 +1331,17 @@ lapic_ipi_vectored(u_int vector, int dest)
 	KASSERT((vector & ~APIC_VECTOR_MASK) == 0,
 	    ("%s: invalid vector %d", __func__, vector));
 
-	icrlo = vector | APIC_DELMODE_FIXED | APIC_DESTMODE_PHY |
-	    APIC_LEVEL_DEASSERT | APIC_TRIGMOD_EDGE;
+	icrlo = APIC_DESTMODE_PHY | APIC_TRIGMOD_EDGE;
+
+	/*
+	 * IPI_STOP_HARD is just a "fake" vector used to send a NMI.
+	 * Use special rules regard NMI if passed, otherwise specify
+	 * the vector.
+	 */
+	if (vector == IPI_STOP_HARD)
+		icrlo |= APIC_DELMODE_NMI | APIC_LEVEL_ASSERT;
+	else
+		icrlo |= vector | APIC_DELMODE_FIXED | APIC_LEVEL_DEASSERT;
 	destfield = 0;
 	switch (dest) {
 	case APIC_IPI_DEST_SELF:
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 1b24af39ce2..1a6b3c6015e 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -261,6 +261,7 @@ cpu_startup(dummy)
 		    strncmp(sysenv, "MacBook3,1", 10) == 0 ||
 		    strncmp(sysenv, "MacBookPro1,1", 13) == 0 ||
 		    strncmp(sysenv, "MacBookPro1,2", 13) == 0 ||
+		    strncmp(sysenv, "MacBookPro3,1", 13) == 0 ||
 		    strncmp(sysenv, "Macmini1,1", 10) == 0) {
 			if (bootverbose)
 				printf("Disabling LEGACY_USB_EN bit on "
@@ -279,19 +280,21 @@ cpu_startup(dummy)
 #ifdef PERFMON
 	perfmon_init();
 #endif
+	realmem = Maxmem;
+
+	/*
+	 * Display physical memory if SMBIOS reports reasonable amount.
+	 */
+	memsize = 0;
 	sysenv = getenv("smbios.memory.enabled");
 	if (sysenv != NULL) {
-		memsize = (uintmax_t)strtoul(sysenv, (char **)NULL, 10);
+		memsize = (uintmax_t)strtoul(sysenv, (char **)NULL, 10) << 10;
 		freeenv(sysenv);
-	} else
-		memsize = 0;
-	if (memsize > 0)
-		printf("real memory  = %ju (%ju MB)\n", memsize << 10,
-		    memsize >> 10);
-	else
-		printf("real memory  = %ju (%ju MB)\n", ptoa((uintmax_t)Maxmem),
-		    ptoa((uintmax_t)Maxmem) / 1048576);
-	realmem = Maxmem;
+	}
+	if (memsize < ptoa((uintmax_t)cnt.v_free_count))
+		memsize = ptoa((uintmax_t)Maxmem);
+	printf("real memory  = %ju (%ju MB)\n", memsize, memsize >> 20);
+
 	/*
 	 * Display any holes after the first chunk of extended memory.
 	 */
@@ -2567,7 +2570,7 @@ init386(first)
 	default_proc_ldt.ldt_base = (caddr_t)ldt;
 	default_proc_ldt.ldt_len = 6;
 	_default_ldt = (int)&default_proc_ldt;
-	PCPU_SET(currentldt, _default_ldt)
+	PCPU_SET(currentldt, _default_ldt);
 	PT_SET_MA(ldt, *vtopte((unsigned long)ldt) & ~PG_RW);
 	xen_set_ldt((unsigned long) ldt, (sizeof ldt_segs / sizeof ldt_segs[0]));
 	
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index 0bfe91d7cff..6729288d69c 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -155,12 +155,6 @@ vm_offset_t smp_tlb_addr1;
 vm_offset_t smp_tlb_addr2;
 volatile int smp_tlb_wait;
 
-#ifdef STOP_NMI
-static volatile cpumask_t ipi_nmi_pending;
-
-static void	ipi_nmi_selected(cpumask_t cpus);
-#endif 
-
 #ifdef COUNT_IPIS
 /* Interrupt counts. */
 static u_long *ipi_preempt_counts[MAXCPU];
@@ -177,21 +171,8 @@ u_long *ipi_lazypmap_counts[MAXCPU];
  * Local data and functions.
  */
 
-#ifdef STOP_NMI
-/* 
- * Provide an alternate method of stopping other CPUs. If another CPU has
- * disabled interrupts the conventional STOP IPI will be blocked. This 
- * NMI-based stop should get through in that case.
- */
-static int stop_cpus_with_nmi = 1;
-SYSCTL_INT(_debug, OID_AUTO, stop_cpus_with_nmi, CTLTYPE_INT | CTLFLAG_RW,
-    &stop_cpus_with_nmi, 0, "");
-TUNABLE_INT("debug.stop_cpus_with_nmi", &stop_cpus_with_nmi);
-#else
-#define	stop_cpus_with_nmi	0
-#endif
-
 static u_int logical_cpus;
+static volatile cpumask_t ipi_nmi_pending;
 
 /* used to hold the AP's until we are ready to release them */
 static struct mtx ap_boot_mtx;
@@ -1318,12 +1299,14 @@ ipi_selected(cpumask_t cpus, u_int ipi)
 		ipi = IPI_BITMAP_VECTOR;
 	}
 
-#ifdef STOP_NMI
-	if (ipi == IPI_STOP && stop_cpus_with_nmi) {
-		ipi_nmi_selected(cpus);
-		return;
-	}
-#endif
+	/*
+	 * IPI_STOP_HARD maps to a NMI and the trap handler needs a bit
+	 * of help in order to understand what is the source.
+	 * Set the mask of receiving CPUs for this purpose.
+	 */
+	if (ipi == IPI_STOP_HARD)
+		atomic_set_int(&ipi_nmi_pending, cpus);
+
 	CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi);
 	while ((cpu = ffs(cpus)) != 0) {
 		cpu--;
@@ -1354,64 +1337,42 @@ void
 ipi_all_but_self(u_int ipi)
 {
 
-	if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
+	if (IPI_IS_BITMAPED(ipi)) {
 		ipi_selected(PCPU_GET(other_cpus), ipi);
 		return;
 	}
+
+	/*
+	 * IPI_STOP_HARD maps to a NMI and the trap handler needs a bit
+	 * of help in order to understand what is the source.
+	 * Set the mask of receiving CPUs for this purpose.
+	 */
+	if (ipi == IPI_STOP_HARD)
+		atomic_set_int(&ipi_nmi_pending, PCPU_GET(other_cpus));
 	CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
 	lapic_ipi_vectored(ipi, APIC_IPI_DEST_OTHERS);
 }
 
-#ifdef STOP_NMI
-/*
- * send NMI IPI to selected CPUs
- */
-
-#define	BEFORE_SPIN	1000000
-
-void
-ipi_nmi_selected(cpumask_t cpus)
-{
-	int cpu;
-	register_t icrlo;
-
-	icrlo = APIC_DELMODE_NMI | APIC_DESTMODE_PHY | APIC_LEVEL_ASSERT 
-		| APIC_TRIGMOD_EDGE; 
-	
-	CTR2(KTR_SMP, "%s: cpus: %x nmi", __func__, cpus);
-
-	atomic_set_int(&ipi_nmi_pending, cpus);
-
-	while ((cpu = ffs(cpus)) != 0) {
-		cpu--;
-		cpus &= ~(1 << cpu);
-
-		KASSERT(cpu_apic_ids[cpu] != -1,
-		    ("IPI NMI to non-existent CPU %d", cpu));
-		
-		/* Wait for an earlier IPI to finish. */
-		if (!lapic_ipi_wait(BEFORE_SPIN))
-			panic("ipi_nmi_selected: previous IPI has not cleared");
-
-		lapic_ipi_raw(icrlo, cpu_apic_ids[cpu]);
-	}
-}
-
 int
-ipi_nmi_handler(void)
+ipi_nmi_handler()
 {
-	int cpumask = PCPU_GET(cpumask);
+	cpumask_t cpumask;
 
-	if (!(ipi_nmi_pending & cpumask))
-		return 1;
+	/*
+	 * As long as there is not a simple way to know about a NMI's
+	 * source, if the bitmask for the current CPU is present in
+	 * the global pending bitword an IPI_STOP_HARD has been issued
+	 * and should be handled.
+	 */
+	cpumask = PCPU_GET(cpumask);
+	if ((ipi_nmi_pending & cpumask) == 0)
+		return (1);
 
 	atomic_clear_int(&ipi_nmi_pending, cpumask);
 	cpustop_handler();
-	return 0;
+	return (0);
 }
 
-#endif /* STOP_NMI */
-
 /*
  * Handle an IPI_STOP by saving our current context and spinning until we
  * are resumed.
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index c6f1d5fe2a4..9b832aefc95 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -212,7 +212,7 @@ pt_entry_t pg_nx;
 static uma_zone_t pdptzone;
 #endif
 
-static int pat_works;			/* Is page attribute table sane? */
+static int pat_works = 0;		/* Is page attribute table sane? */
 
 SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
 
@@ -288,12 +288,15 @@ static boolean_t pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m,
 static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va,
     vm_page_t m, vm_prot_t prot, vm_page_t mpte);
 static void pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte);
+static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte);
 static boolean_t pmap_is_modified_pvh(struct md_page *pvh);
 static void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode);
 static vm_page_t pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va);
+static void pmap_pde_attr(pd_entry_t *pde, int cache_bits);
 static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va);
 static boolean_t pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva,
     vm_prot_t prot);
+static void pmap_pte_attr(pt_entry_t *pte, int cache_bits);
 static void pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva,
     vm_page_t *free);
 static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t sva,
@@ -475,40 +478,69 @@ void
 pmap_init_pat(void)
 {
 	uint64_t pat_msr;
+	char *sysenv;
+	static int pat_tested = 0;
 
 	/* Bail if this CPU doesn't implement PAT. */
 	if (!(cpu_feature & CPUID_PAT))
 		return;
 
-	if (cpu_vendor_id != CPU_VENDOR_INTEL ||
-	    (I386_CPU_FAMILY(cpu_id) == 6 && I386_CPU_MODEL(cpu_id) >= 0xe)) {
+	/*
+	 * Due to some Intel errata, we can only safely use the lower 4
+	 * PAT entries.
+	 *
+	 *   Intel Pentium III Processor Specification Update
+	 * Errata E.27 (Upper Four PAT Entries Not Usable With Mode B
+	 * or Mode C Paging)
+	 *
+	 *   Intel Pentium IV  Processor Specification Update
+	 * Errata N46 (PAT Index MSB May Be Calculated Incorrectly)
+	 *
+	 * Some Apple Macs based on nVidia chipsets cannot enter ACPI mode
+	 * via SMI# when we use upper 4 PAT entries for unknown reason.
+	 */
+	if (!pat_tested) {
+		if (cpu_vendor_id != CPU_VENDOR_INTEL ||
+		    (I386_CPU_FAMILY(cpu_id) == 6 &&
+		    I386_CPU_MODEL(cpu_id) >= 0xe)) {
+			pat_works = 1;
+			sysenv = getenv("smbios.system.product");
+			if (sysenv != NULL) {
+				if (strncmp(sysenv, "MacBook5,1", 10) == 0 ||
+				    strncmp(sysenv, "MacBookPro5,5", 13) == 0 ||
+				    strncmp(sysenv, "Macmini3,1", 10) == 0)
+					pat_works = 0;
+				freeenv(sysenv);
+			}
+		}
+		pat_tested = 1;
+	}
+
+	/* Initialize default PAT entries. */
+	pat_msr = PAT_VALUE(0, PAT_WRITE_BACK) |
+	    PAT_VALUE(1, PAT_WRITE_THROUGH) |
+	    PAT_VALUE(2, PAT_UNCACHED) |
+	    PAT_VALUE(3, PAT_UNCACHEABLE) |
+	    PAT_VALUE(4, PAT_WRITE_BACK) |
+	    PAT_VALUE(5, PAT_WRITE_THROUGH) |
+	    PAT_VALUE(6, PAT_UNCACHED) |
+	    PAT_VALUE(7, PAT_UNCACHEABLE);
+
+	if (pat_works) {
 		/*
-		 * Leave the indices 0-3 at the default of WB, WT, UC, and UC-.
+		 * Leave the indices 0-3 at the default of WB, WT, UC-, and UC.
 		 * Program 4 and 5 as WP and WC.
-		 * Leave 6 and 7 as UC and UC-.
+		 * Leave 6 and 7 as UC- and UC.
 		 */
-		pat_msr = rdmsr(MSR_PAT);
 		pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
 		pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
 		    PAT_VALUE(5, PAT_WRITE_COMBINING);
-		pat_works = 1;
 	} else {
 		/*
-		 * Due to some Intel errata, we can only safely use the lower 4
-		 * PAT entries.  Thus, just replace PAT Index 2 with WC instead
-		 * of UC-.
-		 *
-		 *   Intel Pentium III Processor Specification Update
-		 * Errata E.27 (Upper Four PAT Entries Not Usable With Mode B
-		 * or Mode C Paging)
-		 *
-		 *   Intel Pentium IV  Processor Specification Update
-		 * Errata N46 (PAT Index MSB May Be Calculated Incorrectly)
+		 * Just replace PAT Index 2 with WC instead of UC-.
 		 */
-		pat_msr = rdmsr(MSR_PAT);
 		pat_msr &= ~PAT_MASK(2);
 		pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
-		pat_works = 0;
 	}
 	wrmsr(MSR_PAT, pat_msr);
 }
@@ -967,8 +999,8 @@ pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva)
 		 * coherence domain.
 		 */
 		mfence();
-		for (; eva < sva; eva += cpu_clflush_line_size)
-			clflush(eva);
+		for (; sva < eva; sva += cpu_clflush_line_size)
+			clflush(sva);
 		mfence();
 	} else {
 
@@ -2289,32 +2321,62 @@ pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
 }
 
 /*
- * Tries to demote a 2- or 4MB page mapping.
+ * Fills a page table page with mappings to consecutive physical pages.
+ */
+static void
+pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte)
+{
+	pt_entry_t *pte;
+
+	for (pte = firstpte; pte < firstpte + NPTEPG; pte++) {
+		*pte = newpte;	
+		newpte += PAGE_SIZE;
+	}
+}
+
+/*
+ * Tries to demote a 2- or 4MB page mapping.  If demotion fails, the
+ * 2- or 4MB page mapping is invalidated.
  */
 static boolean_t
 pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va)
 {
 	pd_entry_t newpde, oldpde;
 	pmap_t allpmaps_entry;
-	pt_entry_t *firstpte, newpte, *pte;
+	pt_entry_t *firstpte, newpte;
 	vm_paddr_t mptepa;
 	vm_page_t free, mpte;
 
 	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+	oldpde = *pde;
+	KASSERT((oldpde & (PG_PS | PG_V)) == (PG_PS | PG_V),
+	    ("pmap_demote_pde: oldpde is missing PG_PS and/or PG_V"));
 	mpte = pmap_lookup_pt_page(pmap, va);
 	if (mpte != NULL)
 		pmap_remove_pt_page(pmap, mpte);
 	else {
-		KASSERT((*pde & PG_W) == 0,
+		KASSERT((oldpde & PG_W) == 0,
 		    ("pmap_demote_pde: page table page for a wired mapping"
 		    " is missing"));
-		free = NULL;
-		pmap_remove_pde(pmap, pde, trunc_4mpage(va), &free);
-		pmap_invalidate_page(pmap, trunc_4mpage(va));
-		pmap_free_zero_pages(free);
-		CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#x"
-		    " in pmap %p", va, pmap);
-		return (FALSE);
+
+		/*
+		 * Invalidate the 2- or 4MB page mapping and return
+		 * "failure" if the mapping was never accessed or the
+		 * allocation of the new page table page fails.
+		 */
+		if ((oldpde & PG_A) == 0 || (mpte = vm_page_alloc(NULL,
+		    va >> PDRSHIFT, VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL |
+		    VM_ALLOC_WIRED)) == NULL) {
+			free = NULL;
+			pmap_remove_pde(pmap, pde, trunc_4mpage(va), &free);
+			pmap_invalidate_page(pmap, trunc_4mpage(va));
+			pmap_free_zero_pages(free);
+			CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#x"
+			    " in pmap %p", va, pmap);
+			return (FALSE);
+		}
+		if (va < VM_MAXUSER_ADDRESS)
+			pmap->pm_stats.resident_count++;
 	}
 	mptepa = VM_PAGE_TO_PHYS(mpte);
 
@@ -2348,30 +2410,32 @@ pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va)
 		}
 		firstpte = PADDR2;
 	}
-	oldpde = *pde;
 	newpde = mptepa | PG_M | PG_A | (oldpde & PG_U) | PG_RW | PG_V;
-	KASSERT((oldpde & (PG_A | PG_V)) == (PG_A | PG_V),
-	    ("pmap_demote_pde: oldpde is missing PG_A and/or PG_V"));
+	KASSERT((oldpde & PG_A) != 0,
+	    ("pmap_demote_pde: oldpde is missing PG_A"));
 	KASSERT((oldpde & (PG_M | PG_RW)) != PG_RW,
 	    ("pmap_demote_pde: oldpde is missing PG_M"));
-	KASSERT((oldpde & PG_PS) != 0,
-	    ("pmap_demote_pde: oldpde is missing PG_PS"));
 	newpte = oldpde & ~PG_PS;
 	if ((newpte & PG_PDE_PAT) != 0)
 		newpte ^= PG_PDE_PAT | PG_PTE_PAT;
 
 	/*
-	 * If the mapping has changed attributes, update the page table
-	 * entries.
-	 */ 
+	 * If the page table page is new, initialize it.
+	 */
+	if (mpte->wire_count == 1) {
+		mpte->wire_count = NPTEPG;
+		pmap_fill_ptp(firstpte, newpte);
+	}
 	KASSERT((*firstpte & PG_FRAME) == (newpte & PG_FRAME),
 	    ("pmap_demote_pde: firstpte and newpte map different physical"
 	    " addresses"));
+
+	/*
+	 * If the mapping has changed attributes, update the page table
+	 * entries.
+	 */ 
 	if ((*firstpte & PG_PTE_PROMOTE) != (newpte & PG_PTE_PROMOTE))
-		for (pte = firstpte; pte < firstpte + NPTEPG; pte++) {
-			*pte = newpte;	
-			newpte += PAGE_SIZE;
-		}
+		pmap_fill_ptp(firstpte, newpte);
 	
 	/*
 	 * Demote the mapping.  This pmap is locked.  The old PDE has
@@ -4426,6 +4490,40 @@ pmap_clear_reference(vm_page_t m)
  * Miscellaneous support routines follow
  */
 
+/* Adjust the cache mode for a 4KB page mapped via a PTE. */
+static __inline void
+pmap_pte_attr(pt_entry_t *pte, int cache_bits)
+{
+	u_int opte, npte;
+
+	/*
+	 * The cache mode bits are all in the low 32-bits of the
+	 * PTE, so we can just spin on updating the low 32-bits.
+	 */
+	do {
+		opte = *(u_int *)pte;
+		npte = opte & ~PG_PTE_CACHE;
+		npte |= cache_bits;
+	} while (npte != opte && !atomic_cmpset_int((u_int *)pte, opte, npte));
+}
+
+/* Adjust the cache mode for a 2/4MB page mapped via a PDE. */
+static __inline void
+pmap_pde_attr(pd_entry_t *pde, int cache_bits)
+{
+	u_int opde, npde;
+
+	/*
+	 * The cache mode bits are all in the low 32-bits of the
+	 * PDE, so we can just spin on updating the low 32-bits.
+	 */
+	do {
+		opde = *(u_int *)pde;
+		npde = opde & ~PG_PDE_CACHE;
+		npde |= cache_bits;
+	} while (npde != opde && !atomic_cmpset_int((u_int *)pde, opde, npde));
+}
+
 /*
  * Map a set of physical memory pages into the kernel virtual
  * address space. Return a pointer to where it is mapped. This
@@ -4537,13 +4635,23 @@ pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
 	}
 }
 
+/*
+ * Changes the specified virtual address range's memory type to that given by
+ * the parameter "mode".  The specified virtual address range must be
+ * completely contained within either the kernel map.
+ *
+ * Returns zero if the change completed successfully, and either EINVAL or
+ * ENOMEM if the change failed.  Specifically, EINVAL is returned if some part
+ * of the virtual address range was not mapped, and ENOMEM is returned if
+ * there was insufficient memory available to complete the change.
+ */
 int
 pmap_change_attr(vm_offset_t va, vm_size_t size, int mode)
 {
 	vm_offset_t base, offset, tmpva;
-	pt_entry_t *pte;
-	u_int opte, npte;
 	pd_entry_t *pde;
+	pt_entry_t *pte;
+	int cache_bits_pte, cache_bits_pde;
 	boolean_t changed;
 
 	base = trunc_page(va);
@@ -4556,47 +4664,84 @@ pmap_change_attr(vm_offset_t va, vm_size_t size, int mode)
 	if (base < VM_MIN_KERNEL_ADDRESS)
 		return (EINVAL);
 
-	/* 4MB pages and pages that aren't mapped aren't supported. */
-	for (tmpva = base; tmpva < (base + size); tmpva += PAGE_SIZE) {
-		pde = pmap_pde(kernel_pmap, tmpva);
-		if (*pde & PG_PS)
-			return (EINVAL);
-		if (*pde == 0)
-			return (EINVAL);
-		pte = vtopte(tmpva);
-		if (*pte == 0)
-			return (EINVAL);
-	}
-
+	cache_bits_pde = pmap_cache_bits(mode, 1);
+	cache_bits_pte = pmap_cache_bits(mode, 0);
 	changed = FALSE;
 
 	/*
-	 * Ok, all the pages exist and are 4k, so run through them updating
-	 * their cache mode.
+	 * Pages that aren't mapped aren't supported.  Also break down
+	 * 2/4MB pages into 4KB pages if required.
 	 */
-	for (tmpva = base; size > 0; ) {
-		pte = vtopte(tmpva);
+	PMAP_LOCK(kernel_pmap);
+	for (tmpva = base; tmpva < base + size; ) {
+		pde = pmap_pde(kernel_pmap, tmpva);
+		if (*pde == 0) {
+			PMAP_UNLOCK(kernel_pmap);
+			return (EINVAL);
+		}
+		if (*pde & PG_PS) {
+			/*
+			 * If the current 2/4MB page already has
+			 * the required memory type, then we need not
+			 * demote this page.  Just increment tmpva to
+			 * the next 2/4MB page frame.
+			 */
+			if ((*pde & PG_PDE_CACHE) == cache_bits_pde) {
+				tmpva = trunc_4mpage(tmpva) + NBPDR;
+				continue;
+			}
 
-		/*
-		 * The cache mode bits are all in the low 32-bits of the
-		 * PTE, so we can just spin on updating the low 32-bits.
-		 */
-		do {
-			opte = *(u_int *)pte;
-			npte = opte & ~(PG_PTE_PAT | PG_NC_PCD | PG_NC_PWT);
-			npte |= pmap_cache_bits(mode, 0);
-		} while (npte != opte &&
-		    !atomic_cmpset_int((u_int *)pte, opte, npte));
-		if (npte != opte)
-			changed = TRUE;
+			/*
+			 * If the current offset aligns with a 2/4MB
+			 * page frame and there is at least 2/4MB left
+			 * within the range, then we need not break
+			 * down this page into 4KB pages.
+			 */
+			if ((tmpva & PDRMASK) == 0 &&
+			    tmpva + PDRMASK < base + size) {
+				tmpva += NBPDR;
+				continue;
+			}
+			if (!pmap_demote_pde(kernel_pmap, pde, tmpva)) {
+				PMAP_UNLOCK(kernel_pmap);
+				return (ENOMEM);
+			}
+		}
+		pte = vtopte(tmpva);
+		if (*pte == 0) {
+			PMAP_UNLOCK(kernel_pmap);
+			return (EINVAL);
+		}
 		tmpva += PAGE_SIZE;
-		size -= PAGE_SIZE;
+	}
+	PMAP_UNLOCK(kernel_pmap);
+
+	/*
+	 * Ok, all the pages exist, so run through them updating their
+	 * cache mode if required.
+	 */
+	for (tmpva = base; tmpva < base + size; ) {
+		pde = pmap_pde(kernel_pmap, tmpva);
+		if (*pde & PG_PS) {
+			if ((*pde & PG_PDE_CACHE) != cache_bits_pde) {
+				pmap_pde_attr(pde, cache_bits_pde);
+				changed = TRUE;
+			}
+			tmpva = trunc_4mpage(tmpva) + NBPDR;
+		} else {
+			pte = vtopte(tmpva);
+			if ((*pte & PG_PTE_CACHE) != cache_bits_pte) {
+				pmap_pte_attr(pte, cache_bits_pte);
+				changed = TRUE;
+			}
+			tmpva += PAGE_SIZE;
+		}
 	}
 
 	/*
-	 * Flush CPU caches to make sure any data isn't cached that shouldn't
-	 * be, etc.
-	 */    
+	 * Flush CPU caches to make sure any data isn't cached that
+	 * shouldn't be, etc.
+	 */
 	if (changed) {
 		pmap_invalidate_range(kernel_pmap, base, tmpva);
 		pmap_invalidate_cache_range(base, tmpva);
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index e9671046060..f7064f04a53 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -211,13 +211,11 @@ trap(struct trapframe *frame)
 	type = frame->tf_trapno;
 
 #ifdef SMP
-#ifdef STOP_NMI
 	/* Handler for NMI IPIs used for stopping CPUs. */
 	if (type == T_NMI) {
 	         if (ipi_nmi_handler() == 0)
 	                   goto out;
 	}
-#endif /* STOP_NMI */
 #endif /* SMP */
 
 #ifdef KDB
@@ -425,7 +423,9 @@ trap(struct trapframe *frame)
 					 * This check also covers the images
 					 * without the ABI-tag ELF note.
 					 */
-					if (p->p_osrel >= 700004) {
+					if (SV_CURPROC_ABI() ==
+					    SV_ABI_FREEBSD &&
+					    p->p_osrel >= 700004) {
 						i = SIGSEGV;
 						ucode = SEGV_ACCERR;
 					} else {
diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h
index a03c083705c..b15452b1d81 100644
--- a/sys/i386/include/apicvar.h
+++ b/sys/i386/include/apicvar.h
@@ -100,11 +100,6 @@
  * smp_ipi_mtx and waits for the completion of the IPI (Only one IPI user 
  * at a time) The second group uses a single interrupt and a bitmap to avoid
  * redundant IPI interrupts.
- *
- * Right now IPI_STOP used by kdb shares the interrupt priority class with
- * the two IPI groups mentioned above. As such IPI_STOP may cause a deadlock.
- * Eventually IPI_STOP should use NMI IPIs - this would eliminate this and
- * other deadlocks caused by IPI_STOP.
  */ 
 
 /* Interrupts for local APIC LVT entries other than the timer. */
@@ -134,6 +129,7 @@
 #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
 
 #define	IPI_STOP	(APIC_IPI_INTS + 7)	/* Stop CPU until restarted. */
+#define	IPI_STOP_HARD	(APIC_IPI_INTS + 8)	/* Stop CPU with a NMI. */
 
 #else /* XEN */
 /* These are the normal i386 APIC definitions */
@@ -161,6 +157,7 @@
 #define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
 
 #define	IPI_STOP	(APIC_IPI_INTS + 7)	/* Stop CPU until restarted. */
+#define	IPI_STOP_HARD	(APIC_IPI_INTS + 8)	/* Stop CPU with a NMI. */
 #endif /* XEN */
 
 /*
@@ -233,7 +230,9 @@ int	ioapic_set_triggermode(void *cookie, u_int pin,
 int	ioapic_set_smi(void *cookie, u_int pin);
 void	lapic_create(u_int apic_id, int boot_cpu);
 void	lapic_disable(void);
+void	lapic_disable_pmc(void);
 void	lapic_dump(const char *str);
+int	lapic_enable_pmc(void);
 void	lapic_eoi(void);
 u_int	lapic_error(void);
 int	lapic_id(void);
@@ -244,6 +243,7 @@ void	lapic_ipi_vectored(u_int vector, int dest);
 int	lapic_ipi_wait(int delay);
 void	lapic_handle_intr(int vector, struct trapframe *frame);
 void	lapic_handle_timer(struct trapframe *frame);
+void	lapic_reenable_pmc(void);
 void	lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id);
 int	lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked);
 int	lapic_set_lvt_mode(u_int apic_id, u_int lvt, u_int32_t mode);
diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h
index 594077cf723..6cc03d0de0a 100644
--- a/sys/i386/include/pcpu.h
+++ b/sys/i386/include/pcpu.h
@@ -152,7 +152,7 @@ extern struct pcpu *pcpup;
 #define	__PCPU_GET(name) __extension__ ({				\
 	__pcpu_type(name) __res;					\
 	struct __s {							\
-		u_char	__b[MIN(sizeof(__pcpu_type(name)), 4)];		\
+		u_char	__b[MIN(sizeof(__res), 4)];			\
 	} __s;								\
 									\
 	if (sizeof(__res) == 1 || sizeof(__res) == 2 ||			\
@@ -174,7 +174,7 @@ extern struct pcpu *pcpup;
 #define	__PCPU_ADD(name, val) do {					\
 	__pcpu_type(name) __val;					\
 	struct __s {							\
-		u_char	__b[MIN(sizeof(__pcpu_type(name)), 4)];		\
+		u_char	__b[MIN(sizeof(__val), 4)];			\
 	} __s;								\
 									\
 	__val = (val);							\
@@ -214,10 +214,10 @@ extern struct pcpu *pcpup;
 /*
  * Sets the value of the per-cpu variable name to value val.
  */
-#define	__PCPU_SET(name, val) {						\
+#define	__PCPU_SET(name, val) do {					\
 	__pcpu_type(name) __val;					\
 	struct __s {							\
-		u_char	__b[MIN(sizeof(__pcpu_type(name)), 4)];		\
+		u_char	__b[MIN(sizeof(__val), 4)];			\
 	} __s;								\
 									\
 	__val = (val);							\
@@ -230,7 +230,7 @@ extern struct pcpu *pcpup;
 	} else {							\
 		*__PCPU_PTR(name) = __val;				\
 	}								\
-}
+} while (0)
 
 #define	PCPU_GET(member)	__PCPU_GET(pc_ ## member)
 #define	PCPU_ADD(member, val)	__PCPU_ADD(pc_ ## member, val)
diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
index c90f94707e4..54e8c206cd4 100644
--- a/sys/i386/include/pmap.h
+++ b/sys/i386/include/pmap.h
@@ -81,6 +81,10 @@
 #define	PG_PROT		(PG_RW|PG_U)	/* all protection bits . */
 #define PG_N		(PG_NC_PWT|PG_NC_PCD)	/* Non-cacheable */
 
+/* Page level cache control fields used to determine the PAT type */
+#define PG_PDE_CACHE	(PG_PDE_PAT | PG_NC_PWT | PG_NC_PCD)
+#define PG_PTE_CACHE	(PG_PTE_PAT | PG_NC_PWT | PG_NC_PCD)
+
 /*
  * Promotion to a 2 or 4MB (PDE) page mapping requires that the corresponding
  * 4KB (PTE) page mappings have identical settings for the following fields:
diff --git a/sys/i386/include/pmc_mdep.h b/sys/i386/include/pmc_mdep.h
index 63d5f8bf0b6..4389a20c203 100644
--- a/sys/i386/include/pmc_mdep.h
+++ b/sys/i386/include/pmc_mdep.h
@@ -150,7 +150,6 @@ struct pmc_mdep;
  */
 
 void	start_exceptions(void), end_exceptions(void);
-void	pmc_x86_lapic_enable_pmc_interrupt(void);
 
 struct pmc_mdep *pmc_amd_initialize(void);
 void	pmc_amd_finalize(struct pmc_mdep *_md);
diff --git a/sys/i386/include/smp.h b/sys/i386/include/smp.h
index 917c2851eee..968cdb4f94e 100644
--- a/sys/i386/include/smp.h
+++ b/sys/i386/include/smp.h
@@ -60,7 +60,8 @@ inthand_t
 void	cpu_add(u_int apic_id, char boot_cpu);
 void	cpustop_handler(void);
 void	init_secondary(void);
-void	ipi_selected(u_int cpus, u_int ipi);
+int	ipi_nmi_handler(void);
+void	ipi_selected(cpumask_t cpus, u_int ipi);
 void	ipi_all_but_self(u_int ipi);
 #ifndef XEN
 void 	ipi_bitmap_handler(struct trapframe frame);
@@ -76,9 +77,6 @@ void	smp_masked_invlpg_range(cpumask_t mask, vm_offset_t startva,
 void	smp_invltlb(void);
 void	smp_masked_invltlb(cpumask_t mask);
 
-#ifdef STOP_NMI
-int	ipi_nmi_handler(void);
-#endif
 #ifdef XEN
 void ipi_to_irq_init(void);
 
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 186e14c421f..d07f65563d3 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -108,6 +108,7 @@ static void     linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
 static void	exec_linux_setregs(struct thread *td, u_long entry,
 				   u_long stack, u_long ps_strings);
 static register_t *linux_copyout_strings(struct image_params *imgp);
+static boolean_t linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
 
 static int linux_szplatform;
 const char *linux_platform;
@@ -1027,14 +1028,38 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_flags	= SV_ABI_LINUX | SV_IA32 | SV_ILP32
 };
 
-static char GNULINUX_ABI_VENDOR[] = "GNU";
+static char GNU_ABI_VENDOR[] = "GNU";
+static int GNULINUX_ABI_DESC = 0;
+
+static boolean_t
+linux_trans_osrel(const Elf_Note *note, int32_t *osrel)
+{
+	const Elf32_Word *desc;
+	uintptr_t p;
+
+	p = (uintptr_t)(note + 1);
+	p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
+
+	desc = (const Elf32_Word *)p;
+	if (desc[0] != GNULINUX_ABI_DESC)
+		return (FALSE);
+
+	/*
+	 * For linux we encode osrel as follows (see linux_mib.c):
+	 * VVVMMMIII (version, major, minor), see linux_mib.c.
+	 */
+	*osrel = desc[1] * 1000000 + desc[2] * 1000 + desc[3];
+
+	return (TRUE);
+}
 
 static Elf_Brandnote linux_brandnote = {
-	.hdr.n_namesz	= sizeof(GNULINUX_ABI_VENDOR),
-	.hdr.n_descsz	= 16,
+	.hdr.n_namesz	= sizeof(GNU_ABI_VENDOR),
+	.hdr.n_descsz	= 16,	/* XXX at least 16 */
 	.hdr.n_type	= 1,
-	.vendor		= GNULINUX_ABI_VENDOR,
-	.flags		= 0
+	.vendor		= GNU_ABI_VENDOR,
+	.flags		= BN_TRANSLATE_OSREL,
+	.trans_osrel	= linux_trans_osrel
 };
 
 static Elf32_Brandinfo linux_brand = {
diff --git a/sys/i386/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c
index 3aa03cef41f..92533662b26 100644
--- a/sys/i386/xen/mp_machdep.c
+++ b/sys/i386/xen/mp_machdep.c
@@ -90,8 +90,6 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-#define stop_cpus_with_nmi	0
-
 
 int	mp_naps;		/* # of Applications processors */
 int	boot_cpu_id = -1;	/* designated BSP */
@@ -120,6 +118,7 @@ volatile int smp_tlb_wait;
 typedef void call_data_func_t(uintptr_t , uintptr_t);
 
 static u_int logical_cpus;
+static volatile cpumask_t ipi_nmi_pending;
 
 /* used to hold the AP's until we are ready to release them */
 static struct mtx ap_boot_mtx;
@@ -1111,6 +1110,14 @@ ipi_selected(cpumask_t cpus, u_int ipi)
 		ipi = IPI_BITMAP_VECTOR;
 	} 
 
+	/*
+	 * IPI_STOP_HARD maps to a NMI and the trap handler needs a bit
+	 * of help in order to understand what is the source.
+	 * Set the mask of receiving CPUs for this purpose.
+	 */
+	if (ipi == IPI_STOP_HARD)
+		atomic_set_int(&ipi_nmi_pending, cpus);
+
 	CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi);
 	while ((cpu = ffs(cpus)) != 0) {
 		cpu--;
@@ -1142,10 +1149,39 @@ ipi_selected(cpumask_t cpus, u_int ipi)
 void
 ipi_all_but_self(u_int ipi)
 {
+
+	/*
+	 * IPI_STOP_HARD maps to a NMI and the trap handler needs a bit
+	 * of help in order to understand what is the source.
+	 * Set the mask of receiving CPUs for this purpose.
+	 */
+	if (ipi == IPI_STOP_HARD)
+		atomic_set_int(&ipi_nmi_pending, PCPU_GET(other_cpus));
+
 	CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
 	ipi_selected(PCPU_GET(other_cpus), ipi);
 }
 
+int
+ipi_nmi_handler()
+{
+	cpumask_t cpumask;
+
+	/*
+	 * As long as there is not a simple way to know about a NMI's
+	 * source, if the bitmask for the current CPU is present in
+	 * the global pending bitword an IPI_STOP_HARD has been issued
+	 * and should be handled.
+	 */
+	cpumask = PCPU_GET(cpumask);
+	if ((ipi_nmi_pending & cpumask) == 0)
+		return (1);
+
+	atomic_clear_int(&ipi_nmi_pending, cpumask);
+	cpustop_handler();
+	return (0);
+}
+
 /*
  * Handle an IPI_STOP by saving our current context and spinning until we
  * are resumed.
diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
index 9dc077f8803..4b81aae1699 100644
--- a/sys/i386/xen/pmap.c
+++ b/sys/i386/xen/pmap.c
@@ -223,6 +223,8 @@ static uma_zone_t pdptzone;
 #endif
 #endif
 
+static int pat_works;			/* Is page attribute table sane? */
+
 /*
  * Data for the pv entry allocation mechanism
  */
@@ -311,6 +313,7 @@ static vm_offset_t pmap_kmem_choose(vm_offset_t addr);
 static boolean_t pmap_is_prefaultable_locked(pmap_t pmap, vm_offset_t addr);
 static void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode);
 
+static __inline void pagezero(void *page);
 
 #if defined(PAE) && !defined(XEN)
 static void *pmap_pdpt_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait);
@@ -328,22 +331,6 @@ CTASSERT(KERNBASE % (1 << 24) == 0);
 
 
 
-static __inline void
-pagezero(void *page)
-{
-#if defined(I686_CPU)
-	if (cpu_class == CPUCLASS_686) {
-#if defined(CPU_ENABLE_SSE)
-		if (cpu_feature & CPUID_SSE2)
-			sse2_pagezero(page);
-		else
-#endif
-			i686_pagezero(page);
-	} else
-#endif
-		bzero(page, PAGE_SIZE);
-}
-
 void 
 pd_set(struct pmap *pmap, int ptepindex, vm_paddr_t val, int type)
 {
@@ -529,33 +516,36 @@ pmap_init_pat(void)
 	if (!(cpu_feature & CPUID_PAT))
 		return;
 
-#ifdef PAT_WORKS
-	/*
-	 * Leave the indices 0-3 at the default of WB, WT, UC, and UC-.
-	 * Program 4 and 5 as WP and WC.
-	 * Leave 6 and 7 as UC and UC-.
-	 */
-	pat_msr = rdmsr(MSR_PAT);
-	pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
-	pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
-	    PAT_VALUE(5, PAT_WRITE_COMBINING);
-#else
-	/*
-	 * Due to some Intel errata, we can only safely use the lower 4
-	 * PAT entries.  Thus, just replace PAT Index 2 with WC instead
-	 * of UC-.
-	 *
-	 *   Intel Pentium III Processor Specification Update
-	 * Errata E.27 (Upper Four PAT Entries Not Usable With Mode B
-	 * or Mode C Paging)
-	 *
-	 *   Intel Pentium IV  Processor Specification Update
-	 * Errata N46 (PAT Index MSB May Be Calculated Incorrectly)
-	 */
-	pat_msr = rdmsr(MSR_PAT);
-	pat_msr &= ~PAT_MASK(2);
-	pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
-#endif
+	if (cpu_vendor_id != CPU_VENDOR_INTEL ||
+	    (I386_CPU_FAMILY(cpu_id) == 6 && I386_CPU_MODEL(cpu_id) >= 0xe)) {
+		/*
+		 * Leave the indices 0-3 at the default of WB, WT, UC, and UC-.
+		 * Program 4 and 5 as WP and WC.
+		 * Leave 6 and 7 as UC and UC-.
+		 */
+		pat_msr = rdmsr(MSR_PAT);
+		pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
+		pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
+		    PAT_VALUE(5, PAT_WRITE_COMBINING);
+		pat_works = 1;
+	} else {
+		/*
+		 * Due to some Intel errata, we can only safely use the lower 4
+		 * PAT entries.  Thus, just replace PAT Index 2 with WC instead
+		 * of UC-.
+		 *
+		 *   Intel Pentium III Processor Specification Update
+		 * Errata E.27 (Upper Four PAT Entries Not Usable With Mode B
+		 * or Mode C Paging)
+		 *
+		 *   Intel Pentium IV  Processor Specification Update
+		 * Errata N46 (PAT Index MSB May Be Calculated Incorrectly)
+		 */
+		pat_msr = rdmsr(MSR_PAT);
+		pat_msr &= ~PAT_MASK(2);
+		pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
+		pat_works = 0;
+	}
 	wrmsr(MSR_PAT, pat_msr);
 }
 
@@ -784,44 +774,48 @@ pmap_cache_bits(int mode, boolean_t is_pde)
 	}
 	
 	/* Map the caching mode to a PAT index. */
-	switch (mode) {
-#ifdef PAT_WORKS
-	case PAT_UNCACHEABLE:
-		pat_index = 3;
-		break;
-	case PAT_WRITE_THROUGH:
-		pat_index = 1;
-		break;
-	case PAT_WRITE_BACK:
-		pat_index = 0;
-		break;
-	case PAT_UNCACHED:
-		pat_index = 2;
-		break;
-	case PAT_WRITE_COMBINING:
-		pat_index = 5;
-		break;
-	case PAT_WRITE_PROTECTED:
-		pat_index = 4;
-		break;
-#else
-	case PAT_UNCACHED:
-	case PAT_UNCACHEABLE:
-	case PAT_WRITE_PROTECTED:
-		pat_index = 3;
-		break;
-	case PAT_WRITE_THROUGH:
-		pat_index = 1;
-		break;
-	case PAT_WRITE_BACK:
-		pat_index = 0;
-		break;
-	case PAT_WRITE_COMBINING:
-		pat_index = 2;
-		break;
-#endif
-	default:
-		panic("Unknown caching mode %d\n", mode);
+	if (pat_works) {
+		switch (mode) {
+			case PAT_UNCACHEABLE:
+				pat_index = 3;
+				break;
+			case PAT_WRITE_THROUGH:
+				pat_index = 1;
+				break;
+			case PAT_WRITE_BACK:
+				pat_index = 0;
+				break;
+			case PAT_UNCACHED:
+				pat_index = 2;
+				break;
+			case PAT_WRITE_COMBINING:
+				pat_index = 5;
+				break;
+			case PAT_WRITE_PROTECTED:
+				pat_index = 4;
+				break;
+			default:
+				panic("Unknown caching mode %d\n", mode);
+		}
+	} else {
+		switch (mode) {
+			case PAT_UNCACHED:
+			case PAT_UNCACHEABLE:
+			case PAT_WRITE_PROTECTED:
+				pat_index = 3;
+				break;
+			case PAT_WRITE_THROUGH:
+				pat_index = 1;
+				break;
+			case PAT_WRITE_BACK:
+				pat_index = 0;
+				break;
+			case PAT_WRITE_COMBINING:
+				pat_index = 2;
+				break;
+			default:
+				panic("Unknown caching mode %d\n", mode);
+		}
 	}	
 
 	/* Map the 3-bit index value into the PAT, PCD, and PWT bits. */
@@ -1735,7 +1729,7 @@ retry:
  * Deal with a SMP shootdown of other users of the pmap that we are
  * trying to dispose of.  This can be a bit hairy.
  */
-static u_int *lazymask;
+static cpumask_t *lazymask;
 static u_int lazyptd;
 static volatile u_int lazywait;
 
@@ -1744,7 +1738,7 @@ void pmap_lazyfix_action(void);
 void
 pmap_lazyfix_action(void)
 {
-	u_int mymask = PCPU_GET(cpumask);
+	cpumask_t mymask = PCPU_GET(cpumask);
 
 #ifdef COUNT_IPIS
 	(*ipi_lazypmap_counts[PCPU_GET(cpuid)])++;
@@ -1756,7 +1750,7 @@ pmap_lazyfix_action(void)
 }
 
 static void
-pmap_lazyfix_self(u_int mymask)
+pmap_lazyfix_self(cpumask_t mymask)
 {
 
 	if (rcr3() == lazyptd)
@@ -1768,8 +1762,7 @@ pmap_lazyfix_self(u_int mymask)
 static void
 pmap_lazyfix(pmap_t pmap)
 {
-	u_int mymask;
-	u_int mask;
+	cpumask_t mymask, mask;
 	u_int spins;
 
 	while ((mask = pmap->pm_active) != 0) {
@@ -3343,6 +3336,22 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
 	PMAP_UNLOCK(dst_pmap);
 }	
 
+static __inline void
+pagezero(void *page)
+{
+#if defined(I686_CPU)
+	if (cpu_class == CPUCLASS_686) {
+#if defined(CPU_ENABLE_SSE)
+		if (cpu_feature & CPUID_SSE2)
+			sse2_pagezero(page);
+		else
+#endif
+			i686_pagezero(page);
+	} else
+#endif
+		bzero(page, PAGE_SIZE);
+}
+
 /*
  *	pmap_zero_page zeros the specified hardware page by mapping 
  *	the page into KVM and using bzero to clear its contents.
@@ -4162,7 +4171,6 @@ pmap_activate(struct thread *td)
 	td->td_pcb->pcb_cr3 = cr3;
 	PT_UPDATES_FLUSH();
 	load_cr3(cr3);
-		
 	PCPU_SET(curpmap, pmap);
 	critical_exit();
 }
diff --git a/sys/ia64/ia64/genassym.c b/sys/ia64/ia64/genassym.c
index 8e988b67545..4a192fd79e3 100644
--- a/sys/ia64/ia64/genassym.c
+++ b/sys/ia64/ia64/genassym.c
@@ -91,7 +91,6 @@ ASSYM(MC_SPECIAL_RNAT,	offsetof(mcontext_t, mc_special.rnat));
 ASSYM(PAGE_SHIFT,	PAGE_SHIFT);
 ASSYM(PAGE_SIZE,	PAGE_SIZE);
 
-ASSYM(PC_CPUID,		offsetof(struct pcpu, pc_cpuid));
 ASSYM(PC_CURRENT_PMAP,	offsetof(struct pcpu, pc_current_pmap));
 ASSYM(PC_CURTHREAD,	offsetof(struct pcpu, pc_curthread));
 ASSYM(PC_IDLETHREAD,	offsetof(struct pcpu, pc_idlethread));
diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c
index 0c50b48a88b..b70a807591a 100644
--- a/sys/ia64/ia64/interrupt.c
+++ b/sys/ia64/ia64/interrupt.c
@@ -145,6 +145,8 @@ interrupt(struct trapframe *tf)
 	/*
 	 * Handle ExtINT interrupts by generating an INTA cycle to
 	 * read the vector.
+	 * IPI_STOP_HARD is mapped to IPI_STOP so it is not necessary
+	 * to add it to this switch-like construct.
 	 */
 	if (vector == 0) {
 		inta = ib->ib_inta;
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
index b1e7298fa96..67ca3c28c49 100644
--- a/sys/ia64/ia64/machdep.c
+++ b/sys/ia64/ia64/machdep.c
@@ -424,7 +424,11 @@ void
 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
 {
 
-	pcpu->pc_acpi_id = cpuid;
+	/*
+	 * Set pc_acpi_id to "uninitialized".
+	 * See sys/dev/acpica/acpi_cpu.c
+	 */
+	pcpu->pc_acpi_id = 0xffffffff;
 }
 
 void
diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c
index e94acadd235..92e26216e48 100644
--- a/sys/ia64/ia64/mp_machdep.c
+++ b/sys/ia64/ia64/mp_machdep.c
@@ -208,31 +208,25 @@ cpu_mp_add(u_int acpiid, u_int apicid, u_int apiceid)
 	struct pcpu *pc;
 	u_int64_t lid;
 	void *dpcpu;
-
-	/* Ignore any processor numbers outside our range */
-	if (acpiid > mp_maxid)
-		return;
-
-	KASSERT((all_cpus & (1UL << acpiid)) == 0,
-	    ("%s: cpu%d already in CPU map", __func__, acpiid));
+	u_int cpuid;
 
 	lid = LID_SAPIC_SET(apicid, apiceid);
+	cpuid = ((ia64_get_lid() & LID_SAPIC_MASK) == lid) ? 0 : smp_cpus++;
 
-	if ((ia64_get_lid() & LID_SAPIC_MASK) == lid) {
-		KASSERT(acpiid == 0,
-		    ("%s: the BSP must be cpu0", __func__));
-	}
+	KASSERT((all_cpus & (1UL << cpuid)) == 0,
+	    ("%s: cpu%d already in CPU map", __func__, acpiid));
 
-	if (acpiid != 0) {
+	if (cpuid != 0) {
 		pc = (struct pcpu *)malloc(sizeof(*pc), M_SMP, M_WAITOK);
+		pcpu_init(pc, cpuid, sizeof(*pc));
 		dpcpu = (void *)kmem_alloc(kernel_map, DPCPU_SIZE);
-		pcpu_init(pc, acpiid, sizeof(*pc));
-		dpcpu_init(dpcpu, acpiid);
+		dpcpu_init(dpcpu, cpuid);
 	} else
 		pc = pcpup;
 
+	pc->pc_acpi_id = acpiid;
 	pc->pc_lid = lid;
-	all_cpus |= (1UL << acpiid);
+	all_cpus |= (1UL << cpuid);
 }
 
 void
@@ -244,8 +238,8 @@ cpu_mp_announce()
 	for (i = 0; i <= mp_maxid; i++) {
 		pc = pcpu_find(i);
 		if (pc != NULL) {
-			printf("cpu%d: SAPIC Id=%x, SAPIC Eid=%x", i,
-			    LID_SAPIC_ID(pc->pc_lid),
+			printf("cpu%d: ACPI Id=%x, SAPIC Id=%x, SAPIC Eid=%x",
+			    i, pc->pc_acpi_id, LID_SAPIC_ID(pc->pc_lid),
 			    LID_SAPIC_EID(pc->pc_lid));
 			if (i == 0)
 				printf(" (BSP)\n");
@@ -305,7 +299,9 @@ cpu_mp_unleash(void *dummy)
 	SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
 		cpus++;
 		if (pc->pc_awake) {
-			kproc_create(ia64_store_mca_state, (void*)((uintptr_t)pc->pc_cpuid), NULL, 0, 0, "mca %u", pc->pc_cpuid);
+			kproc_create(ia64_store_mca_state,
+			    (void*)((uintptr_t)pc->pc_cpuid), NULL, 0, 0,
+			    "mca %u", pc->pc_cpuid);
 			smp_cpus++;
 		}
 	}
diff --git a/sys/ia64/include/smp.h b/sys/ia64/include/smp.h
index c6d98f7b4f3..4eddf7434fe 100644
--- a/sys/ia64/include/smp.h
+++ b/sys/ia64/include/smp.h
@@ -21,6 +21,7 @@
 #define	IPI_AST			4
 #define	IPI_RENDEZVOUS		5
 #define	IPI_STOP		6
+#define	IPI_STOP_HARD		6
 #define	IPI_PREEMPT		7
 
 #define	IPI_COUNT		8
diff --git a/sys/isa/isahint.c b/sys/isa/isahint.c
index e2ce6a4d30b..5eccef85949 100644
--- a/sys/isa/isahint.c
+++ b/sys/isa/isahint.c
@@ -118,14 +118,30 @@ isa_hint_device_unit(device_t bus, device_t child, const char *name, int *unitp)
 			continue;
 
 		/*
-		 * Check for matching resources.  We must have at least one,
-		 * and all resources specified have to match.
+		 * Check for matching resources.  We must have at
+		 * least one match.  Since I/O and memory resources
+		 * cannot be shared, if we get a match on either of
+		 * those, ignore any mismatches in IRQs or DRQs.
 		 *
-		 * XXX: We may want to revisit this to be more lenient and wire
-		 * as long as it gets one match.
+		 * XXX: We may want to revisit this to be more lenient
+		 * and wire as long as it gets one match.
 		 */
 		matches = 0;
 		if (resource_long_value(name, unit, "port", &value) == 0) {
+			/*
+			 * Floppy drive controllers are notorious for
+			 * having a wide variety of resources not all
+			 * of which include the first port that is
+			 * specified by the hint (typically 0x3f0)
+			 * (see the comment above
+			 * fdc_isa_alloc_resources() in fdc_isa.c).
+			 * However, they do all seem to include port +
+			 * 2 (e.g. 0x3f2) so for a floppy device, look
+			 * for 'value + 2' in the port resources
+			 * instead of the hint value.
+			 */
+			if (strcmp(name, "fdc") == 0)
+				value += 2;
 			if (isa_match_resource_hint(child, SYS_RES_IOPORT,
 			    value))
 				matches++;
@@ -139,6 +155,8 @@ isa_hint_device_unit(device_t bus, device_t child, const char *name, int *unitp)
 			else
 				continue;
 		}
+		if (matches > 0)
+			goto matched;
 		if (resource_long_value(name, unit, "irq", &value) == 0) {
 			if (isa_match_resource_hint(child, SYS_RES_IRQ, value))
 				matches++;
@@ -152,6 +170,7 @@ isa_hint_device_unit(device_t bus, device_t child, const char *name, int *unitp)
 				continue;
 		}
 
+	matched:
 		if (matches > 0) {
 			/* We have a winner! */
 			*unitp = unit;
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index e2c0a12cb54..ba5833a5bd6 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -86,6 +86,9 @@ static int __elfN(load_section)(struct vmspace *vmspace, vm_object_t object,
     vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
     vm_prot_t prot, size_t pagesize);
 static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp);
+static boolean_t __elfN(freebsd_trans_osrel)(const Elf_Note *note,
+    int32_t *osrel);
+static boolean_t kfreebsd_trans_osrel(const Elf_Note *note, int32_t *osrel);
 static boolean_t __elfN(check_note)(struct image_params *imgp,
     Elf_Brandnote *checknote, int32_t *osrel);
 
@@ -116,9 +119,56 @@ Elf_Brandnote __elfN(freebsd_brandnote) = {
 	.hdr.n_descsz	= sizeof(int32_t),
 	.hdr.n_type	= 1,
 	.vendor		= FREEBSD_ABI_VENDOR,
-	.flags		= BN_CAN_FETCH_OSREL
+	.flags		= BN_TRANSLATE_OSREL,
+	.trans_osrel	= __elfN(freebsd_trans_osrel)
 };
 
+static boolean_t
+__elfN(freebsd_trans_osrel)(const Elf_Note *note, int32_t *osrel)
+{
+	uintptr_t p;
+
+	p = (uintptr_t)(note + 1);
+	p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
+	*osrel = *(const int32_t *)(p);
+
+	return (TRUE);
+}
+
+static const char GNU_ABI_VENDOR[] = "GNU";
+static int GNU_KFREEBSD_ABI_DESC = 3;
+
+Elf_Brandnote __elfN(kfreebsd_brandnote) = {
+	.hdr.n_namesz	= sizeof(GNU_ABI_VENDOR),
+	.hdr.n_descsz	= 16,	/* XXX at least 16 */
+	.hdr.n_type	= 1,
+	.vendor		= GNU_ABI_VENDOR,
+	.flags		= BN_TRANSLATE_OSREL,
+	.trans_osrel	= kfreebsd_trans_osrel
+};
+
+static boolean_t
+kfreebsd_trans_osrel(const Elf_Note *note, int32_t *osrel)
+{
+	const Elf32_Word *desc;
+	uintptr_t p;
+
+	p = (uintptr_t)(note + 1);
+	p += roundup2(note->n_namesz, sizeof(Elf32_Addr));
+
+	desc = (const Elf32_Word *)p;
+	if (desc[0] != GNU_KFREEBSD_ABI_DESC)
+		return (FALSE);
+
+	/*
+	 * Debian GNU/kFreeBSD embed the earliest compatible kernel version
+	 * (__FreeBSD_version: Rxx) in the LSB way.
+	 */
+	*osrel = desc[1] * 100000 + desc[2] * 1000 + desc[3];
+
+	return (TRUE);
+}
+
 int
 __elfN(insert_brand_entry)(Elf_Brandinfo *entry)
 {
@@ -188,8 +238,10 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp,
 	/* Look for an ".note.ABI-tag" ELF section */
 	for (i = 0; i < MAX_BRANDS; i++) {
 		bi = elf_brand_list[i];
-		if (bi != NULL && hdr->e_machine == bi->machine &&
-		    (bi->flags & BI_BRAND_NOTE) != 0) {
+		if (bi == NULL)
+			continue;
+		if (hdr->e_machine == bi->machine && (bi->flags &
+		    (BI_BRAND_NOTE|BI_BRAND_NOTE_MANDATORY)) != 0) {
 			ret = __elfN(check_note)(imgp, bi->brand_note, osrel);
 			if (ret)
 				return (bi);
@@ -199,7 +251,9 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp,
 	/* If the executable has a brand, search for it in the brand list. */
 	for (i = 0; i < MAX_BRANDS; i++) {
 		bi = elf_brand_list[i];
-		if (bi != NULL && hdr->e_machine == bi->machine &&
+		if (bi == NULL || bi->flags & BI_BRAND_NOTE_MANDATORY)
+			continue;
+		if (hdr->e_machine == bi->machine &&
 		    (hdr->e_ident[EI_OSABI] == bi->brand ||
 		    strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND],
 		    bi->compat_3_brand, strlen(bi->compat_3_brand)) == 0))
@@ -210,7 +264,9 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp,
 	if (interp != NULL) {
 		for (i = 0; i < MAX_BRANDS; i++) {
 			bi = elf_brand_list[i];
-			if (bi != NULL && hdr->e_machine == bi->machine &&
+			if (bi == NULL || bi->flags & BI_BRAND_NOTE_MANDATORY)
+				continue;
+			if (hdr->e_machine == bi->machine &&
 			    strcmp(interp, bi->interp_path) == 0)
 				return (bi);
 		}
@@ -219,7 +275,9 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp,
 	/* Lacking a recognized interpreter, try the default brand */
 	for (i = 0; i < MAX_BRANDS; i++) {
 		bi = elf_brand_list[i];
-		if (bi != NULL && hdr->e_machine == bi->machine &&
+		if (bi == NULL || bi->flags & BI_BRAND_NOTE_MANDATORY)
+			continue;
+		if (hdr->e_machine == bi->machine &&
 		    __elfN(fallback_brand) == bi->brand)
 			return (bi);
 	}
@@ -1371,11 +1429,9 @@ __elfN(check_note)(struct image_params *imgp, Elf_Brandnote *checknote,
 		 * Fetch the osreldate for binary
 		 * from the ELF OSABI-note if necessary.
 		 */
-		if ((checknote->flags & BN_CAN_FETCH_OSREL) != 0 &&
-		    osrel != NULL)
-			*osrel = *(const int32_t *) (note_name +
-			    roundup2(checknote->hdr.n_namesz,
-			    sizeof(Elf32_Addr)));
+		if ((checknote->flags & BN_TRANSLATE_OSREL) != 0 &&
+		    checknote->trans_osrel != NULL)
+			return (checknote->trans_osrel(note, osrel));
 		return (TRUE);
 
 nextnote:
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index 8a5577ca274..8504e48d3e5 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -302,7 +302,7 @@ static struct cdevsw dead_cdevsw = {
 #define no_read		(d_read_t *)enodev
 #define no_write	(d_write_t *)enodev
 #define no_ioctl	(d_ioctl_t *)enodev
-#define no_mmap		(d_mmap_t *)enodev
+#define no_mmap		(d_mmap2_t *)enodev
 #define no_kqfilter	(d_kqfilter_t *)enodev
 #define no_mmap_single	(d_mmap_single_t *)enodev
 
@@ -469,7 +469,8 @@ giant_kqfilter(struct cdev *dev, struct knote *kn)
 }
 
 static int
-giant_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
+giant_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot,
+    vm_memattr_t *memattr)
 {
 	struct cdevsw *dsw;
 	int retval;
@@ -478,7 +479,11 @@ giant_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
 	if (dsw == NULL)
 		return (ENXIO);
 	mtx_lock(&Giant);
-	retval = dsw->d_gianttrick->d_mmap(dev, offset, paddr, nprot);
+	if (dsw->d_gianttrick->d_flags & D_MMAP2)
+		retval = dsw->d_gianttrick->d_mmap2(dev, offset, paddr, nprot,
+		    memattr);
+	else
+		retval = dsw->d_gianttrick->d_mmap(dev, offset, paddr, nprot);
 	mtx_unlock(&Giant);
 	dev_relthread(dev);
 	return (retval);
@@ -614,6 +619,7 @@ prep_cdevsw(struct cdevsw *devsw)
 		if (devsw->d_gianttrick == NULL) {
 			memcpy(dsw2, devsw, sizeof *dsw2);
 			devsw->d_gianttrick = dsw2;
+			devsw->d_flags |= D_MMAP2;
 			dsw2 = NULL;
 		}
 	}
@@ -634,7 +640,7 @@ prep_cdevsw(struct cdevsw *devsw)
 	FIXUP(d_write,		no_write,	giant_write);
 	FIXUP(d_ioctl,		no_ioctl,	giant_ioctl);
 	FIXUP(d_poll,		no_poll,	giant_poll);
-	FIXUP(d_mmap,		no_mmap,	giant_mmap);
+	FIXUP(d_mmap2,		no_mmap,	giant_mmap);
 	FIXUP(d_strategy,	no_strategy,	giant_strategy);
 	FIXUP(d_kqfilter,	no_kqfilter,	giant_kqfilter);
 	FIXUP(d_mmap_single,	no_mmap_single,	giant_mmap_single);
diff --git a/sys/kern/kern_cons.c b/sys/kern/kern_cons.c
index 31df2e883e1..2b9854f1730 100644
--- a/sys/kern/kern_cons.c
+++ b/sys/kern/kern_cons.c
@@ -124,9 +124,10 @@ cninit(void)
 	SET_FOREACH(list, cons_set) {
 		cn = *list;
 		cnremove(cn);
-		if (cn->cn_probe == NULL)
+		/* Skip cons_consdev. */
+		if (cn->cn_ops == NULL)
 			continue;
-		cn->cn_probe(cn);
+		cn->cn_ops->cn_probe(cn);
 		if (cn->cn_pri == CN_DEAD)
 			continue;
 		if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri)
@@ -135,14 +136,14 @@ cninit(void)
 			/*
 			 * Initialize console, and attach to it.
 			 */
-			cn->cn_init(cn);
+			cn->cn_ops->cn_init(cn);
 			cnadd(cn);
 		}
 	}
 	if (best_cn == NULL)
 		return;
 	if ((boothowto & RB_MULTIPLE) == 0) {
-		best_cn->cn_init(best_cn);
+		best_cn->cn_ops->cn_init(best_cn);
 		cnadd(best_cn);
 	}
 	if (boothowto & RB_PAUSE)
@@ -218,7 +219,7 @@ cnremove(struct consdev *cn)
 		 * freed after the system has initialized.
 		 */
 		if (cn->cn_term != NULL)
-			cn->cn_term(cn);
+			cn->cn_ops->cn_term(cn);
 #endif
 		return;
 	}
@@ -371,13 +372,9 @@ cncheckc(void)
 	STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
 		cn = cnd->cnd_cn;
 		if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
-			if (cn->cn_checkc != NULL)
-				c = cn->cn_checkc(cn);
-			else
-				c = cn->cn_getc(cn);
-			if (c != -1) {
+			c = cn->cn_ops->cn_getc(cn);
+			if (c != -1)
 				return (c);
-			}
 		}
 	}
 	return (-1);
@@ -396,8 +393,8 @@ cnputc(int c)
 		cn = cnd->cnd_cn;
 		if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
 			if (c == '\n')
-				cn->cn_putc(cn, '\r');
-			cn->cn_putc(cn, c);
+				cn->cn_ops->cn_putc(cn, '\r');
+			cn->cn_ops->cn_putc(cn, c);
 		}
 	}
 	if (console_pausing && c == '\n' && !kdb_active) {
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 36a074d0ef6..39b48e01bde 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -131,7 +131,12 @@ exit1(struct thread *td, int rv)
 	mtx_assert(&Giant, MA_NOTOWNED);
 
 	p = td->td_proc;
-	if (p == initproc) {
+	/*
+	 * XXX in case we're rebooting we just let init die in order to
+	 * work around an unsolved stack overflow seen very late during
+	 * shutdown on sparc64 when the gmirror worker process exists.
+	 */ 
+	if (p == initproc && rebooting == 0) {
 		printf("init died (signal %d, exit %d)\n",
 		    WTERMSIG(rv), WEXITSTATUS(rv));
 		panic("Going nowhere without my init!");
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 4e2eaa98f3a..03d8cbc6bc1 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 
 #include "opt_kdtrace.h"
 #include "opt_ktrace.h"
+#include "opt_kstack_pages.h"
 
 #include 
 #include 
@@ -276,25 +277,29 @@ norfproc_fail:
 
 	mem_charged = 0;
 	vm2 = NULL;
+	if (pages == 0)
+		pages = KSTACK_PAGES;
 	/* Allocate new proc. */
 	newproc = uma_zalloc(proc_zone, M_WAITOK);
-	if (TAILQ_EMPTY(&newproc->p_threads)) {
-		td2 = thread_alloc();
+	td2 = FIRST_THREAD_IN_PROC(newproc);
+	if (td2 == NULL) {
+		td2 = thread_alloc(pages);
 		if (td2 == NULL) {
 			error = ENOMEM;
 			goto fail1;
 		}
 		proc_linkup(newproc, td2);
-	} else
-		td2 = FIRST_THREAD_IN_PROC(newproc);
-
-	/* Allocate and switch to an alternate kstack if specified. */
-	if (pages != 0) {
-		if (!vm_thread_new_altkstack(td2, pages)) {
-			error = ENOMEM;
-			goto fail1;
+	} else {
+		if (td2->td_kstack == 0 || td2->td_kstack_pages != pages) {
+			if (td2->td_kstack != 0)
+				vm_thread_dispose(td2);
+			if (!thread_alloc_stack(td2, pages)) {
+				error = ENOMEM;
+				goto fail1;
+			}
 		}
 	}
+
 	if ((flags & RFMEM) == 0) {
 		vm2 = vmspace_fork(p1->p_vmspace, &mem_charged);
 		if (vm2 == NULL) {
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index cf5dfd8b856..0cc330cd5ad 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -88,7 +88,11 @@ struct prison prison0 = {
 	.pr_childmax	= JAIL_MAX,
 	.pr_hostuuid	= DEFAULT_HOSTUUID,
 	.pr_children	= LIST_HEAD_INITIALIZER(&prison0.pr_children),
+#ifdef VIMAGE
+	.pr_flags	= PR_HOST|PR_VNET,
+#else
 	.pr_flags	= PR_HOST,
+#endif
 	.pr_allow	= PR_ALLOW_ALL,
 };
 MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF);
@@ -472,10 +476,11 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
 #endif
 	struct vfsopt *opt;
 	struct vfsoptlist *opts;
-	struct prison *pr, *deadpr, *mypr, *ppr, *tpr, *tppr;
+	struct prison *pr, *deadpr, *mypr, *ppr, *tpr;
 	struct vnode *root;
-	char *domain, *errmsg, *host, *name, *p, *path, *uuid;
+	char *domain, *errmsg, *host, *name, *namelc, *p, *path, *uuid;
 #if defined(INET) || defined(INET6)
+	struct prison *tppr;
 	void *op;
 #endif
 	unsigned long hid;
@@ -902,6 +907,13 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
 		goto done_unlock_list;
 	}
 	pr = NULL;
+	namelc = NULL;
+	if (cuflags == JAIL_CREATE && jid == 0 && name != NULL) {
+		namelc = strrchr(name, '.');
+		jid = strtoul(namelc != NULL ? namelc + 1 : name, &p, 10);
+		if (*p != '\0')
+			jid = 0;
+	}
 	if (jid != 0) {
 		/*
 		 * See if a requested jid already exists.  There is an
@@ -968,17 +980,19 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
 	 * because that is the jail being updated).
 	 */
 	if (name != NULL) {
-		p = strrchr(name, '.');
-		if (p != NULL) {
+		namelc = strrchr(name, '.');
+		if (namelc == NULL)
+			namelc = name;
+		else {
 			/*
 			 * This is a hierarchical name.  Split it into the
 			 * parent and child names, and make sure the parent
 			 * exists or matches an already found jail.
 			 */
-			*p = '\0';
+			*namelc = '\0';
 			if (pr != NULL) {
-				if (strncmp(name, ppr->pr_name, p - name) ||
-				    ppr->pr_name[p - name] != '\0') {
+				if (strncmp(name, ppr->pr_name, namelc - name)
+				    || ppr->pr_name[namelc - name] != '\0') {
 					mtx_unlock(&pr->pr_mtx);
 					error = EINVAL;
 					vfs_opterror(opts,
@@ -995,7 +1009,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
 				}
 				mtx_unlock(&ppr->pr_mtx);
 			}
-			name = p + 1;
+			name = ++namelc;
 		}
 		if (name[0] != '\0') {
 			namelen =
@@ -1407,9 +1421,11 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
 		/* Give a default name of the jid. */
 		if (name[0] == '\0')
 			snprintf(name = numbuf, sizeof(numbuf), "%d", jid);
-		else if (strtoul(name, &p, 10) != jid && *p == '\0') {
+		else if (*namelc == '0' || (strtoul(namelc, &p, 10) != jid &&
+		    *p == '\0')) {
 			error = EINVAL;
-			vfs_opterror(opts, "name cannot be numeric");
+			vfs_opterror(opts,
+			    "name cannot be numeric (unless it is the jid)");
 			goto done_deref_locked;
 		}
 		/*
@@ -2448,10 +2464,10 @@ prison_deref(struct prison *pr, int flags)
 		ppr = pr->pr_parent;
 		for (tpr = ppr; tpr != NULL; tpr = tpr->pr_parent)
 			tpr->pr_childcount--;
-		sx_downgrade(&allprison_lock);
+		sx_xunlock(&allprison_lock);
 
 #ifdef VIMAGE
-		if (pr->pr_flags & PR_VNET)
+		if (pr->pr_vnet != ppr->pr_vnet)
 			vnet_destroy(pr->pr_vnet);
 #endif
 		if (pr->pr_root != NULL) {
@@ -2474,7 +2490,7 @@ prison_deref(struct prison *pr, int flags)
 		/* Removing a prison frees a reference on its parent. */
 		pr = ppr;
 		mtx_lock(&pr->pr_mtx);
-		flags = PD_DEREF | PD_LIST_SLOCKED;
+		flags = PD_DEREF;
 	}
 }
 
@@ -3307,6 +3323,25 @@ getcredhostid(struct ucred *cred, unsigned long *hostid)
 	mtx_unlock(&cred->cr_prison->pr_mtx);
 }
 
+#ifdef VIMAGE
+/*
+ * Determine whether the prison represented by cred owns
+ * its vnet rather than having it inherited.
+ *
+ * Returns 1 in case the prison owns the vnet, 0 otherwise.
+ */
+int
+prison_owns_vnet(struct ucred *cred)
+{
+
+	/*
+	 * vnets cannot be added/removed after jail creation,
+	 * so no need to lock here.
+	 */
+	return (cred->cr_prison->pr_flags & PR_VNET ? 1 : 0);
+}
+#endif
+
 /*
  * Determine whether the subject represented by cred can "see"
  * status of a mount point.
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index 10928321681..3c5248ebbb6 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -256,7 +256,7 @@ kthread_add(void (*func)(void *), void *arg, struct proc *p,
 	}
 
 	/* Initialize our new td  */
-	newtd = thread_alloc();
+	newtd = thread_alloc(pages);
 	if (newtd == NULL)
 		return (ENOMEM);
 
@@ -282,9 +282,6 @@ kthread_add(void (*func)(void *), void *arg, struct proc *p,
 
 	newtd->td_pflags |= TDP_KTHREAD;
 	newtd->td_ucred = crhold(p->p_ucred);
-	/* Allocate and switch to an alternate kstack if specified. */
-	if (pages != 0)
-		vm_thread_new_altkstack(newtd, pages);
 
 	/* this code almost the same as create_thread() in kern_thr.c */
 	PROC_LOCK(p);
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
index 0affad5f19b..e6f2f536249 100644
--- a/sys/kern/kern_lock.c
+++ b/sys/kern/kern_lock.c
@@ -334,6 +334,9 @@ lockinit(struct lock *lk, int pri, const char *wmesg, int timo, int flags)
 	int iflags;
 
 	MPASS((flags & ~LK_INIT_MASK) == 0);
+	ASSERT_ATOMIC_LOAD_PTR(lk->lk_lock,
+            ("%s: lockmgr not aligned for %s: %p", __func__, wmesg,
+            &lk->lk_lock));
 
 	iflags = LO_SLEEPABLE | LO_UPGRADABLE;
 	if (flags & LK_CANRECURSE)
@@ -464,7 +467,10 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
 			/*
 			 * If the owner is running on another CPU, spin until
 			 * the owner stops running or the state of the lock
-			 * changes.
+			 * changes.  We need a double-state handle here
+			 * because for a failed acquisition the lock can be
+			 * either held in exclusive mode or shared mode
+			 * (for the writer starvation avoidance technique).
 			 */
 			if (LK_CAN_ADAPT(lk, flags) && (x & LK_SHARE) == 0 &&
 			    LK_HOLDER(x) != LK_KERNPROC) {
@@ -488,8 +494,10 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
 				while (LK_HOLDER(lk->lk_lock) ==
 				    (uintptr_t)owner && TD_IS_RUNNING(owner))
 					cpu_spinwait();
+				GIANT_RESTORE();
+				continue;
 			} else if (LK_CAN_ADAPT(lk, flags) &&
-			    (x & LK_SHARE) !=0 && LK_SHARERS(x) &&
+			    (x & LK_SHARE) != 0 && LK_SHARERS(x) &&
 			    spintries < alk_retries) {
 				if (flags & LK_INTERLOCK) {
 					class->lc_unlock(ilk);
@@ -508,6 +516,7 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
 						break;
 					cpu_spinwait();
 				}
+				GIANT_RESTORE();
 				if (i != alk_loops)
 					continue;
 			}
@@ -701,6 +710,8 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
 				while (LK_HOLDER(lk->lk_lock) ==
 				    (uintptr_t)owner && TD_IS_RUNNING(owner))
 					cpu_spinwait();
+				GIANT_RESTORE();
+				continue;
 			} else if (LK_CAN_ADAPT(lk, flags) &&
 			    (x & LK_SHARE) != 0 && LK_SHARERS(x) &&
 			    spintries < alk_retries) {
@@ -724,6 +735,7 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
 						break;
 					cpu_spinwait();
 				}
+				GIANT_RESTORE();
 				if (i != alk_loops)
 					continue;
 			}
diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c
index fc342c53ef4..85ca646370d 100644
--- a/sys/kern/kern_mutex.c
+++ b/sys/kern/kern_mutex.c
@@ -783,6 +783,9 @@ mtx_init(struct mtx *m, const char *name, const char *type, int opts)
 
 	MPASS((opts & ~(MTX_SPIN | MTX_QUIET | MTX_RECURSE |
 		MTX_NOWITNESS | MTX_DUPOK | MTX_NOPROFILE)) == 0);
+	ASSERT_ATOMIC_LOAD_PTR(m->mtx_lock,
+	    ("%s: mtx_lock not aligned for %s: %p", __func__, name,
+	    &m->mtx_lock));
 
 #ifdef MUTEX_DEBUG
 	/* Diagnostic and error correction */
diff --git a/sys/kern/kern_poll.c b/sys/kern/kern_poll.c
index 5df26bbf089..8441126d1da 100644
--- a/sys/kern/kern_poll.c
+++ b/sys/kern/kern_poll.c
@@ -46,8 +46,6 @@ __FBSDID("$FreeBSD$");
 #include 			/* for NETISR_POLL		*/
 #include 
 
-static int poll_switch(SYSCTL_HANDLER_ARGS);
-
 void hardclock_device_poll(void);	/* hook from hardclock		*/
 
 static struct mtx	poll_mtx;
@@ -230,10 +228,6 @@ static uint32_t poll_handlers; /* next free entry in pr[]. */
 SYSCTL_UINT(_kern_polling, OID_AUTO, handlers, CTLFLAG_RD,
 	&poll_handlers, 0, "Number of registered poll handlers");
 
-static int polling = 0;
-SYSCTL_PROC(_kern_polling, OID_AUTO, enable, CTLTYPE_UINT | CTLFLAG_RW,
-	0, sizeof(int), poll_switch, "I", "Switch polling for all interfaces");
-
 static uint32_t phase;
 SYSCTL_UINT(_kern_polling, OID_AUTO, phase, CTLFLAG_RD,
 	&phase, 0, "Polling phase");
@@ -538,49 +532,6 @@ ether_poll_deregister(struct ifnet *ifp)
 	return (0);
 }
 
-/*
- * Legacy interface for turning polling on all interfaces at one time.
- */
-static int
-poll_switch(SYSCTL_HANDLER_ARGS)
-{
-	struct ifnet *ifp;
-	int error;
-	int val = polling;
-
-	error = sysctl_handle_int(oidp, &val, 0, req);
-	if (error || !req->newptr )
-		return (error);
-
-	if (val == polling)
-		return (0);
-
-	if (val < 0 || val > 1)
-		return (EINVAL);
-
-	polling = val;
-
-	IFNET_RLOCK();
-	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
-		if (ifp->if_capabilities & IFCAP_POLLING) {
-			struct ifreq ifr;
-
-			if (val == 1)
-				ifr.ifr_reqcap =
-				    ifp->if_capenable | IFCAP_POLLING;
-			else
-				ifr.ifr_reqcap =
-				    ifp->if_capenable & ~IFCAP_POLLING;
-			(void) (*ifp->if_ioctl)(ifp, SIOCSIFCAP, (caddr_t)&ifr);
-		}
-	}
-	IFNET_RUNLOCK();
-
-	log(LOG_ERR, "kern.polling.enable is deprecated. Use ifconfig(8)");
-
-	return (0);
-}
-
 static void
 poll_idle(void)
 {
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index cdbc01207ea..e012a3ed4c0 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -203,14 +203,6 @@ proc_dtor(void *mem, int size, void *arg)
 #endif
 		/* Free all OSD associated to this thread. */
 		osd_thread_exit(td);
-
-		/* Dispose of an alternate kstack, if it exists.
-		 * XXX What if there are more than one thread in the proc?
-		 *     The first thread in the proc is special and not
-		 *     freed, so you gotta do this here.
-		 */
-		if (((p->p_flag & P_KTHREAD) != 0) && (td->td_altkstack != 0))
-			vm_thread_dispose_altkstack(td);
 	}
 	EVENTHANDLER_INVOKE(process_dtor, p);
 	if (p->p_ksi != NULL)
@@ -767,8 +759,6 @@ fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp)
 		FOREACH_THREAD_IN_PROC(p, td0) {
 			if (!TD_IS_SWAPPED(td0))
 				kp->ki_rssize += td0->td_kstack_pages;
-			if (td0->td_altkstack_obj != NULL)
-				kp->ki_rssize += td0->td_altkstack_pages;
 		}
 		kp->ki_swrss = vm->vm_swrss;
 		kp->ki_tsize = vm->vm_tsize;
diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c
index c07f595cb5a..be05b39de0a 100644
--- a/sys/kern/kern_rwlock.c
+++ b/sys/kern/kern_rwlock.c
@@ -174,6 +174,9 @@ rw_init_flags(struct rwlock *rw, const char *name, int opts)
 
 	MPASS((opts & ~(RW_DUPOK | RW_NOPROFILE | RW_NOWITNESS | RW_QUIET |
 	    RW_RECURSE)) == 0);
+	ASSERT_ATOMIC_LOAD_PTR(rw->rw_lock,
+	    ("%s: rw_lock not aligned for %s: %p", __func__, name,
+	    &rw->rw_lock));
 
 	flags = LO_UPGRADABLE;
 	if (opts & RW_DUPOK)
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index 80dda97f977..0f3a672a299 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -412,9 +412,6 @@ boot(int howto)
 	 */
 	EVENTHANDLER_INVOKE(shutdown_post_sync, howto);
 
-	/* XXX This doesn't disable interrupts any more.  Reconsider? */
-	splhigh();
-
 	if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold && !dumping) 
 		doadump();
 
@@ -488,6 +485,13 @@ static void
 shutdown_reset(void *junk, int howto)
 {
 
+	/*
+	 * Disable interrupts on CPU0 in order to avoid fast handlers
+	 * to preempt the stopping process and to deadlock against other
+	 * CPUs.
+	 */
+	spinlock_enter();
+
 	printf("Rebooting...\n");
 	DELAY(1000000);	/* wait 1 sec for printf's to complete and be read */
 	/* cpu_boot(howto); */ /* doesn't do anything at the moment */
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c
index ce1afd24304..95ce5861509 100644
--- a/sys/kern/kern_subr.c
+++ b/sys/kern/kern_subr.c
@@ -419,9 +419,9 @@ hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask)
 	free(hashtbl, type);
 }
 
-static int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039,
-			2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653,
-			7159, 7673, 8191, 12281, 16381, 24571, 32749 };
+static const int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531,
+			2039, 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143,
+			6653, 7159, 7673, 8191, 12281, 16381, 24571, 32749 };
 #define NPRIMES (sizeof(primes) / sizeof(primes[0]))
 
 /*
diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c
index 04c2c984150..c00b267e5d2 100644
--- a/sys/kern/kern_sx.c
+++ b/sys/kern/kern_sx.c
@@ -205,6 +205,9 @@ sx_init_flags(struct sx *sx, const char *description, int opts)
 
 	MPASS((opts & ~(SX_QUIET | SX_RECURSE | SX_NOWITNESS | SX_DUPOK |
 	    SX_NOPROFILE | SX_NOADAPTIVE)) == 0);
+	ASSERT_ATOMIC_LOAD_PTR(sx->sx_lock,
+	    ("%s: sx_lock not aligned for %s: %p", __func__, description,
+	    &sx->sx_lock));
 
 	flags = LO_SLEEPABLE | LO_UPGRADABLE;
 	if (opts & SX_DUPOK)
@@ -528,13 +531,13 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file,
 					continue;
 				}
 			} else if (SX_SHARERS(x) && spintries < asx_retries) {
+				GIANT_SAVE();
 				spintries++;
 				for (i = 0; i < asx_loops; i++) {
 					if (LOCK_LOG_TEST(&sx->lock_object, 0))
 						CTR4(KTR_LOCK,
 				    "%s: shared spinning on %p with %u and %u",
 						    __func__, sx, spintries, i);
-					GIANT_SAVE();
 					x = sx->sx_lock;
 					if ((x & SX_LOCK_SHARED) == 0 ||
 					    SX_SHARERS(x) == 0)
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index bb5b6a0f3ad..b83502c2f41 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1381,10 +1381,18 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
 
 	/* Is this sysctl writable by only privileged users? */
 	if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) {
+		int priv;
+
 		if (oid->oid_kind & CTLFLAG_PRISON)
-			error = priv_check(req->td, PRIV_SYSCTL_WRITEJAIL);
+			priv = PRIV_SYSCTL_WRITEJAIL;
+#ifdef VIMAGE
+		else if ((oid->oid_kind & CTLFLAG_VNET) &&
+		     prison_owns_vnet(req->td->td_ucred))
+			priv = PRIV_SYSCTL_WRITEJAIL;
+#endif
 		else
-			error = priv_check(req->td, PRIV_SYSCTL_WRITE);
+			priv = PRIV_SYSCTL_WRITE;
+		error = priv_check(req->td, priv);
 		if (error)
 			return (error);
 	}
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index c478c63bd9b..630069b5940 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -176,7 +176,7 @@ create_thread(struct thread *td, mcontext_t *ctx,
 	}
 
 	/* Initialize our td */
-	newtd = thread_alloc();
+	newtd = thread_alloc(0);
 	if (newtd == NULL)
 		return (ENOMEM);
 
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index d47bd8cef8b..4f3b32cdd0a 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -283,7 +283,7 @@ thread_reap(void)
  * Allocate a thread.
  */
 struct thread *
-thread_alloc(void)
+thread_alloc(int pages)
 {
 	struct thread *td;
 
@@ -291,7 +291,7 @@ thread_alloc(void)
 
 	td = (struct thread *)uma_zalloc(thread_zone, M_WAITOK);
 	KASSERT(td->td_kstack == 0, ("thread_alloc got thread with kstack"));
-	if (!vm_thread_new(td, 0)) {
+	if (!vm_thread_new(td, pages)) {
 		uma_zfree(thread_zone, td);
 		return (NULL);
 	}
@@ -299,6 +299,17 @@ thread_alloc(void)
 	return (td);
 }
 
+int
+thread_alloc_stack(struct thread *td, int pages)
+{
+
+	KASSERT(td->td_kstack == 0,
+	    ("thread_alloc_stack called on a thread with kstack"));
+	if (!vm_thread_new(td, pages))
+		return (0);
+	cpu_thread_alloc(td);
+	return (1);
+}
 
 /*
  * Deallocate a thread.
@@ -312,8 +323,6 @@ thread_free(struct thread *td)
 		cpuset_rel(td->td_cpuset);
 	td->td_cpuset = NULL;
 	cpu_thread_free(td);
-	if (td->td_altkstack != 0)
-		vm_thread_dispose_altkstack(td);
 	if (td->td_kstack != 0)
 		vm_thread_dispose(td);
 	uma_zfree(thread_zone, td);
diff --git a/sys/kern/kern_uuid.c b/sys/kern/kern_uuid.c
index 5b61ca416ee..8c083f4e109 100644
--- a/sys/kern/kern_uuid.c
+++ b/sys/kern/kern_uuid.c
@@ -95,7 +95,7 @@ uuid_node(uint16_t *node)
 	int i;
 
 	CURVNET_SET(TD_TO_VNET(curthread));
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		/* Walk the address list */
 		IF_ADDR_LOCK(ifp);
@@ -106,14 +106,14 @@ uuid_node(uint16_t *node)
 				/* Got a MAC address. */
 				bcopy(LLADDR(sdl), node, UUID_NODE_LEN);
 				IF_ADDR_UNLOCK(ifp);
-				IFNET_RUNLOCK();
+				IFNET_RUNLOCK_NOSLEEP();
 				CURVNET_RESTORE();
 				return;
 			}
 		}
 		IF_ADDR_UNLOCK(ifp);
 	}
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 
 	for (i = 0; i < (UUID_NODE_LEN>>1); i++)
 		node[i] = (uint16_t)arc4random();
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 67f09182d5f..e4f99465891 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -192,54 +191,6 @@ void print_devclass_list(void);
 #define print_devclass_list()		/* nop */
 #endif
 
-/*
- * Newbus locking facilities.
- */
-static struct sx newbus_lock;
-
-#define	NBL_LOCK_INIT()		sx_init(&newbus_lock, "newbus")
-#define	NBL_LOCK_DESTROY()	sx_destroy(&newbus_lock)
-#define	NBL_XLOCK()		sx_xlock(&newbus_lock)
-#define	NBL_SLOCK()		sx_slock(&newbus_lock)
-#define	NBL_XUNLOCK()		sx_xunlock(&newbus_lock)
-#define	NBL_SUNLOCK()		sx_sunlock(&newbus_lock)
-#ifdef INVARIANTS
-#define	NBL_ASSERT(what) do {						\
-	if (cold == 0)							\
-		sx_assert(&newbus_lock, (what));			\
-} while (0)
-#else
-#define	NBL_ASSERT(what)
-#endif
-
-void
-newbus_xlock()
-{
-
-	NBL_XLOCK();
-}
-
-void
-newbus_slock()
-{
-
-	NBL_SLOCK();
-}
-
-void
-newbus_xunlock()
-{
-
-	NBL_XUNLOCK();
-}
-
-void
-newbus_sunlock()
-{
-
-	NBL_SUNLOCK();
-}
-
 /*
  * dev sysctl tree
  */
@@ -399,11 +350,18 @@ device_sysctl_fini(device_t dev)
  * tested since 3.4 or 2.2.8!
  */
 
+/* Deprecated way to adjust queue length */
 static int sysctl_devctl_disable(SYSCTL_HANDLER_ARGS);
-static int devctl_disable = 0;
-TUNABLE_INT("hw.bus.devctl_disable", &devctl_disable);
+/* XXX Need to support old-style tunable hw.bus.devctl_disable" */
 SYSCTL_PROC(_hw_bus, OID_AUTO, devctl_disable, CTLTYPE_INT | CTLFLAG_RW, NULL,
-    0, sysctl_devctl_disable, "I", "devctl disable");
+    0, sysctl_devctl_disable, "I", "devctl disable -- deprecated");
+
+#define DEVCTL_DEFAULT_QUEUE_LEN 1000
+static int sysctl_devctl_queue(SYSCTL_HANDLER_ARGS);
+static int devctl_queue_length = DEVCTL_DEFAULT_QUEUE_LEN;
+TUNABLE_INT("hw.bus.devctl_queue", &devctl_queue_length);
+SYSCTL_PROC(_hw_bus, OID_AUTO, devctl_queue, CTLTYPE_INT | CTLFLAG_RW, NULL,
+    0, sysctl_devctl_queue, "I", "devctl queue length");
 
 static d_open_t		devopen;
 static d_close_t	devclose;
@@ -413,6 +371,7 @@ static d_poll_t		devpoll;
 
 static struct cdevsw dev_cdevsw = {
 	.d_version =	D_VERSION,
+	.d_flags =	D_NEEDGIANT,
 	.d_open =	devopen,
 	.d_close =	devclose,
 	.d_read =	devread,
@@ -433,6 +392,7 @@ static struct dev_softc
 {
 	int	inuse;
 	int	nonblock;
+	int	queued;
 	struct mtx mtx;
 	struct cv cv;
 	struct selinfo sel;
@@ -471,7 +431,7 @@ devclose(struct cdev *dev, int fflag, int devtype, struct thread *td)
 	mtx_lock(&devsoftc.mtx);
 	cv_broadcast(&devsoftc.cv);
 	mtx_unlock(&devsoftc.mtx);
-
+	devsoftc.async_proc = NULL;
 	return (0);
 }
 
@@ -506,6 +466,7 @@ devread(struct cdev *dev, struct uio *uio, int ioflag)
 	}
 	n1 = TAILQ_FIRST(&devsoftc.devq);
 	TAILQ_REMOVE(&devsoftc.devq, n1, dei_link);
+	devsoftc.queued--;
 	mtx_unlock(&devsoftc.mtx);
 	rv = uiomove(n1->dei_data, strlen(n1->dei_data), uio);
 	free(n1->dei_data, M_BUS);
@@ -579,21 +540,33 @@ devctl_process_running(void)
 void
 devctl_queue_data(char *data)
 {
-	struct dev_event_info *n1 = NULL;
+	struct dev_event_info *n1 = NULL, *n2 = NULL;
 	struct proc *p;
 
-	/*
-	 * Do not allow empty strings to be queued, as they
-	 * cause devd to exit prematurely.
-	 */
 	if (strlen(data) == 0)
 		return;
+	if (devctl_queue_length == 0)
+		return;
 	n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT);
 	if (n1 == NULL)
 		return;
 	n1->dei_data = data;
 	mtx_lock(&devsoftc.mtx);
+	if (devctl_queue_length == 0) {
+		free(n1->dei_data, M_BUS);
+		free(n1, M_BUS);
+		return;
+	}
+	/* Leave at least one spot in the queue... */
+	while (devsoftc.queued > devctl_queue_length - 1) {
+		n2 = TAILQ_FIRST(&devsoftc.devq);
+		TAILQ_REMOVE(&devsoftc.devq, n2, dei_link);
+		free(n2->dei_data, M_BUS);
+		free(n2, M_BUS);
+		devsoftc.queued--;
+	}
 	TAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link);
+	devsoftc.queued++;
 	cv_broadcast(&devsoftc.cv);
 	mtx_unlock(&devsoftc.mtx);
 	selwakeup(&devsoftc.sel);
@@ -662,7 +635,7 @@ devaddq(const char *type, const char *what, device_t dev)
 	char *pnp = NULL;
 	const char *parstr;
 
-	if (devctl_disable)
+	if (!devctl_queue_length)/* Rare race, but lost races safely discard */
 		return;
 	data = malloc(1024, M_BUS, M_NOWAIT);
 	if (data == NULL)
@@ -779,12 +752,11 @@ sysctl_devctl_disable(SYSCTL_HANDLER_ARGS)
 	struct dev_event_info *n1;
 	int dis, error;
 
-	dis = devctl_disable;
+	dis = devctl_queue_length == 0;
 	error = sysctl_handle_int(oidp, &dis, 0, req);
 	if (error || !req->newptr)
 		return (error);
 	mtx_lock(&devsoftc.mtx);
-	devctl_disable = dis;
 	if (dis) {
 		while (!TAILQ_EMPTY(&devsoftc.devq)) {
 			n1 = TAILQ_FIRST(&devsoftc.devq);
@@ -792,6 +764,35 @@ sysctl_devctl_disable(SYSCTL_HANDLER_ARGS)
 			free(n1->dei_data, M_BUS);
 			free(n1, M_BUS);
 		}
+		devsoftc.queued = 0;
+		devctl_queue_length = 0;
+	} else {
+		devctl_queue_length = DEVCTL_DEFAULT_QUEUE_LEN;
+	}
+	mtx_unlock(&devsoftc.mtx);
+	return (0);
+}
+
+static int
+sysctl_devctl_queue(SYSCTL_HANDLER_ARGS)
+{
+	struct dev_event_info *n1;
+	int q, error;
+
+	q = devctl_queue_length;
+	error = sysctl_handle_int(oidp, &q, 0, req);
+	if (error || !req->newptr)
+		return (error);
+	if (q < 0)
+		return (EINVAL);
+	mtx_lock(&devsoftc.mtx);
+	devctl_queue_length = q;
+	while (devsoftc.queued > devctl_queue_length) {
+		n1 = TAILQ_FIRST(&devsoftc.devq);
+		TAILQ_REMOVE(&devsoftc.devq, n1, dei_link);
+		free(n1->dei_data, M_BUS);
+		free(n1, M_BUS);
+		devsoftc.queued--;
 	}
 	mtx_unlock(&devsoftc.mtx);
 	return (0);
@@ -934,7 +935,7 @@ devclass_find_internal(const char *classname, const char *parentname,
 	if (create && !dc) {
 		PDEBUG(("creating %s", classname));
 		dc = malloc(sizeof(struct devclass) + strlen(classname) + 1,
-		    M_BUS, M_NOWAIT|M_ZERO);
+		    M_BUS, M_NOWAIT | M_ZERO);
 		if (!dc)
 			return (NULL);
 		dc->parent = NULL;
@@ -1109,7 +1110,6 @@ devclass_delete_driver(devclass_t busclass, driver_t *driver)
 	int i;
 	int error;
 
-	NBL_ASSERT(SA_XLOCKED);
 	PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
 
 	if (!dc)
@@ -1808,7 +1808,6 @@ device_delete_child(device_t dev, device_t child)
 	int error;
 	device_t grandchild;
 
-	NBL_ASSERT(SA_XLOCKED);
 	PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
 
 	/* remove children first */
@@ -1907,7 +1906,7 @@ device_probe_child(device_t dev, device_t child)
 	int result, pri = 0;
 	int hasclass = (child->devclass != NULL);
 
-	NBL_ASSERT(SA_XLOCKED);
+	GIANT_REQUIRED;
 
 	dc = dev->devclass;
 	if (!dc)
@@ -2558,7 +2557,7 @@ device_probe(device_t dev)
 {
 	int error;
 
-	NBL_ASSERT(SA_XLOCKED);
+	GIANT_REQUIRED;
 
 	if (dev->state >= DS_ALIVE && (dev->flags & DF_REBID) == 0)
 		return (-1);
@@ -2592,7 +2591,7 @@ device_probe_and_attach(device_t dev)
 {
 	int error;
 
-	NBL_ASSERT(SA_XLOCKED);
+	GIANT_REQUIRED;
 
 	error = device_probe(dev);
 	if (error == -1)
@@ -2626,12 +2625,16 @@ device_attach(device_t dev)
 {
 	int error;
 
-	NBL_ASSERT(SA_XLOCKED);
-
+	if (dev->state >= DS_ATTACHING)
+		return (0);
 	device_sysctl_init(dev);
 	if (!device_is_quiet(dev))
 		device_print_child(dev->parent, dev);
+	dev->state = DS_ATTACHING;
 	if ((error = DEVICE_ATTACH(dev)) != 0) {
+		KASSERT(dev->state == DS_ATTACHING,
+		    ("%s: %p device state must not been changing", __func__,
+		    dev));
 		printf("device_attach: %s%d attach returned %d\n",
 		    dev->driver->name, dev->unit, error);
 		/* Unset the class; set in device_probe_child */
@@ -2642,6 +2645,8 @@ device_attach(device_t dev)
 		dev->state = DS_NOTPRESENT;
 		return (error);
 	}
+	KASSERT(dev->state == DS_ATTACHING,
+	    ("%s: %p device state must not been changing", __func__, dev));
 	device_sysctl_update(dev);
 	dev->state = DS_ATTACHED;
 	devadded(dev);
@@ -2669,7 +2674,7 @@ device_detach(device_t dev)
 {
 	int error;
 
-	NBL_ASSERT(SA_XLOCKED);
+	GIANT_REQUIRED;
 
 	PDEBUG(("%s", DEVICENAME(dev)));
 	if (dev->state == DS_BUSY)
@@ -2677,8 +2682,16 @@ device_detach(device_t dev)
 	if (dev->state != DS_ATTACHED)
 		return (0);
 
-	if ((error = DEVICE_DETACH(dev)) != 0)
+	dev->state = DS_DETACHING;
+	if ((error = DEVICE_DETACH(dev)) != 0) {
+		KASSERT(dev->state == DS_DETACHING,
+		    ("%s: %p device state must not been changing", __func__,
+		    dev));
+		dev->state = DS_ATTACHED;
 		return (error);
+	}
+	KASSERT(dev->state == DS_DETACHING,
+	    ("%s: %p device state must not been changing", __func__, dev));
 	devremoved(dev);
 	if (!device_is_quiet(dev))
 		device_printf(dev, "detached\n");
@@ -2713,8 +2726,6 @@ int
 device_quiesce(device_t dev)
 {
 
-	NBL_ASSERT(SA_XLOCKED);
-
 	PDEBUG(("%s", DEVICENAME(dev)));
 	if (dev->state == DS_BUSY)
 		return (EBUSY);
@@ -2735,8 +2746,7 @@ device_quiesce(device_t dev)
 int
 device_shutdown(device_t dev)
 {
-
-	if (dev->state < DS_ATTACHED)
+	if (dev->state < DS_ATTACHED || dev->state == DS_DETACHING)
 		return (0);
 	return (DEVICE_SHUTDOWN(dev));
 }
@@ -3151,8 +3161,6 @@ bus_generic_attach(device_t dev)
 {
 	device_t child;
 
-	NBL_ASSERT(SA_XLOCKED);
-
 	TAILQ_FOREACH(child, &dev->children, link) {
 		device_probe_and_attach(child);
 	}
@@ -3173,8 +3181,6 @@ bus_generic_detach(device_t dev)
 	device_t child;
 	int error;
 
-	NBL_ASSERT(SA_XLOCKED);
-
 	if (dev->state != DS_ATTACHED)
 		return (EBUSY);
 
@@ -4055,7 +4061,6 @@ root_bus_module_handler(module_t mod, int what, void* arg)
 	switch (what) {
 	case MOD_LOAD:
 		TAILQ_INIT(&bus_data_devices);
-		NBL_LOCK_INIT();
 		kobj_class_compile((kobj_class_t) &root_driver);
 		root_bus = make_device(NULL, "root", 0);
 		root_bus->desc = "System root bus";
@@ -4115,28 +4120,14 @@ driver_module_handler(module_t mod, int what, void *arg)
 	kobj_class_t driver;
 	int error, pass;
 
-	error = 0;
 	dmd = (struct driver_module_data *)arg;
-
-	/*
-	 * If MOD_SHUTDOWN is passed, return immediately in order to
-	 * avoid unnecessary locking and a LOR with the modules sx lock.
-	 */
-	if (what == MOD_SHUTDOWN)
-		return (EOPNOTSUPP);
-	NBL_XLOCK();
 	bus_devclass = devclass_find_internal(dmd->dmd_busname, NULL, TRUE);
-	if (bus_devclass == NULL) {
-		NBL_XUNLOCK();
-		return (ENOMEM);
-	}
+	error = 0;
 
-		switch (what) {
+	switch (what) {
 	case MOD_LOAD:
 		if (dmd->dmd_chainevh)
 			error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
-		if (error != 0)
-			break;
 
 		pass = dmd->dmd_pass;
 		driver = dmd->dmd_driver;
@@ -4189,7 +4180,6 @@ driver_module_handler(module_t mod, int what, void *arg)
 		error = EOPNOTSUPP;
 		break;
 	}
-	NBL_XUNLOCK();
 
 	return (error);
 }
diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c
index e6af53e67b0..3e77db7af83 100644
--- a/sys/kern/subr_kdb.c
+++ b/sys/kern/subr_kdb.c
@@ -88,7 +88,8 @@ SYSCTL_PROC(_debug_kdb, OID_AUTO, trap_code, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
  * Flag indicating whether or not to IPI the other CPUs to stop them on
  * entering the debugger.  Sometimes, this will result in a deadlock as
  * stop_cpus() waits for the other cpus to stop, so we allow it to be
- * disabled.
+ * disabled.  In order to maximize the chances of success, use a hard
+ * stop for that.
  */
 #ifdef SMP
 static int kdb_stop_cpus = 1;
@@ -226,7 +227,7 @@ kdb_panic(const char *msg)
 {
 	
 #ifdef SMP
-	stop_cpus(PCPU_GET(other_cpus));
+	stop_cpus_hard(PCPU_GET(other_cpus));
 #endif
 	printf("KDB: panic\n");
 	panic(msg);
@@ -518,7 +519,7 @@ kdb_trap(int type, int code, struct trapframe *tf)
 
 #ifdef SMP
 	if ((did_stop_cpus = kdb_stop_cpus) != 0)
-		stop_cpus(PCPU_GET(other_cpus));
+		stop_cpus_hard(PCPU_GET(other_cpus));
 #endif
 
 	kdb_active++;
diff --git a/sys/kern/subr_pcpu.c b/sys/kern/subr_pcpu.c
index c0372b0e12c..5610980eef6 100644
--- a/sys/kern/subr_pcpu.c
+++ b/sys/kern/subr_pcpu.c
@@ -313,6 +313,18 @@ sysctl_dpcpu_int(SYSCTL_HANDLER_ARGS)
 }
 
 #ifdef DDB
+DB_SHOW_COMMAND(dpcpu_off, db_show_dpcpu_off)
+{
+	int id;
+
+	for (id = 0; id <= mp_maxid; id++) {
+		if (CPU_ABSENT(id))
+			continue;
+		db_printf("dpcpu_off[%2d] = 0x%jx (+ DPCPU_START = %p)\n",
+		    id, (uintmax_t)dpcpu_off[id],
+		    (void *)(uintptr_t)(dpcpu_off[id] + DPCPU_START));
+	}
+}
 
 static void
 show_pcpu(struct pcpu *pc)
diff --git a/sys/kern/subr_sglist.c b/sys/kern/subr_sglist.c
index 7f551d99cd8..ea7716110d7 100644
--- a/sys/kern/subr_sglist.c
+++ b/sys/kern/subr_sglist.c
@@ -47,6 +47,32 @@ __FBSDID("$FreeBSD$");
 
 static MALLOC_DEFINE(M_SGLIST, "sglist", "scatter/gather lists");
 
+/*
+ * Convenience macros to save the state of an sglist so it can be restored
+ * if an append attempt fails.  Since sglist's only grow we only need to
+ * save the current count of segments and the length of the ending segment.
+ * Earlier segments will not be changed by an append, and the only change
+ * that can occur to the ending segment is that it can be extended.
+ */
+struct sgsave {
+	u_short sg_nseg;
+	size_t ss_len;
+};
+
+#define	SGLIST_SAVE(sg, sgsave) do {					\
+	(sgsave).sg_nseg = (sg)->sg_nseg;				\
+	if ((sgsave).sg_nseg > 0)					\
+		(sgsave).ss_len = (sg)->sg_segs[(sgsave).sg_nseg - 1].ss_len; \
+	else								\
+		(sgsave).ss_len = 0;					\
+} while (0)
+
+#define	SGLIST_RESTORE(sg, sgsave) do {					\
+	(sg)->sg_nseg = (sgsave).sg_nseg;				\
+	if ((sgsave).sg_nseg > 0)					\
+		(sg)->sg_segs[(sgsave).sg_nseg - 1].ss_len = (sgsave).ss_len; \
+} while (0)
+
 /*
  * Append a single (paddr, len) to a sglist.  sg is the list and ss is
  * the current segment in the list.  If we run out of segments then
@@ -62,10 +88,8 @@ _sglist_append_range(struct sglist *sg, struct sglist_seg **ssp,
 	if (ss->ss_paddr + ss->ss_len == paddr)
 		ss->ss_len += len;
 	else {
-		if (sg->sg_nseg == sg->sg_maxseg) {
-			sg->sg_nseg = 0;
+		if (sg->sg_nseg == sg->sg_maxseg)
 			return (EFBIG);
-		}
 		ss++;
 		ss->ss_paddr = paddr;
 		ss->ss_len = len;
@@ -107,26 +131,33 @@ _sglist_append_buf(struct sglist *sg, void *buf, size_t len, pmap_t pmap,
 		ss->ss_paddr = paddr;
 		ss->ss_len = seglen;
 		sg->sg_nseg = 1;
-		error = 0;
 	} else {
 		ss = &sg->sg_segs[sg->sg_nseg - 1];
 		error = _sglist_append_range(sg, &ss, paddr, seglen);
+		if (error)
+			return (error);
 	}
+	vaddr += seglen;
+	len -= seglen;
+	if (donep)
+		*donep += seglen;
 
-	while (error == 0 && len > seglen) {
-		vaddr += seglen;
-		len -= seglen;
-		if (donep)
-			*donep += seglen;
+	while (len > 0) {
 		seglen = MIN(len, PAGE_SIZE);
 		if (pmap != NULL)
 			paddr = pmap_extract(pmap, vaddr);
 		else
 			paddr = pmap_kextract(vaddr);
 		error = _sglist_append_range(sg, &ss, paddr, seglen);
+		if (error)
+			return (error);
+		vaddr += seglen;
+		len -= seglen;
+		if (donep)
+			*donep += seglen;
 	}
 
-	return (error);
+	return (0);
 }
 
 /*
@@ -195,10 +226,16 @@ sglist_free(struct sglist *sg)
 int
 sglist_append(struct sglist *sg, void *buf, size_t len)
 {
+	struct sgsave save;
+	int error;
 
 	if (sg->sg_maxseg == 0)
 		return (EINVAL);
-	return (_sglist_append_buf(sg, buf, len, NULL, NULL));
+	SGLIST_SAVE(sg, save);
+	error = _sglist_append_buf(sg, buf, len, NULL, NULL);
+	if (error)
+		SGLIST_RESTORE(sg, save);
+	return (error);
 }
 
 /*
@@ -209,6 +246,8 @@ int
 sglist_append_phys(struct sglist *sg, vm_paddr_t paddr, size_t len)
 {
 	struct sglist_seg *ss;
+	struct sgsave save;
+	int error;
 
 	if (sg->sg_maxseg == 0)
 		return (EINVAL);
@@ -222,7 +261,11 @@ sglist_append_phys(struct sglist *sg, vm_paddr_t paddr, size_t len)
 		return (0);
 	}
 	ss = &sg->sg_segs[sg->sg_nseg - 1];
-	return (_sglist_append_range(sg, &ss, paddr, len));
+	SGLIST_SAVE(sg, save);
+	error = _sglist_append_range(sg, &ss, paddr, len);
+	if (error)
+		SGLIST_RESTORE(sg, save);
+	return (error);
 }
 
 /*
@@ -233,6 +276,7 @@ sglist_append_phys(struct sglist *sg, vm_paddr_t paddr, size_t len)
 int
 sglist_append_mbuf(struct sglist *sg, struct mbuf *m0)
 {
+	struct sgsave save;
 	struct mbuf *m;
 	int error;
 
@@ -240,11 +284,14 @@ sglist_append_mbuf(struct sglist *sg, struct mbuf *m0)
 		return (EINVAL);
 
 	error = 0;
+	SGLIST_SAVE(sg, save);
 	for (m = m0; m != NULL; m = m->m_next) {
 		if (m->m_len > 0) {
 			error = sglist_append(sg, m->m_data, m->m_len);
-			if (error)
+			if (error) {
+				SGLIST_RESTORE(sg, save);
 				return (error);
+			}
 		}
 	}
 	return (0);
@@ -258,11 +305,17 @@ sglist_append_mbuf(struct sglist *sg, struct mbuf *m0)
 int
 sglist_append_user(struct sglist *sg, void *buf, size_t len, struct thread *td)
 {
+	struct sgsave save;
+	int error;
 
 	if (sg->sg_maxseg == 0)
 		return (EINVAL);
-	return (_sglist_append_buf(sg, buf, len,
-	    vmspace_pmap(td->td_proc->p_vmspace), NULL));
+	SGLIST_SAVE(sg, save);
+	error = _sglist_append_buf(sg, buf, len,
+	    vmspace_pmap(td->td_proc->p_vmspace), NULL);
+	if (error)
+		SGLIST_RESTORE(sg, save);
+	return (error);
 }
 
 /*
@@ -274,6 +327,7 @@ int
 sglist_append_uio(struct sglist *sg, struct uio *uio)
 {
 	struct iovec *iov;
+	struct sgsave save;
 	size_t resid, minlen;
 	pmap_t pmap;
 	int error, i;
@@ -292,6 +346,7 @@ sglist_append_uio(struct sglist *sg, struct uio *uio)
 		pmap = NULL;
 
 	error = 0;
+	SGLIST_SAVE(sg, save);
 	for (i = 0; i < uio->uio_iovcnt && resid != 0; i++) {
 		/*
 		 * Now at the first iovec to load.  Load each iovec
@@ -301,8 +356,10 @@ sglist_append_uio(struct sglist *sg, struct uio *uio)
 		if (minlen > 0) {
 			error = _sglist_append_buf(sg, iov[i].iov_base, minlen,
 			    pmap, NULL);
-			if (error)
+			if (error) {
+				SGLIST_RESTORE(sg, save);
 				return (error);
+			}
 			resid -= minlen;
 		}
 	}
@@ -315,7 +372,7 @@ sglist_append_uio(struct sglist *sg, struct uio *uio)
  * segments, then only the amount that fits is appended.
  */
 int
-sglist_consume_uio(struct sglist *sg, struct uio *uio, int resid)
+sglist_consume_uio(struct sglist *sg, struct uio *uio, size_t resid)
 {
 	struct iovec *iov;
 	size_t done;
@@ -397,6 +454,7 @@ sglist_clone(struct sglist *sg, int mflags)
 	new = sglist_alloc(sg->sg_maxseg, mflags);
 	if (new == NULL)
 		return (NULL);
+	new->sg_nseg = sg->sg_nseg;
 	bcopy(sg->sg_segs, new->sg_segs, sizeof(struct sglist_seg) *
 	    sg->sg_nseg);
 	return (new);
diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c
index d64e80604b3..d28001f7cc7 100644
--- a/sys/kern/subr_smp.c
+++ b/sys/kern/subr_smp.c
@@ -233,18 +233,21 @@ forward_roundrobin(void)
  * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
  *            from executing at same time.
  */
-int
-stop_cpus(cpumask_t map)
+static int
+generic_stop_cpus(cpumask_t map, u_int type)
 {
 	int i;
 
+	KASSERT(type == IPI_STOP || type == IPI_STOP_HARD,
+	    ("%s: invalid stop type", __func__));
+
 	if (!smp_started)
 		return 0;
 
-	CTR1(KTR_SMP, "stop_cpus(%x)", map);
+	CTR2(KTR_SMP, "stop_cpus(%x) with %u type", map, type);
 
 	/* send the stop IPI to all CPUs in map */
-	ipi_selected(map, IPI_STOP);
+	ipi_selected(map, type);
 
 	i = 0;
 	while ((stopped_cpus & map) != map) {
@@ -262,6 +265,20 @@ stop_cpus(cpumask_t map)
 	return 1;
 }
 
+int
+stop_cpus(cpumask_t map)
+{
+
+	return (generic_stop_cpus(map, IPI_STOP));
+}
+
+int
+stop_cpus_hard(cpumask_t map)
+{
+
+	return (generic_stop_cpus(map, IPI_STOP_HARD));
+}
+
 #if defined(__amd64__)
 /*
  * When called the executing CPU will send an IPI to all other CPUs
diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c
index bd4f34d9b9b..22c1809a8a2 100644
--- a/sys/kern/subr_taskqueue.c
+++ b/sys/kern/subr_taskqueue.c
@@ -45,11 +45,8 @@ __FBSDID("$FreeBSD$");
 static MALLOC_DEFINE(M_TASKQUEUE, "taskqueue", "Task Queues");
 static void	*taskqueue_giant_ih;
 static void	*taskqueue_ih;
-static STAILQ_HEAD(taskqueue_list, taskqueue) taskqueue_queues;
-static struct mtx taskqueue_queues_mutex;
 
 struct taskqueue {
-	STAILQ_ENTRY(taskqueue)	tq_link;
 	STAILQ_HEAD(, task)	tq_queue;
 	const char		*tq_name;
 	taskqueue_enqueue_fn	tq_enqueue;
@@ -84,8 +81,6 @@ TQ_UNLOCK(struct taskqueue *tq)
 		mtx_unlock(&tq->tq_mutex);
 }
 
-static void	init_taskqueue_list(void *data);
-
 static __inline int
 TQ_SLEEP(struct taskqueue *tq, void *p, struct mtx *m, int pri, const char *wm,
     int t)
@@ -95,16 +90,6 @@ TQ_SLEEP(struct taskqueue *tq, void *p, struct mtx *m, int pri, const char *wm,
 	return (msleep(p, m, pri, wm, t));
 }
 
-static void
-init_taskqueue_list(void *data __unused)
-{
-
-	mtx_init(&taskqueue_queues_mutex, "taskqueue list", NULL, MTX_DEF);
-	STAILQ_INIT(&taskqueue_queues);
-}
-SYSINIT(taskqueue_list, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_taskqueue_list,
-    NULL);
-
 static struct taskqueue *
 _taskqueue_create(const char *name, int mflags,
 		 taskqueue_enqueue_fn enqueue, void *context,
@@ -124,10 +109,6 @@ _taskqueue_create(const char *name, int mflags,
 	queue->tq_flags |= TQ_FLAGS_ACTIVE;
 	mtx_init(&queue->tq_mutex, mtxname, NULL, mtxflags);
 
-	mtx_lock(&taskqueue_queues_mutex);
-	STAILQ_INSERT_TAIL(&taskqueue_queues, queue, tq_link);
-	mtx_unlock(&taskqueue_queues_mutex);
-
 	return queue;
 }
 
@@ -156,10 +137,6 @@ void
 taskqueue_free(struct taskqueue *queue)
 {
 
-	mtx_lock(&taskqueue_queues_mutex);
-	STAILQ_REMOVE(&taskqueue_queues, queue, taskqueue, tq_link);
-	mtx_unlock(&taskqueue_queues_mutex);
-
 	TQ_LOCK(queue);
 	queue->tq_flags &= ~TQ_FLAGS_ACTIVE;
 	taskqueue_run(queue);
@@ -169,26 +146,6 @@ taskqueue_free(struct taskqueue *queue)
 	free(queue, M_TASKQUEUE);
 }
 
-/*
- * Returns with the taskqueue locked.
- */
-struct taskqueue *
-taskqueue_find(const char *name)
-{
-	struct taskqueue *queue;
-
-	mtx_lock(&taskqueue_queues_mutex);
-	STAILQ_FOREACH(queue, &taskqueue_queues, tq_link) {
-		if (strcmp(queue->tq_name, name) == 0) {
-			TQ_LOCK(queue);
-			mtx_unlock(&taskqueue_queues_mutex);
-			return queue;
-		}
-	}
-	mtx_unlock(&taskqueue_queues_mutex);
-	return NULL;
-}
-
 int
 taskqueue_enqueue(struct taskqueue *queue, struct task *task)
 {
@@ -401,6 +358,13 @@ taskqueue_thread_loop(void *arg)
 	TQ_LOCK(tq);
 	while ((tq->tq_flags & TQ_FLAGS_ACTIVE) != 0) {
 		taskqueue_run(tq);
+		/*
+		 * Because taskqueue_run() can drop tq_mutex, we need to
+		 * check if the TQ_FLAGS_ACTIVE flag wasn't removed in the
+		 * meantime, which means we missed a wakeup.
+		 */
+		if ((tq->tq_flags & TQ_FLAGS_ACTIVE) == 0)
+			break;
 		TQ_SLEEP(tq, tq, &tq->tq_mutex, 0, "-", 0);
 	}
 
@@ -465,3 +429,23 @@ taskqueue_fast_run(void *dummy)
 TASKQUEUE_FAST_DEFINE(fast, taskqueue_fast_enqueue, NULL,
 	swi_add(NULL, "Fast task queue", taskqueue_fast_run, NULL,
 	SWI_TQ_FAST, INTR_MPSAFE, &taskqueue_fast_ih));
+
+int
+taskqueue_member(struct taskqueue *queue, struct thread *td)
+{
+	int i, j, ret = 0;
+
+	TQ_LOCK(queue);
+	for (i = 0, j = 0; ; i++) {
+		if (queue->tq_threads[i] == NULL)
+			continue;
+		if (queue->tq_threads[i] == td) {
+			ret = 1;
+			break;
+		}
+		if (++j >= queue->tq_tcount)
+			break;
+	}
+	TQ_UNLOCK(queue);
+	return (ret);
+}
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 799dbccfea5..aa46edb60f0 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -469,8 +469,8 @@ static struct witness_lock_order_data *w_lofree = NULL;
 static struct witness_lock_order_hash w_lohash;
 static int w_max_used_index = 0;
 static unsigned int w_generation = 0;
-static const char *w_notrunning = "Witness not running\n";
-static const char *w_stillcold = "Witness is still cold\n";
+static const char w_notrunning[] = "Witness not running\n";
+static const char w_stillcold[] = "Witness is still cold\n";
 
 
 static struct witness_order_list_entry order_lists[] = {
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index de703483b0c..bd0f2793378 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -1228,6 +1228,13 @@ pollscan(td, fds, nfd)
 				selfdalloc(td, fds);
 				fds->revents = fo_poll(fp, fds->events,
 				    td->td_ucred, td);
+				/*
+				 * POSIX requires POLLOUT to be never
+				 * set simultaneously with POLLHUP.
+				 */
+				if ((fds->revents & POLLHUP) != 0)
+					fds->revents &= ~POLLOUT;
+
 				if (fds->revents != 0)
 					n++;
 			}
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index d5045c17b4d..350244b334d 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -30,14 +30,10 @@
 #include 
 __FBSDID("$FreeBSD$");
 
-#include "opt_tty.h"
-
 /* Add compatibility bits for FreeBSD. */
 #define PTS_COMPAT
-#ifdef DEV_PTY
-/* Add /dev/ptyXX compat bits. */
+/* Add pty(4) compat bits. */
 #define PTS_EXTERNAL
-#endif /* DEV_PTY */
 /* Add bits to make Linux binaries work. */
 #define PTS_LINUX
 
@@ -215,25 +211,12 @@ ptsdev_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
 		 */
 		MPASS(iblen > 0);
 		do {
-			if (ttydisc_can_bypass(tp)) {
-				/* Store data at once. */
-				rintlen = ttydisc_rint_bypass(tp,
-				    ibstart, iblen);
-				ibstart += rintlen;
-				iblen -= rintlen;
-
-				if (iblen == 0) {
-					/* All data written. */
-					break;
-				}
-			} else {
-				error = ttydisc_rint(tp, *ibstart, 0);
-				if (error == 0) {
-					/* Character stored successfully. */
-					ibstart++;
-					iblen--;
-					continue;
-				}
+			rintlen = ttydisc_rint_simple(tp, ibstart, iblen);
+			ibstart += rintlen;
+			iblen -= rintlen;
+			if (iblen == 0) {
+				/* All data written. */
+				break;
 			}
 
 			/* Maybe the device isn't used anyway. */
@@ -711,7 +694,10 @@ static struct ttydevsw pts_class = {
 	.tsw_free	= ptsdrv_free,
 };
 
-static int
+#ifndef PTS_EXTERNAL
+static
+#endif /* !PTS_EXTERNAL */
+int
 pts_alloc(int fflags, struct thread *td, struct file *fp)
 {
 	int unit, ok;
@@ -832,29 +818,11 @@ posix_openpt(struct thread *td, struct posix_openpt_args *uap)
 	return (0);
 }
 
-#if defined(PTS_COMPAT) || defined(PTS_LINUX)
-static int
-ptmx_fdopen(struct cdev *dev, int fflags, struct thread *td, struct file *fp)
-{
-
-	return (pts_alloc(fflags & (FREAD|FWRITE), td, fp));
-}
-
-static struct cdevsw ptmx_cdevsw = {
-	.d_version	= D_VERSION,
-	.d_fdopen	= ptmx_fdopen,
-	.d_name		= "ptmx",
-};
-#endif /* PTS_COMPAT || PTS_LINUX */
-
 static void
 pts_init(void *unused)
 {
 
 	pts_pool = new_unrhdr(0, INT_MAX, NULL);
-#if defined(PTS_COMPAT) || defined(PTS_LINUX)
-	make_dev(&ptmx_cdevsw, 0, UID_ROOT, GID_WHEEL, 0666, "ptmx");
-#endif /* PTS_COMPAT || PTS_LINUX */
 }
 
 SYSINIT(pts, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, pts_init, NULL);
diff --git a/sys/kern/tty_ttydisc.c b/sys/kern/tty_ttydisc.c
index debaa1cc1e9..d79a2b761d5 100644
--- a/sys/kern/tty_ttydisc.c
+++ b/sys/kern/tty_ttydisc.c
@@ -1044,6 +1044,22 @@ print:
 	return (0);
 }
 
+size_t
+ttydisc_rint_simple(struct tty *tp, const void *buf, size_t len)
+{
+	const char *cbuf;
+
+	if (ttydisc_can_bypass(tp))
+		return (ttydisc_rint_bypass(tp, buf, len));
+
+	for (cbuf = buf; len-- > 0; cbuf++) {
+		if (ttydisc_rint(tp, *cbuf, 0) != 0)
+			break;
+	}
+
+	return (cbuf - (const char *)buf);
+}
+
 size_t
 ttydisc_rint_bypass(struct tty *tp, const void *buf, size_t len)
 {
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 257e9fae775..0d5043e3ee7 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -336,6 +336,7 @@ found:
 int
 pf_proto_register(int family, struct protosw *npr)
 {
+	VNET_ITERATOR_DECL(vnet_iter);
 	struct domain *dp;
 	struct protosw *pr, *fpr;
 
@@ -391,7 +392,13 @@ found:
 	mtx_unlock(&dom_mtx);
 
 	/* Initialize and activate the protocol. */
-	protosw_init(fpr);
+	VNET_LIST_RLOCK();
+	VNET_FOREACH(vnet_iter) {
+		CURVNET_SET_QUIET(vnet_iter);
+		protosw_init(fpr);
+		CURVNET_RESTORE();
+	}
+	VNET_LIST_RUNLOCK();
 
 	return (0);
 }
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index f21f4afc881..78548033ea2 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -416,7 +416,8 @@ retry_wlocked:
 				if (dvp->v_cache_dd->nc_flag & NCF_ISDOTDOT)
 					cache_zap(dvp->v_cache_dd);
 				dvp->v_cache_dd = NULL;
-				goto unlock;
+				CACHE_WUNLOCK();
+				return (0);
 			}
 			if (dvp->v_cache_dd->nc_flag & NCF_ISDOTDOT)
 				*vpp = dvp->v_cache_dd->nc_vp;
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index f5705f9ca06..0a8ef463957 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -3134,8 +3134,7 @@ getutimes(usrtvp, tvpseg, tsp)
 	int error;
 
 	if (usrtvp == NULL) {
-		microtime(&tv[0]);
-		TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
+		vfs_timestamp(&tsp[0]);
 		tsp[1] = tsp[0];
 	} else {
 		if (tvpseg == UIO_SYSSPACE) {
@@ -4440,12 +4439,15 @@ fhopen(td, uap)
 			goto bad;
 	}
 	if (fmode & O_TRUNC) {
+		vfs_ref(mp);
 		VOP_UNLOCK(vp, 0);				/* XXX */
 		if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
 			vrele(vp);
+			vfs_rel(mp);
 			goto out;
 		}
 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);	/* XXX */
+		vfs_rel(mp);
 #ifdef MAC
 		/*
 		 * We don't yet have fp->f_cred, so use td->td_ucred, which
@@ -4517,7 +4519,6 @@ fhopen(td, uap)
 
 	VOP_UNLOCK(vp, 0);
 	fdrop(fp, td);
-	vfs_rel(mp);
 	VFS_UNLOCK_GIANT(vfslocked);
 	td->td_retval[0] = indx;
 	return (0);
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index f67064613e0..1b77352b1c6 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -999,7 +999,8 @@ vn_start_write(vp, mpp, flags)
 		goto unlock;
 	mp->mnt_writeopcount++;
 unlock:
-	MNT_REL(mp);
+	if (error != 0 || (flags & V_XSLEEP) != 0)
+		MNT_REL(mp);
 	MNT_IUNLOCK(mp);
 	return (error);
 }
@@ -1049,7 +1050,6 @@ vn_start_secondary_write(vp, mpp, flags)
 	if ((mp->mnt_kern_flag & (MNTK_SUSPENDED | MNTK_SUSPEND2)) == 0) {
 		mp->mnt_secondary_writes++;
 		mp->mnt_secondary_accwrites++;
-		MNT_REL(mp);
 		MNT_IUNLOCK(mp);
 		return (0);
 	}
@@ -1081,6 +1081,7 @@ vn_finished_write(mp)
 	if (mp == NULL)
 		return;
 	MNT_ILOCK(mp);
+	MNT_REL(mp);
 	mp->mnt_writeopcount--;
 	if (mp->mnt_writeopcount < 0)
 		panic("vn_finished_write: neg cnt");
@@ -1103,6 +1104,7 @@ vn_finished_secondary_write(mp)
 	if (mp == NULL)
 		return;
 	MNT_ILOCK(mp);
+	MNT_REL(mp);
 	mp->mnt_secondary_writes--;
 	if (mp->mnt_secondary_writes < 0)
 		panic("vn_finished_secondary_write: neg cnt");
diff --git a/sys/mips/include/smp.h b/sys/mips/include/smp.h
index 798beed245c..d614dd3dbf9 100644
--- a/sys/mips/include/smp.h
+++ b/sys/mips/include/smp.h
@@ -24,6 +24,7 @@
 #define	IPI_RENDEZVOUS		0x0002
 #define	IPI_AST			0x0004
 #define	IPI_STOP		0x0008
+#define	IPI_STOP_HARD		0x0008
 
 #ifndef LOCORE
 
diff --git a/sys/mips/mips/mp_machdep.c b/sys/mips/mips/mp_machdep.c
index d688a52b24e..bf323922d72 100644
--- a/sys/mips/mips/mp_machdep.c
+++ b/sys/mips/mips/mp_machdep.c
@@ -129,7 +129,12 @@ smp_handle_ipi(struct trapframe *frame)
 			break;
 
 		case IPI_STOP:
-			CTR0(KTR_SMP, "IPI_STOP");
+
+			/*
+			 * IPI_STOP_HARD is mapped to IPI_STOP so it is not
+			 * necessary to add it in the switch.
+			 */
+			CTR0(KTR_SMP, "IPI_STOP or IPI_STOP_HARD");
 			atomic_set_int(&stopped_cpus, cpumask);
 
 			while ((started_cpus & cpumask) == 0)
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 30d21963564..51408b3b6bb 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -40,6 +40,7 @@ SUBDIR=	${_3dfx} \
 	${_bktr} \
 	${_bm} \
 	bridgestp \
+	bwi \
 	cam \
 	${_canbepm} \
 	${_canbus} \
@@ -225,6 +226,7 @@ SUBDIR=	${_3dfx} \
 	procfs \
 	pseudofs \
 	${_pst} \
+	pty  \
 	puc \
 	ral \
 	ralfw \
diff --git a/sys/modules/drm/radeon/Makefile b/sys/modules/drm/radeon/Makefile
index 4b8b7d17842..72c364bdd55 100644
--- a/sys/modules/drm/radeon/Makefile
+++ b/sys/modules/drm/radeon/Makefile
@@ -2,8 +2,8 @@
 
 .PATH:	${.CURDIR}/../../../dev/drm
 KMOD	= radeon
-SRCS	= r300_cmdbuf.c r600_cp.c radeon_cp.c radeon_drv.c radeon_irq.c \
-	radeon_mem.c radeon_state.c
+SRCS	= r300_cmdbuf.c r600_blit.c r600_cp.c radeon_cp.c radeon_cs.c \
+	radeon_drv.c radeon_irq.c radeon_mem.c radeon_state.c
 SRCS	+=device_if.h bus_if.h pci_if.h opt_drm.h
 
 .include 
diff --git a/sys/modules/pty/Makefile b/sys/modules/pty/Makefile
new file mode 100644
index 00000000000..fd563fe1e2f
--- /dev/null
+++ b/sys/modules/pty/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/pty
+
+KMOD=	pty
+SRCS=	pty.c
+
+.include 
diff --git a/sys/modules/zfs/Makefile b/sys/modules/zfs/Makefile
index fc7049df56b..c95a8409ed4 100644
--- a/sys/modules/zfs/Makefile
+++ b/sys/modules/zfs/Makefile
@@ -23,6 +23,7 @@ SRCS+=	opensolaris_kstat.c
 SRCS+=	opensolaris_lookup.c
 SRCS+=	opensolaris_policy.c
 SRCS+=	opensolaris_string.c
+SRCS+=	opensolaris_taskq.c
 SRCS+=	opensolaris_vfs.c
 SRCS+=	opensolaris_zone.c
 
@@ -42,7 +43,6 @@ SRCS+=	vnode.c
 SRCS+=	callb.c
 SRCS+=	list.c
 SRCS+=	nvpair_alloc_system.c
-SRCS+=	taskq.c
 
 .PATH:	${SUNW}/uts/common/zmod
 SRCS+=	adler32.c
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 08c9a5eee26..9656a6e7b3d 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -1585,6 +1585,9 @@ void
 bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
 {
 	struct bpf_d *d;
+#ifdef BPF_JITTER
+	bpf_jit_filter *bf;
+#endif
 	u_int slen;
 	int gottime;
 	struct timeval tv;
@@ -1601,8 +1604,9 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
 		 * the interface pointers on the mbuf to figure it out.
 		 */
 #ifdef BPF_JITTER
-		if (bpf_jitter_enable != 0 && d->bd_bfilter != NULL)
-			slen = (*(d->bd_bfilter->func))(pkt, pktlen, pktlen);
+		bf = bpf_jitter_enable != 0 ? d->bd_bfilter : NULL;
+		if (bf != NULL)
+			slen = (*(bf->func))(pkt, pktlen, pktlen);
 		else
 #endif
 		slen = bpf_filter(d->bd_rfilter, pkt, pktlen, pktlen);
@@ -1634,6 +1638,9 @@ void
 bpf_mtap(struct bpf_if *bp, struct mbuf *m)
 {
 	struct bpf_d *d;
+#ifdef BPF_JITTER
+	bpf_jit_filter *bf;
+#endif
 	u_int pktlen, slen;
 	int gottime;
 	struct timeval tv;
@@ -1655,11 +1662,10 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m)
 		BPFD_LOCK(d);
 		++d->bd_rcount;
 #ifdef BPF_JITTER
+		bf = bpf_jitter_enable != 0 ? d->bd_bfilter : NULL;
 		/* XXX We cannot handle multiple mbufs. */
-		if (bpf_jitter_enable != 0 && d->bd_bfilter != NULL &&
-		    m->m_next == NULL)
-			slen = (*(d->bd_bfilter->func))(mtod(m, u_char *),
-			    pktlen, pktlen);
+		if (bf != NULL && m->m_next == NULL)
+			slen = (*(bf->func))(mtod(m, u_char *), pktlen, pktlen);
 		else
 #endif
 		slen = bpf_filter(d->bd_rfilter, (u_char *)m, pktlen, 0);
diff --git a/sys/net/bpf_buffer.c b/sys/net/bpf_buffer.c
index 5f740b31fc3..8924c8841fc 100644
--- a/sys/net/bpf_buffer.c
+++ b/sys/net/bpf_buffer.c
@@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#include 
 #include 
 
 /*
diff --git a/sys/net/bpf_zerocopy.c b/sys/net/bpf_zerocopy.c
index 35b27b9c02c..a1dd923a4f5 100644
--- a/sys/net/bpf_zerocopy.c
+++ b/sys/net/bpf_zerocopy.c
@@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
 
 #include 
 #include 
-#include 
 #include 
 #include 
 
diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h
index 2ff3d5e9216..5784763ed8a 100644
--- a/sys/net/bpfdesc.h
+++ b/sys/net/bpfdesc.h
@@ -72,9 +72,7 @@ struct bpf_d {
 	u_long		bd_rtout;	/* Read timeout in 'ticks' */
 	struct bpf_insn *bd_rfilter; 	/* read filter code */
 	struct bpf_insn *bd_wfilter;	/* write filter code */
-#ifdef BPF_JITTER
-	bpf_jit_filter	*bd_bfilter;	/* binary filter code */
-#endif
+	void		*bd_bfilter;	/* binary filter code */
 	u_int64_t	bd_rcount;	/* number of packets received */
 	u_int64_t	bd_dcount;	/* number of packets dropped */
 
diff --git a/sys/net/bridgestp.c b/sys/net/bridgestp.c
index 3e65113c2d5..2993838ac68 100644
--- a/sys/net/bridgestp.c
+++ b/sys/net/bridgestp.c
@@ -2019,7 +2019,7 @@ bstp_reinit(struct bstp_state *bs)
 	 * not need to be part of the bridge, it just needs to be a unique
 	 * value.
 	 */
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		if (ifp->if_type != IFT_ETHER)
 			continue;
@@ -2036,7 +2036,7 @@ bstp_reinit(struct bstp_state *bs)
 			continue;
 		}
 	}
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 
 	if (LIST_EMPTY(&bs->bs_bplist) || mif == NULL) {
 		/* Set the bridge and root id (lower bits) to zero */
diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
index 4078ae9138e..22cab54e47a 100644
--- a/sys/net/flowtable.c
+++ b/sys/net/flowtable.c
@@ -29,6 +29,7 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include "opt_route.h"
 #include "opt_mpath.h"
+#include "opt_ddb.h"
 
 #include 
 __FBSDID("$FreeBSD$");
@@ -36,6 +37,7 @@ __FBSDID("$FreeBSD$");
 #include   
 #include 
 #include 
+#include 
 #include 
 #include   
 #include 
@@ -66,6 +68,7 @@ __FBSDID("$FreeBSD$");
 #include 
 
 #include 
+#include 
 
 struct ipv4_tuple {
 	uint16_t 	ip_sport;	/* source port */
@@ -94,8 +97,9 @@ union ipv6_flow {
 struct flentry {
 	volatile uint32_t	f_fhash;	/* hash flowing forward */
 	uint16_t		f_flags;	/* flow flags */
-	uint8_t			f_pad;		/* alignment */
+	uint8_t			f_pad;		
 	uint8_t			f_proto;	/* protocol */
+	uint32_t		f_fibnum;	/* fib index */
 	uint32_t		f_uptime;	/* uptime at last access */
 	struct flentry		*f_next;	/* pointer to collision entry */
 	volatile struct rtentry *f_rt;		/* rtentry for flow */
@@ -173,6 +177,10 @@ static VNET_DEFINE(uma_zone_t, flow_ipv6_zone);
 #define	V_flow_ipv4_zone	VNET(flow_ipv4_zone)
 #define	V_flow_ipv6_zone	VNET(flow_ipv6_zone)
 
+static struct cv 	flowclean_cv;
+static struct mtx	flowclean_lock;
+static uint32_t		flowclean_cycles;
+
 /*
  * TODO:
  * - Make flowtable stats per-cpu, aggregated at sysctl call time,
@@ -191,6 +199,7 @@ static VNET_DEFINE(uma_zone_t, flow_ipv6_zone);
  * - idetach() cleanup for options VIMAGE builds.
  */
 VNET_DEFINE(int, flowtable_enable) = 1;
+static VNET_DEFINE(int, flowtable_debug);
 static VNET_DEFINE(int, flowtable_hits);
 static VNET_DEFINE(int, flowtable_lookups);
 static VNET_DEFINE(int, flowtable_misses);
@@ -203,8 +212,10 @@ static VNET_DEFINE(int, flowtable_udp_expire) = UDP_IDLE;
 static VNET_DEFINE(int, flowtable_fin_wait_expire) = FIN_WAIT_IDLE;
 static VNET_DEFINE(int, flowtable_tcp_expire) = TCP_IDLE;
 static VNET_DEFINE(int, flowtable_nmbflows) = 4096;
+static VNET_DEFINE(int, flowtable_ready) = 0;
 
 #define	V_flowtable_enable		VNET(flowtable_enable)
+#define	V_flowtable_debug		VNET(flowtable_debug)
 #define	V_flowtable_hits		VNET(flowtable_hits)
 #define	V_flowtable_lookups		VNET(flowtable_lookups)
 #define	V_flowtable_misses		VNET(flowtable_misses)
@@ -217,8 +228,11 @@ static VNET_DEFINE(int, flowtable_nmbflows) = 4096;
 #define	V_flowtable_fin_wait_expire	VNET(flowtable_fin_wait_expire)
 #define	V_flowtable_tcp_expire		VNET(flowtable_tcp_expire)
 #define	V_flowtable_nmbflows		VNET(flowtable_nmbflows)
+#define	V_flowtable_ready		VNET(flowtable_ready)
 
 SYSCTL_NODE(_net_inet, OID_AUTO, flowtable, CTLFLAG_RD, NULL, "flowtable");
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, debug, CTLFLAG_RW,
+    &VNET_NAME(flowtable_debug), 0, "print debug info.");
 SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, enable, CTLFLAG_RW,
     &VNET_NAME(flowtable_enable), 0, "enable flowtable caching.");
 SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, hits, CTLFLAG_RD,
@@ -286,10 +300,10 @@ SYSCTL_VNET_PROC(_net_inet_flowtable, OID_AUTO, nmbflows,
 
 #ifndef RADIX_MPATH
 static void
-in_rtalloc_ign_wrapper(struct route *ro, uint32_t hash, u_int fib)
+in_rtalloc_ign_wrapper(struct route *ro, uint32_t hash, u_int fibnum)
 {
 
-	rtalloc_ign_fib(ro, 0, fib);
+	rtalloc_ign_fib(ro, 0, fibnum);
 }
 #endif
 
@@ -345,7 +359,7 @@ ipv4_flow_lookup_hash_internal(struct mbuf *m, struct route *ro,
 	struct udphdr *uh;
 	struct sctphdr *sh;
 
-	if (V_flowtable_enable == 0)
+	if ((V_flowtable_enable == 0) || (V_flowtable_ready == 0))
 		return (0);
 
 	key[1] = key[0] = 0;
@@ -423,7 +437,7 @@ static bitstr_t *
 flowtable_mask(struct flowtable *ft)
 {
 	bitstr_t *mask;
-	
+
 	if (ft->ft_flags & FL_PCPU)
 		mask = ft->ft_masks[curcpu];
 	else
@@ -499,7 +513,7 @@ flowtable_set_hashkey(struct flentry *fle, uint32_t *key)
 
 static int
 flowtable_insert(struct flowtable *ft, uint32_t hash, uint32_t *key,
-    uint8_t proto, struct route *ro, uint16_t flags)
+    uint8_t proto, uint32_t fibnum, struct route *ro, uint16_t flags)
 {
 	struct flentry *fle, *fletail, *newfle, **flep;
 	int depth;
@@ -562,6 +576,7 @@ skip:
 	fle->f_rt = ro->ro_rt;
 	fle->f_lle = ro->ro_lle;
 	fle->f_fhash = hash;
+	fle->f_fibnum = fibnum;
 	fle->f_uptime = time_uptime;
 	FL_ENTRY_UNLOCK(ft, hash);
 	return (0);
@@ -589,13 +604,13 @@ flowtable_key_equal(struct flentry *fle, uint32_t *key)
 }
 
 int
-flowtable_lookup(struct flowtable *ft, struct mbuf *m, struct route *ro)
+flowtable_lookup(struct flowtable *ft, struct mbuf *m, struct route *ro, uint32_t fibnum)
 {
 	uint32_t key[9], hash;
 	struct flentry *fle;
 	uint16_t flags;
 	uint8_t proto = 0;
-	int error = 0, fib = 0;
+	int error = 0;
 	struct rtentry *rt;
 	struct llentry *lle;
 
@@ -638,6 +653,7 @@ keycheck:
 	    && fle->f_fhash == hash
 	    && flowtable_key_equal(fle, key)
 	    && (proto == fle->f_proto)
+	    && (fibnum == fle->f_fibnum)
 	    && (rt->rt_flags & RTF_UP)
 	    && (rt->rt_ifp != NULL)) {
 		V_flowtable_hits++;
@@ -666,10 +682,8 @@ uncached:
 	 * of arpresolve with an rt_check variant that expected to
 	 * receive the route locked
 	 */
-	if (m != NULL)
-		fib = M_GETFIB(m);
 
-	ft->ft_rtalloc(ro, hash, fib);
+	ft->ft_rtalloc(ro, hash, fibnum);
 	if (ro->ro_rt == NULL) 
 		error = ENETUNREACH;
 	else {
@@ -678,6 +692,12 @@ uncached:
 		struct rtentry *rt = ro->ro_rt;
 		struct ifnet *ifp = rt->rt_ifp;
 
+		if (ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) {
+			RTFREE(rt);
+			ro->ro_rt = NULL;
+			return (ENOENT);
+		}
+
 		if (rt->rt_flags & RTF_GATEWAY)
 			l3addr = rt->rt_gateway;
 		else
@@ -690,7 +710,7 @@ uncached:
 			ro->ro_rt = NULL;
 			return (ENOENT);
 		}
-		error = flowtable_insert(ft, hash, key, proto,
+		error = flowtable_insert(ft, hash, key, proto, fibnum,
 		    ro, flags);
 				
 		if (error) {
@@ -789,34 +809,6 @@ flowtable_alloc(int nentry, int flags)
 	return (ft);
 }
 
-static void
-flowtable_init(const void *unused __unused)
-{
-
-	V_flow_ipv4_zone = uma_zcreate("ip4flow", sizeof(struct flentry_v4),
-	    NULL, NULL, NULL, NULL, 64, UMA_ZONE_MAXBUCKET);
-	V_flow_ipv6_zone = uma_zcreate("ip6flow", sizeof(struct flentry_v6),
-	    NULL, NULL, NULL, NULL, 64, UMA_ZONE_MAXBUCKET);	
-	uma_zone_set_max(V_flow_ipv4_zone, V_flowtable_nmbflows);
-	uma_zone_set_max(V_flow_ipv6_zone, V_flowtable_nmbflows);
-}
-
-VNET_SYSINIT(flowtable_init, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
-    flowtable_init, NULL);
-
-#ifdef VIMAGE
-static void
-flowtable_uninit(const void *unused __unused)
-{
-
-	uma_zdestroy(V_flow_ipv4_zone);
-	uma_zdestroy(V_flow_ipv6_zone);
-}
-
-VNET_SYSUNINIT(flowtable_uninit, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
-    flowtable_uninit, NULL);
-#endif
-
 /*
  * The rest of the code is devoted to garbage collection of expired entries.
  * It is a new additon made necessary by the switch to dynamically allocating
@@ -920,7 +912,7 @@ flowtable_free_stale(struct flowtable *ft)
 		V_flowtable_frees++;
 		fle_free(fle);
 	}
-	if (bootverbose && count)
+	if (V_flowtable_debug && count)
 		log(LOG_DEBUG, "freed %d flow entries\n", count);
 }
 
@@ -970,14 +962,32 @@ flowtable_cleaner(void)
 		}
 		VNET_LIST_RUNLOCK();
 
+		flowclean_cycles++;
 		/*
-		 * The 20 second interval between cleaning checks
+		 * The 10 second interval between cleaning checks
 		 * is arbitrary
 		 */
-		pause("flowcleanwait", 20*hz);
+		mtx_lock(&flowclean_lock);
+		cv_broadcast(&flowclean_cv);
+		cv_timedwait(&flowclean_cv, &flowclean_lock, 10*hz);
+		mtx_unlock(&flowclean_lock);
 	}
 }
 
+static void
+flowtable_flush(void *unused __unused)
+{
+	uint64_t start;
+	
+	mtx_lock(&flowclean_lock);
+	start = flowclean_cycles;
+	while (start == flowclean_cycles) {
+		cv_broadcast(&flowclean_cv);
+		cv_wait(&flowclean_cv, &flowclean_lock);
+	}
+	mtx_unlock(&flowclean_lock);
+}
+
 static struct kproc_desc flow_kp = {
 	"flowcleaner",
 	flowtable_cleaner,
@@ -985,3 +995,160 @@ static struct kproc_desc flow_kp = {
 };
 SYSINIT(flowcleaner, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, kproc_start, &flow_kp);
 
+static void
+flowtable_init_vnet(const void *unused __unused)
+{
+
+	V_flow_ipv4_zone = uma_zcreate("ip4flow", sizeof(struct flentry_v4),
+	    NULL, NULL, NULL, NULL, 64, UMA_ZONE_MAXBUCKET);
+	V_flow_ipv6_zone = uma_zcreate("ip6flow", sizeof(struct flentry_v6),
+	    NULL, NULL, NULL, NULL, 64, UMA_ZONE_MAXBUCKET);	
+	uma_zone_set_max(V_flow_ipv4_zone, V_flowtable_nmbflows);
+	uma_zone_set_max(V_flow_ipv6_zone, V_flowtable_nmbflows);
+	V_flowtable_ready = 1;
+}
+VNET_SYSINIT(flowtable_init_vnet, SI_SUB_KTHREAD_INIT, SI_ORDER_MIDDLE,
+    flowtable_init_vnet, NULL);
+
+static void
+flowtable_init(const void *unused __unused)
+{
+
+	cv_init(&flowclean_cv, "flowcleanwait");
+	mtx_init(&flowclean_lock, "flowclean lock", NULL, MTX_DEF);
+	EVENTHANDLER_REGISTER(ifnet_departure_event, flowtable_flush, NULL,
+	    EVENTHANDLER_PRI_ANY);
+}
+SYSINIT(flowtable_init, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
+    flowtable_init, NULL);
+
+
+#ifdef VIMAGE
+static void
+flowtable_uninit(const void *unused __unused)
+{
+
+	V_flowtable_ready = 0;
+	uma_zdestroy(V_flow_ipv4_zone);
+	uma_zdestroy(V_flow_ipv6_zone);
+}
+
+VNET_SYSUNINIT(flowtable_uninit, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
+    flowtable_uninit, NULL);
+#endif
+
+#ifdef DDB
+static bitstr_t *
+flowtable_mask_pcpu(struct flowtable *ft, int cpuid)
+{
+	bitstr_t *mask;
+
+	if (ft->ft_flags & FL_PCPU)
+		mask = ft->ft_masks[cpuid];
+	else
+		mask = ft->ft_masks[0];
+
+	return (mask);
+}
+
+static struct flentry **
+flowtable_entry_pcpu(struct flowtable *ft, uint32_t hash, int cpuid)
+{
+	struct flentry **fle;
+	int index = (hash % ft->ft_size);
+
+	if (ft->ft_flags & FL_PCPU) {
+		fle = &ft->ft_table.pcpu[cpuid][index];
+	} else {
+		fle = &ft->ft_table.global[index];
+	}
+	
+	return (fle);
+}
+
+static void
+flow_show(struct flowtable *ft, struct flentry *fle)
+{
+	int idle_time;
+	int rt_valid;
+
+	idle_time = (int)(time_uptime - fle->f_uptime);
+	rt_valid = fle->f_rt != NULL;
+	db_printf("hash=0x%08x idle_time=%03d rt=%p ifp=%p",
+	    fle->f_fhash, idle_time,
+	    fle->f_rt, rt_valid ? fle->f_rt->rt_ifp : NULL);
+	if (rt_valid && (fle->f_rt->rt_flags & RTF_UP))
+		db_printf(" RTF_UP ");
+	if (fle->f_flags & FL_STALE)
+		db_printf(" FL_STALE ");
+	db_printf("\n");
+}
+
+static void
+flowtable_show(struct flowtable *ft, int cpuid)
+{
+	int curbit = 0;
+	struct flentry *fle,  **flehead;
+	bitstr_t *mask, *tmpmask;
+
+	db_printf("cpu: %d\n", cpuid);
+	mask = flowtable_mask_pcpu(ft, cpuid);
+	tmpmask = ft->ft_tmpmask;
+	memcpy(tmpmask, mask, ft->ft_size/8);
+	/*
+	 * XXX Note to self, bit_ffs operates at the byte level
+	 * and thus adds gratuitous overhead
+	 */
+	bit_ffs(tmpmask, ft->ft_size, &curbit);
+	while (curbit != -1) {
+		if (curbit >= ft->ft_size || curbit < -1) {
+			db_printf("warning: bad curbit value %d \n",
+			    curbit);
+			break;
+		}
+
+		flehead = flowtable_entry_pcpu(ft, curbit, cpuid);
+		fle = *flehead;
+
+		while (fle != NULL) {	
+			flow_show(ft, fle);
+			fle = fle->f_next;
+			continue;
+		}
+		bit_clear(tmpmask, curbit);
+		bit_ffs(tmpmask, ft->ft_size, &curbit);
+	}
+}
+
+static void
+flowtable_show_vnet(void)
+{
+	struct flowtable *ft;
+	int i;
+
+	ft = V_flow_list_head;
+	while (ft != NULL) {
+		if (ft->ft_flags & FL_PCPU) {
+			for (i = 0; i <= mp_maxid; i++) {
+				if (CPU_ABSENT(i))
+					continue;
+				flowtable_show(ft, i);
+			}
+		} else {
+			flowtable_show(ft, 0);
+		}
+		ft = ft->ft_next;
+	}
+}
+
+DB_SHOW_COMMAND(flowtables, db_show_flowtables)
+{
+	VNET_ITERATOR_DECL(vnet_iter);
+
+	VNET_FOREACH(vnet_iter) {
+		CURVNET_SET(vnet_iter);
+		flowtable_show_vnet();
+		CURVNET_RESTORE();
+	}
+}
+#endif
diff --git a/sys/net/flowtable.h b/sys/net/flowtable.h
index 6334d8b42b0..afc8fb77a03 100644
--- a/sys/net/flowtable.h
+++ b/sys/net/flowtable.h
@@ -49,7 +49,7 @@ struct flowtable *flowtable_alloc(int nentry, int flags);
  *
  */
 int flowtable_lookup(struct flowtable *ft, struct mbuf *m,
-    struct route *ro);
+    struct route *ro, uint32_t fibnum);
 
 #endif /* _KERNEL */
 #endif
diff --git a/sys/net/if.c b/sys/net/if.c
index 3ac7db05c14..36c0d037b9a 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -124,6 +124,7 @@ static void	if_attachdomain1(struct ifnet *);
 static int	ifconf(u_long, caddr_t);
 static void	if_freemulti(struct ifmultiaddr *);
 static void	if_init(void *);
+static void	if_grow(void);
 static void	if_check(void *);
 static void	if_route(struct ifnet *, int flag, int fam);
 static int	if_setflag(struct ifnet *, int, int, int *, int);
@@ -154,14 +155,33 @@ VNET_DEFINE(struct ifgrouphead, ifg_head);
 VNET_DEFINE(int, if_index);
 static VNET_DEFINE(int, if_indexlim) = 8;
 
-/* Table of ifnet by index.  Locked with ifnet_lock. */
+/* Table of ifnet by index. */
 static VNET_DEFINE(struct ifindex_entry *, ifindex_table);
 
 #define	V_if_indexlim		VNET(if_indexlim)
 #define	V_ifindex_table		VNET(ifindex_table)
 
 int	ifqmaxlen = IFQ_MAXLEN;
-struct rwlock ifnet_lock;
+
+/*
+ * The global network interface list (V_ifnet) and related state (such as
+ * if_index, if_indexlim, and ifindex_table) are protected by an sxlock and
+ * an rwlock.  Either may be acquired shared to stablize the list, but both
+ * must be acquired writable to modify the list.  This model allows us to
+ * both stablize the interface list during interrupt thread processing, but
+ * also to stablize it over long-running ioctls, without introducing priority
+ * inversions and deadlocks.
+ */
+struct rwlock ifnet_rwlock;
+struct sx ifnet_sxlock;
+
+/*
+ * The allocation of network interfaces is a rather non-atomic affair; we
+ * need to select an index before we are ready to expose the interface for
+ * use, so will use this pointer value to indicate reservation.
+ */
+#define	IFNET_HOLD	(void *)(uintptr_t)(-1)
+
 static	if_com_alloc_t *if_com_alloc[256];
 static	if_com_free_t *if_com_free[256];
 
@@ -180,6 +200,8 @@ ifnet_byindex_locked(u_short idx)
 
 	if (idx > V_if_index)
 		return (NULL);
+	if (V_ifindex_table[idx].ife_ifnet == IFNET_HOLD)
+		return (NULL);
 	return (V_ifindex_table[idx].ife_ifnet);
 }
 
@@ -188,9 +210,9 @@ ifnet_byindex(u_short idx)
 {
 	struct ifnet *ifp;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	ifp = ifnet_byindex_locked(idx);
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	return (ifp);
 }
 
@@ -199,19 +221,71 @@ ifnet_byindex_ref(u_short idx)
 {
 	struct ifnet *ifp;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	ifp = ifnet_byindex_locked(idx);
 	if (ifp == NULL || (ifp->if_flags & IFF_DYING)) {
-		IFNET_RUNLOCK();
+		IFNET_RUNLOCK_NOSLEEP();
 		return (NULL);
 	}
 	if_ref(ifp);
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	return (ifp);
 }
 
+/*
+ * Allocate an ifindex array entry; return 0 on success or an error on
+ * failure.
+ */
+static int
+ifindex_alloc_locked(u_short *idxp)
+{
+	u_short idx;
+
+	IFNET_WLOCK_ASSERT();
+
+	/*
+	 * Try to find an empty slot below V_if_index.  If we fail, take the
+	 * next slot.
+	 */
+	for (idx = 1; idx <= V_if_index; idx++) {
+		if (V_ifindex_table[idx].ife_ifnet == NULL)
+			break;
+	}
+
+	/* Catch if_index overflow. */
+	if (idx < 1)
+		return (ENOSPC);
+	if (idx > V_if_index)
+		V_if_index = idx;
+	if (V_if_index >= V_if_indexlim)
+		if_grow();
+	*idxp = idx;
+	return (0);
+}
+
 static void
-ifnet_setbyindex(u_short idx, struct ifnet *ifp)
+ifindex_free_locked(u_short idx)
+{
+
+	IFNET_WLOCK_ASSERT();
+
+	V_ifindex_table[idx].ife_ifnet = NULL;
+	while (V_if_index > 0 &&
+	    V_ifindex_table[V_if_index].ife_ifnet == NULL)
+		V_if_index--;
+}
+
+static void
+ifindex_free(u_short idx)
+{
+
+	IFNET_WLOCK();
+	ifindex_free_locked(idx);
+	IFNET_WUNLOCK();
+}
+
+static void
+ifnet_setbyindex_locked(u_short idx, struct ifnet *ifp)
 {
 
 	IFNET_WLOCK_ASSERT();
@@ -219,16 +293,25 @@ ifnet_setbyindex(u_short idx, struct ifnet *ifp)
 	V_ifindex_table[idx].ife_ifnet = ifp;
 }
 
+static void
+ifnet_setbyindex(u_short idx, struct ifnet *ifp)
+{
+
+	IFNET_WLOCK();
+	ifnet_setbyindex_locked(idx, ifp);
+	IFNET_WUNLOCK();
+}
+
 struct ifaddr *
 ifaddr_byindex(u_short idx)
 {
 	struct ifaddr *ifa;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	ifa = ifnet_byindex_locked(idx)->if_addr;
 	if (ifa != NULL)
 		ifa_ref(ifa);
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	return (ifa);
 }
 
@@ -276,7 +359,7 @@ VNET_SYSUNINIT(vnet_if_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST,
     vnet_if_uninit, NULL);
 #endif
 
-void
+static void
 if_grow(void)
 {
 	u_int n;
@@ -313,36 +396,25 @@ struct ifnet *
 if_alloc(u_char type)
 {
 	struct ifnet *ifp;
+	u_short idx;
 
 	ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO);
-
-	/*
-	 * Try to find an empty slot below if_index.  If we fail, take
-	 * the next slot.
-	 *
-	 * XXX: should be locked!
-	 */
-	for (ifp->if_index = 1; ifp->if_index <= V_if_index; ifp->if_index++) {
-		if (ifnet_byindex(ifp->if_index) == NULL)
-			break;
-	}
-	/* Catch if_index overflow. */
-	if (ifp->if_index < 1) {
+	IFNET_WLOCK();
+	if (ifindex_alloc_locked(&idx) != 0) {
+		IFNET_WUNLOCK();
 		free(ifp, M_IFNET);
 		return (NULL);
 	}
-	if (ifp->if_index > V_if_index)
-		V_if_index = ifp->if_index;
-	if (V_if_index >= V_if_indexlim)
-		if_grow();
-
+	ifnet_setbyindex_locked(idx, IFNET_HOLD);
+	IFNET_WUNLOCK();
+	ifp->if_index = idx;
 	ifp->if_type = type;
 	ifp->if_alloctype = type;
-
 	if (if_com_alloc[type] != NULL) {
 		ifp->if_l2com = if_com_alloc[type](type, ifp);
 		if (ifp->if_l2com == NULL) {
 			free(ifp, M_IFNET);
+			ifindex_free(idx);
 			return (NULL);
 		}
 	}
@@ -361,9 +433,7 @@ if_alloc(u_char type)
 	ifq_init(&ifp->if_snd, ifp);
 
 	refcount_init(&ifp->if_refcount, 1);	/* Index reference. */
-	IFNET_WLOCK();
 	ifnet_setbyindex(ifp->if_index, ifp);
-	IFNET_WUNLOCK();
 	return (ifp);
 }
 
@@ -383,9 +453,7 @@ if_free_internal(struct ifnet *ifp)
 	KASSERT(ifp == ifnet_byindex_locked(ifp->if_index),
 	    ("%s: freeing unallocated ifnet", ifp->if_xname));
 
-	ifnet_setbyindex(ifp->if_index, NULL);
-	while (V_if_index > 0 && ifnet_byindex_locked(V_if_index) == NULL)
-		V_if_index--;
+	ifindex_free_locked(ifp->if_index);
 	IFNET_WUNLOCK();
 
 	if (if_com_free[ifp->if_alloctype] != NULL)
@@ -570,6 +638,21 @@ if_attach_internal(struct ifnet *ifp, int vmove)
 		/* Reliably crash if used uninitialized. */
 		ifp->if_broadcastaddr = NULL;
 	}
+#ifdef VIMAGE
+	else {
+		/*
+		 * Update the interface index in the link layer address
+		 * of the interface.
+		 */
+		for (ifa = ifp->if_addr; ifa != NULL;
+		    ifa = TAILQ_NEXT(ifa, ifa_link)) {
+			if (ifa->ifa_addr->sa_family == AF_LINK) {
+				sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+				sdl->sdl_index = ifp->if_index;
+			}
+		}
+	}
+#endif
 
 	IFNET_WLOCK();
 	TAILQ_INSERT_TAIL(&V_ifnet, ifp, if_link);
@@ -847,6 +930,7 @@ if_detach_internal(struct ifnet *ifp, int vmove)
 void
 if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
 {
+	u_short idx;
 
 	/*
 	 * Detach from current vnet, but preserve LLADDR info, do not
@@ -855,38 +939,26 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
 	if_detach_internal(ifp, 1);
 
 	/*
-	 * Unlink the ifnet from ifindex_table[] in current vnet,
-	 * and shrink the if_index for that vnet if possible.
+	 * Unlink the ifnet from ifindex_table[] in current vnet, and shrink
+	 * the if_index for that vnet if possible.
+	 *
+	 * NOTE: IFNET_WLOCK/IFNET_WUNLOCK() are assumed to be unvirtualized,
+	 * or we'd lock on one vnet and unlock on another.
 	 */
 	IFNET_WLOCK();
-	ifnet_setbyindex(ifp->if_index, NULL);
-	while (V_if_index > 0 && ifnet_byindex_locked(V_if_index) == NULL)
-		V_if_index--;
-	IFNET_WUNLOCK();
+	ifindex_free_locked(ifp->if_index);
 
 	/*
 	 * Switch to the context of the target vnet.
 	 */
 	CURVNET_SET_QUIET(new_vnet);
 
-	/*
-	 * Try to find an empty slot below if_index.  If we fail, take 
-	 * the next slot.
-	 */
-	IFNET_WLOCK();
-	for (ifp->if_index = 1; ifp->if_index <= V_if_index; ifp->if_index++) {
-		if (ifnet_byindex_locked(ifp->if_index) == NULL)
-			break;
-	}
-	/* Catch if_index overflow. */
-	if (ifp->if_index < 1)
+	if (ifindex_alloc_locked(&idx) != 0) {
+		IFNET_WUNLOCK();
 		panic("if_index overflow");
-
-	if (ifp->if_index > V_if_index)
-		V_if_index = ifp->if_index;
-	if (V_if_index >= V_if_indexlim)
-		if_grow();
-	ifnet_setbyindex(ifp->if_index, ifp);
+	}
+	ifp->if_index = idx;
+	ifnet_setbyindex_locked(ifp->if_index, ifp);
 	IFNET_WUNLOCK();
 
 	if_attach_internal(ifp, 1);
@@ -920,7 +992,7 @@ if_vmove_loan(struct thread *td, struct ifnet *ifp, char *ifname, int jid)
 
 	/* Make sure the named iface does not exists in the dst. prison/vnet. */
 	/* XXX Lock interfaces to avoid races. */
-	CURVNET_SET(pr->pr_vnet);
+	CURVNET_SET_QUIET(pr->pr_vnet);
 	difp = ifunit(ifname);
 	CURVNET_RESTORE();
 	if (difp != NULL) {
@@ -1368,7 +1440,7 @@ ifa_ifwithaddr_internal(struct sockaddr *addr, int getref)
 	struct ifnet *ifp;
 	struct ifaddr *ifa;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
@@ -1395,7 +1467,7 @@ ifa_ifwithaddr_internal(struct sockaddr *addr, int getref)
 	}
 	ifa = NULL;
 done:
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	return (ifa);
 }
 
@@ -1423,7 +1495,7 @@ ifa_ifwithbroadaddr(struct sockaddr *addr)
 	struct ifnet *ifp;
 	struct ifaddr *ifa;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
@@ -1442,7 +1514,7 @@ ifa_ifwithbroadaddr(struct sockaddr *addr)
 	}
 	ifa = NULL;
 done:
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	return (ifa);
 }
 
@@ -1456,7 +1528,7 @@ ifa_ifwithdstaddr(struct sockaddr *addr)
 	struct ifnet *ifp;
 	struct ifaddr *ifa;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
 			continue;
@@ -1475,7 +1547,7 @@ ifa_ifwithdstaddr(struct sockaddr *addr)
 	}
 	ifa = NULL;
 done:
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	return (ifa);
 }
 
@@ -1508,7 +1580,7 @@ ifa_ifwithnet(struct sockaddr *addr)
 	 * we find one, as we release the IF_ADDR_LOCK() that kept it stable
 	 * when we move onto the next interface.
 	 */
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
@@ -1584,7 +1656,7 @@ next:				continue;
 	ifa = ifa_maybe;
 	ifa_maybe = NULL;
 done:
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	if (ifa_maybe != NULL)
 		ifa_free(ifa_maybe);
 	return (ifa);
@@ -1863,7 +1935,7 @@ if_slowtimo(void *arg)
 	int s = splimp();
 
 	VNET_LIST_RLOCK_NOSLEEP();
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	VNET_FOREACH(vnet_iter) {
 		CURVNET_SET(vnet_iter);
 		TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
@@ -1874,7 +1946,7 @@ if_slowtimo(void *arg)
 		}
 		CURVNET_RESTORE();
 	}
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	VNET_LIST_RUNLOCK_NOSLEEP();
 	splx(s);
 	timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
@@ -1889,7 +1961,7 @@ ifunit_ref(const char *name)
 {
 	struct ifnet *ifp;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		if (strncmp(name, ifp->if_xname, IFNAMSIZ) == 0 &&
 		    !(ifp->if_flags & IFF_DYING))
@@ -1897,7 +1969,7 @@ ifunit_ref(const char *name)
 	}
 	if (ifp != NULL)
 		if_ref(ifp);
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	return (ifp);
 }
 
@@ -1906,12 +1978,12 @@ ifunit(const char *name)
 {
 	struct ifnet *ifp;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		if (strncmp(name, ifp->if_xname, IFNAMSIZ) == 0)
 			break;
 	}
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	return (ifp);
 }
 
@@ -2521,7 +2593,7 @@ again:
 	max_len = 0;
 	valid_len = 0;
 
-	IFNET_RLOCK();		/* could sleep XXX */
+	IFNET_RLOCK();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		int addrs;
 
@@ -2846,13 +2918,13 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
 #ifdef INVARIANTS
 	struct ifnet *oifp;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(oifp, &V_ifnet, if_link)
 		if (ifp == oifp)
 			break;
 	if (ifp != oifp)
 		ifp = NULL;
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 
 	KASSERT(ifp != NULL, ("%s: ifnet went away", __func__));
 #endif
@@ -2895,7 +2967,7 @@ if_delmulti_ifma(struct ifmultiaddr *ifma)
 	} else {
 		struct ifnet *oifp;
 
-		IFNET_RLOCK();
+		IFNET_RLOCK_NOSLEEP();
 		TAILQ_FOREACH(oifp, &V_ifnet, if_link)
 			if (ifp == oifp)
 				break;
@@ -2903,7 +2975,7 @@ if_delmulti_ifma(struct ifmultiaddr *ifma)
 			printf("%s: ifnet %p disappeared\n", __func__, ifp);
 			ifp = NULL;
 		}
-		IFNET_RUNLOCK();
+		IFNET_RUNLOCK_NOSLEEP();
 	}
 #endif
 	/*
diff --git a/sys/net/if_arp.h b/sys/net/if_arp.h
index 1e18804ffde..2bb63582800 100644
--- a/sys/net/if_arp.h
+++ b/sys/net/if_arp.h
@@ -108,6 +108,31 @@ struct	arpcom {
 #define IFP2AC(ifp) ((struct arpcom *)(ifp->if_l2com))
 #define AC2IFP(ac) ((ac)->ac_ifp)
 
-#endif
+#endif /* _KERNEL */
+
+struct arpstat {
+	/* Normal things that happen: */
+	u_long txrequests;	/* # of ARP requests sent by this host. */
+	u_long txreplies;	/* # of ARP replies sent by this host. */
+	u_long rxrequests;	/* # of ARP requests received by this host. */
+	u_long rxreplies;	/* # of ARP replies received by this host. */
+	u_long received;	/* # of ARP packets received by this host. */
+
+	u_long arp_spares[4];	/* For either the upper or lower half. */
+	/* Abnormal event and error  counting: */
+	u_long dropped;		/* # of packets dropped waiting for a reply. */
+	u_long timeouts;	/* # of times with entries removed */
+				/* due to timeout. */
+	u_long dupips;		/* # of duplicate IPs detected. */
+};
+
+/*
+ * In-kernel consumers can use these accessor macros directly to update
+ * stats.
+ */
+#define	ARPSTAT_ADD(name, val)	V_arpstat.name += (val)
+#define	ARPSTAT_SUB(name, val)	V_arpstat.name -= (val)
+#define	ARPSTAT_INC(name)	ARPSTAT_ADD(name, 1)
+#define	ARPSTAT_DEC(name)	ARPSTAT_SUB(name, 1)
 
 #endif /* !_NET_IF_ARP_H_ */
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index f1a79cbf21a..d3a55fd15af 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -170,6 +170,11 @@ __FBSDID("$FreeBSD$");
  */
 #define	BRIDGE_IFCAPS_MASK		(IFCAP_TOE|IFCAP_TSO|IFCAP_TXCSUM)
 
+/*
+ * List of capabilities to strip
+ */
+#define	BRIDGE_IFCAPS_STRIP		IFCAP_LRO
+
 /*
  * Bridge interface list entry.
  */
@@ -802,16 +807,10 @@ bridge_mutecaps(struct bridge_softc *sc)
 
 	LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 		enabled = bif->bif_ifp->if_capenable;
+		enabled &= ~BRIDGE_IFCAPS_STRIP;
 		/* strip off mask bits and enable them again if allowed */
 		enabled &= ~BRIDGE_IFCAPS_MASK;
 		enabled |= mask;
-		/*
-		 * Receive offload can only be enabled if all members also
-		 * support send offload.
-		 */
-		if ((enabled & IFCAP_TSO) == 0)
-			enabled &= ~IFCAP_LRO;
-
 		bridge_set_ifcap(sc, bif, enabled);
 	}
 
diff --git a/sys/net/if_ef.c b/sys/net/if_ef.c
index 7a5fca916d7..2af3a177204 100644
--- a/sys/net/if_ef.c
+++ b/sys/net/if_ef.c
@@ -492,7 +492,20 @@ ef_load(void)
 	VNET_LIST_RLOCK();
 	VNET_FOREACH(vnet_iter) {
 		CURVNET_SET(vnet_iter);
-		IFNET_RLOCK();
+
+		/*
+		 * XXXRW: The following loop walks the ifnet list while
+		 * modifying it, something not well-supported by ifnet
+		 * locking.  To avoid lock upgrade/recursion issues, manually
+		 * acquire a write lock of ifnet_sxlock here, rather than a
+		 * read lock, so that when if_alloc() recurses the lock, we
+		 * don't panic.  This structure, in which if_ef automatically
+		 * attaches to all ethernet interfaces, should be replaced
+		 * with a model like that found in if_vlan, in which
+		 * interfaces are explicitly configured, which would avoid
+		 * this (and other) problems.
+		 */
+		sx_xlock(&ifnet_sxlock);
 		TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 			if (ifp->if_type != IFT_ETHER) continue;
 			EFDEBUG("Found interface %s\n", ifp->if_xname);
@@ -523,7 +536,7 @@ ef_load(void)
 			efcount++;
 			SLIST_INSERT_HEAD(&efdev, efl, el_next);
 		}
-		IFNET_RUNLOCK();
+		sx_xunlock(&ifnet_sxlock);
 		CURVNET_RESTORE();
 	}
 	VNET_LIST_RUNLOCK();
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index a1b574f9f37..b66d6e154b2 100644
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -62,6 +62,9 @@ static	SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables);
 extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *,
 	u_char *);
 
+struct rwlock lltable_rwlock;
+RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock");
+
 /*
  * Dump arp state for a specific address family.
  */
@@ -71,7 +74,7 @@ lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
 	struct lltable *llt;
 	int error = 0;
 
-	IFNET_RLOCK();
+	LLTABLE_RLOCK();
 	SLIST_FOREACH(llt, &lltables, llt_link) {
 		if (llt->llt_af == af) {
 			error = llt->llt_dump(llt, wr);
@@ -80,7 +83,7 @@ lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
 		}
 	}
 done:
-	IFNET_RUNLOCK();
+	LLTABLE_RUNLOCK();
 	return (error);
 }
 
@@ -144,8 +147,6 @@ llentry_update(struct llentry **llep, struct lltable *lt,
 
 /*
  * Free all entries from given table and free itself.
- * Since lltables collects from all of the intefaces,
- * the caller of this function must acquire IFNET_WLOCK().
  */
 void
 lltable_free(struct lltable *llt)
@@ -155,9 +156,9 @@ lltable_free(struct lltable *llt)
 
 	KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
 
-	IFNET_WLOCK();
+	LLTABLE_WLOCK();
 	SLIST_REMOVE(&lltables, llt, lltable, llt_link);
-	IFNET_WUNLOCK();
+	LLTABLE_WUNLOCK();
 
 	for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
 		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
@@ -178,7 +179,7 @@ lltable_drain(int af)
 	struct llentry	*lle;
 	register int i;
 
-	IFNET_RLOCK();
+	LLTABLE_RLOCK();
 	SLIST_FOREACH(llt, &lltables, llt_link) {
 		if (llt->llt_af != af)
 			continue;
@@ -192,7 +193,7 @@ lltable_drain(int af)
 			}
 		}
 	}
-	IFNET_RUNLOCK();
+	LLTABLE_RUNLOCK();
 }
 
 void
@@ -200,14 +201,14 @@ lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask)
 {
 	struct lltable *llt;
 
-	IFNET_RLOCK();
+	LLTABLE_RLOCK();
 	SLIST_FOREACH(llt, &lltables, llt_link) {
 		if (llt->llt_af != af)
 			continue;
 
 		llt->llt_prefix_free(llt, prefix, mask);
 	}
-	IFNET_RUNLOCK();
+	LLTABLE_RUNLOCK();
 }
 
 
@@ -230,9 +231,9 @@ lltable_init(struct ifnet *ifp, int af)
 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++)
 		LIST_INIT(&llt->lle_head[i]);
 
-	IFNET_WLOCK();
+	LLTABLE_WLOCK();
 	SLIST_INSERT_HEAD(&lltables, llt, llt_link);
-	IFNET_WUNLOCK();
+	LLTABLE_WUNLOCK();
 
 	return (llt);
 }
@@ -300,13 +301,13 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
 	}
 
 	/* XXX linked list may be too expensive */
-	IFNET_RLOCK();
+	LLTABLE_RLOCK();
 	SLIST_FOREACH(llt, &lltables, llt_link) {
 		if (llt->llt_af == dst->sa_family &&
 		    llt->llt_ifp == ifp)
 			break;
 	}
-	IFNET_RUNLOCK();
+	LLTABLE_RUNLOCK();
 	KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n"));
 
 	if (flags && LLE_CREATE)
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
index 4d721efc35f..f54c78ad8a2 100644
--- a/sys/net/if_llatbl.h
+++ b/sys/net/if_llatbl.h
@@ -41,6 +41,13 @@ struct rt_addrinfo;
 struct llentry;
 LIST_HEAD(llentries, llentry);
 
+extern struct rwlock lltable_rwlock;
+#define	LLTABLE_RLOCK()		rw_rlock(&lltable_rwlock)
+#define	LLTABLE_RUNLOCK()	rw_runlock(&lltable_rwlock)
+#define	LLTABLE_WLOCK()		rw_wlock(&lltable_rwlock)
+#define	LLTABLE_WUNLOCK()	rw_wunlock(&lltable_rwlock)
+#define	LLTABLE_LOCK_ASSERT()	rw_assert(&lltable_rwlock, RA_LOCKED)
+
 /*
  * Code referencing llentry must at least hold
  * a shared lock
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 428645fa206..3ab620816a4 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -85,6 +85,7 @@ struct	vnet;
 #include 		/* XXX */
 #include 		/* XXX */
 #include 		/* XXX */
+#include 		/* XXX */
 #include 		/* XXX */
 #include 
 
@@ -235,7 +236,6 @@ typedef void if_init_f_t(void *);
 #define	if_iqdrops	if_data.ifi_iqdrops
 #define	if_noproto	if_data.ifi_noproto
 #define	if_lastchange	if_data.ifi_lastchange
-#define if_rawoutput(if, m, sa) if_output(if, m, sa, (struct rtentry *)NULL)
 
 /* for compatibility with other BSDs */
 #define	if_addrlist	if_addrhead
@@ -755,14 +755,39 @@ struct ifmultiaddr {
 
 #ifdef _KERNEL
 
-extern	struct rwlock ifnet_lock;
-#define	IFNET_LOCK_INIT() \
-   rw_init_flags(&ifnet_lock, "ifnet",  RW_RECURSE)
-#define	IFNET_WLOCK()		rw_wlock(&ifnet_lock)
-#define	IFNET_WUNLOCK()		rw_wunlock(&ifnet_lock)
-#define	IFNET_WLOCK_ASSERT()	rw_assert(&ifnet_lock, RA_LOCKED)
-#define	IFNET_RLOCK()		rw_rlock(&ifnet_lock)
-#define	IFNET_RUNLOCK()		rw_runlock(&ifnet_lock)	
+extern	struct rwlock ifnet_rwlock;
+extern	struct sx ifnet_sxlock;
+
+#define	IFNET_LOCK_INIT() do {						\
+	rw_init_flags(&ifnet_rwlock, "ifnet_rw",  RW_RECURSE);		\
+	sx_init_flags(&ifnet_sxlock, "ifnet_sx",  SX_RECURSE);		\
+} while(0)
+
+#define	IFNET_WLOCK() do {						\
+	sx_xlock(&ifnet_sxlock);					\
+	rw_wlock(&ifnet_rwlock);					\
+} while (0)
+
+#define	IFNET_WUNLOCK() do {						\
+	rw_wunlock(&ifnet_rwlock);					\
+	sx_xunlock(&ifnet_sxlock);					\
+} while (0)
+
+/*
+ * To assert the ifnet lock, you must know not only whether it's for read or
+ * write, but also whether it was acquired with sleep support or not.
+ */
+#define	IFNET_RLOCK_ASSERT()		sx_assert(&ifnet_sxlock, SA_SLOCKED)
+#define	IFNET_RLOCK_NOSLEEP_ASSERT()	rw_assert(&ifnet_rwlock, RA_RLOCKED)
+#define	IFNET_WLOCK_ASSERT() do {					\
+	sx_assert(&ifnet_sxlock, SA_XLOCKED);				\
+	rw_assert(&ifnet_rwlock, RA_WLOCKED);				\
+} while (0)
+
+#define	IFNET_RLOCK()		sx_slock(&ifnet_sxlock)
+#define	IFNET_RLOCK_NOSLEEP()	rw_rlock(&ifnet_rwlock)
+#define	IFNET_RUNLOCK()		sx_sunlock(&ifnet_sxlock)
+#define	IFNET_RUNLOCK_NOSLEEP()	rw_runlock(&ifnet_rwlock)
 
 /*
  * Look up an ifnet given its index; the _ref variant also acquires a
@@ -801,7 +826,6 @@ int	if_allmulti(struct ifnet *, int);
 struct	ifnet* if_alloc(u_char);
 void	if_attach(struct ifnet *);
 void	if_dead(struct ifnet *);
-void	if_grow(void);
 int	if_delmulti(struct ifnet *, struct sockaddr *);
 void	if_delmulti_ifma(struct ifmultiaddr *);
 void	if_detach(struct ifnet *);
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index 04c2c0dc644..126d83ffb35 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -580,7 +580,7 @@ vlan_clone_match_ethertag(struct if_clone *ifc, const char *name, int *tag)
 	int t = 0;
 
 	/* Check for . style interface names. */
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 		if (ifp->if_type != IFT_ETHER)
 			continue;
@@ -598,7 +598,7 @@ vlan_clone_match_ethertag(struct if_clone *ifc, const char *name, int *tag)
 			*tag = t;
 		break;
 	}
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 
 	return (ifp);
 }
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 645cf7e54eb..4bbd6e32fa9 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -513,6 +513,39 @@ route_output(struct mbuf *m, struct socket *so)
 			senderr(error);
 	}
 
+	/*
+	 * The given gateway address may be an interface address.
+	 * For example, issuing a "route change" command on a route
+	 * entry that was created from a tunnel, and the gateway
+	 * address given is the local end point. In this case the 
+	 * RTF_GATEWAY flag must be cleared or the destination will
+	 * not be reachable even though there is no error message.
+	 */
+	if (info.rti_info[RTAX_GATEWAY] != NULL &&
+	    info.rti_info[RTAX_GATEWAY]->sa_family != AF_LINK) {
+		struct route gw_ro;
+
+		bzero(&gw_ro, sizeof(gw_ro));
+		gw_ro.ro_dst = *info.rti_info[RTAX_GATEWAY];
+		rtalloc_ign_fib(&gw_ro, 0, so->so_fibnum);
+		/* 
+		 * A host route through the loopback interface is 
+		 * installed for each interface adddress. In pre 8.0
+		 * releases the interface address of a PPP link type
+		 * is not reachable locally. This behavior is fixed as 
+		 * part of the new L2/L3 redesign and rewrite work. The
+		 * signature of this interface address route is the
+		 * AF_LINK sa_family type of the rt_gateway, and the
+		 * rt_ifp has the IFF_LOOPBACK flag set.
+		 */
+		if (gw_ro.ro_rt != NULL &&
+		    gw_ro.ro_rt->rt_gateway->sa_family == AF_LINK &&
+		    gw_ro.ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)
+			info.rti_flags &= ~RTF_GATEWAY;
+		if (gw_ro.ro_rt != NULL)
+			RTFREE(gw_ro.ro_rt);
+	}
+
 	switch (rtm->rtm_type) {
 		struct rtentry *saved_nrt;
 
@@ -714,7 +747,7 @@ route_output(struct mbuf *m, struct socket *so)
 					RT_UNLOCK(rt);
 					senderr(error);
 				}
-				rt->rt_flags |= RTF_GATEWAY;
+				rt->rt_flags |= (RTF_GATEWAY & info.rti_flags);
 			}
 			if (info.rti_ifa != NULL &&
 			    info.rti_ifa != rt->rt_ifa) {
@@ -1473,7 +1506,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
 		/*
 		 * take care of routing entries
 		 */
-		for (error = 0; error == 0 && i <= lim; i++)
+		for (error = 0; error == 0 && i <= lim; i++) {
 			rnh = rt_tables_get_rnh(req->td->td_proc->p_fibnum, i);
 			if (rnh != NULL) {
 				RADIX_NODE_HEAD_LOCK(rnh); 
@@ -1482,6 +1515,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
 				RADIX_NODE_HEAD_UNLOCK(rnh);
 			} else if (af != 0)
 				error = EAFNOSUPPORT;
+		}
 		break;
 
 	case NET_RT_IFLIST:
diff --git a/sys/net/vnet.c b/sys/net/vnet.c
index 7866bb98c90..298ffb28457 100644
--- a/sys/net/vnet.c
+++ b/sys/net/vnet.c
@@ -182,14 +182,21 @@ static VNET_DEFINE(char, modspace[VNET_MODMIN]);
 
 /*
  * Global lists of subsystem constructor and destructors for vnets.  They are
- * registered via VNET_SYSINIT() and VNET_SYSUNINIT().  The lists are
- * protected by the vnet_sxlock global lock.
+ * registered via VNET_SYSINIT() and VNET_SYSUNINIT().  Both lists are
+ * protected by the vnet_sysinit_sxlock global lock.
  */
 static TAILQ_HEAD(vnet_sysinit_head, vnet_sysinit) vnet_constructors =
 	TAILQ_HEAD_INITIALIZER(vnet_constructors);
 static TAILQ_HEAD(vnet_sysuninit_head, vnet_sysinit) vnet_destructors =
 	TAILQ_HEAD_INITIALIZER(vnet_destructors);
 
+struct sx		vnet_sysinit_sxlock;
+
+#define	VNET_SYSINIT_WLOCK()	sx_xlock(&vnet_sysinit_sxlock);
+#define	VNET_SYSINIT_WUNLOCK()	sx_xunlock(&vnet_sysinit_sxlock);
+#define	VNET_SYSINIT_RLOCK()	sx_slock(&vnet_sysinit_sxlock);
+#define	VNET_SYSINIT_RUNLOCK()	sx_sunlock(&vnet_sysinit_sxlock);
+
 struct vnet_data_free {
 	uintptr_t	vnd_start;
 	int		vnd_len;
@@ -228,12 +235,10 @@ vnet_alloc(void)
 
 	/* Initialize / attach vnet module instances. */
 	CURVNET_SET_QUIET(vnet);
-
-	sx_xlock(&vnet_sxlock);
 	vnet_sysinit();
 	CURVNET_RESTORE();
 
-	rw_wlock(&vnet_rwlock);
+	VNET_LIST_WLOCK();
 	LIST_INSERT_HEAD(&vnet_head, vnet, vnet_le);
 	VNET_LIST_WUNLOCK();
 
@@ -253,7 +258,7 @@ vnet_destroy(struct vnet *vnet)
 
 	VNET_LIST_WLOCK();
 	LIST_REMOVE(vnet, vnet_le);
-	rw_wunlock(&vnet_rwlock);
+	VNET_LIST_WUNLOCK();
 
 	CURVNET_SET_QUIET(vnet);
 
@@ -264,8 +269,6 @@ vnet_destroy(struct vnet *vnet)
 	}
 
 	vnet_sysuninit();
-	sx_xunlock(&vnet_sxlock);
-
 	CURVNET_RESTORE();
 
 	/*
@@ -287,6 +290,7 @@ vnet_init_prelink(void *arg)
 
 	rw_init(&vnet_rwlock, "vnet_rwlock");
 	sx_init(&vnet_sxlock, "vnet_sxlock");
+	sx_init(&vnet_sysinit_sxlock, "vnet_sysinit_sxlock");
 	LIST_INIT(&vnet_head);
 }
 SYSINIT(vnet_init_prelink, SI_SUB_VNET_PRELINK, SI_ORDER_FIRST,
@@ -494,7 +498,7 @@ vnet_register_sysinit(void *arg)
 	KASSERT(vs->subsystem > SI_SUB_VNET, ("vnet sysinit too early"));
 
 	/* Add the constructor to the global list of vnet constructors. */
-	sx_xlock(&vnet_sxlock);
+	VNET_SYSINIT_WLOCK();
 	TAILQ_FOREACH(vs2, &vnet_constructors, link) {
 		if (vs2->subsystem > vs->subsystem)
 			break;
@@ -515,7 +519,7 @@ vnet_register_sysinit(void *arg)
 		vs->func(vs->arg);
 		CURVNET_RESTORE();
 	}
-	sx_xunlock(&vnet_sxlock);
+	VNET_SYSINIT_WUNLOCK();
 }
 
 void
@@ -526,9 +530,9 @@ vnet_deregister_sysinit(void *arg)
 	vs = arg;
 
 	/* Remove the constructor from the global list of vnet constructors. */
-	sx_xlock(&vnet_sxlock);
+	VNET_SYSINIT_WLOCK();
 	TAILQ_REMOVE(&vnet_constructors, vs, link);
-	sx_xunlock(&vnet_sxlock);
+	VNET_SYSINIT_WUNLOCK();
 }
 
 void
@@ -539,7 +543,7 @@ vnet_register_sysuninit(void *arg)
 	vs = arg;
 
 	/* Add the destructor to the global list of vnet destructors. */
-	sx_xlock(&vnet_sxlock);
+	VNET_SYSINIT_WLOCK();
 	TAILQ_FOREACH(vs2, &vnet_destructors, link) {
 		if (vs2->subsystem > vs->subsystem)
 			break;
@@ -550,7 +554,7 @@ vnet_register_sysuninit(void *arg)
 		TAILQ_INSERT_BEFORE(vs2, vs, link);
 	else
 		TAILQ_INSERT_TAIL(&vnet_destructors, vs, link);
-	sx_xunlock(&vnet_sxlock);
+	VNET_SYSINIT_WUNLOCK();
 }
 
 void
@@ -565,7 +569,7 @@ vnet_deregister_sysuninit(void *arg)
 	 * Invoke the destructor on all the existing vnets when it is
 	 * deregistered.
 	 */
-	sx_xlock(&vnet_sxlock);
+	VNET_SYSINIT_WLOCK();
 	VNET_FOREACH(vnet) {
 		CURVNET_SET_QUIET(vnet);
 		vs->func(vs->arg);
@@ -574,40 +578,42 @@ vnet_deregister_sysuninit(void *arg)
 
 	/* Remove the destructor from the global list of vnet destructors. */
 	TAILQ_REMOVE(&vnet_destructors, vs, link);
-	sx_xunlock(&vnet_sxlock);
+	VNET_SYSINIT_WUNLOCK();
 }
 
 /*
  * Invoke all registered vnet constructors on the current vnet.  Used during
  * vnet construction.  The caller is responsible for ensuring the new vnet is
- * the current vnet and that the vnet_sxlock lock is locked.
+ * the current vnet and that the vnet_sysinit_sxlock lock is locked.
  */
 void
 vnet_sysinit(void)
 {
 	struct vnet_sysinit *vs;
 
-	sx_assert(&vnet_sxlock, SA_LOCKED);
+	VNET_SYSINIT_RLOCK();
 	TAILQ_FOREACH(vs, &vnet_constructors, link) {
 		vs->func(vs->arg);
 	}
+	VNET_SYSINIT_RUNLOCK();
 }
 
 /*
  * Invoke all registered vnet destructors on the current vnet.  Used during
  * vnet destruction.  The caller is responsible for ensuring the dying vnet
- * is the current vnet and that the vnet_sxlock lock is locked.
+ * the current vnet and that the vnet_sysinit_sxlock lock is locked.
  */
 void
 vnet_sysuninit(void)
 {
 	struct vnet_sysinit *vs;
 
-	sx_assert(&vnet_sxlock, SA_LOCKED);
+	VNET_SYSINIT_RLOCK();
 	TAILQ_FOREACH_REVERSE(vs, &vnet_destructors, vnet_sysuninit_head,
 	    link) {
 		vs->func(vs->arg);
 	}
+	VNET_SYSINIT_RUNLOCK();
 }
 
 #ifdef DDB
@@ -615,14 +621,20 @@ DB_SHOW_COMMAND(vnets, db_show_vnets)
 {
 	VNET_ITERATOR_DECL(vnet_iter);
 
-#if SIZE_MAX == UINT32_MAX /* 32-bit arch */
-	db_printf("      vnet ifs socks\n");
-#else /* 64-bit arch, most probaly... */
-	db_printf("              vnet ifs socks\n");
-#endif
 	VNET_FOREACH(vnet_iter) {
-		db_printf("%p %3d %5d\n", vnet_iter, vnet_iter->vnet_ifcnt,
-		    vnet_iter->vnet_sockcnt);
+		db_printf("vnet            = %p\n", vnet_iter);
+		db_printf(" vnet_magic_n   = 0x%x (%s, orig 0x%x)\n",
+		    vnet_iter->vnet_magic_n,
+		    (vnet_iter->vnet_magic_n == VNET_MAGIC_N) ?
+			"ok" : "mismatch", VNET_MAGIC_N);
+		db_printf(" vnet_ifcnt     = %u\n", vnet_iter->vnet_ifcnt);
+		db_printf(" vnet_sockcnt   = %u\n", vnet_iter->vnet_sockcnt);
+		db_printf(" vnet_data_mem  = %p\n", vnet_iter->vnet_data_mem);
+		db_printf(" vnet_data_base = 0x%jx\n",
+		    (uintmax_t)vnet_iter->vnet_data_base);
+		db_printf("\n");
+		if (db_pager_quit)
+			break;
 	}
 }
 #endif
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
index 01d824d68b2..116d7af3288 100644
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -107,9 +107,6 @@ void	vnet_destroy(struct vnet *vnet);
  * Various macros -- get and set the current network stack, but also
  * assertions.
  */
-#ifdef INVARIANTS
-#define	VNET_DEBUG
-#endif
 #ifdef VNET_DEBUG
 #define	VNET_ASSERT(condition)						\
 	if (!(condition)) {						\
@@ -185,12 +182,14 @@ extern struct sx vnet_sxlock;
  * Virtual network stack memory allocator, which allows global variables to
  * be automatically instantiated for each network stack instance.
  */
+__asm__(
 #if defined(__arm__)
-__asm__(".section " VNET_SETNAME ", \"aw\", %progbits");
+	".section " VNET_SETNAME ", \"aw\", %progbits\n"
 #else
-__asm__(".section " VNET_SETNAME ", \"aw\", @progbits");
+	".section " VNET_SETNAME ", \"aw\", @progbits\n"
 #endif
-__asm__(".previous");
+	"\t.p2align " __XSTRING(CACHE_LINE_SHIFT) "\n"
+	"\t.previous");
 
 #define	VNET_NAME(n)		vnet_entry_##n
 #define	VNET_DECLARE(t, n)	extern t VNET_NAME(n)
@@ -230,21 +229,25 @@ int	vnet_sysctl_handle_string(SYSCTL_HANDLER_ARGS);
 int	vnet_sysctl_handle_uint(SYSCTL_HANDLER_ARGS);
 
 #define	SYSCTL_VNET_INT(parent, nbr, name, access, ptr, val, descr)	\
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|CTLFLAG_MPSAFE|(access), \
+	SYSCTL_OID(parent, nbr, name,					\
+	    CTLTYPE_INT|CTLFLAG_MPSAFE|CTLFLAG_VNET|(access),		\
 	    ptr, val, vnet_sysctl_handle_int, "I", descr)
 #define	SYSCTL_VNET_PROC(parent, nbr, name, access, ptr, arg, handler,	\
 	    fmt, descr)							\
-	SYSCTL_OID(parent, nbr, name, access, ptr, arg, handler, fmt,	\
-	    descr)
+	SYSCTL_OID(parent, nbr, name, CTLFLAG_VNET|(access), ptr, arg, 	\
+	    handler, fmt, descr)
 #define	SYSCTL_VNET_STRING(parent, nbr, name, access, arg, len, descr)	\
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_STRING|(access), arg,	\
-	    len, vnet_sysctl_handle_string, "A", descr)
+	SYSCTL_OID(parent, nbr, name,					\
+	    CTLTYPE_STRING|CTLFLAG_VNET|(access),			\
+	    arg, len, vnet_sysctl_handle_string, "A", descr)
 #define	SYSCTL_VNET_STRUCT(parent, nbr, name, access, ptr, type, descr)	\
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_OPAQUE|(access), ptr,	\
+	SYSCTL_OID(parent, nbr, name,					\
+	    CTLTYPE_OPAQUE|CTLFLAG_VNET|(access), ptr,			\
 	    sizeof(struct type), vnet_sysctl_handle_opaque, "S," #type,	\
 	    descr)
 #define	SYSCTL_VNET_UINT(parent, nbr, name, access, ptr, val, descr)	\
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_UINT|CTLFLAG_MPSAFE|(access), \
+	SYSCTL_OID(parent, nbr, name,					\
+	    CTLTYPE_UINT|CTLFLAG_MPSAFE|CTLFLAG_VNET|(access),		\
 	    ptr, val, vnet_sysctl_handle_uint, "IU", descr)
 #define	VNET_SYSCTL_ARG(req, arg1) do {					\
 	if (arg1 != NULL)						\
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index 081c6db3b1c..b14f13f90fe 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -573,11 +573,13 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
 
 	/*
 	 * Flush any deferred vap tasks.
-	 * NB: must be before ether_ifdetach() and removal from ic_vaps list
 	 */
 	ieee80211_draintask(ic, &vap->iv_nstate_task);
 	ieee80211_draintask(ic, &vap->iv_swbmiss_task);
 
+	/* XXX band-aid until ifnet handles this for us */
+	taskqueue_drain(taskqueue_swi, &ifp->if_linktask);
+
 	IEEE80211_LOCK(ic);
 	KASSERT(vap->iv_state == IEEE80211_S_INIT , ("vap still running"));
 	TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
diff --git a/sys/net80211/ieee80211_dfs.c b/sys/net80211/ieee80211_dfs.c
index eec819bb8d3..e15445d6a5f 100644
--- a/sys/net80211/ieee80211_dfs.c
+++ b/sys/net80211/ieee80211_dfs.c
@@ -235,7 +235,7 @@ dfs_timeout(void *arg)
 	}
 	if (oldest != now) {
 		/* arrange to process next channel up for a status change */
-		callout_schedule(&dfs->nol_timer, oldest + NOL_TIMEOUT);
+		callout_schedule(&dfs->nol_timer, oldest + NOL_TIMEOUT - now);
 	}
 }
 
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 3c87a3ae34e..e701cb5eba1 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -524,7 +524,7 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
 		case IEEE80211_ELEMID_HTINFO:
 			scan->htinfo = frm;
 			break;
-#ifdef IEEE80211_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_MESH
 		case IEEE80211_ELEMID_MESHID:
 			scan->meshid = frm;
 			break;
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index fe8c9fa10eb..a4f538dbdfb 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -431,7 +431,7 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 			goto invalid;
 		break;
 	case IEEE80211_S_SLEEP:
-		ieee80211_sta_pwrsave(vap, 0);
+		ieee80211_sta_pwrsave(vap, 1);
 		break;
 	default:
 	invalid:
diff --git a/sys/netatalk/at_control.c b/sys/netatalk/at_control.c
index 5193d668efe..b2d84225c7f 100644
--- a/sys/netatalk/at_control.c
+++ b/sys/netatalk/at_control.c
@@ -276,7 +276,7 @@ at_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
 			 * If the request is specifying phase 1, then
 			 * only look at a phase one address
 			 */
-			AT_IFADDR_RUNLOCK();
+			AT_IFADDR_RLOCK();
 			for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
 				if (aa->aa_ifp == ifp &&
 				    (aa->aa_flags & AFA_PHASE2) == 0)
@@ -286,7 +286,7 @@ at_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
 				ifa_free(&oaa->aa_ifa);
 			if (aa != NULL && oaa != aa)
 				ifa_ref(&aa->aa_ifa);
-			AT_IFADDR_RLOCK();
+			AT_IFADDR_RUNLOCK();
 		} else {
 			struct at_ifaddr *oaa;
 
diff --git a/sys/netgraph/ng_gif.c b/sys/netgraph/ng_gif.c
index ccff05a92d0..1790cbd91e5 100644
--- a/sys/netgraph/ng_gif.c
+++ b/sys/netgraph/ng_gif.c
@@ -560,7 +560,7 @@ ng_gif_mod_event(module_t mod, int event, void *data)
 		ng_gif_input_orphan_p = ng_gif_input_orphan;
 
 		/* Create nodes for any already-existing gif interfaces */
-		VNET_LIST_RLOCK_NOSLEEP();
+		VNET_LIST_RLOCK();
 		IFNET_RLOCK();
 		VNET_FOREACH(vnet_iter) {
 			CURVNET_SET_QUIET(vnet_iter); /* XXX revisit quiet */
@@ -571,7 +571,7 @@ ng_gif_mod_event(module_t mod, int event, void *data)
 			CURVNET_RESTORE();
 		}
 		IFNET_RUNLOCK();
-		VNET_LIST_RUNLOCK_NOSLEEP();
+		VNET_LIST_RUNLOCK();
 		break;
 
 	case MOD_UNLOAD:
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 9d1c13afe86..c170c7ab711 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$");
 
 SYSCTL_DECL(_net_link_ether);
 SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
+SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, "");
 
 VNET_DEFINE(int, useloopback) = 1;	/* use loopback interface for
 					 * local traffic */
@@ -89,10 +90,12 @@ static VNET_DEFINE(int, arpt_keep) = (20*60);	/* once resolved, good for 20
 						 * minutes */
 static VNET_DEFINE(int, arp_maxtries) = 5;
 static VNET_DEFINE(int, arp_proxyall);
+static VNET_DEFINE(struct arpstat, arpstat);  /* ARP statistics, see if_arp.h */
 
 #define	V_arpt_keep		VNET(arpt_keep)
 #define	V_arp_maxtries		VNET(arp_maxtries)
 #define	V_arp_proxyall		VNET(arp_proxyall)
+#define	V_arpstat		VNET(arpstat)
 
 SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW,
 	&VNET_NAME(arpt_keep), 0,
@@ -107,6 +110,9 @@ SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW,
 SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW,
 	&VNET_NAME(arp_proxyall), 0,
 	"Enable proxy ARP for all suitable requests");
+SYSCTL_VNET_STRUCT(_net_link_ether_arp, OID_AUTO, stats, CTLFLAG_RW,
+	&VNET_NAME(arpstat), arpstat,
+	"ARP statistics (struct arpstat, net/if_arp.h)");
 
 static void	arp_init(void);
 void		arprequest(struct ifnet *,
@@ -163,20 +169,23 @@ arptimer(void *arg)
 		return;
 	}
 	ifp = lle->lle_tbl->llt_ifp;
+	CURVNET_SET(ifp->if_vnet);
 	IF_AFDATA_LOCK(ifp);
 	LLE_WLOCK(lle);
-	if (((lle->la_flags & LLE_DELETED)
-		|| (time_second >= lle->la_expire))
-	    && (!callout_pending(&lle->la_timer) &&
-		callout_active(&lle->la_timer)))
+	if (((lle->la_flags & LLE_DELETED) ||
+	    (time_second >= lle->la_expire)) &&
+	    (!callout_pending(&lle->la_timer) &&
+	    callout_active(&lle->la_timer))) {
 		(void) llentry_free(lle);
-	else {
+		ARPSTAT_INC(timeouts);
+	} else {
 		/*
 		 * Still valid, just drop our reference
 		 */
 		LLE_FREE_LOCKED(lle);
 	}
 	IF_AFDATA_UNLOCK(ifp);
+	CURVNET_RESTORE();
 }
 
 /*
@@ -238,6 +247,7 @@ arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr  *tip,
 	sa.sa_len = 2;
 	m->m_flags |= M_BCAST;
 	(*ifp->if_output)(ifp, m, &sa, NULL);
+	ARPSTAT_INC(txrequests);
 }
 
 /*
@@ -339,8 +349,10 @@ retry:
 	 * latest one.
 	 */
 	if (m != NULL) {
-		if (la->la_hold != NULL)
+		if (la->la_hold != NULL) {
 			m_freem(la->la_hold);
+			ARPSTAT_INC(dropped);
+		}
 		la->la_hold = m;
 		if (renew == 0 && (flags & LLE_EXCLUSIVE)) {
 			flags &= ~LLE_EXCLUSIVE;
@@ -413,6 +425,7 @@ arpintr(struct mbuf *m)
 		ar = mtod(m, struct arphdr *);
 	}
 
+	ARPSTAT_INC(received);
 	switch (ntohs(ar->ar_pro)) {
 #ifdef INET
 	case ETHERTYPE_IP:
@@ -462,11 +475,11 @@ in_arpinput(struct mbuf *m)
 	struct rtentry *rt;
 	struct ifaddr *ifa;
 	struct in_ifaddr *ia;
+	struct mbuf *hold;
 	struct sockaddr sa;
 	struct in_addr isaddr, itaddr, myaddr;
 	u_int8_t *enaddr = NULL;
 	int op, flags;
-	struct mbuf *m0;
 	int req_len;
 	int bridged = 0, is_bridge = 0;
 #ifdef DEV_CARP
@@ -493,6 +506,9 @@ in_arpinput(struct mbuf *m)
 	(void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr));
 	(void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr));
 
+	if (op == ARPOP_REPLY)
+		ARPSTAT_INC(rxreplies);
+
 	/*
 	 * For a bridge, we want to check the address irrespective
 	 * of the receive interface. (This will change slightly
@@ -603,6 +619,7 @@ match:
 		   ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
 		   inet_ntoa(isaddr), ifp->if_xname);
 		itaddr = myaddr;
+		ARPSTAT_INC(dupips);
 		goto reply;
 	}
 	if (ifp->if_flags & IFF_STATICARP)
@@ -631,11 +648,13 @@ match:
 				    la->lle_tbl->llt_ifp->if_xname,
 				    ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
 				    ifp->if_xname);
+			LLE_WUNLOCK(la);
 			goto reply;
 		}
 		if ((la->la_flags & LLE_VALID) &&
 		    bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) {
 			if (la->la_flags & LLE_STATIC) {
+				LLE_WUNLOCK(la);
 				log(LOG_ERR,
 				    "arp: %*D attempts to modify permanent "
 				    "entry for %s on %s\n",
@@ -655,6 +674,7 @@ match:
 		}
 		    
 		if (ifp->if_addrlen != ah->ar_hln) {
+			LLE_WUNLOCK(la);
 			log(LOG_WARNING,
 			    "arp from %*D: addr len: new %d, i/f %d (ignored)",
 			    ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
@@ -671,19 +691,19 @@ match:
 		}
 		la->la_asked = 0;
 		la->la_preempt = V_arp_maxtries;
-		if (la->la_hold != NULL) {
-			m0 = la->la_hold;
-			la->la_hold = 0;
+		hold = la->la_hold;
+		if (hold != NULL) {
+			la->la_hold = NULL;
 			memcpy(&sa, L3_ADDR(la), sizeof(sa));
-			LLE_WUNLOCK(la);
-			
-			(*ifp->if_output)(ifp, m0, &sa, NULL);
-			return;
 		}
+		LLE_WUNLOCK(la);
+		if (hold != NULL)
+			(*ifp->if_output)(ifp, hold, &sa, NULL);
 	}
 reply:
 	if (op != ARPOP_REQUEST)
 		goto drop;
+	ARPSTAT_INC(rxrequests);
 
 	if (itaddr.s_addr == myaddr.s_addr) {
 		/* Shortcut.. the receiving interface is the target. */
@@ -750,8 +770,6 @@ reply:
 #endif
 	}
 
-	if (la != NULL)
-		LLE_WUNLOCK(la);
 	if (itaddr.s_addr == myaddr.s_addr &&
 	    IN_LINKLOCAL(ntohl(itaddr.s_addr))) {
 		/* RFC 3927 link-local IPv4; always reply by broadcast. */
@@ -774,11 +792,10 @@ reply:
 	sa.sa_family = AF_ARP;
 	sa.sa_len = 2;
 	(*ifp->if_output)(ifp, m, &sa, NULL);
+	ARPSTAT_INC(txreplies);
 	return;
 
 drop:
-	if (la != NULL)
-		LLE_WUNLOCK(la);
 	m_freem(m);
 }
 #endif
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 15d38b191b5..4edc1dbfb17 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -536,7 +536,6 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
 				hostIsNew = 0;
 		}
 		if (ifra->ifra_mask.sin_len) {
-			in_ifscrub(ifp, ia);
 			ia->ia_sockmask = ifra->ifra_mask;
 			ia->ia_sockmask.sin_family = AF_INET;
 			ia->ia_subnetmask =
@@ -545,7 +544,6 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
 		}
 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
-			in_ifscrub(ifp, ia);
 			ia->ia_dstaddr = ifra->ifra_dstaddr;
 			maskIsNew  = 1; /* We lie; but the effect's the same */
 		}
@@ -991,6 +989,40 @@ in_addprefix(struct in_ifaddr *target, int flags)
 				IN_IFADDR_RUNLOCK();
 				return (EEXIST);
 			} else {
+				struct route pfx_ro;
+				struct sockaddr_in *pfx_addr;
+				struct rtentry msg_rt;
+
+				/* QL: XXX
+				 * This is a bit questionable because there is no
+				 * additional route entry added for an address alias.
+				 * Therefore this route report is inaccurate. Perhaps
+				 * it's better to supply a empty rtentry as how it
+				 * is done in in_scrubprefix().
+				 */
+				bzero(&pfx_ro, sizeof(pfx_ro));
+				pfx_addr = (struct sockaddr_in *)(&pfx_ro.ro_dst);
+				pfx_addr->sin_len = sizeof(*pfx_addr);
+				pfx_addr->sin_family = AF_INET;
+				pfx_addr->sin_addr = prefix;
+				rtalloc_ign_fib(&pfx_ro, 0, 0);
+				if (pfx_ro.ro_rt != NULL) {
+					msg_rt = *pfx_ro.ro_rt;
+					/* QL: XXX
+					 * Point the gateway to the given interface
+					 * address as if a new prefix route entry has 
+					 * been added through the new address alias. 
+					 * All other parts of the rtentry is accurate, 
+					 * e.g., rt_key, rt_mask, rt_ifp etc.
+					 */
+					msg_rt.rt_gateway = 
+						(struct sockaddr *)&ia->ia_addr;
+					rt_newaddrmsg(RTM_ADD, 
+						      (struct ifaddr *)target,
+						      0, &msg_rt);
+					RTFREE(pfx_ro.ro_rt);
+				}
+
 				IN_IFADDR_RUNLOCK();
 				return (0);
 			}
@@ -1024,9 +1056,6 @@ in_scrubprefix(struct in_ifaddr *target)
 	struct rt_addrinfo info;
 	struct sockaddr_dl null_sdl;
 
-	if ((target->ia_flags & IFA_ROUTE) == 0)
-		return (0);
-
 	/*
 	 * Remove the loopback route to the interface address.
 	 * The "useloopback" setting is not consulted because if the
@@ -1054,6 +1083,20 @@ in_scrubprefix(struct in_ifaddr *target)
 			log(LOG_INFO, "in_scrubprefix: deletion failed\n");
 	}
 
+	if ((target->ia_flags & IFA_ROUTE) == 0) {
+		struct rtentry rt;
+
+		/* QL: XXX
+		 * Report a blank rtentry when a route has not been
+		 * installed for the given interface address.
+		 */
+		bzero(&rt, sizeof(rt));
+		rt_newaddrmsg(RTM_DELETE, 
+			      (struct ifaddr *)target,
+			      0, &rt);
+		return (0);
+	}
+
 	if (rtinitflags(target))
 		prefix = target->ia_dstaddr.sin_addr;
 	else {
@@ -1407,12 +1450,7 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
 	} arpc;
 	int error, i;
 
-	/* XXXXX
-	 * current IFNET_RLOCK() is mapped to IFNET_WLOCK()
-	 * so it is okay to use this ASSERT, change it when
-	 * IFNET lock is finalized
-	 */
-	IFNET_WLOCK_ASSERT();
+	LLTABLE_LOCK_ASSERT();
 
 	error = 0;
 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index ad07aba4604..1f60bce04a2 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -89,27 +89,7 @@ typedef	__socklen_t	socklen_t;
 #define	_SOCKLEN_T_DECLARED
 #endif
 
-/* Avoid collision with original definition in sys/socket.h. */
-#ifndef	_STRUCT_SOCKADDR_STORAGE_DECLARED
-/*
- * RFC 2553: protocol-independent placeholder for socket addresses
- */
-#define	_SS_MAXSIZE	128U
-#define	_SS_ALIGNSIZE	(sizeof(__int64_t))
-#define	_SS_PAD1SIZE	(_SS_ALIGNSIZE - sizeof(unsigned char) - \
-			    sizeof(sa_family_t))
-#define	_SS_PAD2SIZE	(_SS_MAXSIZE - sizeof(unsigned char) - \
-			    sizeof(sa_family_t) - _SS_PAD1SIZE - _SS_ALIGNSIZE)
-
-struct sockaddr_storage {
-	unsigned char	ss_len;		/* address length */
-	sa_family_t	ss_family;	/* address family */
-	char		__ss_pad1[_SS_PAD1SIZE];
-	__int64_t	__ss_align;	/* force desired struct alignment */
-	char		__ss_pad2[_SS_PAD2SIZE];
-};
-#define	_STRUCT_SOCKADDR_STORAGE_DECLARED
-#endif
+#include 
 
 /* Socket address, internet style. */
 struct sockaddr_in {
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
index d0e139751e9..9a828210cc6 100644
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -1899,6 +1899,9 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
 			ssa->sin.sin_addr = mreqs.imr_sourceaddr;
 		}
 
+		if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
+			return (EINVAL);
+
 		ifp = inp_lookup_mcast_ifp(inp, &gsa->sin,
 		    mreqs.imr_interface);
 		CTR3(KTR_IGMPV3, "%s: imr_interface = %s, ifp = %p",
@@ -1936,6 +1939,9 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
 			ssa->sin.sin_port = 0;
 		}
 
+		if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
+			return (EINVAL);
+
 		if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface)
 			return (EADDRNOTAVAIL);
 		ifp = ifnet_byindex(gsr.gsr_interface);
@@ -1948,9 +1954,6 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
 		break;
 	}
 
-	if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
-		return (EINVAL);
-
 	if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
 		return (EADDRNOTAVAIL);
 
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 18e446f8fc0..e3ffe5a4a6d 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -501,7 +501,7 @@ carpdetach(struct carp_softc *sc, int unlock)
 			ifpromisc(sc->sc_carpdev, 0);
 			sc->sc_carpdev->if_carp = NULL;
 			CARP_LOCK_DESTROY(cif);
-			free(cif, M_IFADDR);
+			free(cif, M_CARP);
 		} else if (unlock)
 			CARP_UNLOCK(cif);
 		sc->sc_carpdev = NULL;
@@ -1639,7 +1639,7 @@ carp_del_addr(struct carp_softc *sc, struct sockaddr_in *sin)
 		if (!--cif->vhif_nvrs) {
 			sc->sc_carpdev->if_carp = NULL;
 			CARP_LOCK_DESTROY(cif);
-			free(cif, M_IFADDR);
+			free(cif, M_CARP);
 		} else {
 			CARP_UNLOCK(cif);
 		}
@@ -1843,7 +1843,7 @@ carp_del_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
 		if (!--cif->vhif_nvrs) {
 			CARP_LOCK_DESTROY(cif);
 			sc->sc_carpdev->if_carp = NULL;
-			free(cif, M_IFADDR);
+			free(cif, M_CARP);
 		} else
 			CARP_UNLOCK(cif);
 	}
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index 31059e9acd7..401c0908de5 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -125,6 +125,8 @@ static VNET_DEFINE(struct inpcbinfo, divcbinfo);
 static u_long	div_sendspace = DIVSNDQ;	/* XXX sysctl ? */
 static u_long	div_recvspace = DIVRCVQ;	/* XXX sysctl ? */
 
+static eventhandler_tag ip_divert_event_tag;
+
 /*
  * Initialize divert connection block queue.
  */
@@ -152,7 +154,7 @@ div_inpcb_fini(void *mem, int size)
 	INP_LOCK_DESTROY(inp);
 }
 
-void
+static void
 div_init(void)
 {
 
@@ -174,8 +176,17 @@ div_init(void)
 	    NULL, NULL, div_inpcb_init, div_inpcb_fini, UMA_ALIGN_PTR,
 	    UMA_ZONE_NOFREE);
 	uma_zone_set_max(V_divcbinfo.ipi_zone, maxsockets);
-	EVENTHANDLER_REGISTER(maxsockets_change, div_zone_change,
-		NULL, EVENTHANDLER_PRI_ANY);
+}
+
+static void
+div_destroy(void)
+{
+
+	INP_INFO_LOCK_DESTROY(&V_divcbinfo);
+	uma_zdestroy(V_divcbinfo.ipi_zone);
+	hashdestroy(V_divcbinfo.ipi_hashbase, M_PCB, V_divcbinfo.ipi_hashmask);
+	hashdestroy(V_divcbinfo.ipi_porthashbase, M_PCB,
+	    V_divcbinfo.ipi_porthashmask);
 }
 
 /*
@@ -709,6 +720,9 @@ struct protosw div_protosw = {
 	.pr_ctlinput =		div_ctlinput,
 	.pr_ctloutput =		ip_ctloutput,
 	.pr_init =		div_init,
+#ifdef VIMAGE
+	.pr_destroy =		div_destroy,
+#endif
 	.pr_usrreqs =		&div_usrreqs
 };
 
@@ -716,7 +730,9 @@ static int
 div_modevent(module_t mod, int type, void *unused)
 {
 	int err = 0;
+#ifndef VIMAGE
 	int n;
+#endif
 
 	switch (type) {
 	case MOD_LOAD:
@@ -726,7 +742,11 @@ div_modevent(module_t mod, int type, void *unused)
 		 * a true IP protocol that goes over the wire.
 		 */
 		err = pf_proto_register(PF_INET, &div_protosw);
+		if (err != 0)
+			return (err);
 		ip_divert_ptr = divert_packet;
+		ip_divert_event_tag = EVENTHANDLER_REGISTER(maxsockets_change,
+		    div_zone_change, NULL, EVENTHANDLER_PRI_ANY);
 		break;
 	case MOD_QUIESCE:
 		/*
@@ -737,6 +757,10 @@ div_modevent(module_t mod, int type, void *unused)
 		err = EPERM;
 		break;
 	case MOD_UNLOAD:
+#ifdef VIMAGE
+		err = EPERM;
+		break;
+#else
 		/*
 		 * Forced unload.
 		 *
@@ -758,9 +782,10 @@ div_modevent(module_t mod, int type, void *unused)
 		ip_divert_ptr = NULL;
 		err = pf_proto_unregister(PF_INET, IPPROTO_DIVERT, SOCK_RAW);
 		INP_INFO_WUNLOCK(&V_divcbinfo);
-		INP_INFO_LOCK_DESTROY(&V_divcbinfo);
-		uma_zdestroy(V_divcbinfo.ipi_zone);
+		div_destroy();
+		EVENTHANDLER_DEREGISTER(maxsockets_change, ip_divert_event_tag);
 		break;
+#endif /* !VIMAGE */
 	default:
 		err = EOPNOTSUPP;
 		break;
diff --git a/sys/netinet/ip_divert.h b/sys/netinet/ip_divert.h
index 1bb09447b23..50363554982 100644
--- a/sys/netinet/ip_divert.h
+++ b/sys/netinet/ip_divert.h
@@ -83,7 +83,6 @@ divert_find_info(struct mbuf *m)
 typedef	void ip_divert_packet_t(struct mbuf *m, int incoming);
 extern	ip_divert_packet_t *ip_divert_ptr;
 
-extern	void div_init(void);
 extern	void div_input(struct mbuf *, int);
 extern	void div_ctlinput(int, struct sockaddr *, void *);
 #endif /* _NETINET_IP_DIVERT_H_ */
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index f53f787ed87..78b6d3046e2 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -151,8 +151,8 @@ ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m)
 /*
  * Try to forward a packet based on the destination address.
  * This is a fast path optimized for the plain forwarding case.
- * If the packet is handled (and consumed) here then we return 1;
- * otherwise 0 is returned and the packet should be delivered
+ * If the packet is handled (and consumed) here then we return NULL;
+ * otherwise mbuf is returned and the packet should be delivered
  * to ip_input for full processing.
  */
 struct mbuf *
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 18920a0242c..9967a29607b 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -645,8 +645,10 @@ int ipfw_check_out(void *, struct mbuf **, struct ifnet *, int, struct inpcb *in
 
 int ipfw_chk(struct ip_fw_args *);
 
-int ipfw_init(void);
-void ipfw_destroy(void);
+int ipfw_hook(void);
+int ipfw6_hook(void);
+int ipfw_unhook(void);
+int ipfw6_unhook(void);
 #ifdef NOTYET
 void ipfw_nat_destroy(void);
 #endif
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index bf2a5f8bb53..e222cdaaa1f 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -156,7 +157,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
 		 * longer than that long for the stability of ro_rt.  The
 		 * flow ID assignment must have happened before this point.
 		 */
-		if (flowtable_lookup(V_ip_ft, m, ro) == 0)
+		if (flowtable_lookup(V_ip_ft, m, ro, M_GETFIB(m)) == 0)
 			nortfree = 1;
 #endif
 	}
@@ -204,6 +205,7 @@ again:
 		if (!nortfree)
 			RTFREE(ro->ro_rt);
 		ro->ro_rt = (struct rtentry *)NULL;
+		ro->ro_lle = (struct llentry *)NULL;
 	}
 #ifdef IPFIREWALL_FORWARD
 	if (ro->ro_rt == NULL && fwd_tag == NULL) {
diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
index da6593c46ce..e35669dc3a2 100644
--- a/sys/netinet/ipfw/ip_fw2.c
+++ b/sys/netinet/ipfw/ip_fw2.c
@@ -102,6 +102,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #endif
 
+static VNET_DEFINE(int, ipfw_vnet_ready) = 0;
+#define	V_ipfw_vnet_ready	VNET(ipfw_vnet_ready)
 /*
  * set_disable contains one bit per set value (0..31).
  * If the bit is set, all rules with the corresponding set
@@ -2057,7 +2059,7 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
 				dst_ip, htons(dst_port),
 				wildcard, NULL);
 		if (pcb != NULL) {
-			*uc = crhold(inp->inp_cred);
+			*uc = crhold(pcb->inp_cred);
 			*ugid_lookupp = 1;
 		}
 		INP_INFO_RUNLOCK(pi);
@@ -2237,7 +2239,7 @@ ipfw_chk(struct ip_fw_args *args)
 	/* end of ipv6 variables */
 	int is_ipv4 = 0;
 
-	if (m->m_flags & M_SKIP_FIREWALL)
+	if (m->m_flags & M_SKIP_FIREWALL || (! V_ipfw_vnet_ready))
 		return (IP_FW_PASS);	/* accept */
 
 	dst_ip.s_addr = 0;		/* make sure it is initialized */
@@ -4579,12 +4581,10 @@ done:
 	CURVNET_RESTORE();
 }
 
-
-
 /****************
  * Stuff that must be initialised only on boot or module load
  */
-int
+static int
 ipfw_init(void)
 {
 	int error = 0;
@@ -4623,9 +4623,11 @@ ipfw_init(void)
 		default_to_accept ? "accept" : "deny");
 
 	/*
-	 * Note: V_xxx variables can be accessed here but the iattach()
-     	 * may not have been called yet for the VIMGE case.
-	 * Tuneables will have been processed.
+	 * Note: V_xxx variables can be accessed here but the vnet specific
+	 * initializer may not have been called yet for the VIMAGE case.
+	 * Tuneables will have been processed. We will print out values for
+	 * the default vnet. 
+	 * XXX This should all be rationalized AFTER 8.0
 	 */
 	if (V_fw_verbose == 0)
 		printf("disabled\n");
@@ -4635,9 +4637,23 @@ ipfw_init(void)
 		printf("limited to %d packets/entry by default\n",
 		    V_verbose_limit);
 
+	/*
+	 * Hook us up to pfil.
+	 * Eventually pfil will be per vnet.
+	 */
+	if ((error = ipfw_hook()) != 0) {
+		printf("ipfw_hook() error\n");
+		return (error);
+	}
+#ifdef INET6
+	if ((error = ipfw6_hook()) != 0) {
+		printf("ipfw6_hook() error\n");
+		return (error);
+	}
+#endif
 	/*
 	 * Other things that are only done the first time.
-	 * (now that we a re cuaranteed of success).
+	 * (now that we are guaranteed of success).
 	 */
 	ip_fw_ctl_ptr = ipfw_ctl;
 	ip_fw_chk_ptr = ipfw_chk;
@@ -4645,8 +4661,8 @@ ipfw_init(void)
 }
 
 /****************
- * Stuff that must be initialised for every instance
- * (including the forst of course).
+ * Stuff that must be initialized for every instance
+ * (including the first of course).
  */
 static int
 vnet_ipfw_init(const void *unused)
@@ -4726,17 +4742,17 @@ vnet_ipfw_init(const void *unused)
 #endif
 
 	/* First set up some values that are compile time options */
+	V_ipfw_vnet_ready = 1;		/* Open for business */
 	return (0);
 }
 
 /**********************
  * Called for the removal of the last instance only on module unload.
  */
-void
+static void
 ipfw_destroy(void)
 {
-	ip_fw_chk_ptr = NULL;
-	ip_fw_ctl_ptr = NULL;
+
 	uma_zdestroy(ipfw_dyn_rule_zone);
 	IPFW_DYN_LOCK_DESTROY();
 	printf("IP firewall unloaded\n");
@@ -4750,7 +4766,9 @@ vnet_ipfw_uninit(const void *unused)
 {
 	struct ip_fw *reap;
 
+	V_ipfw_vnet_ready = 0; /* tell new callers to go away */
 	callout_drain(&V_ipfw_timeout);
+	/* We wait on the wlock here until the last user leaves */
 	IPFW_WLOCK(&V_layer3_chain);
 	flush_tables(&V_layer3_chain);
 	V_layer3_chain.reap = NULL;
@@ -4766,10 +4784,86 @@ vnet_ipfw_uninit(const void *unused)
 	return 0;
 }
 
-VNET_SYSINIT(vnet_ipfw_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY - 255,
-    vnet_ipfw_init, NULL);
+/*
+ * Module event handler.
+ * In general we have the choice of handling most of these events by the
+ * event handler or by the (VNET_)SYS(UN)INIT handlers. I have chosen to
+ * use the SYSINIT handlers as they are more capable of expressing the
+ * flow of control during module and vnet operations, so this is just
+ * a skeleton. Note there is no SYSINIT equivalent of the module
+ * SHUTDOWN handler, but we don't have anything to do in that case anyhow.
+ */
+static int
+ipfw_modevent(module_t mod, int type, void *unused)
+{
+	int err = 0;
 
-VNET_SYSUNINIT(vnet_ipfw_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY - 255,
-    vnet_ipfw_uninit, NULL);
+	switch (type) {
+	case MOD_LOAD:
+		/* Called once at module load or
+	 	 * system boot if compiled in. */
+		break;
+	case MOD_UNLOAD:
+		break;
+	case MOD_QUIESCE:
+		/* Yes, the unhooks can return errors, we can safely ignore
+		 * them. Eventually these will be done per jail as they
+		 * shut down. We will wait on each vnet's l3 lock as existing
+		 * callers go away.
+		 */
+		ipfw_unhook();
+#ifdef INET6
+		ipfw6_unhook();
+#endif
+		/* layer2 and other entrypoints still come in this way. */
+		ip_fw_chk_ptr = NULL;
+		ip_fw_ctl_ptr = NULL;
+		/* Called during unload. */
+		break;
+	case MOD_SHUTDOWN:
+		/* Called during system shutdown. */
+		break;
+	default:
+		err = EOPNOTSUPP;
+		break;
+	}
+	return err;
+}
+
+static moduledata_t ipfwmod = {
+	"ipfw",
+	ipfw_modevent,
+	0
+};
+
+/* Define startup order. */
+#define	IPFW_SI_SUB_FIREWALL	SI_SUB_PROTO_IFATTACHDOMAIN
+#define	IPFW_MODEVENT_ORDER	(SI_ORDER_ANY - 255) /* On boot slot in here. */
+#define	IPFW_MODULE_ORDER	(IPFW_MODEVENT_ORDER + 1) /* A little later. */
+#define	IPFW_VNET_ORDER		(IPFW_MODEVENT_ORDER + 2) /* Later still. */
+
+DECLARE_MODULE(ipfw, ipfwmod, IPFW_SI_SUB_FIREWALL, IPFW_MODEVENT_ORDER);
+MODULE_VERSION(ipfw, 2);
+/* should declare some dependencies here */
+
+/*
+ * Starting up. Done in order after ipfwmod() has been called.
+ * VNET_SYSINIT is also called for each existing vnet and each new vnet.
+ */
+SYSINIT(ipfw_init, IPFW_SI_SUB_FIREWALL, IPFW_MODULE_ORDER,
+	    ipfw_init, NULL);
+VNET_SYSINIT(vnet_ipfw_init, IPFW_SI_SUB_FIREWALL, IPFW_VNET_ORDER,
+	    vnet_ipfw_init, NULL);
+ 
+/*
+ * Closing up shop. These are done in REVERSE ORDER, but still
+ * after ipfwmod() has been called. Not called on reboot.
+ * VNET_SYSUNINIT is also called for each exiting vnet as it exits.
+ * or when the module is unloaded.
+ */
+SYSUNINIT(ipfw_destroy, IPFW_SI_SUB_FIREWALL, IPFW_MODULE_ORDER,
+	    ipfw_destroy, NULL);
+VNET_SYSUNINIT(vnet_ipfw_uninit, IPFW_SI_SUB_FIREWALL, IPFW_VNET_ORDER,
+	    vnet_ipfw_uninit, NULL);
 
  
diff --git a/sys/netinet/ipfw/ip_fw_pfil.c b/sys/netinet/ipfw/ip_fw_pfil.c
index e28d5ca6403..ffffb594546 100644
--- a/sys/netinet/ipfw/ip_fw_pfil.c
+++ b/sys/netinet/ipfw/ip_fw_pfil.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -441,7 +442,7 @@ nodivert:
 	return 1;
 }
 
-static int
+int
 ipfw_hook(void)
 {
 	struct pfil_head *pfh_inet;
@@ -458,7 +459,7 @@ ipfw_hook(void)
 	return 0;
 }
 
-static int
+int
 ipfw_unhook(void)
 {
 	struct pfil_head *pfh_inet;
@@ -476,7 +477,7 @@ ipfw_unhook(void)
 }
 
 #ifdef INET6
-static int
+int
 ipfw6_hook(void)
 {
 	struct pfil_head *pfh_inet6;
@@ -493,7 +494,7 @@ ipfw6_hook(void)
 	return 0;
 }
 
-static int
+int
 ipfw6_unhook(void)
 {
 	struct pfil_head *pfh_inet6;
@@ -517,6 +518,10 @@ ipfw_chg_hook(SYSCTL_HANDLER_ARGS)
 	int enable = *(int *)arg1;
 	int error;
 
+#ifdef VIMAGE /* Since enabling is global, only let base do it. */
+	if (! IS_DEFAULT_VNET(curvnet))
+		return (EPERM);
+#endif
 	error = sysctl_handle_int(oidp, &enable, 0, req);
 	if (error)
 		return (error);
@@ -549,50 +554,3 @@ ipfw_chg_hook(SYSCTL_HANDLER_ARGS)
 	return (0);
 }
 
-static int
-ipfw_modevent(module_t mod, int type, void *unused)
-{
-	int err = 0;
-
-	switch (type) {
-	case MOD_LOAD:
-		if ((err = ipfw_init()) != 0) {
-			printf("ipfw_init() error\n");
-			break;
-		}
-		if ((err = ipfw_hook()) != 0) {
-			printf("ipfw_hook() error\n");
-			break;
-		}
-#ifdef INET6
-		if ((err = ipfw6_hook()) != 0) {
-			printf("ipfw_hook() error\n");
-			break;
-		}
-#endif
-		break;
-
-	case MOD_UNLOAD:
-		if ((err = ipfw_unhook()) > 0)
-			break;
-#ifdef INET6
-		if ((err = ipfw6_unhook()) > 0)
-			break;
-#endif
-		ipfw_destroy();
-		break;
-
-	default:
-		return EOPNOTSUPP;
-		break;
-	}
-	return err;
-}
-
-static moduledata_t ipfwmod = {
-	"ipfw",
-	ipfw_modevent,
-	0
-};
-DECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY - 256);
-MODULE_VERSION(ipfw, 2);
diff --git a/sys/netinet/sctp_bsd_addr.c b/sys/netinet/sctp_bsd_addr.c
index 4b857815dc9..792a720b6df 100644
--- a/sys/netinet/sctp_bsd_addr.c
+++ b/sys/netinet/sctp_bsd_addr.c
@@ -175,6 +175,7 @@ sctp_is_desired_interface_type(struct ifaddr *ifa)
 	case IFT_LOOP:
 	case IFT_SLIP:
 	case IFT_GIF:
+	case IFT_L2VLAN:
 	case IFT_IP:
 	case IFT_IPOVERCDLC:
 	case IFT_IPOVERCLAW:
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 7abdd710a47..9174522237b 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -900,7 +900,7 @@ sctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc)
 {
 	struct sctp_tmit_chunk *chk;
 	uint16_t nxt_todel;
-	uint32_t tsize;
+	uint32_t tsize, pd_point;
 
 doit_again:
 	chk = TAILQ_FIRST(&asoc->reasmqueue);
@@ -920,8 +920,13 @@ doit_again:
 			 * Yep the first one is here and its ok to deliver
 			 * but should we?
 			 */
-			if ((sctp_is_all_msg_on_reasm(asoc, &tsize) ||
-			    (tsize >= stcb->sctp_ep->partial_delivery_point))) {
+			if (stcb->sctp_socket) {
+				pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket),
+				    stcb->sctp_ep->partial_delivery_point);
+			} else {
+				pd_point = stcb->sctp_ep->partial_delivery_point;
+			}
+			if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) {
 
 				/*
 				 * Yes, we setup to start reception, by
@@ -2520,6 +2525,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
 	 */
 	struct sctp_association *asoc;
 	int at;
+	uint8_t comb_byte;
 	int last_all_ones = 0;
 	int slide_from, slide_end, lgap, distance;
 
@@ -2550,7 +2556,6 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
 		memcpy(aux_array, asoc->mapping_array, 64);
 	/* EY do the same for nr_mapping_array */
 	if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) {
-
 		if (asoc->nr_mapping_array_size != asoc->mapping_array_size) {
 			/*
 			 * printf("\nEY-IN sack_check method: \nEY-" "The
@@ -2577,13 +2582,18 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
 	 */
 	at = 0;
 	for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) {
-
-		if (asoc->mapping_array[slide_from] == 0xff) {
+		/*
+		 * We must combine the renegable and non-renegable arrays
+		 * here to form a unified view of what is acked right now
+		 * (since they are kept separate
+		 */
+		comb_byte = asoc->mapping_array[slide_from] | asoc->nr_mapping_array[slide_from];
+		if (comb_byte == 0xff) {
 			at += 8;
 			last_all_ones = 1;
 		} else {
 			/* there is a 0 bit */
-			at += sctp_map_lookup_tab[asoc->mapping_array[slide_from]];
+			at += sctp_map_lookup_tab[comb_byte];
 			last_all_ones = 0;
 			break;
 		}
@@ -2824,7 +2834,7 @@ void
 sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc)
 {
 	struct sctp_tmit_chunk *chk;
-	uint32_t tsize;
+	uint32_t tsize, pd_point;
 	uint16_t nxt_todel;
 
 	if (asoc->fragmented_delivery_inprogress) {
@@ -2857,11 +2867,16 @@ doit_again:
 
 		/*
 		 * Before we start though either all of the message should
-		 * be here or 1/4 the socket buffer max or nothing on the
+		 * be here or the socket buffer max or nothing on the
 		 * delivery queue and something can be delivered.
 		 */
-		if ((sctp_is_all_msg_on_reasm(asoc, &tsize) ||
-		    (tsize >= stcb->sctp_ep->partial_delivery_point))) {
+		if (stcb->sctp_socket) {
+			pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket),
+			    stcb->sctp_ep->partial_delivery_point);
+		} else {
+			pd_point = stcb->sctp_ep->partial_delivery_point;
+		}
+		if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) {
 			asoc->fragmented_delivery_inprogress = 1;
 			asoc->tsn_last_delivered = chk->rec.data.TSN_seq - 1;
 			asoc->str_of_pdapi = chk->rec.data.stream_number;
@@ -3172,6 +3187,235 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
 	return (0);
 }
 
+static int
+sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1, uint32_t last_tsn,
+    uint16_t frag_strt, uint16_t frag_end, int nr_sacking,
+    int *num_frs,
+    uint32_t * biggest_newly_acked_tsn,
+    uint32_t * this_sack_lowest_newack,
+    int *ecn_seg_sums)
+{
+	struct sctp_tmit_chunk *tp1;
+	unsigned int theTSN;
+	int j, wake_him = 0;
+
+	/* Recover the tp1 we last saw */
+	tp1 = *p_tp1;
+	if (tp1 == NULL) {
+		tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
+	}
+	for (j = frag_strt; j <= frag_end; j++) {
+		theTSN = j + last_tsn;
+		while (tp1) {
+			if (tp1->rec.data.doing_fast_retransmit)
+				(*num_frs) += 1;
+
+			/*-
+			 * CMT: CUCv2 algorithm. For each TSN being
+			 * processed from the sent queue, track the
+			 * next expected pseudo-cumack, or
+			 * rtx_pseudo_cumack, if required. Separate
+			 * cumack trackers for first transmissions,
+			 * and retransmissions.
+			 */
+			if ((tp1->whoTo->find_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
+			    (tp1->snd_count == 1)) {
+				tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq;
+				tp1->whoTo->find_pseudo_cumack = 0;
+			}
+			if ((tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
+			    (tp1->snd_count > 1)) {
+				tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq;
+				tp1->whoTo->find_rtx_pseudo_cumack = 0;
+			}
+			if (tp1->rec.data.TSN_seq == theTSN) {
+				if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
+					/*-
+					 * must be held until
+					 * cum-ack passes
+					 */
+					/*-
+					 * ECN Nonce: Add the nonce
+					 * value to the sender's
+					 * nonce sum
+					 */
+					if (tp1->sent < SCTP_DATAGRAM_RESEND) {
+						/*-
+						 * If it is less than RESEND, it is
+						 * now no-longer in flight.
+						 * Higher values may already be set
+						 * via previous Gap Ack Blocks...
+						 * i.e. ACKED or RESEND.
+						 */
+						if (compare_with_wrap(tp1->rec.data.TSN_seq,
+						    *biggest_newly_acked_tsn, MAX_TSN)) {
+							*biggest_newly_acked_tsn = tp1->rec.data.TSN_seq;
+						}
+						/*-
+						 * CMT: SFR algo (and HTNA) - set
+						 * saw_newack to 1 for dest being
+						 * newly acked. update
+						 * this_sack_highest_newack if
+						 * appropriate.
+						 */
+						if (tp1->rec.data.chunk_was_revoked == 0)
+							tp1->whoTo->saw_newack = 1;
+
+						if (compare_with_wrap(tp1->rec.data.TSN_seq,
+						    tp1->whoTo->this_sack_highest_newack,
+						    MAX_TSN)) {
+							tp1->whoTo->this_sack_highest_newack =
+							    tp1->rec.data.TSN_seq;
+						}
+						/*-
+						 * CMT DAC algo: also update
+						 * this_sack_lowest_newack
+						 */
+						if (*this_sack_lowest_newack == 0) {
+							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
+								sctp_log_sack(*this_sack_lowest_newack,
+								    last_tsn,
+								    tp1->rec.data.TSN_seq,
+								    0,
+								    0,
+								    SCTP_LOG_TSN_ACKED);
+							}
+							*this_sack_lowest_newack = tp1->rec.data.TSN_seq;
+						}
+						/*-
+						 * CMT: CUCv2 algorithm. If (rtx-)pseudo-cumack for corresp
+						 * dest is being acked, then we have a new (rtx-)pseudo-cumack. Set
+						 * new_(rtx_)pseudo_cumack to TRUE so that the cwnd for this dest can be
+						 * updated. Also trigger search for the next expected (rtx-)pseudo-cumack.
+						 * Separate pseudo_cumack trackers for first transmissions and
+						 * retransmissions.
+						 */
+						if (tp1->rec.data.TSN_seq == tp1->whoTo->pseudo_cumack) {
+							if (tp1->rec.data.chunk_was_revoked == 0) {
+								tp1->whoTo->new_pseudo_cumack = 1;
+							}
+							tp1->whoTo->find_pseudo_cumack = 1;
+						}
+						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
+							sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK);
+						}
+						if (tp1->rec.data.TSN_seq == tp1->whoTo->rtx_pseudo_cumack) {
+							if (tp1->rec.data.chunk_was_revoked == 0) {
+								tp1->whoTo->new_pseudo_cumack = 1;
+							}
+							tp1->whoTo->find_rtx_pseudo_cumack = 1;
+						}
+						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
+							sctp_log_sack(*biggest_newly_acked_tsn,
+							    last_tsn,
+							    tp1->rec.data.TSN_seq,
+							    frag_strt,
+							    frag_end,
+							    SCTP_LOG_TSN_ACKED);
+						}
+						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
+							sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP,
+							    tp1->whoTo->flight_size,
+							    tp1->book_size,
+							    (uintptr_t) tp1->whoTo,
+							    tp1->rec.data.TSN_seq);
+						}
+						sctp_flight_size_decrease(tp1);
+						sctp_total_flight_decrease(stcb, tp1);
+
+						tp1->whoTo->net_ack += tp1->send_size;
+						if (tp1->snd_count < 2) {
+							/*-
+							 * True non-retransmited chunk
+							 */
+							tp1->whoTo->net_ack2 += tp1->send_size;
+
+							/*-
+							 * update RTO too ?
+							 */
+							if (tp1->do_rtt) {
+								tp1->whoTo->RTO =
+								    sctp_calculate_rto(stcb,
+								    &stcb->asoc,
+								    tp1->whoTo,
+								    &tp1->sent_rcv_time,
+								    sctp_align_safe_nocopy);
+								tp1->do_rtt = 0;
+							}
+						}
+					}
+					if (tp1->sent <= SCTP_DATAGRAM_RESEND) {
+						(*ecn_seg_sums) += tp1->rec.data.ect_nonce;
+						(*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM;
+						if (compare_with_wrap(tp1->rec.data.TSN_seq,
+						    stcb->asoc.this_sack_highest_gap,
+						    MAX_TSN)) {
+							stcb->asoc.this_sack_highest_gap =
+							    tp1->rec.data.TSN_seq;
+						}
+						if (tp1->sent == SCTP_DATAGRAM_RESEND) {
+							sctp_ucount_decr(stcb->asoc.sent_queue_retran_cnt);
+#ifdef SCTP_AUDITING_ENABLED
+							sctp_audit_log(0xB2,
+							    (stcb->asoc.sent_queue_retran_cnt & 0x000000ff));
+#endif
+						}
+					}
+					/*-
+					 * All chunks NOT UNSENT fall through here and are marked
+					 * (leave PR-SCTP ones that are to skip alone though)
+					 */
+					if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+						tp1->sent = SCTP_DATAGRAM_MARKED;
+
+					if (tp1->rec.data.chunk_was_revoked) {
+						/* deflate the cwnd */
+						tp1->whoTo->cwnd -= tp1->book_size;
+						tp1->rec.data.chunk_was_revoked = 0;
+					}
+					/* NR Sack code here */
+					if (nr_sacking) {
+						if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+							tp1->sent = SCTP_DATAGRAM_NR_MARKED;
+						/*
+						 * TAILQ_REMOVE(&asoc->sent_q
+						 * ueue, tp1, sctp_next);
+						 */
+						if (tp1->data) {
+							/*
+							 * sa_ignore
+							 * NO_NULL_CHK
+							 */
+							sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
+							sctp_m_freem(tp1->data);
+						}
+						tp1->data = NULL;
+						/* asoc->sent_queue_cnt--; */
+						/*
+						 * sctp_free_a_chunk(stcb,
+						 * tp1);
+						 */
+						wake_him++;
+					}
+				}
+				break;
+			}	/* if (tp1->TSN_seq == theTSN) */
+			if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN,
+			    MAX_TSN))
+				break;
+
+			tp1 = TAILQ_NEXT(tp1, sctp_next);
+		}		/* end while (tp1) */
+		/* In case the fragments were not in order we must reset */
+		if (tp1 == NULL) {
+			tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
+		}
+	}			/* end for (j = fragStart */
+	*p_tp1 = tp1;
+	return (wake_him);	/* Return value only used for nr-sack */
+}
+
+
 static void
 sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_association *asoc,
     struct sctp_sack_chunk *ch, uint32_t last_tsn, uint32_t * biggest_tsn_acked,
@@ -3184,8 +3428,7 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct
 	struct sctp_sack *sack;
 	struct sctp_gap_ack_block *frag, block;
 	struct sctp_tmit_chunk *tp1;
-	int i, j;
-	unsigned int theTSN;
+	int i;
 	int num_frs = 0;
 
 	uint16_t frag_strt, frag_end, primary_flag_set;
@@ -3253,214 +3496,9 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct
 			}
 			last_frag_high = frag_end + last_tsn;
 		}
-		for (j = frag_strt; j <= frag_end; j++) {
-			theTSN = j + last_tsn;
-			while (tp1) {
-				if (tp1->rec.data.doing_fast_retransmit)
-					num_frs++;
-
-				/*
-				 * CMT: CUCv2 algorithm. For each TSN being
-				 * processed from the sent queue, track the
-				 * next expected pseudo-cumack, or
-				 * rtx_pseudo_cumack, if required. Separate
-				 * cumack trackers for first transmissions,
-				 * and retransmissions.
-				 */
-				if ((tp1->whoTo->find_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
-				    (tp1->snd_count == 1)) {
-					tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq;
-					tp1->whoTo->find_pseudo_cumack = 0;
-				}
-				if ((tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
-				    (tp1->snd_count > 1)) {
-					tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq;
-					tp1->whoTo->find_rtx_pseudo_cumack = 0;
-				}
-				if (tp1->rec.data.TSN_seq == theTSN) {
-					if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
-						/*
-						 * must be held until
-						 * cum-ack passes
-						 */
-						/*
-						 * ECN Nonce: Add the nonce
-						 * value to the sender's
-						 * nonce sum
-						 */
-						if (tp1->sent < SCTP_DATAGRAM_RESEND) {
-							/*-
-							 * If it is less than RESEND, it is
-							 * now no-longer in flight.
-							 * Higher values may already be set
-							 * via previous Gap Ack Blocks...
-							 * i.e. ACKED or RESEND.
-							 */
-							if (compare_with_wrap(tp1->rec.data.TSN_seq,
-							    *biggest_newly_acked_tsn, MAX_TSN)) {
-								*biggest_newly_acked_tsn = tp1->rec.data.TSN_seq;
-							}
-							/*
-							 * CMT: SFR algo
-							 * (and HTNA) - set
-							 * saw_newack to 1
-							 * for dest being
-							 * newly acked.
-							 * update
-							 * this_sack_highest_
-							 * newack if
-							 * appropriate.
-							 */
-							if (tp1->rec.data.chunk_was_revoked == 0)
-								tp1->whoTo->saw_newack = 1;
-
-							if (compare_with_wrap(tp1->rec.data.TSN_seq,
-							    tp1->whoTo->this_sack_highest_newack,
-							    MAX_TSN)) {
-								tp1->whoTo->this_sack_highest_newack =
-								    tp1->rec.data.TSN_seq;
-							}
-							/*
-							 * CMT DAC algo:
-							 * also update
-							 * this_sack_lowest_n
-							 * ewack
-							 */
-							if (*this_sack_lowest_newack == 0) {
-								if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
-									sctp_log_sack(*this_sack_lowest_newack,
-									    last_tsn,
-									    tp1->rec.data.TSN_seq,
-									    0,
-									    0,
-									    SCTP_LOG_TSN_ACKED);
-								}
-								*this_sack_lowest_newack = tp1->rec.data.TSN_seq;
-							}
-							/*
-							 * CMT: CUCv2
-							 * algorithm. If
-							 * (rtx-)pseudo-cumac
-							 * k for corresp
-							 * dest is being
-							 * acked, then we
-							 * have a new
-							 * (rtx-)pseudo-cumac
-							 * k. Set
-							 * new_(rtx_)pseudo_c
-							 * umack to TRUE so
-							 * that the cwnd for
-							 * this dest can be
-							 * updated. Also
-							 * trigger search
-							 * for the next
-							 * expected
-							 * (rtx-)pseudo-cumac
-							 * k. Separate
-							 * pseudo_cumack
-							 * trackers for
-							 * first
-							 * transmissions and
-							 * retransmissions.
-							 */
-							if (tp1->rec.data.TSN_seq == tp1->whoTo->pseudo_cumack) {
-								if (tp1->rec.data.chunk_was_revoked == 0) {
-									tp1->whoTo->new_pseudo_cumack = 1;
-								}
-								tp1->whoTo->find_pseudo_cumack = 1;
-							}
-							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
-								sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK);
-							}
-							if (tp1->rec.data.TSN_seq == tp1->whoTo->rtx_pseudo_cumack) {
-								if (tp1->rec.data.chunk_was_revoked == 0) {
-									tp1->whoTo->new_pseudo_cumack = 1;
-								}
-								tp1->whoTo->find_rtx_pseudo_cumack = 1;
-							}
-							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
-								sctp_log_sack(*biggest_newly_acked_tsn,
-								    last_tsn,
-								    tp1->rec.data.TSN_seq,
-								    frag_strt,
-								    frag_end,
-								    SCTP_LOG_TSN_ACKED);
-							}
-							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
-								sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP,
-								    tp1->whoTo->flight_size,
-								    tp1->book_size,
-								    (uintptr_t) tp1->whoTo,
-								    tp1->rec.data.TSN_seq);
-							}
-							sctp_flight_size_decrease(tp1);
-							sctp_total_flight_decrease(stcb, tp1);
-
-							tp1->whoTo->net_ack += tp1->send_size;
-							if (tp1->snd_count < 2) {
-								/*
-								 * True
-								 * non-retran
-								 * smited
-								 * chunk */
-								tp1->whoTo->net_ack2 += tp1->send_size;
-
-								/*
-								 * update RTO
-								 * too ? */
-								if (tp1->do_rtt) {
-									tp1->whoTo->RTO =
-									    sctp_calculate_rto(stcb,
-									    asoc,
-									    tp1->whoTo,
-									    &tp1->sent_rcv_time,
-									    sctp_align_safe_nocopy);
-									tp1->do_rtt = 0;
-								}
-							}
-						}
-						if (tp1->sent <= SCTP_DATAGRAM_RESEND) {
-							(*ecn_seg_sums) += tp1->rec.data.ect_nonce;
-							(*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM;
-							if (compare_with_wrap(tp1->rec.data.TSN_seq,
-							    asoc->this_sack_highest_gap,
-							    MAX_TSN)) {
-								asoc->this_sack_highest_gap =
-								    tp1->rec.data.TSN_seq;
-							}
-							if (tp1->sent == SCTP_DATAGRAM_RESEND) {
-								sctp_ucount_decr(asoc->sent_queue_retran_cnt);
-#ifdef SCTP_AUDITING_ENABLED
-								sctp_audit_log(0xB2,
-								    (asoc->sent_queue_retran_cnt & 0x000000ff));
-#endif
-							}
-						}
-						/*
-						 * All chunks NOT UNSENT
-						 * fall through here and are
-						 * marked (leave PR-SCTP
-						 * ones that are to skip
-						 * alone though)
-						 */
-						if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
-							tp1->sent = SCTP_DATAGRAM_MARKED;
-
-						if (tp1->rec.data.chunk_was_revoked) {
-							/* deflate the cwnd */
-							tp1->whoTo->cwnd -= tp1->book_size;
-							tp1->rec.data.chunk_was_revoked = 0;
-						}
-					}
-					break;
-				}	/* if (tp1->TSN_seq == theTSN) */
-				if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN,
-				    MAX_TSN))
-					break;
-
-				tp1 = TAILQ_NEXT(tp1, sctp_next);
-			}	/* end while (tp1) */
-		}		/* end for (j = fragStart */
+		sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end,
+		    0, &num_frs, biggest_newly_acked_tsn,
+		    this_sack_lowest_newack, ecn_seg_sums);
 		frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset,
 		    sizeof(struct sctp_gap_ack_block), (uint8_t *) & block);
 		*offset += sizeof(block);
@@ -5192,7 +5230,7 @@ skip_segments:
 			/* sa_ignore NO_NULL_CHK */
 			sctp_free_bufspace(stcb, asoc, tp1, 1);
 			sctp_m_freem(tp1->data);
-			if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
+			if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(tp1->flags)) {
 				asoc->sent_queue_cnt_removeable--;
 			}
 		}
@@ -6289,10 +6327,11 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
 					ctl->pdapi_aborted = 1;
 					sv = stcb->asoc.control_pdapi;
 					stcb->asoc.control_pdapi = ctl;
-					sctp_notify_partial_delivery_indication(stcb,
+					sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
+					    stcb,
 					    SCTP_PARTIAL_DELIVERY_ABORTED,
-					    SCTP_HOLDS_LOCK,
-					    str_seq);
+					    (void *)&str_seq,
+					    SCTP_SO_NOT_LOCKED);
 					stcb->asoc.control_pdapi = sv;
 					break;
 				} else if ((ctl->sinfo_stream == stseq->stream) &&
@@ -6844,9 +6883,8 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
 	struct sctp_gap_ack_block *frag, block;
 	struct sctp_nr_gap_ack_block *nr_frag, nr_block;
 	struct sctp_tmit_chunk *tp1;
-	uint32_t i, j;
+	uint32_t i;
 	int wake_him = 0;
-	uint32_t theTSN;
 	int num_frs = 0;
 
 	uint16_t frag_strt, frag_end, primary_flag_set;
@@ -6921,213 +6959,9 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
 			}
 			last_frag_high = frag_end + last_tsn;
 		}
-		for (j = frag_strt; j <= frag_end; j++) {
-			theTSN = j + last_tsn;
-			while (tp1) {
-				if (tp1->rec.data.doing_fast_retransmit)
-					num_frs++;
-
-				/*
-				 * CMT: CUCv2 algorithm. For each TSN being
-				 * processed from the sent queue, track the
-				 * next expected pseudo-cumack, or
-				 * rtx_pseudo_cumack, if required. Separate
-				 * cumack trackers for first transmissions,
-				 * and retransmissions.
-				 */
-				if ((tp1->whoTo->find_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
-				    (tp1->snd_count == 1)) {
-					tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq;
-					tp1->whoTo->find_pseudo_cumack = 0;
-				}
-				if ((tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
-				    (tp1->snd_count > 1)) {
-					tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq;
-					tp1->whoTo->find_rtx_pseudo_cumack = 0;
-				}
-				if (tp1->rec.data.TSN_seq == theTSN) {
-					if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
-						/*
-						 * must be held until
-						 * cum-ack passes
-						 */
-						/*
-						 * ECN Nonce: Add the nonce
-						 * value to the sender's
-						 * nonce sum
-						 */
-						if (tp1->sent < SCTP_DATAGRAM_RESEND) {
-							/*-
-						         * If it is less than RESEND, it is
-						         * now no-longer in flight.
-						         * Higher values may already be set
-						         * via previous Gap Ack Blocks...
-						         * i.e. ACKED or RESEND.
-						         */
-							if (compare_with_wrap(tp1->rec.data.TSN_seq,
-							    *biggest_newly_acked_tsn, MAX_TSN)) {
-								*biggest_newly_acked_tsn = tp1->rec.data.TSN_seq;
-							}
-							/*
-							 * CMT: SFR algo
-							 * (and HTNA) - set
-							 * saw_newack to 1
-							 * for dest being
-							 * newly acked.
-							 * update
-							 * this_sack_highest_
-							 * newack if
-							 * appropriate.
-							 */
-							if (tp1->rec.data.chunk_was_revoked == 0)
-								tp1->whoTo->saw_newack = 1;
-
-							if (compare_with_wrap(tp1->rec.data.TSN_seq,
-							    tp1->whoTo->this_sack_highest_newack,
-							    MAX_TSN)) {
-								tp1->whoTo->this_sack_highest_newack =
-								    tp1->rec.data.TSN_seq;
-							}
-							/*
-							 * CMT DAC algo:
-							 * also update
-							 * this_sack_lowest_n
-							 * ewack
-							 */
-							if (*this_sack_lowest_newack == 0) {
-								if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
-									sctp_log_sack(*this_sack_lowest_newack,
-									    last_tsn,
-									    tp1->rec.data.TSN_seq,
-									    0,
-									    0,
-									    SCTP_LOG_TSN_ACKED);
-								}
-								*this_sack_lowest_newack = tp1->rec.data.TSN_seq;
-							}
-							/*
-							 * CMT: CUCv2
-							 * algorithm. If
-							 * (rtx-)pseudo-cumac
-							 * k for corresp
-							 * dest is being
-							 * acked, then we
-							 * have a new
-							 * (rtx-)pseudo-cumac
-							 * k. Set
-							 * new_(rtx_)pseudo_c
-							 * umack to TRUE so
-							 * that the cwnd for
-							 * this dest can be
-							 * updated. Also
-							 * trigger search
-							 * for the next
-							 * expected
-							 * (rtx-)pseudo-cumac
-							 * k. Separate
-							 * pseudo_cumack
-							 * trackers for
-							 * first
-							 * transmissions and
-							 * retransmissions.
-							 */
-							if (tp1->rec.data.TSN_seq == tp1->whoTo->pseudo_cumack) {
-								if (tp1->rec.data.chunk_was_revoked == 0) {
-									tp1->whoTo->new_pseudo_cumack = 1;
-								}
-								tp1->whoTo->find_pseudo_cumack = 1;
-							}
-							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
-								sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK);
-							}
-							if (tp1->rec.data.TSN_seq == tp1->whoTo->rtx_pseudo_cumack) {
-								if (tp1->rec.data.chunk_was_revoked == 0) {
-									tp1->whoTo->new_pseudo_cumack = 1;
-								}
-								tp1->whoTo->find_rtx_pseudo_cumack = 1;
-							}
-							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
-								sctp_log_sack(*biggest_newly_acked_tsn,
-								    last_tsn,
-								    tp1->rec.data.TSN_seq,
-								    frag_strt,
-								    frag_end,
-								    SCTP_LOG_TSN_ACKED);
-							}
-							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
-								sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP,
-								    tp1->whoTo->flight_size,
-								    tp1->book_size,
-								    (uintptr_t) tp1->whoTo,
-								    tp1->rec.data.TSN_seq);
-							}
-							sctp_flight_size_decrease(tp1);
-							sctp_total_flight_decrease(stcb, tp1);
-
-							tp1->whoTo->net_ack += tp1->send_size;
-							if (tp1->snd_count < 2) {
-								/*
-								 * True
-								 * non-retran
-								 * smited
-								 * chunk
-								 */
-								tp1->whoTo->net_ack2 += tp1->send_size;
-
-								/*
-								 * update
-								 * RTO too ?
-								 */
-								if (tp1->do_rtt) {
-									tp1->whoTo->RTO =
-									    sctp_calculate_rto(stcb,
-									    asoc,
-									    tp1->whoTo,
-									    &tp1->sent_rcv_time,
-									    sctp_align_safe_nocopy);
-									tp1->do_rtt = 0;
-								}
-							}
-						}
-						if (tp1->sent <= SCTP_DATAGRAM_RESEND) {
-							(*ecn_seg_sums) += tp1->rec.data.ect_nonce;
-							(*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM;
-							if (compare_with_wrap(tp1->rec.data.TSN_seq,
-							    asoc->this_sack_highest_gap,
-							    MAX_TSN)) {
-								asoc->this_sack_highest_gap =
-								    tp1->rec.data.TSN_seq;
-							}
-							if (tp1->sent == SCTP_DATAGRAM_RESEND) {
-								sctp_ucount_decr(asoc->sent_queue_retran_cnt);
-#ifdef SCTP_AUDITING_ENABLED
-								sctp_audit_log(0xB2,
-								    (asoc->sent_queue_retran_cnt & 0x000000ff));
-#endif
-							}
-						}
-						/*
-						 * All chunks NOT UNSENT
-						 * fall through here and are
-						 * marked
-						 */
-						if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
-							tp1->sent = SCTP_DATAGRAM_NR_MARKED;
-						if (tp1->rec.data.chunk_was_revoked) {
-							/* deflate the cwnd */
-							tp1->whoTo->cwnd -= tp1->book_size;
-							tp1->rec.data.chunk_was_revoked = 0;
-						}
-					}
-					break;
-				}	/* if (tp1->TSN_seq == theTSN) */
-				if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN,
-				    MAX_TSN))
-					break;
-
-				tp1 = TAILQ_NEXT(tp1, sctp_next);
-			}	/* end while (tp1) */
-		}		/* end for (j = fragStart */
+		sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end,
+		    0, &num_frs, biggest_newly_acked_tsn,
+		    this_sack_lowest_newack, ecn_seg_sums);
 		frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset,
 		    sizeof(struct sctp_gap_ack_block), (uint8_t *) & block);
 		*offset += sizeof(block);
@@ -7153,6 +6987,8 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
 	}
 	tp1 = NULL;
 	last_nr_frag_high = 0;
+	/* Reset to beginning for the nr_sack section */
+	tp1 = TAILQ_FIRST(&asoc->sent_queue);
 
 	for (i = 0; i < num_nr_seg; i++) {
 
@@ -7196,45 +7032,15 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
 			}
 			last_nr_frag_high = nr_frag_end + last_tsn;
 		}
-
-		for (j = nr_frag_strt + last_tsn; (compare_with_wrap((nr_frag_end + last_tsn), j, MAX_TSN)); j++) {
-			while (tp1) {
-				if (tp1->rec.data.TSN_seq == j) {
-					if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
-						if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
-							tp1->sent = SCTP_DATAGRAM_NR_MARKED;
-						/*
-						 * TAILQ_REMOVE(&asoc->sent_q
-						 * ueue, tp1, sctp_next);
-						 */
-						if (tp1->data) {
-							/*
-							 * sa_ignore
-							 * NO_NULL_CHK
-							 */
-							sctp_free_bufspace(stcb, asoc, tp1, 1);
-							sctp_m_freem(tp1->data);
-						}
-						tp1->data = NULL;
-						/* asoc->sent_queue_cnt--; */
-						/*
-						 * sctp_free_a_chunk(stcb,
-						 * tp1);
-						 */
-						wake_him++;
-					}
-					break;
-				}	/* if (tp1->TSN_seq == j) */
-				if (compare_with_wrap(tp1->rec.data.TSN_seq, j,
-				    MAX_TSN))
-					break;
-				tp1 = TAILQ_NEXT(tp1, sctp_next);
-			}	/* end while (tp1) */
-
-		}		/* end for (j = nrFragStart */
+		num_frs = 0;
+		wake_him = sctp_process_segment_range(stcb, &tp1, last_tsn,
+		    nr_frag_strt, nr_frag_end, 1,
+		    &num_frs, biggest_newly_acked_tsn,
+		    this_sack_lowest_newack, ecn_seg_sums);
 
 		nr_frag = (struct sctp_nr_gap_ack_block *)sctp_m_getptr(m, *offset,
-		    sizeof(struct sctp_nr_gap_ack_block), (uint8_t *) & nr_block);
+		    sizeof(struct sctp_nr_gap_ack_block),
+		    (uint8_t *) & nr_block);
 		*offset += sizeof(nr_block);
 		if (nr_frag == NULL) {
 			break;
@@ -7786,7 +7592,7 @@ skip_segments:
 			/* sa_ignore NO_NULL_CHK */
 			sctp_free_bufspace(stcb, asoc, tp1, 1);
 			sctp_m_freem(tp1->data);
-			if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
+			if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(tp1->flags)) {
 				asoc->sent_queue_cnt_removeable--;
 			}
 		}
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 989fd452b5d..4a916265b9e 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -278,18 +278,38 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
 		unsigned int newcnt;
 		struct sctp_stream_out *outs;
 		struct sctp_stream_queue_pending *sp;
+		struct sctp_tmit_chunk *chk, *chk_next;
 
-		/* cut back on number of streams */
+		/* abandon the upper streams */
 		newcnt = ntohs(init->num_inbound_streams);
-		/* This if is probably not needed but I am cautious */
+		if (!TAILQ_EMPTY(&asoc->send_queue)) {
+			chk = TAILQ_FIRST(&asoc->send_queue);
+			while (chk) {
+				chk_next = TAILQ_NEXT(chk, sctp_next);
+				if (chk->rec.data.stream_number >= newcnt) {
+					TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
+					asoc->send_queue_cnt--;
+					if (chk->data != NULL) {
+						sctp_free_bufspace(stcb, asoc, chk, 1);
+						sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
+						    SCTP_NOTIFY_DATAGRAM_UNSENT, chk, SCTP_SO_NOT_LOCKED);
+						if (chk->data) {
+							sctp_m_freem(chk->data);
+							chk->data = NULL;
+						}
+					}
+					sctp_free_a_chunk(stcb, chk);
+					/* sa_ignore FREED_MEMORY */
+				}
+				chk = chk_next;
+			}
+		}
 		if (asoc->strmout) {
-			/* First make sure no data chunks are trapped */
 			for (i = newcnt; i < asoc->pre_open_streams; i++) {
 				outs = &asoc->strmout[i];
 				sp = TAILQ_FIRST(&outs->outqueue);
 				while (sp) {
-					TAILQ_REMOVE(&outs->outqueue, sp,
-					    next);
+					TAILQ_REMOVE(&outs->outqueue, sp, next);
 					asoc->stream_queue_cnt--;
 					sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL,
 					    stcb, SCTP_NOTIFY_DATAGRAM_UNSENT,
@@ -301,16 +321,13 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
 					sctp_free_remote_addr(sp->net);
 					sp->net = NULL;
 					/* Free the chunk */
-					SCTP_PRINTF("sp:%p tcb:%p weird free case\n",
-					    sp, stcb);
-
 					sctp_free_a_strmoq(stcb, sp);
 					/* sa_ignore FREED_MEMORY */
 					sp = TAILQ_FIRST(&outs->outqueue);
 				}
 			}
 		}
-		/* cut back the count and abandon the upper streams */
+		/* cut back the count */
 		asoc->pre_open_streams = newcnt;
 	}
 	SCTP_TCB_SEND_UNLOCK(stcb);
diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h
index f3ccb634d7b..d01879081bd 100644
--- a/sys/netinet/sctp_os_bsd.h
+++ b/sys/netinet/sctp_os_bsd.h
@@ -78,6 +78,10 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#ifdef VIMAGE
+#error "SCTP is not yet compatible with VIMAGE."
+#endif
+
 #ifdef IPSEC
 #include 
 #include 
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 21b8f8f89c0..1e768fc5bbe 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -4200,7 +4200,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
 	/* place in my tag */
 	init->init.initiate_tag = htonl(stcb->asoc.my_vtag);
 	/* set up some of the credits. */
-	init->init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket),
+	init->init.a_rwnd = htonl(max(inp->sctp_socket ? SCTP_SB_LIMIT_RCV(inp->sctp_socket) : 0,
 	    SCTP_MINIMAL_RWND));
 
 	init->init.num_outbound_streams = htons(stcb->asoc.pre_open_streams);
@@ -4411,7 +4411,6 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
 	    net->port, so_locked, NULL);
 	SCTPDBG(SCTP_DEBUG_OUTPUT4, "lowlevel_output - %d\n", ret);
 	SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
-	sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
 	(void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time);
 }
 
@@ -5786,61 +5785,58 @@ sctp_get_frag_point(struct sctp_tcb *stcb,
 }
 
 static void
-sctp_set_prsctp_policy(struct sctp_tcb *stcb,
-    struct sctp_stream_queue_pending *sp)
+sctp_set_prsctp_policy(struct sctp_stream_queue_pending *sp)
 {
 	sp->pr_sctp_on = 0;
-	if (stcb->asoc.peer_supports_prsctp) {
+	/*
+	 * We assume that the user wants PR_SCTP_TTL if the user provides a
+	 * positive lifetime but does not specify any PR_SCTP policy. This
+	 * is a BAD assumption and causes problems at least with the
+	 * U-Vancovers MPI folks. I will change this to be no policy means
+	 * NO PR-SCTP.
+	 */
+	if (PR_SCTP_ENABLED(sp->sinfo_flags)) {
+		sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags);
+		sp->pr_sctp_on = 1;
+	} else {
+		return;
+	}
+	switch (PR_SCTP_POLICY(sp->sinfo_flags)) {
+	case CHUNK_FLAGS_PR_SCTP_BUF:
 		/*
-		 * We assume that the user wants PR_SCTP_TTL if the user
-		 * provides a positive lifetime but does not specify any
-		 * PR_SCTP policy. This is a BAD assumption and causes
-		 * problems at least with the U-Vancovers MPI folks. I will
-		 * change this to be no policy means NO PR-SCTP.
+		 * Time to live is a priority stored in tv_sec when doing
+		 * the buffer drop thing.
 		 */
-		if (PR_SCTP_ENABLED(sp->sinfo_flags)) {
-			sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags);
-			sp->pr_sctp_on = 1;
-		} else {
-			return;
-		}
-		switch (PR_SCTP_POLICY(sp->sinfo_flags)) {
-		case CHUNK_FLAGS_PR_SCTP_BUF:
-			/*
-			 * Time to live is a priority stored in tv_sec when
-			 * doing the buffer drop thing.
-			 */
-			sp->ts.tv_sec = sp->timetolive;
-			sp->ts.tv_usec = 0;
-			break;
-		case CHUNK_FLAGS_PR_SCTP_TTL:
-			{
-				struct timeval tv;
+		sp->ts.tv_sec = sp->timetolive;
+		sp->ts.tv_usec = 0;
+		break;
+	case CHUNK_FLAGS_PR_SCTP_TTL:
+		{
+			struct timeval tv;
 
-				(void)SCTP_GETTIME_TIMEVAL(&sp->ts);
-				tv.tv_sec = sp->timetolive / 1000;
-				tv.tv_usec = (sp->timetolive * 1000) % 1000000;
-				/*
-				 * TODO sctp_constants.h needs alternative
-				 * time macros when _KERNEL is undefined.
-				 */
-				timevaladd(&sp->ts, &tv);
-			}
-			break;
-		case CHUNK_FLAGS_PR_SCTP_RTX:
+			(void)SCTP_GETTIME_TIMEVAL(&sp->ts);
+			tv.tv_sec = sp->timetolive / 1000;
+			tv.tv_usec = (sp->timetolive * 1000) % 1000000;
 			/*
-			 * Time to live is a the number or retransmissions
-			 * stored in tv_sec.
+			 * TODO sctp_constants.h needs alternative time
+			 * macros when _KERNEL is undefined.
 			 */
-			sp->ts.tv_sec = sp->timetolive;
-			sp->ts.tv_usec = 0;
-			break;
-		default:
-			SCTPDBG(SCTP_DEBUG_USRREQ1,
-			    "Unknown PR_SCTP policy %u.\n",
-			    PR_SCTP_POLICY(sp->sinfo_flags));
-			break;
+			timevaladd(&sp->ts, &tv);
 		}
+		break;
+	case CHUNK_FLAGS_PR_SCTP_RTX:
+		/*
+		 * Time to live is a the number or retransmissions stored in
+		 * tv_sec.
+		 */
+		sp->ts.tv_sec = sp->timetolive;
+		sp->ts.tv_usec = 0;
+		break;
+	default:
+		SCTPDBG(SCTP_DEBUG_USRREQ1,
+		    "Unknown PR_SCTP policy %u.\n",
+		    PR_SCTP_POLICY(sp->sinfo_flags));
+		break;
 	}
 }
 
@@ -5911,7 +5907,7 @@ sctp_msg_append(struct sctp_tcb *stcb,
 	sp->tail_mbuf = NULL;
 	sp->length = 0;
 	at = m;
-	sctp_set_prsctp_policy(stcb, sp);
+	sctp_set_prsctp_policy(sp);
 	/*
 	 * We could in theory (for sendall) sifa the length in, but we would
 	 * still have to hunt through the chain since we need to setup the
@@ -7138,7 +7134,7 @@ dont_do_it:
 	}
 	/* We only re-set the policy if it is on */
 	if (sp->pr_sctp_on) {
-		sctp_set_prsctp_policy(stcb, sp);
+		sctp_set_prsctp_policy(sp);
 		asoc->pr_sctp_cnt++;
 		chk->pr_sctp_on = 1;
 	} else {
@@ -12285,7 +12281,7 @@ skip_copy:
 			sp->addr_over = 0;
 		}
 		atomic_add_int(&sp->net->ref_count, 1);
-		sctp_set_prsctp_policy(stcb, sp);
+		sctp_set_prsctp_policy(sp);
 	}
 out_now:
 	return (sp);
@@ -12468,7 +12464,8 @@ sctp_lower_sosend(struct socket *so,
 			error = ENOTCONN;
 			goto out_unlocked;
 		}
-		hold_tcblock = 0;
+		SCTP_TCB_LOCK(stcb);
+		hold_tcblock = 1;
 		SCTP_INP_RUNLOCK(inp);
 		if (addr) {
 			/* Must locate the net structure if addr given */
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 3b16293393e..c5a8ddfc1a6 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -4547,8 +4547,11 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
 
 						stcb->asoc.control_pdapi = sq;
 						strseq = (sq->sinfo_stream << 16) | sq->sinfo_ssn;
-						sctp_notify_partial_delivery_indication(stcb,
-						    SCTP_PARTIAL_DELIVERY_ABORTED, 1, strseq);
+						sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
+						    stcb,
+						    SCTP_PARTIAL_DELIVERY_ABORTED,
+						    (void *)&strseq,
+						    SCTP_SO_LOCKED);
 						stcb->asoc.control_pdapi = NULL;
 					}
 				}
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 477c0b13e45..b40ef503f61 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -588,7 +588,7 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
 				/* sa_ignore NO_NULL_CHK */
 				sctp_free_bufspace(stcb, asoc, chk, 1);
 				sctp_m_freem(chk->data);
-				if (PR_SCTP_BUF_ENABLED(chk->flags)) {
+				if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(chk->flags)) {
 					asoc->sent_queue_cnt_removeable--;
 				}
 			}
@@ -757,7 +757,7 @@ start_again:
 					continue;
 				}
 			}
-			if (PR_SCTP_TTL_ENABLED(chk->flags)) {
+			if (stcb->asoc.peer_supports_prsctp && PR_SCTP_TTL_ENABLED(chk->flags)) {
 				/* Is it expired? */
 				if ((now.tv_sec > chk->rec.data.timetodrop.tv_sec) ||
 				    ((chk->rec.data.timetodrop.tv_sec == now.tv_sec) &&
@@ -772,7 +772,7 @@ start_again:
 					continue;
 				}
 			}
-			if (PR_SCTP_RTX_ENABLED(chk->flags)) {
+			if (stcb->asoc.peer_supports_prsctp && PR_SCTP_RTX_ENABLED(chk->flags)) {
 				/* Has it been retransmitted tv_sec times? */
 				if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) {
 					if (chk->data) {
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 420f4a1b4af..c7bdfb54b5c 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1484,6 +1484,7 @@ sctp_timeout_handler(void *t)
 		SCTP_INP_INCR_REF(inp);
 		if ((inp->sctp_socket == 0) &&
 		    ((tmr->type != SCTP_TIMER_TYPE_INPKILL) &&
+		    (tmr->type != SCTP_TIMER_TYPE_INIT) &&
 		    (tmr->type != SCTP_TIMER_TYPE_SEND) &&
 		    (tmr->type != SCTP_TIMER_TYPE_RECV) &&
 		    (tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) &&
@@ -2984,8 +2985,6 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
 	ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
 	ssf->ssf_assoc_id = sctp_get_associd(stcb);
 
-	SCTP_BUF_NEXT(m_notify) = chk->data;
-	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
 	if (chk->data) {
 		/*
 		 * trim off the sctp chunk header(it should be there)
@@ -2996,6 +2995,8 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
 			chk->send_size -= sizeof(struct sctp_data_chunk);
 		}
 	}
+	SCTP_BUF_NEXT(m_notify) = chk->data;
+	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
 	/* Steal off the mbuf */
 	chk->data = NULL;
 	/*
@@ -3146,9 +3147,13 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb,
 }
 
 /* This always must be called with the read-queue LOCKED in the INP */
-void
+static void
 sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
-    int nolock, uint32_t val)
+    uint32_t val, int so_locked
+#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
+    SCTP_UNUSED
+#endif
+)
 {
 	struct mbuf *m_notify;
 	struct sctp_pdapi_event *pdapi;
@@ -3189,9 +3194,6 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
 	control->tail_mbuf = m_notify;
 	control->held_length = 0;
 	control->length = 0;
-	if (nolock == 0) {
-		SCTP_INP_READ_LOCK(stcb->sctp_ep);
-	}
 	sb = &stcb->sctp_socket->so_rcv;
 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
 		sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify));
@@ -3208,12 +3210,30 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
 		/* we really should not see this case */
 		TAILQ_INSERT_TAIL(&stcb->sctp_ep->read_queue, control, next);
 	}
-	if (nolock == 0) {
-		SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
-	}
 	if (stcb->sctp_ep && stcb->sctp_socket) {
 		/* This should always be the case */
+#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+		struct socket *so;
+
+		so = SCTP_INP_SO(stcb->sctp_ep);
+		if (!so_locked) {
+			atomic_add_int(&stcb->asoc.refcnt, 1);
+			SCTP_TCB_UNLOCK(stcb);
+			SCTP_SOCKET_LOCK(so, 1);
+			SCTP_TCB_LOCK(stcb);
+			atomic_subtract_int(&stcb->asoc.refcnt, 1);
+			if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
+				SCTP_SOCKET_UNLOCK(so, 1);
+				return;
+			}
+		}
+#endif
 		sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
+#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+		if (!so_locked) {
+			SCTP_SOCKET_UNLOCK(so, 1);
+		}
+#endif
 	}
 }
 
@@ -3540,9 +3560,9 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
 
 			val = *((uint32_t *) data);
 
-			sctp_notify_partial_delivery_indication(stcb, error, 0, val);
+			sctp_notify_partial_delivery_indication(stcb, error, val, so_locked);
+			break;
 		}
-		break;
 	case SCTP_NOTIFY_STRDATA_ERR:
 		break;
 	case SCTP_NOTIFY_ASSOC_ABORTED:
@@ -3585,11 +3605,9 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
 	case SCTP_NOTIFY_STR_RESET_FAILED_OUT:
 		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), (SCTP_STRRESET_OUTBOUND_STR | SCTP_STRRESET_FAILED));
 		break;
-
 	case SCTP_NOTIFY_STR_RESET_FAILED_IN:
 		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), (SCTP_STRRESET_INBOUND_STR | SCTP_STRRESET_FAILED));
 		break;
-
 	case SCTP_NOTIFY_ASCONF_ADD_IP:
 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
 		    error);
@@ -3671,8 +3689,10 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
 				sctp_free_bufspace(stcb, asoc, chk, 1);
 				sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
 				    SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
-				sctp_m_freem(chk->data);
-				chk->data = NULL;
+				if (chk->data) {
+					sctp_m_freem(chk->data);
+					chk->data = NULL;
+				}
 			}
 			sctp_free_a_chunk(stcb, chk);
 			/* sa_ignore FREED_MEMORY */
@@ -3689,8 +3709,10 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
 				sctp_free_bufspace(stcb, asoc, chk, 1);
 				sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
 				    SCTP_NOTIFY_DATAGRAM_UNSENT, chk, so_locked);
-				sctp_m_freem(chk->data);
-				chk->data = NULL;
+				if (chk->data) {
+					sctp_m_freem(chk->data);
+					chk->data = NULL;
+				}
 			}
 			sctp_free_a_chunk(stcb, chk);
 			/* sa_ignore FREED_MEMORY */
@@ -4645,8 +4667,10 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
 			stcb->asoc.peers_rwnd += tp1->send_size;
 			stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh);
 			sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, so_locked);
-			sctp_m_freem(tp1->data);
-			tp1->data = NULL;
+			if (tp1->data) {
+				sctp_m_freem(tp1->data);
+				tp1->data = NULL;
+			}
 			do_wakeup_routine = 1;
 			if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
 				stcb->asoc.sent_queue_cnt_removeable--;
@@ -4693,12 +4717,14 @@ next_on_sent:
 			 */
 			chk = tp1;
 			ret_sz += tp1->book_size;
-			sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, so_locked);
 			sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
-			sctp_m_freem(tp1->data);
+			sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, so_locked);
+			if (tp1->data) {
+				sctp_m_freem(tp1->data);
+				tp1->data = NULL;
+			}
 			/* No flight involved here book the size to 0 */
 			tp1->book_size = 0;
-			tp1->data = NULL;
 			if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
 				foundeom = 1;
 			}
@@ -5346,6 +5372,38 @@ restart_nosblocks:
 		}
 		goto restart;
 	}
+	if ((control->length == 0) &&
+	    (control->end_added == 1)) {
+		/*
+		 * Do we also need to check for (control->pdapi_aborted ==
+		 * 1)?
+		 */
+		if (hold_rlock == 0) {
+			hold_rlock = 1;
+			SCTP_INP_READ_LOCK(inp);
+		}
+		TAILQ_REMOVE(&inp->read_queue, control, next);
+		if (control->data) {
+#ifdef INVARIANTS
+			panic("control->data not null but control->length == 0");
+#else
+			SCTP_PRINTF("Strange, data left in the control buffer. Cleaning up.\n");
+			sctp_m_freem(control->data);
+			control->data = NULL;
+#endif
+		}
+		if (control->aux_data) {
+			sctp_m_free(control->aux_data);
+			control->aux_data = NULL;
+		}
+		sctp_free_remote_addr(control->whoFrom);
+		sctp_free_a_readq(stcb, control);
+		if (hold_rlock) {
+			hold_rlock = 0;
+			SCTP_INP_READ_UNLOCK(inp);
+		}
+		goto restart;
+	}
 	if (control->length == 0) {
 		if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
 		    (filling_sinfo)) {
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index 89657e77fb4..f3a731ea1a0 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -234,10 +234,6 @@ int sctp_cmpaddr(struct sockaddr *, struct sockaddr *);
 void sctp_print_address(struct sockaddr *);
 void sctp_print_address_pkt(struct ip *, struct sctphdr *);
 
-void
-sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
-    uint32_t error, int no_lock, uint32_t strseq);
-
 int
 sctp_release_pr_sctp_chunk(struct sctp_tcb *, struct sctp_tmit_chunk *,
     int, int
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 96626fb3fa6..f755fa1eea8 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -603,7 +603,7 @@ tcp_tw_2msl_scan(int reuse)
 	INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
 	for (;;) {
 		tw = TAILQ_FIRST(&V_twq_2msl);
-		if (tw == NULL || (!reuse && tw->tw_time > ticks))
+		if (tw == NULL || (!reuse && (tw->tw_time - ticks) > 0))
 			break;
 		INP_WLOCK(tw->tw_inpcb);
 		tcp_twclose(tw, reuse);
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 7fe63b603cf..04810c36273 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -1705,7 +1705,7 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m, struct ifnet **ifpp,
 		}
 	}
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	for (ifp = TAILQ_FIRST(&V_ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
 		addrsofif = 0;
 		IF_ADDR_LOCK(ifp);
@@ -1762,13 +1762,13 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m, struct ifnet **ifpp,
 		IF_ADDR_UNLOCK(ifp);
 		if (iffound) {
 			*ifpp = ifp;
-			IFNET_RUNLOCK();
+			IFNET_RUNLOCK_NOSLEEP();
 			return (addrsofif);
 		}
 
 		addrs += addrsofif;
 	}
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 
 	return (addrs);
 }
@@ -1789,7 +1789,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
 	if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL))
 		return (0);	/* needless to copy */
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
   again:
 
 	for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
@@ -1854,7 +1854,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
 				 * Set the truncate flag and return.
 				 */
 				nni6->ni_flags |= NI_NODEADDR_FLAG_TRUNCATE;
-				IFNET_RUNLOCK();
+				IFNET_RUNLOCK_NOSLEEP();
 				return (copied);
 			}
 
@@ -1907,7 +1907,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
 		goto again;
 	}
 
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 
 	return (copied);
 }
@@ -2170,6 +2170,10 @@ icmp6_reflect(struct mbuf *m, size_t off)
 		}
 	}
 
+	if ((srcp != NULL) && 
+	    (in6_addrscope(srcp) != in6_addrscope(&ip6->ip6_src)))
+		srcp = NULL;
+
 	if (srcp == NULL) {
 		int e;
 		struct sockaddr_in6 sin6;
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index c099da70e89..c832305b162 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1192,17 +1192,18 @@ in6_purgeaddr(struct ifaddr *ifa)
 
 	/*
 	 * Remove the loopback route to the interface address.
-	 * The check for the current setting of "nd6_useloopback" is not needed.
+	 * The check for the current setting of "nd6_useloopback" 
+	 * is not needed.
 	 */
-	if (!(ia->ia_ifp->if_flags & IFF_LOOPBACK)) {
+	{
 		struct rt_addrinfo info;
 		struct sockaddr_dl null_sdl;
 
 		bzero(&null_sdl, sizeof(null_sdl));
 		null_sdl.sdl_len = sizeof(null_sdl);
 		null_sdl.sdl_family = AF_LINK;
-		null_sdl.sdl_type = V_loif->if_type;
-		null_sdl.sdl_index = V_loif->if_index;
+		null_sdl.sdl_type = ia->ia_ifp->if_type;
+		null_sdl.sdl_index = ia->ia_ifp->if_index;
 		bzero(&info, sizeof(info));
 		info.rti_flags = ia->ia_flags | RTF_HOST | RTF_STATIC;
 		info.rti_info[RTAX_DST] = (struct sockaddr *)&ia->ia_addr;
@@ -1750,21 +1751,12 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
 	 * interface that share the same destination.
 	 */
 	plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
-	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128) {
-		struct sockaddr *dstaddr;
+	if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
+	    ia->ia_dstaddr.sin6_family == AF_INET6) {
 		int rtflags = RTF_UP | RTF_HOST;
 
-		/* 
-		 * use the interface address if configuring an
-		 * interface address with a /128 prefix len
-		 */
-		if (ia->ia_dstaddr.sin6_family == AF_INET6)
-			dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
-		else
-			dstaddr = (struct sockaddr *)&ia->ia_addr;
-
 		error = rtrequest(RTM_ADD,
-		    (struct sockaddr *)dstaddr,
+		    (struct sockaddr *)&ia->ia_dstaddr,
 		    (struct sockaddr *)&ia->ia_addr,
 		    (struct sockaddr *)&ia->ia_prefixmask,
 		    ia->ia_flags | rtflags, NULL);
@@ -1776,7 +1768,9 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
 	/*
 	 * add a loopback route to self
 	 */
-	if (V_nd6_useloopback && !(ifp->if_flags & IFF_LOOPBACK)) {
+	if (!(ia->ia_flags & IFA_ROUTE)
+	    && (V_nd6_useloopback
+		|| (ifp->if_flags & IFF_LOOPBACK))) {
 		struct rt_addrinfo info;
 		struct rtentry *rt = NULL;
 		static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
@@ -1791,13 +1785,13 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
 		if (error == 0 && rt != NULL) {
 			RT_LOCK(rt);
 			((struct sockaddr_dl *)rt->rt_gateway)->sdl_type  =
-				rt->rt_ifp->if_type;
+				ifp->if_type;
 			((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
-				rt->rt_ifp->if_index;
+				ifp->if_index;
 			RT_REMREF(rt);
 			RT_UNLOCK(rt);
 		} else if (error != 0)
-			log(LOG_INFO, "in6_ifinit: insertion failed\n");
+			log(LOG_INFO, "in6_ifinit: error = %d, insertion failed\n", error);
 	}
 
 	/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
@@ -2243,7 +2237,7 @@ in6_setmaxmtu(void)
 	unsigned long maxmtu = 0;
 	struct ifnet *ifp;
 
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	for (ifp = TAILQ_FIRST(&V_ifnet); ifp;
 	    ifp = TAILQ_NEXT(ifp, if_list)) {
 		/* this function can be called during ifnet initialization */
@@ -2253,7 +2247,7 @@ in6_setmaxmtu(void)
 		    IN6_LINKMTU(ifp) > maxmtu)
 			maxmtu = IN6_LINKMTU(ifp);
 	}
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	if (maxmtu)	     /* update only when maxmtu is positive */
 		V_in6_maxmtu = maxmtu;
 }
@@ -2504,12 +2498,10 @@ in6_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
 	} ndpc;
 	int i, error;
 
-	/* XXXXX
-	 * current IFNET_RLOCK() is mapped to IFNET_WLOCK()
-	 * so it is okay to use this ASSERT, change it when
-	 * IFNET lock is finalized
-	 */
-	IFNET_WLOCK_ASSERT();
+	if (ifp->if_flags & IFF_LOOPBACK)
+		return 0;
+
+	LLTABLE_LOCK_ASSERT();
 
 	error = 0;
 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 1fc54c62793..6f9f11dbd33 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -398,7 +398,7 @@ get_ifid(struct ifnet *ifp0, struct ifnet *altifp,
 	}
 
 	/* next, try to get it from some other hardware interface */
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	for (ifp = V_ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
 		if (ifp == ifp0)
 			continue;
@@ -413,11 +413,11 @@ get_ifid(struct ifnet *ifp0, struct ifnet *altifp,
 			nd6log((LOG_DEBUG,
 			    "%s: borrow interface identifier from %s\n",
 			    if_name(ifp0), if_name(ifp)));
-			IFNET_RUNLOCK();
+			IFNET_RUNLOCK_NOSLEEP();
 			goto success;
 		}
 	}
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 
 	/* last resort: get from random number source */
 	if (get_rand_ifid(ifp, in6) == 0) {
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index f087faef539..8e82ef117ae 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #ifdef RADIX_MPATH
@@ -697,8 +698,25 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
 	if (error == EHOSTUNREACH)
 		V_ip6stat.ip6s_noroute++;
 
-	if (retifp != NULL)
+	if (retifp != NULL) {
 		*retifp = ifp;
+
+		/*
+		 * Adjust the "outgoing" interface.  If we're going to loop 
+		 * the packet back to ourselves, the ifp would be the loopback 
+		 * interface. However, we'd rather know the interface associated 
+		 * to the destination address (which should probably be one of 
+		 * our own addresses.)
+		 */
+		if (rt) {
+			if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) &&
+			    (rt->rt_gateway->sa_family == AF_LINK))
+				*retifp = 
+					ifnet_byindex(((struct sockaddr_dl *)
+						       rt->rt_gateway)->sdl_index);
+		}
+	}
+
 	if (retrt != NULL)
 		*retrt = rt;	/* rt may be NULL */
 
@@ -750,16 +768,6 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
 		return (flags);
 	}
 
-	/*
-	 * Adjust the "outgoing" interface.  If we're going to loop the packet
-	 * back to ourselves, the ifp would be the loopback interface.
-	 * However, we'd rather know the interface associated to the
-	 * destination address (which should probably be one of our own
-	 * addresses.)
-	 */
-	if (rt && rt->rt_ifa && rt->rt_ifa->ifa_ifp)
-		*retifp = rt->rt_ifa->ifa_ifp;
-
 	if (ro == &sro && rt && rt == sro.ro_rt)
 		RTFREE(rt);
 	return (0);
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 019d57fea6b..4958d748a89 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -628,8 +628,27 @@ passin:
 	    &rt6_key(rin6.ro_rt)->sin6_addr)
 #endif
 	    rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) {
-		struct in6_ifaddr *ia6 =
-			(struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
+		int free_ia6 = 0;
+		struct in6_ifaddr *ia6;
+
+		/*
+		 * found the loopback route to the interface address
+		 */
+		if (rin6.ro_rt->rt_gateway->sa_family == AF_LINK) {
+			struct sockaddr_in6 dest6;
+
+			bzero(&dest6, sizeof(dest6));
+			dest6.sin6_family = AF_INET6;
+			dest6.sin6_len = sizeof(dest6);
+			dest6.sin6_addr = ip6->ip6_dst;
+			ia6 = (struct in6_ifaddr *)
+			    ifa_ifwithaddr((struct sockaddr *)&dest6);
+			if (ia6 == NULL)
+				goto bad;
+			free_ia6 = 1;
+		}
+		else
+			ia6 = (struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
 
 		/*
 		 * record address information into m_tag.
@@ -647,6 +666,8 @@ passin:
 			/* Count the packet in the ip address stats */
 			ia6->ia_ifa.if_ipackets++;
 			ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
+			if (ia6 != NULL && free_ia6 != 0)
+				ifa_free(&ia6->ia_ifa);
 			goto hbhcheck;
 		} else {
 			char ip6bufs[INET6_ADDRSTRLEN];
@@ -657,6 +678,8 @@ passin:
 			    ip6_sprintf(ip6bufs, &ip6->ip6_src),
 			    ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
 
+			if (ia6 != NULL && free_ia6 != 0)
+				ifa_free(&ia6->ia_ifa);
 			goto bad;
 		}
 	}
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index c48ac7b1594..98875640e7a 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -602,15 +602,12 @@ again:
 		rt->rt_use++;
 	}
 
+
 	/*
 	 * The outgoing interface must be in the zone of source and
-	 * destination addresses.  We should use ia_ifp to support the
-	 * case of sending packets to an address of our own.
+	 * destination addresses.  
 	 */
-	if (ia != NULL && ia->ia_ifp)
-		origifp = ia->ia_ifp;
-	else
-		origifp = ifp;
+	origifp = ifp;
 
 	src0 = ip6->ip6_src;
 	if (in6_setscope(&src0, origifp, &zone))
@@ -634,6 +631,12 @@ again:
 		goto badscope;
 	}
 
+	/* We should use ia_ifp to support the case of 
+	 * sending packets to an address of our own.
+	 */
+	if (ia != NULL && ia->ia_ifp)
+		ifp = ia->ia_ifp;
+
 	/* scope check is done. */
 	goto routefound;
 
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 48635c5b548..acaa87e63a3 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1662,7 +1662,7 @@ nd6_slowtimo(void *arg)
 
 	callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
 	    nd6_slowtimo, curvnet);
-	IFNET_RLOCK();
+	IFNET_RLOCK_NOSLEEP();
 	for (ifp = TAILQ_FIRST(&V_ifnet); ifp;
 	    ifp = TAILQ_NEXT(ifp, if_list)) {
 		nd6if = ND_IFINFO(ifp);
@@ -1678,7 +1678,7 @@ nd6_slowtimo(void *arg)
 			nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable);
 		}
 	}
-	IFNET_RUNLOCK();
+	IFNET_RUNLOCK_NOSLEEP();
 	CURVNET_RESTORE();
 }
 
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 9d1f0d6e8cb..4ec64fbadbd 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -1415,6 +1415,9 @@ pfxlist_onlink_check()
 			if (pr->ndpr_raf_onlink == 0)
 				continue;
 
+			if (pr->ndpr_raf_auto == 0)
+				continue;
+
 			if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
 			    find_pfxlist_reachable_router(pr) == NULL)
 				pr->ndpr_stateflags |= NDPRF_DETACHED;
@@ -1431,6 +1434,9 @@ pfxlist_onlink_check()
 			if (pr->ndpr_raf_onlink == 0)
 				continue;
 
+			if (pr->ndpr_raf_auto == 0)
+				continue;
+
 			if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0)
 				pr->ndpr_stateflags &= ~NDPRF_DETACHED;
 		}
@@ -1454,6 +1460,9 @@ pfxlist_onlink_check()
 		if (pr->ndpr_raf_onlink == 0)
 			continue;
 
+		if (pr->ndpr_raf_auto == 0)
+			continue;
+
 		if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
 		    (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
 			if ((e = nd6_prefix_offlink(pr)) != 0) {
diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h
index 97756e56987..92539b9cf32 100644
--- a/sys/netipsec/ipsec.h
+++ b/sys/netipsec/ipsec.h
@@ -61,7 +61,7 @@
  * specifies ICMPv6 type, and the port field in "dst" specifies ICMPv6 code.
  */
 struct secpolicyindex {
-	u_int8_t dir;			/* direction of packet flow, see blow */
+	u_int8_t dir;			/* direction of packet flow, see below */
 	union sockaddr_union src;	/* IP src address for SP */
 	union sockaddr_union dst;	/* IP dst address for SP */
 	u_int8_t prefs;			/* prefix length in bits for src */
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 99dce21b2f2..bf9db684656 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -906,6 +906,9 @@ key_allocsa_policy(const struct secasindex *saidx)
 	u_int stateidx, arraysize;
 	const u_int *state_valid;
 
+	state_valid = NULL;	/* silence gcc */
+	arraysize = 0;		/* silence gcc */
+
 	SAHTREE_LOCK();
 	LIST_FOREACH(sah, &V_sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
@@ -918,15 +921,13 @@ key_allocsa_policy(const struct secasindex *saidx)
 				state_valid = saorder_state_valid_prefer_new;
 				arraysize = N(saorder_state_valid_prefer_new);
 			}
-			SAHTREE_UNLOCK();
-			goto found;
+			break;
 		}
 	}
 	SAHTREE_UNLOCK();
+	if (sah == NULL)
+		return NULL;
 
-	return NULL;
-
-    found:
 	/* search valid state */
 	for (stateidx = 0; stateidx < arraysize; stateidx++) {
 		sav = key_do_allocsa_policy(sah, state_valid[stateidx]);
diff --git a/sys/netipsec/xform_ipip.c b/sys/netipsec/xform_ipip.c
index c9669b16bc2..78ab0978c4a 100644
--- a/sys/netipsec/xform_ipip.c
+++ b/sys/netipsec/xform_ipip.c
@@ -303,7 +303,7 @@ _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
 	if ((m->m_pkthdr.rcvif == NULL ||
 	    !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) &&
 	    V_ipip_allow != 2) {
-	    	IFNET_RLOCK();
+	    	IFNET_RLOCK_NOSLEEP();
 		TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 			TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 #ifdef INET
@@ -318,7 +318,7 @@ _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
 					    ipo->ip_src.s_addr)	{
 						V_ipipstat.ipips_spoof++;
 						m_freem(m);
-						IFNET_RUNLOCK();
+						IFNET_RUNLOCK_NOSLEEP();
 						return;
 					}
 				}
@@ -335,7 +335,7 @@ _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
 					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) {
 						V_ipipstat.ipips_spoof++;
 						m_freem(m);
-						IFNET_RUNLOCK();
+						IFNET_RUNLOCK_NOSLEEP();
 						return;
 					}
 
@@ -343,7 +343,7 @@ _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
 #endif /* INET6 */
 			}
 		}
-		IFNET_RUNLOCK();
+		IFNET_RUNLOCK_NOSLEEP();
 	}
 
 	/* Statistics */
diff --git a/sys/nfsclient/bootp_subr.c b/sys/nfsclient/bootp_subr.c
index e1096bed2a0..e57b32a1bed 100644
--- a/sys/nfsclient/bootp_subr.c
+++ b/sys/nfsclient/bootp_subr.c
@@ -389,7 +389,7 @@ bootpboot_p_iflist(void)
 	struct ifaddr *ifa;
 
 	printf("Interface list:\n");
-	IFNET_RLOCK(); /* could sleep, but okay for debugging XXX */
+	IFNET_RLOCK();
 	for (ifp = TAILQ_FIRST(&V_ifnet);
 	     ifp != NULL;
 	     ifp = TAILQ_NEXT(ifp, if_link)) {
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index 6f4ef7b5d40..329294bae30 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -409,28 +409,25 @@ int
 nfs_upgrade_vnlock(struct vnode *vp)
 {
 	int old_lock;
-	
- 	if ((old_lock = VOP_ISLOCKED(vp)) != LK_EXCLUSIVE) {
- 		if (old_lock == LK_SHARED) {
- 			/* Upgrade to exclusive lock, this might block */
- 			vn_lock(vp, LK_UPGRADE | LK_RETRY);
- 		} else {
- 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- 		}
+
+	ASSERT_VOP_LOCKED(vp, "nfs_upgrade_vnlock");
+	old_lock = VOP_ISLOCKED(vp);
+	if (old_lock != LK_EXCLUSIVE) {
+		KASSERT(old_lock == LK_SHARED,
+		    ("nfs_upgrade_vnlock: wrong old_lock %d", old_lock));
+		/* Upgrade to exclusive lock, this might block */
+		vn_lock(vp, LK_UPGRADE | LK_RETRY);
   	}
-	return old_lock;
+	return (old_lock);
 }
 
 void
 nfs_downgrade_vnlock(struct vnode *vp, int old_lock)
 {
 	if (old_lock != LK_EXCLUSIVE) {
- 		if (old_lock == LK_SHARED) {
- 			/* Downgrade from exclusive lock, this might block */
- 			vn_lock(vp, LK_DOWNGRADE);
- 		} else {
- 			VOP_UNLOCK(vp, 0);
- 		}
+		KASSERT(old_lock == LK_SHARED, ("wrong old_lock %d", old_lock));
+		/* Downgrade from exclusive lock. */
+		vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
   	}
 }
 
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 165849b399f..7dfd298da6d 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1552,6 +1553,7 @@ again:
 			*tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
 			tl = nfsm_build(u_int32_t *, NFSX_V3CREATEVERF);
 #ifdef INET
+			CURVNET_SET(CRED_TO_VNET(cnp->cn_cred));
 			IN_IFADDR_RLOCK();
 			if (!TAILQ_EMPTY(&V_in_ifaddrhead))
 				*tl++ = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr.s_addr;
@@ -1560,6 +1562,7 @@ again:
 				*tl++ = create_verf;
 #ifdef INET
 			IN_IFADDR_RUNLOCK();
+			CURVNET_RESTORE();
 #endif
 			*tl = ++create_verf;
 		} else {
diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c
index 5f1331d693a..6ba4425adaa 100644
--- a/sys/opencrypto/cryptodev.c
+++ b/sys/opencrypto/cryptodev.c
@@ -496,6 +496,7 @@ cryptodev_op(
 		goto bail;
 	}
 
+again:
 	/*
 	 * Let the dispatch run unlocked, then, interlock against the
 	 * callback before checking if the operation completed and going
@@ -512,6 +513,12 @@ cryptodev_op(
 	if (error != 0)
 		goto bail;
 
+	if (crp->crp_etype == EAGAIN) {
+		crp->crp_etype = 0;
+		crp->crp_flags &= ~CRYPTO_F_DONE;
+		goto again;
+	}
+
 	if (crp->crp_etype != 0) {
 		error = crp->crp_etype;
 		goto bail;
@@ -545,16 +552,10 @@ cryptodev_cb(void *op)
 {
 	struct cryptop *crp = (struct cryptop *) op;
 	struct csession *cse = (struct csession *)crp->crp_opaque;
-	int error;
 
-	error = crp->crp_etype;
-	if (error == EAGAIN)
-		error = crypto_dispatch(crp);
 	mtx_lock(&cse->lock);
-	if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
-		cse->error = error;
-		wakeup_one(crp);
-	}
+	cse->error = crp->crp_etype;
+	wakeup_one(crp);
 	mtx_unlock(&cse->lock);
 	return (0);
 }
diff --git a/sys/pc98/cbus/fdc.c b/sys/pc98/cbus/fdc.c
index 294711787a9..8373f45163c 100644
--- a/sys/pc98/cbus/fdc.c
+++ b/sys/pc98/cbus/fdc.c
@@ -1499,9 +1499,7 @@ fdstrategy(struct bio *bp)
 	bioq_disksort(&fdc->head, bp);
 	untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */
 	devstat_start_transaction_bio(fd->device_stats, bp);
-	newbus_xlock();
 	device_busy(fd->dev);
-	newbus_xunlock();
 	fdstart(fdc);
 	splx(s);
 	return;
@@ -2180,9 +2178,7 @@ fdstate(fdc_p fdc)
 			fd->skip = 0;
 			bp->bio_resid = 0;
 			fdc->bp = NULL;
-			newbus_xlock();
 			device_unbusy(fd->dev);
-			newbus_xunlock();
 			biofinish(bp, fd->device_stats, 0);
 			fdc->fd = (fd_p) 0;
 			fdc->fdu = -1;
@@ -2343,9 +2339,7 @@ retrier(struct fdc_data *fdc)
 			bp->bio_resid = 0;
 		fdc->bp = NULL;
 		fdc->fd->skip = 0;
-		newbus_xlock();
 		device_unbusy(fd->dev);
-		newbus_xunlock();
 		biofinish(bp, fdc->fd->device_stats, 0);
 		fdc->state = FINDWORK;
 		fdc->flags |= FDC_NEEDS_RESET;
diff --git a/sys/pc98/conf/NOTES b/sys/pc98/conf/NOTES
index 02f8d07ecf2..9ab70b9e5d1 100644
--- a/sys/pc98/conf/NOTES
+++ b/sys/pc98/conf/NOTES
@@ -29,10 +29,6 @@ device		apic			# I/O apic
 #
 options 	MP_WATCHDOG
 
-# Debugging options.
-#
-options 	STOP_NMI		# Stop CPUS using NMI instead of IPI
-
 
 
 #####################################################################
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index 9de350c9d9d..d112d024c5a 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -161,6 +161,7 @@
 #define RL_HWREV_8102EL		0x24800000
 #define RL_HWREV_8102EL_SPIN1	0x24c00000
 #define RL_HWREV_8168D		0x28000000
+#define RL_HWREV_8168DP		0x28800000
 #define RL_HWREV_8168_SPIN1	0x30000000
 #define RL_HWREV_8100E		0x30800000
 #define RL_HWREV_8101E		0x34000000
diff --git a/sys/powerpc/include/smp.h b/sys/powerpc/include/smp.h
index 3929b8c7e7e..0e5ec16eb90 100644
--- a/sys/powerpc/include/smp.h
+++ b/sys/powerpc/include/smp.h
@@ -35,6 +35,7 @@
 #define	IPI_PREEMPT		1
 #define	IPI_RENDEZVOUS		2
 #define	IPI_STOP		3
+#define	IPI_STOP_HARD		3
 
 #ifndef LOCORE
 
diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c
index 2c6d11bef5c..1ae7d6d6f7f 100644
--- a/sys/powerpc/powerpc/mp_machdep.c
+++ b/sys/powerpc/powerpc/mp_machdep.c
@@ -281,7 +281,13 @@ powerpc_ipi_handler(void *arg)
 			smp_rendezvous_action();
 			break;
 		case IPI_STOP:
-			CTR1(KTR_SMP, "%s: IPI_STOP (stop)", __func__);
+
+			/*
+			 * IPI_STOP_HARD is mapped to IPI_STOP so it is not
+			 * necessary to add such case in the switch.
+			 */
+			CTR1(KTR_SMP, "%s: IPI_STOP or IPI_STOP_HARD (stop)",
+			    __func__);
 			self = PCPU_GET(cpumask);
 			savectx(PCPU_GET(curpcb));
 			atomic_set_int(&stopped_cpus, self);
diff --git a/sys/rpc/clnt_dg.c b/sys/rpc/clnt_dg.c
index 0b49375b993..78f4a9a2128 100644
--- a/sys/rpc/clnt_dg.c
+++ b/sys/rpc/clnt_dg.c
@@ -57,6 +57,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 
@@ -197,11 +199,14 @@ clnt_dg_create(
 		return (NULL);
 	}
 
+	CURVNET_SET(so->so_vnet);
 	if (!__rpc_socket2sockinfo(so, &si)) {
 		rpc_createerr.cf_stat = RPC_TLIERROR;
 		rpc_createerr.cf_error.re_errno = 0;
+		CURVNET_RESTORE();
 		return (NULL);
 	}
+	CURVNET_RESTORE();
 
 	/*
 	 * Find the receive and the send size
diff --git a/sys/rpc/clnt_rc.c b/sys/rpc/clnt_rc.c
index 217608c4bb3..24fc09a3605 100644
--- a/sys/rpc/clnt_rc.c
+++ b/sys/rpc/clnt_rc.c
@@ -175,15 +175,16 @@ clnt_reconnect_connect(CLIENT *cl)
 	rc->rc_connecting = TRUE;
 	mtx_unlock(&rc->rc_lock);
 
+	oldcred = td->td_ucred;
+	td->td_ucred = rc->rc_ucred;
 	so = __rpc_nconf2socket(rc->rc_nconf);
 	if (!so) {
 		stat = rpc_createerr.cf_stat = RPC_TLIERROR;
 		rpc_createerr.cf_error.re_errno = 0;
+		td->td_ucred = oldcred;
 		goto out;
 	}
 
-	oldcred = td->td_ucred;
-	td->td_ucred = rc->rc_ucred;
 	if (rc->rc_privport)
 		bindresvport(so, NULL);
 
diff --git a/sys/rpc/clnt_vc.c b/sys/rpc/clnt_vc.c
index 3f15c435c75..85e89abe5c3 100644
--- a/sys/rpc/clnt_vc.c
+++ b/sys/rpc/clnt_vc.c
@@ -70,6 +70,9 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+
+#include 
+
 #include 
 
 #include 
@@ -217,8 +220,11 @@ clnt_vc_create(
 		}
 	}
 
-	if (!__rpc_socket2sockinfo(so, &si))
+	CURVNET_SET(so->so_vnet);
+	if (!__rpc_socket2sockinfo(so, &si)) {
+		CURVNET_RESTORE();
 		goto err;
+	}
 
 	if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
 		bzero(&sopt, sizeof(sopt));
@@ -239,6 +245,7 @@ clnt_vc_create(
 		sopt.sopt_valsize = sizeof(one);
 		sosetopt(so, &sopt);
 	}
+	CURVNET_RESTORE();
 
 	ct->ct_closeit = FALSE;
 
diff --git a/sys/rpc/rpc_generic.c b/sys/rpc/rpc_generic.c
index d9100b340b1..f15ad28f294 100644
--- a/sys/rpc/rpc_generic.c
+++ b/sys/rpc/rpc_generic.c
@@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 
@@ -822,6 +824,7 @@ bindresvport(struct socket *so, struct sockaddr *sa)
 	sa->sa_len = salen;
 
 	if (*portp == 0) {
+		CURVNET_SET(so->so_vnet);
 		bzero(&opt, sizeof(opt));
 		opt.sopt_dir = SOPT_GET;
 		opt.sopt_level = proto;
@@ -829,12 +832,15 @@ bindresvport(struct socket *so, struct sockaddr *sa)
 		opt.sopt_val = &old;
 		opt.sopt_valsize = sizeof(old);
 		error = sogetopt(so, &opt);
-		if (error)
+		if (error) {
+			CURVNET_RESTORE();
 			goto out;
+		}
 
 		opt.sopt_dir = SOPT_SET;
 		opt.sopt_val = &portlow;
 		error = sosetopt(so, &opt);
+		CURVNET_RESTORE();
 		if (error)
 			goto out;
 	}
@@ -845,7 +851,9 @@ bindresvport(struct socket *so, struct sockaddr *sa)
 		if (error) {
 			opt.sopt_dir = SOPT_SET;
 			opt.sopt_val = &old;
+			CURVNET_SET(so->so_vnet);
 			sosetopt(so, &opt);
+			CURVNET_RESTORE();
 		}
 	}
 out:
diff --git a/sys/rpc/svc_dg.c b/sys/rpc/svc_dg.c
index 0747d1d9639..9d7696b0145 100644
--- a/sys/rpc/svc_dg.c
+++ b/sys/rpc/svc_dg.c
@@ -57,6 +57,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#include 
+
 #include 
 
 #include 
@@ -101,8 +103,10 @@ svc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
 	struct sockaddr* sa;
 	int error;
 
+	CURVNET_SET(so->so_vnet);
 	if (!__rpc_socket2sockinfo(so, &si)) {
 		printf(svc_dg_str, svc_dg_err1);
+		CURVNET_RESTORE();
 		return (NULL);
 	}
 	/*
@@ -112,6 +116,7 @@ svc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
 	recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
 	if ((sendsize == 0) || (recvsize == 0)) {
 		printf(svc_dg_str, svc_dg_err2);
+		CURVNET_RESTORE();
 		return (NULL);
 	}
 
@@ -124,6 +129,7 @@ svc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
 	xprt->xp_ops = &svc_dg_ops;
 
 	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
+	CURVNET_RESTORE();
 	if (error)
 		goto freedata;
 
diff --git a/sys/rpc/svc_generic.c b/sys/rpc/svc_generic.c
index 38380f25def..e6e8acdb1d9 100644
--- a/sys/rpc/svc_generic.c
+++ b/sys/rpc/svc_generic.c
@@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 #include 
@@ -228,11 +230,14 @@ svc_tli_create(
 		/*
 		 * It is an open socket. Get the transport info.
 		 */
+		CURVNET_SET(so->so_vnet);
 		if (!__rpc_socket2sockinfo(so, &si)) {
 			printf(
 		"svc_tli_create: could not get transport information\n");
+			CURVNET_RESTORE();
 			return (NULL);
 		}
+		CURVNET_RESTORE();
 	}
 
 	/*
@@ -259,7 +264,9 @@ svc_tli_create(
 		"svc_tli_create: could not bind to requested address\n");
 				goto freedata;
 			}
+			CURVNET_SET(so->so_vnet);
 			solisten(so, (int)bindaddr->qlen, curthread);
+			CURVNET_RESTORE();
 		}
 			
 	}
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c
index b7da5e22787..85d335fa015 100644
--- a/sys/rpc/svc_vc.c
+++ b/sys/rpc/svc_vc.c
@@ -58,6 +58,9 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+
+#include 
+
 #include 
 
 #include 
@@ -151,9 +154,12 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
 	xprt->xp_p2 = NULL;
 	xprt->xp_ops = &svc_vc_rendezvous_ops;
 
+	CURVNET_SET(so->so_vnet);
 	error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
-	if (error)
+	if (error) {
+		CURVNET_RESTORE();
 		goto cleanup_svc_vc_create;
+	}
 
 	memcpy(&xprt->xp_ltaddr, sa, sa->sa_len);
 	free(sa, M_SONAME);
@@ -161,6 +167,7 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize,
 	xprt_register(xprt);
 
 	solisten(so, SOMAXCONN, curthread);
+	CURVNET_RESTORE();
 
 	SOCKBUF_LOCK(&so->so_rcv);
 	xprt->xp_upcallset = 1;
@@ -193,9 +200,12 @@ svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr)
 	opt.sopt_name = SO_KEEPALIVE;
 	opt.sopt_val = &one;
 	opt.sopt_valsize = sizeof(one);
+	CURVNET_SET(so->so_vnet);
 	error = sosetopt(so, &opt);
-	if (error)
+	if (error) {
+		CURVNET_RESTORE();
 		return (NULL);
+	}
 
 	if (so->so_proto->pr_protocol == IPPROTO_TCP) {
 		bzero(&opt, sizeof(struct sockopt));
@@ -205,9 +215,12 @@ svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr)
 		opt.sopt_val = &one;
 		opt.sopt_valsize = sizeof(one);
 		error = sosetopt(so, &opt);
-		if (error)
+		if (error) {
+			CURVNET_RESTORE();
 			return (NULL);
+		}
 	}
+	CURVNET_RESTORE();
 
 	cd = mem_alloc(sizeof(*cd));
 	cd->strm_stat = XPRT_IDLE;
@@ -625,8 +638,10 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
 		uio.uio_td = curthread;
 		m = NULL;
 		rcvflag = MSG_DONTWAIT;
+		CURVNET_SET(xprt->xp_socket->so_vnet);
 		error = soreceive(xprt->xp_socket, NULL, &uio, &m, NULL,
 		    &rcvflag);
+		CURVNET_RESTORE();
 
 		if (error == EWOULDBLOCK) {
 			/*
diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h
index 52bb425b55d..f66f33a4448 100644
--- a/sys/security/audit/audit.h
+++ b/sys/security/audit/audit.h
@@ -232,7 +232,7 @@ void	 audit_thread_free(struct thread *td);
 
 #define	AUDIT_ARG_RGID(rgid) do {					\
 	if (AUDITING_TD(curthread))					\
-		audit_arg_gid((rgid));					\
+		audit_arg_rgid((rgid));					\
 } while (0)
 
 #define	AUDIT_ARG_RUID(ruid) do {					\
diff --git a/sys/security/audit/audit_bsm_token.c b/sys/security/audit/audit_bsm_token.c
index 5523ea4ef13..a050df11d7c 100644
--- a/sys/security/audit/audit_bsm_token.c
+++ b/sys/security/audit/audit_bsm_token.c
@@ -36,6 +36,7 @@
 #include 
 __FBSDID("$FreeBSD$");
 
+#include 
 #include 
 #include 
 #include 
diff --git a/sys/sparc64/include/smp.h b/sys/sparc64/include/smp.h
index 8eb5636c939..87355430ca3 100644
--- a/sys/sparc64/include/smp.h
+++ b/sys/sparc64/include/smp.h
@@ -56,6 +56,7 @@
 #define	IPI_RENDEZVOUS	PIL_RENDEZVOUS
 #define	IPI_PREEMPT	PIL_PREEMPT
 #define	IPI_STOP	PIL_STOP
+#define	IPI_STOP_HARD	PIL_STOP
 
 #define	IPI_RETRIES	5000
 
diff --git a/sys/sun4v/include/smp.h b/sys/sun4v/include/smp.h
index 4f5adc53c36..63a8e01bef0 100644
--- a/sys/sun4v/include/smp.h
+++ b/sys/sun4v/include/smp.h
@@ -44,6 +44,7 @@
 #define	IPI_AST		PIL_AST
 #define	IPI_RENDEZVOUS	PIL_RENDEZVOUS
 #define	IPI_STOP	PIL_STOP
+#define	IPI_STOP_HARD	PIL_STOP
 #define IPI_PREEMPT     PIL_PREEMPT
 
 
diff --git a/sys/sys/_sockaddr_storage.h b/sys/sys/_sockaddr_storage.h
new file mode 100644
index 00000000000..5c0048b56b7
--- /dev/null
+++ b/sys/sys/_sockaddr_storage.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1982, 1985, 1986, 1988, 1993, 1994
+ *	The Regents of the University of California.  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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *	@(#)socket.h	8.4 (Berkeley) 2/21/94
+ * $FreeBSD$
+ */
+
+#ifndef _SYS__SOCKADDR_STORAGE_H_
+#define	_SYS__SOCKADDR_STORAGE_H_
+
+/*
+ * RFC 2553: protocol-independent placeholder for socket addresses
+ */
+#define	_SS_MAXSIZE	128U
+#define	_SS_ALIGNSIZE	(sizeof(__int64_t))
+#define	_SS_PAD1SIZE	(_SS_ALIGNSIZE - sizeof(unsigned char) - \
+			    sizeof(sa_family_t))
+#define	_SS_PAD2SIZE	(_SS_MAXSIZE - sizeof(unsigned char) - \
+			    sizeof(sa_family_t) - _SS_PAD1SIZE - _SS_ALIGNSIZE)
+
+struct sockaddr_storage {
+	unsigned char	ss_len;		/* address length */
+	sa_family_t	ss_family;	/* address family */
+	char		__ss_pad1[_SS_PAD1SIZE];
+	__int64_t	__ss_align;	/* force desired struct alignment */
+	char		__ss_pad2[_SS_PAD2SIZE];
+};
+
+#endif /* !_SYS__SOCKADDR_STORAGE_H_ */
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 7ed06f4fed9..f005ed1adb3 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -52,8 +52,11 @@ struct u_businfo {
 typedef enum device_state {
 	DS_NOTPRESENT,			/**< @brief not probed or probe failed */
 	DS_ALIVE,			/**< @brief probe succeeded */
+	DS_ATTACHING,			/**< @brief attaching is in progress */
 	DS_ATTACHED,			/**< @brief attach method called */
-	DS_BUSY				/**< @brief device is open */
+	DS_BUSY,			/**< @brief device is open */
+	DS_DETACHING			/**< @brief detaching is in progress */
+
 } device_state_t;
 
 /**
@@ -478,14 +481,6 @@ int	resource_set_string(const char *name, int unit, const char *resname,
 int	bus_data_generation_check(int generation);
 void	bus_data_generation_update(void);
 
-/*
- * Exported locking facilities.
- */
-void	 newbus_xlock(void);
-void	 newbus_slock(void);
-void	 newbus_xunlock(void);
-void	 newbus_sunlock(void);
-
 /**
  * Some convenience defines for probe routines to return.  These are just
  * suggested values, and there's nothing magical about them.
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index a41028b8f8e..3df4284fa92 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -137,6 +137,8 @@ typedef int d_poll_t(struct cdev *dev, int events, struct thread *td);
 typedef int d_kqfilter_t(struct cdev *dev, struct knote *kn);
 typedef int d_mmap_t(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr,
    		     int nprot);
+typedef int d_mmap2_t(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr,
+		     int nprot, vm_memattr_t *memattr);
 typedef int d_mmap_single_t(struct cdev *cdev, vm_ooffset_t *offset,
     vm_size_t size, struct vm_object **object, int nprot);
 typedef void d_purge_t(struct cdev *dev);
@@ -170,6 +172,7 @@ typedef int dumper_t(
 #define D_PSEUDO	0x00200000	/* make_dev() can return NULL */
 #define D_NEEDGIANT	0x00400000	/* driver want Giant */
 #define	D_NEEDMINOR	0x00800000	/* driver uses clone_create() */
+#define	D_MMAP2		0x01000000	/* driver uses d_mmap2() */
 
 /*
  * Version numbers.
@@ -198,7 +201,10 @@ struct cdevsw {
 	d_write_t		*d_write;
 	d_ioctl_t		*d_ioctl;
 	d_poll_t		*d_poll;
-	d_mmap_t		*d_mmap;
+	union {
+		d_mmap_t		*old;
+		d_mmap2_t		*new;
+	} __d_mmap;
 	d_strategy_t		*d_strategy;
 	dumper_t		*d_dump;
 	d_kqfilter_t		*d_kqfilter;
@@ -218,6 +224,8 @@ struct cdevsw {
 		SLIST_ENTRY(cdevsw)	postfree_list;
 	} __d_giant;
 };
+#define	d_mmap			__d_mmap.old
+#define	d_mmap2			__d_mmap.new
 #define	d_gianttrick		__d_giant.gianttrick
 #define	d_postfree_list		__d_giant.postfree_list
 
diff --git a/sys/sys/cons.h b/sys/sys/cons.h
index ac97ce437b6..e84318fbc68 100644
--- a/sys/sys/cons.h
+++ b/sys/sys/cons.h
@@ -45,10 +45,9 @@ typedef	void	cn_probe_t(struct consdev *);
 typedef	void	cn_init_t(struct consdev *);
 typedef	void	cn_term_t(struct consdev *);
 typedef	int	cn_getc_t(struct consdev *);
-typedef	int	cn_checkc_t(struct consdev *);
 typedef	void	cn_putc_t(struct consdev *, int);
 
-struct consdev {
+struct consdev_ops {
 	cn_probe_t	*cn_probe;
 				/* probe hardware and fill in consdev info */
 	cn_init_t	*cn_init;
@@ -57,10 +56,13 @@ struct consdev {
 				/* turn off as console */
 	cn_getc_t	*cn_getc;
 				/* kernel getchar interface */
-	cn_checkc_t	*cn_checkc;
-				/* kernel "return char if available" interface */
 	cn_putc_t	*cn_putc;
 				/* kernel putchar interface */
+};
+
+struct consdev {
+	const struct consdev_ops *cn_ops;
+				/* console device operations. */
 	short	cn_pri;		/* pecking order; the higher the better */
 	void	*cn_arg;	/* drivers method argument */
 	int	cn_flags;	/* capabilities of this console */
@@ -83,21 +85,22 @@ struct consdev {
 extern	struct msgbuf consmsgbuf; /* Message buffer for constty. */
 extern	struct tty *constty;	/* Temporary virtual console. */
 
-#define CONS_DRIVER(name, probe, init, term, getc, checkc, putc, dbctl)	\
-	static struct consdev name##_consdev = {			\
-		probe, init, term, getc, checkc, putc			\
+#define	CONSOLE_DEVICE(name, ops, arg)					\
+	static struct consdev name = {					\
+		.cn_ops = &ops,						\
+		.cn_arg = (arg),					\
 	};								\
-	DATA_SET(cons_set, name##_consdev)
+	DATA_SET(cons_set, name)
 
-#define CONSOLE_DRIVER(name)						\
-	static struct consdev name##_consdev = {			\
+#define	CONSOLE_DRIVER(name)						\
+	static const struct consdev_ops name##_consdev_ops = {		\
 		.cn_probe = name##_cnprobe,				\
 		.cn_init = name##_cninit,				\
 		.cn_term = name##_cnterm,				\
 		.cn_getc = name##_cngetc,				\
 		.cn_putc = name##_cnputc,				\
 	};								\
-	DATA_SET(cons_set, name##_consdev)
+	CONSOLE_DEVICE(name##_consdev, name##_consdev_ops, NULL)
 
 /* Other kernel entry points. */
 void	cninit(void);
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index 60979d96f12..4ccee5df082 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -58,7 +58,10 @@ typedef struct {
 	Elf_Note	hdr;
 	const char *	vendor;
 	int		flags;
-#define	BN_CAN_FETCH_OSREL	0x0001
+	boolean_t	(*trans_osrel)(const Elf_Note *, int32_t *);
+#define	BN_CAN_FETCH_OSREL	0x0001	/* Deprecated. */
+#define	BN_TRANSLATE_OSREL	0x0002	/* Use trans_osrel fetch osrel after */
+					/* checking ABI contraint if needed. */
 } Elf_Brandnote;
 
 typedef struct {
@@ -71,8 +74,9 @@ typedef struct {
 	const char *interp_newpath;
 	int flags;
 	Elf_Brandnote *brand_note;
-#define	BI_CAN_EXEC_DYN	0x0001
-#define	BI_BRAND_NOTE	0x0002
+#define	BI_CAN_EXEC_DYN		0x0001
+#define	BI_BRAND_NOTE		0x0002	/* May have note.ABI-tag section. */
+#define	BI_BRAND_NOTE_MANDATORY	0x0004	/* Must have note.ABI-tag section. */
 } __ElfN(Brandinfo);
 
 __ElfType(Auxargs);
@@ -91,6 +95,7 @@ void	__elfN(dump_thread)(struct thread *, void *, size_t *);
 
 extern int __elfN(fallback_brand);
 extern Elf_Brandnote __elfN(freebsd_brandnote);
+extern Elf_Brandnote __elfN(kfreebsd_brandnote);
 #endif /* _KERNEL */
 
 #endif /* !_SYS_IMGACT_ELF_H_ */
diff --git a/sys/sys/ioctl_compat.h b/sys/sys/ioctl_compat.h
index f4a9af62da2..d12cd5a8862 100644
--- a/sys/sys/ioctl_compat.h
+++ b/sys/sys/ioctl_compat.h
@@ -73,12 +73,12 @@ struct sgttyb {
 
 #define	OTIOCGETD	_IOR('t', 0, int)	/* get line discipline */
 #define	OTIOCSETD	_IOW('t', 1, int)	/* set line discipline */
-#define	TIOCHPCL	_IO('t', 2)		/* hang up on last close */
-#define	TIOCGETP	_IOR('t', 8,struct sgttyb)/* get parameters -- gtty */
-#define	TIOCSETP	_IOW('t', 9,struct sgttyb)/* set parameters -- stty */
-#define	TIOCSETN	_IOW('t',10,struct sgttyb)/* as above, but no flushtty*/
-#define	TIOCSETC	_IOW('t',17,struct tchars)/* set special characters */
-#define	TIOCGETC	_IOR('t',18,struct tchars)/* get special characters */
+#define	TIOCHPCL	 _IO('t', 2)		/* hang up on last close */
+#define	TIOCGETP	_IOR('t', 8, struct sgttyb) /* get parameters */
+#define	TIOCSETP	_IOW('t', 9, struct sgttyb) /* set parameters */
+#define	TIOCSETN	_IOW('t',10, struct sgttyb) /* as above, but no flush */
+#define	TIOCSETC	_IOW('t',17, struct tchars) /* set special characters */
+#define	TIOCGETC	_IOR('t',18, struct tchars) /* get special characters */
 #define		TANDEM		0x00000001	/* send stopc on out q full */
 #define		CBREAK		0x00000002	/* half-cooked mode */
 #define		LCASE		0x00000004	/* simulate lower case */
@@ -126,9 +126,9 @@ struct sgttyb {
 #define		PENDIN		0x20000000	/* tp->t_rawq needs reread */
 #define		DECCTQ		0x40000000	/* only ^Q starts after ^S */
 #define		NOFLSH		0x80000000	/* no output flush on signal */
-#define	TIOCLBIS	_IOW('t', 127, int)	/* bis local mode bits */
-#define	TIOCLBIC	_IOW('t', 126, int)	/* bic local mode bits */
-#define	TIOCLSET	_IOW('t', 125, int)	/* set entire local mode word */
+#define	OTIOCCONS	 _IO('t', 98)	/* for hp300 -- sans int arg */
+#define	TIOCGLTC	_IOR('t', 116,struct ltchars) /* get special chars */
+#define	TIOCSLTC	_IOW('t', 117,struct ltchars) /* set special chars */
 #define	TIOCLGET	_IOR('t', 124, int)	/* get local modes */
 #define		LCRTBS		(CRTBS>>16)
 #define		LPRTERA		(PRTERA>>16)
@@ -145,8 +145,8 @@ struct sgttyb {
 #define		LPENDIN		(PENDIN>>16)
 #define		LDECCTQ		(DECCTQ>>16)
 #define		LNOFLSH		(NOFLSH>>16)
-#define	TIOCSLTC	_IOW('t',117,struct ltchars)/* set local special chars*/
-#define	TIOCGLTC	_IOR('t',116,struct ltchars)/* get local special chars*/
-#define OTIOCCONS	_IO('t', 98)	/* for hp300 -- sans int arg */
+#define	TIOCLSET	_IOW('t', 125, int)	/* set entire local mode word */
+#define	TIOCLBIC	_IOW('t', 126, int)	/* bic local mode bits */
+#define	TIOCLBIS	_IOW('t', 127, int)	/* bis local mode bits */
 
 #endif /* !_SYS_IOCTL_COMPAT_H_ */
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
index d7457bfd427..cb26a64ec7d 100644
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -341,6 +341,7 @@ void getcredhostuuid(struct ucred *, char *, size_t);
 void getcredhostid(struct ucred *, unsigned long *);
 int prison_allow(struct ucred *, unsigned);
 int prison_check(struct ucred *cred1, struct ucred *cred2);
+int prison_owns_vnet(struct ucred *);
 int prison_canseemount(struct ucred *cred, struct mount *mp);
 void prison_enforce_statfs(struct ucred *cred, struct mount *mp,
     struct statfs *sp);
diff --git a/sys/sys/lock.h b/sys/sys/lock.h
index 9e47ab4b41d..01c70ffc66c 100644
--- a/sys/sys/lock.h
+++ b/sys/sys/lock.h
@@ -155,16 +155,16 @@ struct lock_class {
 
 #define	LOCK_LOG_LOCK(opname, lo, flags, recurse, file, line) do {	\
 	if (LOCK_LOG_TEST((lo), (flags)))				\
-		CTR5(KTR_LOCK, opname " (%s) %s r = %d at %s:%d",	\
+		CTR6(KTR_LOCK, opname " (%s) %s %p r = %d at %s:%d",	\
 		    LOCK_CLASS(lo)->lc_name, (lo)->lo_name,		\
-		    (u_int)(recurse), (file), (line));			\
+		    (lo), (u_int)(recurse), (file), (line));		\
 } while (0)
 
 #define	LOCK_LOG_TRY(opname, lo, flags, result, file, line) do {	\
 	if (LOCK_LOG_TEST((lo), (flags)))				\
-		CTR5(KTR_LOCK, "TRY_" opname " (%s) %s result=%d at %s:%d",\
+		CTR6(KTR_LOCK, "TRY_" opname " (%s) %s %p result=%d at %s:%d",\
 		    LOCK_CLASS(lo)->lc_name, (lo)->lo_name,		\
-		    (u_int)(result), (file), (line));			\
+		    (lo), (u_int)(result), (file), (line));		\
 } while (0)
 
 #define	LOCK_LOG_INIT(lo, flags) do {					\
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 10a1a9a79f9..0c7f34b4c81 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 800107	/* Master, propagated to newvers */
+#define __FreeBSD_version 900000	/* Master, propagated to newvers */
 
 #ifndef LOCORE
 #include 
diff --git a/sys/sys/pcpu.h b/sys/sys/pcpu.h
index 8c0e0d55a95..ae6cc0953ba 100644
--- a/sys/sys/pcpu.h
+++ b/sys/sys/pcpu.h
@@ -56,12 +56,14 @@ struct thread;
 extern uintptr_t *__start_set_pcpu;
 extern uintptr_t *__stop_set_pcpu;
 
+__asm__(
 #if defined(__arm__)
-__asm__(".section set_pcpu, \"aw\", %progbits");
+	".section set_pcpu, \"aw\", %progbits\n"
 #else
-__asm__(".section set_pcpu, \"aw\", @progbits");
+	".section set_pcpu, \"aw\", @progbits\n"
 #endif
-__asm__(".previous");
+	"\t.p2align " __XSTRING(CACHE_LINE_SHIFT) "\n"
+	"\t.previous");
 
 /*
  * Array of dynamic pcpu base offsets.  Indexed by id.
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index b65db627a90..6e5716788e9 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -267,9 +267,6 @@ struct thread {
 	struct vm_object *td_kstack_obj;/* (a) Kstack object. */
 	vm_offset_t	td_kstack;	/* (a) Kernel VA of kstack. */
 	int		td_kstack_pages; /* (a) Size of the kstack. */
-	struct vm_object *td_altkstack_obj;/* (a) Alternate kstack object. */
-	vm_offset_t	td_altkstack;	/* (a) Kernel VA of alternate kstack. */
-	int		td_altkstack_pages; /* (a) Size of alternate kstack. */
 	volatile u_int	td_critnest;	/* (k*) Critical section nest level. */
 	struct mdthread td_md;		/* (k) Any machine-dependent fields. */
 	struct td_sched	*td_sched;	/* (*) Scheduler-specific data. */
@@ -850,7 +847,8 @@ void	cpu_thread_exit(struct thread *);
 void	cpu_thread_free(struct thread *);
 void	cpu_thread_swapin(struct thread *);
 void	cpu_thread_swapout(struct thread *);
-struct	thread *thread_alloc(void);
+struct	thread *thread_alloc(int pages);
+int	thread_alloc_stack(struct thread *, int pages);
 void	thread_exit(void) __dead2;
 void	thread_free(struct thread *td);
 void	thread_link(struct thread *td, struct proc *p);
diff --git a/sys/sys/sglist.h b/sys/sys/sglist.h
index a1854d885ca..7c17baa8d7e 100644
--- a/sys/sys/sglist.h
+++ b/sys/sys/sglist.h
@@ -91,7 +91,7 @@ int	sglist_append_user(struct sglist *sg, void *buf, size_t len,
 	    struct thread *td);
 struct sglist *sglist_build(void *buf, size_t len, int mflags);
 struct sglist *sglist_clone(struct sglist *sg, int mflags);
-int	sglist_consume_uio(struct sglist *sg, struct uio *uio, int resid);
+int	sglist_consume_uio(struct sglist *sg, struct uio *uio, size_t resid);
 int	sglist_count(void *buf, size_t len);
 void	sglist_free(struct sglist *sg);
 int	sglist_join(struct sglist *first, struct sglist *second);
diff --git a/sys/sys/smp.h b/sys/sys/smp.h
index 05c86424720..d80b9e46ef9 100644
--- a/sys/sys/smp.h
+++ b/sys/sys/smp.h
@@ -123,6 +123,7 @@ void	forward_signal(struct thread *);
 void	forward_roundrobin(void);
 int	restart_cpus(cpumask_t);
 int	stop_cpus(cpumask_t);
+int	stop_cpus_hard(cpumask_t);
 #if defined(__amd64__)
 int	suspend_cpus(cpumask_t);
 #endif
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index 0de965f6b4d..ab9f213fc20 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -290,26 +290,7 @@ struct sockproto {
 };
 #endif
 
-#ifndef	_STRUCT_SOCKADDR_STORAGE_DECLARED
-/*
- * RFC 2553: protocol-independent placeholder for socket addresses
- */
-#define	_SS_MAXSIZE	128U
-#define	_SS_ALIGNSIZE	(sizeof(__int64_t))
-#define	_SS_PAD1SIZE	(_SS_ALIGNSIZE - sizeof(unsigned char) - \
-			    sizeof(sa_family_t))
-#define	_SS_PAD2SIZE	(_SS_MAXSIZE - sizeof(unsigned char) - \
-			    sizeof(sa_family_t) - _SS_PAD1SIZE - _SS_ALIGNSIZE)
-
-struct sockaddr_storage {
-	unsigned char	ss_len;		/* address length */
-	sa_family_t	ss_family;	/* address family */
-	char		__ss_pad1[_SS_PAD1SIZE];
-	__int64_t	__ss_align;	/* force desired struct alignment */
-	char		__ss_pad2[_SS_PAD2SIZE];
-};
-#define	_STRUCT_SOCKADDR_STORAGE_DECLARED
-#endif
+#include 
 
 #if __BSD_VISIBLE
 /*
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 4cab1599dc9..e1ce71889ee 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -85,6 +85,7 @@ struct ctlname {
 #define CTLMASK_SECURE	0x00F00000	/* Secure level */
 #define CTLFLAG_TUN	0x00080000	/* Tunable variable */
 #define CTLFLAG_MPSAFE	0x00040000	/* Handler is MP safe */
+#define CTLFLAG_VNET	0x00020000	/* Prisons with vnet can fiddle */
 #define CTLFLAG_RDTUN	(CTLFLAG_RD|CTLFLAG_TUN)
 
 /*
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 1956a8f122f..96222da9152 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -89,6 +89,17 @@ extern int maxusers;		/* system tune hint */
 #define	__CTASSERT(x, y)	typedef char __assert ## y[(x) ? 1 : -1]
 #endif
 
+/*
+ * Assert that a pointer can be loaded from memory atomically.
+ *
+ * This assertion enforces stronger alignment than necessary.  For example,
+ * on some architectures, atomicity for unaligned loads will depend on
+ * whether or not the load spans multiple cache lines.
+ */
+#define	ASSERT_ATOMIC_LOAD_PTR(var, msg)				\
+	KASSERT(sizeof(var) == sizeof(void *) &&			\
+	    ((uintptr_t)&(var) & (sizeof(void *) - 1)) == 0, msg)
+
 /*
  * XXX the hints declarations are even more misplaced than most declarations
  * in this file, since they are needed in one file (per arch) and only used
diff --git a/sys/sys/taskqueue.h b/sys/sys/taskqueue.h
index 4065a58b3ed..bf2e4ee31d0 100644
--- a/sys/sys/taskqueue.h
+++ b/sys/sys/taskqueue.h
@@ -37,6 +37,7 @@
 #include 
 
 struct taskqueue;
+struct thread;
 
 /*
  * A notification callback function which is called from
@@ -47,7 +48,6 @@ struct taskqueue;
  */
 typedef void (*taskqueue_enqueue_fn)(void *context);
 
-struct proc;
 struct taskqueue *taskqueue_create(const char *name, int mflags,
 				    taskqueue_enqueue_fn enqueue,
 				    void *context);
@@ -55,11 +55,11 @@ int	taskqueue_start_threads(struct taskqueue **tqp, int count, int pri,
 				const char *name, ...) __printflike(4, 5);
 int	taskqueue_enqueue(struct taskqueue *queue, struct task *task);
 void	taskqueue_drain(struct taskqueue *queue, struct task *task);
-struct taskqueue *taskqueue_find(const char *name);
 void	taskqueue_free(struct taskqueue *queue);
 void	taskqueue_run(struct taskqueue *queue);
 void	taskqueue_block(struct taskqueue *queue);
 void	taskqueue_unblock(struct taskqueue *queue);
+int	taskqueue_member(struct taskqueue *queue, struct thread *td);
 
 /*
  * Functions for dedicated thread taskqueues
diff --git a/sys/sys/tty.h b/sys/sys/tty.h
index d5d38459ee4..13c89f92c07 100644
--- a/sys/sys/tty.h
+++ b/sys/sys/tty.h
@@ -202,6 +202,7 @@ void	tty_info(struct tty *tp);
 void	ttyconsdev_select(const char *name);
 
 /* Pseudo-terminal hooks. */
+int	pts_alloc(int fflags, struct thread *td, struct file *fp);
 int	pts_alloc_external(int fd, struct thread *td, struct file *fp,
     struct cdev *dev, const char *name);
 
diff --git a/sys/sys/ttycom.h b/sys/sys/ttycom.h
index 60b6145ef27..68a411ea108 100644
--- a/sys/sys/ttycom.h
+++ b/sys/sys/ttycom.h
@@ -57,10 +57,9 @@ struct winsize {
 };
 
 						/* 0-2 compat */
-						/* 3-4 obsolete */
-						/* 5-7 obsolete or unused */
+						/* 3-7 unused */
 						/* 8-10 compat */
-						/* 11-12 obsolete or unused */
+						/* 11-12 unused */
 #define	TIOCEXCL	 _IO('t', 13)		/* set exclusive use of tty */
 #define	TIOCNXCL	 _IO('t', 14)		/* reset exclusive use of tty */
 #define	TIOCGPTN	_IOR('t', 15, int)	/* Get pts number. */
@@ -70,34 +69,34 @@ struct winsize {
 #define	TIOCSETA	_IOW('t', 20, struct termios) /* set termios struct */
 #define	TIOCSETAW	_IOW('t', 21, struct termios) /* drain output, set */
 #define	TIOCSETAF	_IOW('t', 22, struct termios) /* drn out, fls in, set */
-						/* 23-25 obsolete or unused */
+						/* 23-25 unused */
 #define	TIOCGETD	_IOR('t', 26, int)	/* get line discipline */
 #define	TIOCSETD	_IOW('t', 27, int)	/* set line discipline */
 #define	TIOCPTMASTER	 _IO('t', 28)		/* pts master validation */
-						/* 29-69 free */
-						/* 80-84 slip */
+						/* 29-85 unused */
 #define	TIOCGDRAINWAIT	_IOR('t', 86, int)	/* get ttywait timeout */
 #define	TIOCSDRAINWAIT	_IOW('t', 87, int)	/* set ttywait timeout */
-						/* 88 slip, ppp; conflicts */
+						/* 88 unused */
+						/* 89-91 conflicts: tun and tap */
 #define	TIOCTIMESTAMP	_IOR('t', 89, struct timeval)	/* enable/get timestamp
 						 * of last input event */
-						/* 70-90 ppp; many conflicts */
 #define	TIOCMGDTRWAIT	_IOR('t', 90, int)	/* modem: get wait on close */
 #define	TIOCMSDTRWAIT	_IOW('t', 91, int)	/* modem: set wait on close */
-						/* 90-92 tap; some conflicts */
+						/* 92-93 tun and tap */
+						/* 94-97 conflicts: tun and tap */
 #define	TIOCDRAIN	 _IO('t', 94)		/* wait till output drained */
 #define	TIOCSIG		_IOWINT('t', 95)	/* pty: generate signal */
 #define	TIOCEXT		_IOW('t', 96, int)	/* pty: external processing */
-						/* 90-97 tun; some conflicts */
 #define	TIOCSCTTY	 _IO('t', 97)		/* become controlling tty */
 #define	TIOCCONS	_IOW('t', 98, int)	/* become virtual console */
 #define	TIOCGSID	_IOR('t', 99, int)	/* get session id */
-						/* 100 see consio.h */
+						/* 100 unused */
 #define	TIOCSTAT	 _IO('t', 101)		/* simulate ^T status message */
 #define	TIOCUCNTL	_IOW('t', 102, int)	/* pty: set/clr usr cntl mode */
 #define		UIOCCMD(n)	_IO('u', n)	/* usr cntl op "n" */
 #define	TIOCSWINSZ	_IOW('t', 103, struct winsize)	/* set window size */
 #define	TIOCGWINSZ	_IOR('t', 104, struct winsize)	/* get window size */
+						/* 105 unused */
 #define	TIOCMGET	_IOR('t', 106, int)	/* get all modem bits */
 #define		TIOCM_LE	0001		/* line enable */
 #define		TIOCM_DTR	0002		/* data terminal ready */
diff --git a/sys/sys/ttydisc.h b/sys/sys/ttydisc.h
index 2ea54666c56..74a1a0ed927 100644
--- a/sys/sys/ttydisc.h
+++ b/sys/sys/ttydisc.h
@@ -52,6 +52,7 @@ void	ttydisc_optimize(struct tty *tp);
 void	ttydisc_modem(struct tty *tp, int open);
 #define ttydisc_can_bypass(tp) ((tp)->t_flags & TF_BYPASS)
 int	ttydisc_rint(struct tty *tp, char c, int flags);
+size_t	ttydisc_rint_simple(struct tty *tp, const void *buf, size_t len);
 size_t	ttydisc_rint_bypass(struct tty *tp, const void *buf, size_t len);
 void	ttydisc_rint_done(struct tty *tp);
 size_t	ttydisc_rint_poll(struct tty *tp);
diff --git a/sys/sys/types.h b/sys/sys/types.h
index 66be699d6e0..6696de67091 100644
--- a/sys/sys/types.h
+++ b/sys/sys/types.h
@@ -299,6 +299,7 @@ typedef	__uint32_t	intrmask_t;	/* Interrupt mask (spl, xxx_imask...) */
 
 typedef	__uintfptr_t	uintfptr_t;
 typedef	__uint64_t	uoff_t;
+typedef	char		vm_memattr_t;	/* memory attribute codes */
 typedef	struct vm_page	*vm_page_t;
 
 #define offsetof(type, field) __offsetof(type, field)
diff --git a/sys/dev/syscons/teken/Makefile b/sys/teken/Makefile
similarity index 100%
rename from sys/dev/syscons/teken/Makefile
rename to sys/teken/Makefile
diff --git a/sys/dev/syscons/teken/gensequences b/sys/teken/gensequences
similarity index 100%
rename from sys/dev/syscons/teken/gensequences
rename to sys/teken/gensequences
diff --git a/sys/dev/syscons/teken/sequences b/sys/teken/sequences
similarity index 100%
rename from sys/dev/syscons/teken/sequences
rename to sys/teken/sequences
diff --git a/sys/dev/syscons/teken/teken.c b/sys/teken/teken.c
similarity index 95%
rename from sys/dev/syscons/teken/teken.c
rename to sys/teken/teken.c
index 5a16f8df47c..58f4f37162d 100644
--- a/sys/dev/syscons/teken/teken.c
+++ b/sys/teken/teken.c
@@ -70,9 +70,6 @@ static FILE *df;
 #define	teken_scs_switch(t, g)
 #endif /* TEKEN_XTERM && TEKEN_UTF8 */
 
-/* Private flags for teken_format_t. */
-#define	TF_REVERSE	0x08
-
 /* Private flags for t_stateflags. */
 #define	TS_FIRSTDIGIT	0x01	/* First numeric digit in escape sequence. */
 #define	TS_INSERT	0x02	/* Insert mode. */
@@ -114,19 +111,10 @@ static inline void
 teken_funcs_putchar(teken_t *t, const teken_pos_t *p, teken_char_t c,
     const teken_attr_t *a)
 {
-	teken_attr_t ta;
 
 	teken_assert(p->tp_row < t->t_winsize.tp_row);
 	teken_assert(p->tp_col < t->t_winsize.tp_col);
 
-	/* Apply inversion. */
-	if (a->ta_format & TF_REVERSE) {
-		ta.ta_format = a->ta_format;
-		ta.ta_fgcolor = a->ta_bgcolor;
-		ta.ta_bgcolor = a->ta_fgcolor;
-		a = &ta;
-	}
-
 	t->t_funcs->tf_putchar(t->t_softc, p, c, a);
 }
 
@@ -134,21 +122,12 @@ static inline void
 teken_funcs_fill(teken_t *t, const teken_rect_t *r,
     const teken_char_t c, const teken_attr_t *a)
 {
-	teken_attr_t ta;
 
 	teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
 	teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
 	teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
 	teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
 
-	/* Apply inversion. */
-	if (a->ta_format & TF_REVERSE) {
-		ta.ta_format = a->ta_format;
-		ta.ta_fgcolor = a->ta_bgcolor;
-		ta.ta_bgcolor = a->ta_fgcolor;
-		a = &ta;
-	}
-
 	t->t_funcs->tf_fill(t->t_softc, r, c, a);
 }
 
diff --git a/sys/dev/syscons/teken/teken.h b/sys/teken/teken.h
similarity index 99%
rename from sys/dev/syscons/teken/teken.h
rename to sys/teken/teken.h
index dd19e76f6c1..e1a2cada7dd 100644
--- a/sys/dev/syscons/teken/teken.h
+++ b/sys/teken/teken.h
@@ -54,6 +54,7 @@ typedef unsigned char teken_format_t;
 #define	TF_BOLD		0x01
 #define	TF_UNDERLINE	0x02
 #define	TF_BLINK	0x04
+#define	TF_REVERSE	0x08
 typedef unsigned char teken_color_t;
 #define	TC_BLACK	0
 #define	TC_RED		1
diff --git a/sys/dev/syscons/teken/teken_demo.c b/sys/teken/teken_demo.c
similarity index 99%
rename from sys/dev/syscons/teken/teken_demo.c
rename to sys/teken/teken_demo.c
index 02463a7f1b1..e68cca1ae77 100644
--- a/sys/dev/syscons/teken/teken_demo.c
+++ b/sys/teken/teken_demo.c
@@ -121,6 +121,8 @@ printchar(const teken_pos_t *p)
 		attr |= A_UNDERLINE;
 	if (px->a.ta_format & TF_BLINK)
 		attr |= A_BLINK;
+	if (px->a.ta_format & TF_REVERSE)
+		attr |= A_REVERSE;
 
 	bkgdset(attr | COLOR_PAIR(px->a.ta_fgcolor + 8 * px->a.ta_bgcolor));
 	mvaddstr(p->tp_row, p->tp_col, str);
diff --git a/sys/dev/syscons/teken/teken_scs.h b/sys/teken/teken_scs.h
similarity index 100%
rename from sys/dev/syscons/teken/teken_scs.h
rename to sys/teken/teken_scs.h
diff --git a/sys/dev/syscons/teken/teken_stress.c b/sys/teken/teken_stress.c
similarity index 100%
rename from sys/dev/syscons/teken/teken_stress.c
rename to sys/teken/teken_stress.c
diff --git a/sys/dev/syscons/teken/teken_subr.h b/sys/teken/teken_subr.h
similarity index 100%
rename from sys/dev/syscons/teken/teken_subr.h
rename to sys/teken/teken_subr.h
diff --git a/sys/dev/syscons/teken/teken_subr_compat.h b/sys/teken/teken_subr_compat.h
similarity index 100%
rename from sys/dev/syscons/teken/teken_subr_compat.h
rename to sys/teken/teken_subr_compat.h
diff --git a/sys/dev/syscons/teken/teken_wcwidth.h b/sys/teken/teken_wcwidth.h
similarity index 100%
rename from sys/dev/syscons/teken/teken_wcwidth.h
rename to sys/teken/teken_wcwidth.h
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 72522b2594e..4d652c114dd 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -663,6 +663,8 @@ static int req_clear_inodedeps;	/* syncer process flush some inodedeps */
 static int req_clear_remove;	/* syncer process flush some freeblks */
 #define FLUSH_REMOVE		2
 #define FLUSH_REMOVE_WAIT	3
+static long num_freeblkdep;	/* number of freeblks workitems allocated */
+
 /*
  * runtime statistics
  */
@@ -2223,6 +2225,9 @@ softdep_setup_freeblocks(ip, length, flags)
 	freeblks->fb_uid = ip->i_uid;
 	freeblks->fb_previousinum = ip->i_number;
 	freeblks->fb_devvp = ip->i_devvp;
+	ACQUIRE_LOCK(&lk);
+	num_freeblkdep++;
+	FREE_LOCK(&lk);
 	extblocks = 0;
 	if (fs->fs_magic == FS_UFS2_MAGIC)
 		extblocks = btodb(fragroundup(fs, ip->i_din2->di_extsize));
@@ -2815,6 +2820,7 @@ handle_workitem_freeblocks(freeblks, flags)
 
 	ACQUIRE_LOCK(&lk);
 	WORKITEM_FREE(freeblks, D_FREEBLKS);
+	num_freeblkdep--;
 	FREE_LOCK(&lk);
 }
 
@@ -5768,7 +5774,8 @@ softdep_slowdown(vp)
 	max_softdeps_hard = max_softdeps * 11 / 10;
 	if (num_dirrem < max_softdeps_hard / 2 &&
 	    num_inodedep < max_softdeps_hard &&
-	    VFSTOUFS(vp->v_mount)->um_numindirdeps < maxindirdeps) {
+	    VFSTOUFS(vp->v_mount)->um_numindirdeps < maxindirdeps &&
+	    num_freeblkdep < max_softdeps_hard) {
 		FREE_LOCK(&lk);
   		return (0);
 	}
@@ -5970,12 +5977,19 @@ clear_remove(td)
 			if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
 				continue;
 			FREE_LOCK(&lk);
-			if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
-			     FFSV_FORCEINSMQ))) {
+
+			/*
+			 * Let unmount clear deps
+			 */
+			error = vfs_busy(mp, MBF_NOWAIT);
+			if (error != 0)
+				goto finish_write;
+			error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
+			     FFSV_FORCEINSMQ);
+			vfs_unbusy(mp);
+			if (error != 0) {
 				softdep_error("clear_remove: vget", error);
-				vn_finished_write(mp);
-				ACQUIRE_LOCK(&lk);
-				return;
+				goto finish_write;
 			}
 			if ((error = ffs_syncvnode(vp, MNT_NOWAIT)))
 				softdep_error("clear_remove: fsync", error);
@@ -5984,6 +5998,7 @@ clear_remove(td)
 			drain_output(vp);
 			BO_UNLOCK(bo);
 			vput(vp);
+		finish_write:
 			vn_finished_write(mp);
 			ACQUIRE_LOCK(&lk);
 			return;
@@ -6043,13 +6058,21 @@ clear_inodedeps(td)
 		if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
 			continue;
 		FREE_LOCK(&lk);
-		if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
-		    FFSV_FORCEINSMQ)) != 0) {
-			softdep_error("clear_inodedeps: vget", error);
+		error = vfs_busy(mp, MBF_NOWAIT); /* Let unmount clear deps */
+		if (error != 0) {
 			vn_finished_write(mp);
 			ACQUIRE_LOCK(&lk);
 			return;
 		}
+		if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
+		    FFSV_FORCEINSMQ)) != 0) {
+			softdep_error("clear_inodedeps: vget", error);
+			vfs_unbusy(mp);
+			vn_finished_write(mp);
+			ACQUIRE_LOCK(&lk);
+			return;
+		}
+		vfs_unbusy(mp);
 		if (ino == lastino) {
 			if ((error = ffs_syncvnode(vp, MNT_WAIT)))
 				softdep_error("clear_inodedeps: fsync1", error);
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 7aae80828c4..d3d7c2c6073 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1467,6 +1467,7 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags)
 		vp->v_vflag |= VV_FORCEINSMQ;
 	error = insmntque(vp, mp);
 	if (error != 0) {
+		uma_zfree(uma_inode, ip);
 		*vpp = NULL;
 		return (error);
 	}
diff --git a/sys/ufs/ufs/ufs_acl.c b/sys/ufs/ufs/ufs_acl.c
index c04a5d2ffaa..68e5015c2d4 100644
--- a/sys/ufs/ufs/ufs_acl.c
+++ b/sys/ufs/ufs/ufs_acl.c
@@ -255,9 +255,6 @@ ufs_getacl_posix1e(struct vop_getacl_args *ap)
 			old->acl_cnt = 0;
 			break;
 		}
-
-		error = 0;
-
 		/* FALLTHROUGH */
 	case 0:
 		error = acl_copy_oldacl_into_acl(old, ap->a_aclp);
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 0d762de0705..c7f559381fd 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -93,6 +93,17 @@ dev_pager_init()
 	    UMA_ZONE_NOFREE|UMA_ZONE_VM); 
 }
 
+static __inline int
+dev_mmap(struct cdevsw *csw, struct cdev *dev, vm_offset_t offset,
+    vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr)
+{
+
+	if (csw->d_flags & D_MMAP2)
+		return (csw->d_mmap2(dev, offset, paddr, nprot, memattr));
+	else
+		return (csw->d_mmap(dev, offset, paddr, nprot));
+}
+
 /*
  * MPSAFE
  */
@@ -106,6 +117,7 @@ dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
 	unsigned int npages;
 	vm_paddr_t paddr;
 	vm_offset_t off;
+	vm_memattr_t dummy;
 	struct cdevsw *csw;
 
 	/*
@@ -133,7 +145,7 @@ dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
 	 */
 	npages = OFF_TO_IDX(size);
 	for (off = foff; npages--; off += PAGE_SIZE)
-		if ((*csw->d_mmap)(dev, off, &paddr, (int)prot) != 0) {
+		if (dev_mmap(csw, dev, off, &paddr, (int)prot, &dummy) != 0) {
 			dev_relthread(dev);
 			return (NULL);
 		}
@@ -214,7 +226,6 @@ dev_pager_getpages(object, m, count, reqpage)
 	vm_memattr_t memattr;
 	struct cdev *dev;
 	int i, ret;
-	int prot;
 	struct cdevsw *csw;
 	struct thread *td;
 	struct file *fpop;
@@ -228,12 +239,11 @@ dev_pager_getpages(object, m, count, reqpage)
 	csw = dev_refthread(dev);
 	if (csw == NULL)
 		panic("dev_pager_getpage: no cdevsw");
-	prot = PROT_READ;	/* XXX should pass in? */
-
 	td = curthread;
 	fpop = td->td_fpop;
 	td->td_fpop = NULL;
-	ret = (*csw->d_mmap)(dev, (vm_offset_t)offset << PAGE_SHIFT, &paddr, prot);
+	ret = dev_mmap(csw, dev, (vm_offset_t)offset << PAGE_SHIFT, &paddr,
+	    PROT_READ, &memattr);
 	KASSERT(ret == 0, ("dev_pager_getpage: map function returns error"));
 	td->td_fpop = fpop;
 	dev_relthread(dev);
diff --git a/sys/vm/sg_pager.c b/sys/vm/sg_pager.c
index 6e3da803295..a17fe82c2ef 100644
--- a/sys/vm/sg_pager.c
+++ b/sys/vm/sg_pager.c
@@ -204,6 +204,7 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
 	vm_page_unlock_queues();
 	vm_page_insert(page, object, offset);
 	m[reqpage] = page;
+	page->valid = VM_PAGE_BITS_ALL;
 
 	return (VM_PAGER_OK);
 }
diff --git a/sys/vm/vm.h b/sys/vm/vm.h
index b547514a378..941300a0894 100644
--- a/sys/vm/vm.h
+++ b/sys/vm/vm.h
@@ -63,12 +63,6 @@
 
 #include 
 
-/*
- * The exact set of memory attributes is machine dependent.  However, every
- * machine is required to define VM_MEMATTR_DEFAULT.
- */
-typedef	char vm_memattr_t;	/* memory attribute codes */
-
 typedef char vm_inherit_t;	/* inheritance codes */
 
 #define	VM_INHERIT_SHARE	((vm_inherit_t) 0)
@@ -114,6 +108,12 @@ typedef struct vm_object *vm_object_t;
  */
 typedef int boolean_t;
 
+/*
+ * The exact set of memory attributes is machine dependent.  However, every
+ * machine is required to define VM_MEMATTR_DEFAULT.
+ */
+typedef	char vm_memattr_t;	/* memory attribute codes */
+
 /*
  * This is defined in  for the kernel so that vnode_if.h
  * doesn't have to include .
diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h
index 53f76947ee8..65b6c8e8e4a 100644
--- a/sys/vm/vm_extern.h
+++ b/sys/vm/vm_extern.h
@@ -80,9 +80,7 @@ int vm_fault_quick(caddr_t v, int prot);
 struct sf_buf *vm_imgact_map_page(vm_object_t object, vm_ooffset_t offset);
 void vm_imgact_unmap_page(struct sf_buf *sf);
 void vm_thread_dispose(struct thread *td);
-void vm_thread_dispose_altkstack(struct thread *td);
 int vm_thread_new(struct thread *td, int pages);
-int vm_thread_new_altkstack(struct thread *td, int pages);
 void vm_thread_swapin(struct thread *td);
 void vm_thread_swapout(struct thread *td);
 #endif				/* _KERNEL */
diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c
index 9e43a3fe005..851c73361ee 100644
--- a/sys/vm/vm_glue.c
+++ b/sys/vm/vm_glue.c
@@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -308,6 +309,20 @@ vm_imgact_unmap_page(struct sf_buf *sf)
 	vm_page_unlock_queues();
 }
 
+struct kstack_cache_entry {
+	vm_object_t ksobj;
+	struct kstack_cache_entry *next_ks_entry;
+};
+
+static struct kstack_cache_entry *kstack_cache;
+static int kstack_cache_size = 128;
+static int kstacks;
+static struct mtx kstack_cache_mtx;
+SYSCTL_INT(_vm, OID_AUTO, kstack_cache_size, CTLFLAG_RW, &kstack_cache_size, 0,
+    "");
+SYSCTL_INT(_vm, OID_AUTO, kstacks, CTLFLAG_RD, &kstacks, 0,
+    "");
+
 #ifndef KSTACK_MAX_PAGES
 #define KSTACK_MAX_PAGES 32
 #endif
@@ -323,6 +338,7 @@ vm_thread_new(struct thread *td, int pages)
 	vm_object_t ksobj;
 	vm_offset_t ks;
 	vm_page_t m, ma[KSTACK_MAX_PAGES];
+	struct kstack_cache_entry *ks_ce;
 	int i;
 
 	/* Bounds check */
@@ -330,6 +346,22 @@ vm_thread_new(struct thread *td, int pages)
 		pages = KSTACK_PAGES;
 	else if (pages > KSTACK_MAX_PAGES)
 		pages = KSTACK_MAX_PAGES;
+
+	if (pages == KSTACK_PAGES) {
+		mtx_lock(&kstack_cache_mtx);
+		if (kstack_cache != NULL) {
+			ks_ce = kstack_cache;
+			kstack_cache = ks_ce->next_ks_entry;
+			mtx_unlock(&kstack_cache_mtx);
+
+			td->td_kstack_obj = ks_ce->ksobj;
+			td->td_kstack = (vm_offset_t)ks_ce;
+			td->td_kstack_pages = KSTACK_PAGES;
+			return (1);
+		}
+		mtx_unlock(&kstack_cache_mtx);
+	}
+
 	/*
 	 * Allocate an object for the kstack.
 	 */
@@ -345,7 +377,8 @@ vm_thread_new(struct thread *td, int pages)
 		vm_object_deallocate(ksobj);
 		return (0);
 	}
-	
+
+	atomic_add_int(&kstacks, 1);
 	if (KSTACK_GUARD_PAGES != 0) {
 		pmap_qremove(ks, KSTACK_GUARD_PAGES);
 		ks += KSTACK_GUARD_PAGES * PAGE_SIZE;
@@ -376,20 +409,13 @@ vm_thread_new(struct thread *td, int pages)
 	return (1);
 }
 
-/*
- * Dispose of a thread's kernel stack.
- */
-void
-vm_thread_dispose(struct thread *td)
+static void
+vm_thread_stack_dispose(vm_object_t ksobj, vm_offset_t ks, int pages)
 {
-	vm_object_t ksobj;
-	vm_offset_t ks;
 	vm_page_t m;
-	int i, pages;
+	int i;
 
-	pages = td->td_kstack_pages;
-	ksobj = td->td_kstack_obj;
-	ks = td->td_kstack;
+	atomic_add_int(&kstacks, -1);
 	pmap_qremove(ks, pages);
 	VM_OBJECT_LOCK(ksobj);
 	for (i = 0; i < pages; i++) {
@@ -405,9 +431,66 @@ vm_thread_dispose(struct thread *td)
 	vm_object_deallocate(ksobj);
 	kmem_free(kernel_map, ks - (KSTACK_GUARD_PAGES * PAGE_SIZE),
 	    (pages + KSTACK_GUARD_PAGES) * PAGE_SIZE);
-	td->td_kstack = 0;
 }
 
+/*
+ * Dispose of a thread's kernel stack.
+ */
+void
+vm_thread_dispose(struct thread *td)
+{
+	vm_object_t ksobj;
+	vm_offset_t ks;
+	struct kstack_cache_entry *ks_ce;
+	int pages;
+
+	pages = td->td_kstack_pages;
+	ksobj = td->td_kstack_obj;
+	ks = td->td_kstack;
+	td->td_kstack = 0;
+	td->td_kstack_pages = 0;
+	if (pages == KSTACK_PAGES && kstacks <= kstack_cache_size) {
+		ks_ce = (struct kstack_cache_entry *)ks;
+		ks_ce->ksobj = ksobj;
+		mtx_lock(&kstack_cache_mtx);
+		ks_ce->next_ks_entry = kstack_cache;
+		kstack_cache = ks_ce;
+		mtx_unlock(&kstack_cache_mtx);
+		return;
+	}
+	vm_thread_stack_dispose(ksobj, ks, pages);
+}
+
+static void
+vm_thread_stack_lowmem(void *nulll)
+{
+	struct kstack_cache_entry *ks_ce, *ks_ce1;
+
+	mtx_lock(&kstack_cache_mtx);
+	ks_ce = kstack_cache;
+	kstack_cache = NULL;
+	mtx_unlock(&kstack_cache_mtx);
+
+	while (ks_ce != NULL) {
+		ks_ce1 = ks_ce;
+		ks_ce = ks_ce->next_ks_entry;
+
+		vm_thread_stack_dispose(ks_ce1->ksobj, (vm_offset_t)ks_ce1,
+		    KSTACK_PAGES);
+	}
+}
+
+static void
+kstack_cache_init(void *nulll)
+{
+
+	EVENTHANDLER_REGISTER(vm_lowmem, vm_thread_stack_lowmem, NULL,
+	    EVENTHANDLER_PRI_ANY);
+}
+
+MTX_SYSINIT(kstack_cache, &kstack_cache_mtx, "kstkch", MTX_DEF);
+SYSINIT(vm_kstacks, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, kstack_cache_init, NULL);
+
 /*
  * Allow a thread's kernel stack to be paged out.
  */
@@ -467,37 +550,6 @@ vm_thread_swapin(struct thread *td)
 	cpu_thread_swapin(td);
 }
 
-/*
- * Set up a variable-sized alternate kstack.
- */
-int
-vm_thread_new_altkstack(struct thread *td, int pages)
-{
-
-	td->td_altkstack = td->td_kstack;
-	td->td_altkstack_obj = td->td_kstack_obj;
-	td->td_altkstack_pages = td->td_kstack_pages;
-
-	return (vm_thread_new(td, pages));
-}
-
-/*
- * Restore the original kstack.
- */
-void
-vm_thread_dispose_altkstack(struct thread *td)
-{
-
-	vm_thread_dispose(td);
-
-	td->td_kstack = td->td_altkstack;
-	td->td_kstack_obj = td->td_altkstack_obj;
-	td->td_kstack_pages = td->td_altkstack_pages;
-	td->td_altkstack = 0;
-	td->td_altkstack_obj = NULL;
-	td->td_altkstack_pages = 0;
-}
-
 /*
  * Implement fork's actions on an address space.
  * Here we arrange for the address space to be copied or referenced,
diff --git a/sys/xdr/xdr_mbuf.c b/sys/xdr/xdr_mbuf.c
index ab79e19e29a..bcfdb1866c0 100644
--- a/sys/xdr/xdr_mbuf.c
+++ b/sys/xdr/xdr_mbuf.c
@@ -282,6 +282,8 @@ xdrmbuf_inline(XDR *xdrs, u_int len)
 	size_t available;
 	char *p;
 
+	if (!m)
+		return (0);
 	if (xdrs->x_op == XDR_ENCODE) {
 		available = M_TRAILINGSPACE(m) + (m->m_len - xdrs->x_handy);
 	} else {
diff --git a/sys/xen/xenbus/xenbus_probe.c b/sys/xen/xenbus/xenbus_probe.c
index f930c8ff71b..f04f8eca463 100644
--- a/sys/xen/xenbus/xenbus_probe.c
+++ b/sys/xen/xenbus/xenbus_probe.c
@@ -348,9 +348,7 @@ xenbus_devices_changed(struct xenbus_watch *watch,
 	if (p)
 		*p = 0;
 
-	newbus_xlock();
 	xenbus_add_device(dev, bus, type, id);
-	newbus_xunlock();
 	taskqueue_enqueue(taskqueue_thread, &sc->xs_probechildren);
 out:
 	free(node, M_DEVBUF);
@@ -363,9 +361,7 @@ xenbus_attach_deferred(void *arg)
 	struct xenbus_softc *sc = device_get_softc(dev);
 	int error;
 	
-	newbus_xlock();
 	error = xenbus_enumerate_bus(dev, "device");
-	newbus_xunlock();
 	if (error)
 		return;
 	xenbus_probe_children(dev);
diff --git a/tools/kerneldoc/subsys/Dependencies b/tools/kerneldoc/subsys/Dependencies
index 6307b485b48..537bdbaa179 100644
--- a/tools/kerneldoc/subsys/Dependencies
+++ b/tools/kerneldoc/subsys/Dependencies
@@ -6,15 +6,15 @@
 
 $(.OBJDIR)/dev_sound/dev_sound.tag:	$(.OBJDIR)/dev_pci/dev_pci.tag \
 					$(.OBJDIR)/dev_usb/dev_usb.tag \
-					$(.OBJDIR)/ac97_if.h \
-					$(.OBJDIR)/channel_if.h \
-					$(.OBJDIR)/feeder_if.h \
-					$(.OBJDIR)/mixer_if.h
+					$(.OBJDIR)/include/ac97_if.h \
+					$(.OBJDIR)/include/channel_if.h \
+					$(.OBJDIR)/include/feeder_if.h \
+					$(.OBJDIR)/include/mixer_if.h
 
 $(.OBJDIR)/dev_usb/dev_usb.tag:	$(.OBJDIR)/dev_pci/dev_pci.tag \
-				$(.OBJDIR)/usb_if.h
+				$(.OBJDIR)/include/usb_if.h
 
-$(.OBJDIR)/dev_pci/dev_pci.tag:	$(.OBJDIR)/pci_if.h \
-				$(.OBJDIR)/pcib_if.h \
-				$(.OBJDIR)/bus_if.h
+$(.OBJDIR)/dev_pci/dev_pci.tag:	$(.OBJDIR)/include/pci_if.h \
+				$(.OBJDIR)/include/pcib_if.h \
+				$(.OBJDIR)/include/bus_if.h
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-cam b/tools/kerneldoc/subsys/Doxyfile-cam
index 006cdcb12dd..7646cc06d14 100644
--- a/tools/kerneldoc/subsys/Doxyfile-cam
+++ b/tools/kerneldoc/subsys/Doxyfile-cam
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-crypto b/tools/kerneldoc/subsys/Doxyfile-crypto
index f3e6c5a7c08..404993d5171 100644
--- a/tools/kerneldoc/subsys/Doxyfile-crypto
+++ b/tools/kerneldoc/subsys/Doxyfile-crypto
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-dev_pci b/tools/kerneldoc/subsys/Doxyfile-dev_pci
index d8d91a7ca9c..6b6f96460cc 100644
--- a/tools/kerneldoc/subsys/Doxyfile-dev_pci
+++ b/tools/kerneldoc/subsys/Doxyfile-dev_pci
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-dev_sound b/tools/kerneldoc/subsys/Doxyfile-dev_sound
index 5a55398759e..724b6f9396f 100644
--- a/tools/kerneldoc/subsys/Doxyfile-dev_sound
+++ b/tools/kerneldoc/subsys/Doxyfile-dev_sound
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-dev_usb b/tools/kerneldoc/subsys/Doxyfile-dev_usb
index 731a018d82e..ad84bb5fa27 100644
--- a/tools/kerneldoc/subsys/Doxyfile-dev_usb
+++ b/tools/kerneldoc/subsys/Doxyfile-dev_usb
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-geom b/tools/kerneldoc/subsys/Doxyfile-geom
index 374665f3f6e..d7e4041f13c 100644
--- a/tools/kerneldoc/subsys/Doxyfile-geom
+++ b/tools/kerneldoc/subsys/Doxyfile-geom
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-kern b/tools/kerneldoc/subsys/Doxyfile-kern
index 5857465d76a..87f3c5a4e27 100644
--- a/tools/kerneldoc/subsys/Doxyfile-kern
+++ b/tools/kerneldoc/subsys/Doxyfile-kern
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-libkern b/tools/kerneldoc/subsys/Doxyfile-libkern
index 42c53de0d9d..f0f38d6caa9 100644
--- a/tools/kerneldoc/subsys/Doxyfile-libkern
+++ b/tools/kerneldoc/subsys/Doxyfile-libkern
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-linux b/tools/kerneldoc/subsys/Doxyfile-linux
index 3f210479444..a239d55496a 100644
--- a/tools/kerneldoc/subsys/Doxyfile-linux
+++ b/tools/kerneldoc/subsys/Doxyfile-linux
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
@@ -12,6 +12,8 @@ EXTRACT_ALL            = YES    # for undocumented src, no warnings enabled
 # configuration options related to the input files
 #---------------------------------------------------------------------------
 INPUT                  = $(DOXYGEN_SRC_PATH)/compat/linux \
+			 $(DOXYGEN_SRC_PATH)/compat/linprocfs \
+			 $(DOXYGEN_SRC_PATH)/compat/linsysfs \
                          $(DOXYGEN_LINUX_PATH) $(NOTREVIEWED)
 
 GENERATE_TAGFILE       = linux/linux.tag
diff --git a/tools/kerneldoc/subsys/Doxyfile-net80211 b/tools/kerneldoc/subsys/Doxyfile-net80211
index 869f06b4af7..7e622cf937d 100644
--- a/tools/kerneldoc/subsys/Doxyfile-net80211
+++ b/tools/kerneldoc/subsys/Doxyfile-net80211
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-netgraph b/tools/kerneldoc/subsys/Doxyfile-netgraph
index 5641cb08bf9..585725edfb6 100644
--- a/tools/kerneldoc/subsys/Doxyfile-netgraph
+++ b/tools/kerneldoc/subsys/Doxyfile-netgraph
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-netinet b/tools/kerneldoc/subsys/Doxyfile-netinet
index 7fedb3db11b..c9ed7e0df09 100644
--- a/tools/kerneldoc/subsys/Doxyfile-netinet
+++ b/tools/kerneldoc/subsys/Doxyfile-netinet
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-netinet6 b/tools/kerneldoc/subsys/Doxyfile-netinet6
index 2f902d3a00c..0c9e5d2bf0c 100644
--- a/tools/kerneldoc/subsys/Doxyfile-netinet6
+++ b/tools/kerneldoc/subsys/Doxyfile-netinet6
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-netipsec b/tools/kerneldoc/subsys/Doxyfile-netipsec
index b7038f2440c..75f4685e0a6 100644
--- a/tools/kerneldoc/subsys/Doxyfile-netipsec
+++ b/tools/kerneldoc/subsys/Doxyfile-netipsec
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-opencrypto b/tools/kerneldoc/subsys/Doxyfile-opencrypto
index 33f1654d9d8..d27501b5bf0 100644
--- a/tools/kerneldoc/subsys/Doxyfile-opencrypto
+++ b/tools/kerneldoc/subsys/Doxyfile-opencrypto
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Doxyfile-vm b/tools/kerneldoc/subsys/Doxyfile-vm
index 22bb8c56cc9..daa4224db36 100644
--- a/tools/kerneldoc/subsys/Doxyfile-vm
+++ b/tools/kerneldoc/subsys/Doxyfile-vm
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
diff --git a/tools/kerneldoc/subsys/Makefile b/tools/kerneldoc/subsys/Makefile
index f0e2613132c..0153d58a335 100644
--- a/tools/kerneldoc/subsys/Makefile
+++ b/tools/kerneldoc/subsys/Makefile
@@ -10,49 +10,7 @@ TARGET_ARCH?=	${MACHINE_ARCH}
 S?=/usr/src/sys
 LOCALBASE?=/usr/local
 
-MFILES+=dev/acpica/acpi_if.m
-MFILES+=dev/ata/ata_if.m
-MFILES+=dev/eisa/eisa_if.m
-MFILES+=dev/iicbus/iicbb_if.m
-MFILES+=dev/iicbus/iicbus_if.m
-MFILES+=dev/mii/miibus_if.m
-MFILES+=dev/mmc/mmcbr_if.m
-MFILES+=dev/mmc/mmcbus_if.m
-MFILES+=dev/ofw/ofw_bus_if.m
-MFILES+=dev/pccard/card_if.m
-MFILES+=dev/pccard/power_if.m
-MFILES+=dev/pci/pci_if.m
-MFILES+=dev/pci/pcib_if.m
-MFILES+=dev/ppbus/ppbus_if.m
-MFILES+=dev/scc/scc_if.m
-MFILES+=dev/smbus/smbus_if.m
-MFILES+=dev/sound/midi/mpu_if.m
-MFILES+=dev/sound/midi/mpufoi_if.m
-MFILES+=dev/sound/midi/synth_if.m
-MFILES+=dev/sound/pcm/ac97_if.m
-MFILES+=dev/sound/pcm/channel_if.m
-MFILES+=dev/sound/pcm/feeder_if.m
-MFILES+=dev/sound/pcm/mixer_if.m
-MFILES+=dev/spibus/spibus_if.m
-MFILES+=dev/uart/uart_if.m
-MFILES+=dev/usb/usb_if.m
-MFILES+=geom/part/g_part_if.m
-MFILES+=isa/isa_if.m
-MFILES+=kern/bus_if.m
-MFILES+=kern/clock_if.m
-MFILES+=kern/cpufreq_if.m
-MFILES+=kern/device_if.m
-MFILES+=kern/linker_if.m
-MFILES+=kern/serdev_if.m
-MFILES+=libkern/iconv_converter_if.m
-MFILES+=opencrypto/cryptodev_if.m
-MFILES+=pc98/pc98/canbus_if.m
-MFILES+=pci/agp_if.m
-MFILES+=powerpc/powerpc/mmu_if.m
-MFILES+=powerpc/powerpc/pic_if.m
-MFILES+=sparc64/pci/ofw_pci_if.m
-MFILES+=sun4v/mdesc/mdesc_bus_if.m
-
+MFILES!= find ${S} -name \*.m | sed -e 's:${S}/::g'
 HFILES=	${MFILES:T:S/.m$/.h/}
 AWK?=	awk
 
@@ -73,16 +31,16 @@ usage:
 all:	${ALL}
 pdf-all:${PDF_ALL}
 
-mfiles: ${HFILES:S/^/${.OBJDIR}\//}
+mfiles: ${HFILES:S/^/${.OBJDIR}\/include\//}
 
-DOXYGEN_DEST_PATH=	${.OBJDIR}
-DOXYGEN_LATEX_DEST_PATH=${.OBJDIR}
-DOXYGEN_PDF_DEST_PATH=	${.OBJDIR}
+DOXYGEN_DEST_PATH?=	${.OBJDIR}
+DOXYGEN_LATEX_DEST_PATH?=${.OBJDIR}
+DOXYGEN_PDF_DEST_PATH?=	${.OBJDIR}
 
-.if exists{${S}/${TARGET_ARCH}/linux}
+.if exists(${S}/${TARGET_ARCH}/linux)
 DOXYGEN_LINUX_PATH=	${S}/${TARGET_ARCH}/linux
 .endif
-.if exists{${S}/${TARGET_ARCH}/linux32}
+.if exists(${S}/${TARGET_ARCH}/linux32)
 DOXYGEN_LINUX_PATH+=	${S}/${TARGET_ARCH}/linux32
 .endif
 
@@ -98,13 +56,13 @@ ${.OBJDIR}/${target}/${target}.tag:
 		env DOXYGEN_INCLUDE_PATH=${.CURDIR} \
 		    DOXYGEN_SRC_PATH=${S}  \
 		    DOXYGEN_DEST_PATH=${DOXYGEN_DEST_PATH} \
-		    DOXYGEN_SRC_INCLUDE_PATH="${S}/sys ${S}/../include ${S}/${TARGET_ARCH}/include" \
+		    DOXYGEN_SRC_INCLUDE_PATH="${S}/sys ${S}/../include ${S}/${TARGET_ARCH}/include ${.OBJDIR}/include" \
 		    DOXYGEN_TARGET_ARCH=${TARGET_ARCH} \
 		    DOXYGEN_LINUX_PATH=${DOXYGEN_LINUX_PATH} \
 		    NOTREVIEWED=${.CURDIR}/notreviewed.dox \
 		    PATH=${LOCALBASE}/bin:${PATH} \
 			doxygen ${.CURDIR}/Doxyfile-${target}
-	@echo "API docs for ${target} are now available in ${.OBJDIR}/${target}/." | /usr/bin/fmt
+	@echo "API docs for ${target} are now available in ${DOXYGEN_DEST_PATH}/${target}/." | /usr/bin/fmt
 
 pdf-${target}:	${.OBJDIR}/${target}/${target}.tag
 	@cd ${DOXYGEN_LATEX_DEST_PATH}/${target}/latex && ${MAKE} refman.pdf && cp refman.pdf ${DOXYGEN_PDF_DEST_PATH}/${target}.pdf
@@ -117,10 +75,12 @@ clean-${target}:
 	rm -rf ${DOXYGEN_DEST_PATH}/${target} ${.OBJDIR}/${target}
 .endfor
 
+CLEANDIRS+=	${.OBJDIR}/include
 .for file in ${MFILES}
-CLEANDIRS+=     ${.OBJDIR}/${file:T:S/.m$/.h/}
-${.OBJDIR}/${file:T:S/.m$/.h/}: ${S}/${file}
-	cd ${.OBJDIR}; ${AWK} -f $S/tools/makeobjops.awk ${S}/${file} -h
+CLEANFILES+=     ${.OBJDIR}/include/${file:T:S/.m$/.h/}
+${.OBJDIR}/include/${file:T:S/.m$/.h/}: ${S}/${file}
+	@mkdir -p ${.OBJDIR}/include
+	cd ${.OBJDIR}/include && ${AWK} -f $S/tools/makeobjops.awk ${S}/${file} -h
 .endfor
 
 #
diff --git a/tools/kerneldoc/subsys/common-Doxyfile b/tools/kerneldoc/subsys/common-Doxyfile
index 537241877b1..cdac7abc994 100644
--- a/tools/kerneldoc/subsys/common-Doxyfile
+++ b/tools/kerneldoc/subsys/common-Doxyfile
@@ -1,14 +1,14 @@
-# Doxyfile 1.4.1
+# Doxyfile 1.5.2
 
 # $FreeBSD$
 
 #---------------------------------------------------------------------------
 # Project related configuration options
 #---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
 PROJECT_NUMBER         = 
 CREATE_SUBDIRS         = YES
 OUTPUT_LANGUAGE        = English
-USE_WINDOWS_ENCODING   = NO
 BRIEF_MEMBER_DESC      = YES
 REPEAT_BRIEF           = YES
 ABBREVIATE_BRIEF       = "The $name class" \
@@ -25,18 +25,20 @@ ABBREVIATE_BRIEF       = "The $name class" \
 ALWAYS_DETAILED_SEC    = NO
 INLINE_INHERITED_MEMB  = NO
 FULL_PATH_NAMES        = YES
-STRIP_FROM_PATH        = 
+STRIP_FROM_PATH        = $(DOXYGEN_SRC_PATH) $(DOXYGEN_DEST_PATH)
 STRIP_FROM_INC_PATH    = 
 SHORT_NAMES            = NO
 JAVADOC_AUTOBRIEF      = NO
 MULTILINE_CPP_IS_BRIEF = NO
-DETAILS_AT_TOP         = NO
 INHERIT_DOCS           = YES
-DISTRIBUTE_GROUP_DOC   = NO
+SEPARATE_MEMBER_PAGES  = NO
 TAB_SIZE               = 8
 ALIASES                = 
 OPTIMIZE_OUTPUT_FOR_C  = YES
 OPTIMIZE_OUTPUT_JAVA   = NO
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+DISTRIBUTE_GROUP_DOC   = NO
 SUBGROUPING            = YES
 #---------------------------------------------------------------------------
 # Build related configuration options
@@ -76,9 +78,11 @@ WARN_IF_DOC_ERROR      = YES
 WARN_NO_PARAMDOC       = NO
 WARN_FORMAT            = "$file:$line: $text"
 WARN_LOGFILE           = 
+
 #---------------------------------------------------------------------------
 # configuration options related to the input files
 #---------------------------------------------------------------------------
+INPUT_ENCODING         = UTF-8
 FILE_PATTERNS          = *.c \
                          *.cc \
                          *.cxx \
@@ -120,7 +124,8 @@ FILE_PATTERNS          = *.c \
 RECURSIVE              = YES
 EXCLUDE                = 
 EXCLUDE_SYMLINKS       = NO
-EXCLUDE_PATTERNS       = */.\#*
+EXCLUDE_PATTERNS       = */.\#* */.svn/*
+EXCLUDE_SYMBOLS        = 
 EXAMPLE_PATH           = 
 EXAMPLE_PATTERNS       = *
 EXAMPLE_RECURSIVE      = NO
@@ -136,11 +141,13 @@ INLINE_SOURCES         = NO
 STRIP_CODE_COMMENTS    = YES
 REFERENCED_BY_RELATION = YES
 REFERENCES_RELATION    = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
 VERBATIM_HEADERS       = YES
 #---------------------------------------------------------------------------
 # configuration options related to the alphabetical class index
 #---------------------------------------------------------------------------
-ALPHABETICAL_INDEX     = NO
+ALPHABETICAL_INDEX     = YES
 COLS_IN_ALPHA_INDEX    = 5
 IGNORE_PREFIX          = 
 #---------------------------------------------------------------------------
@@ -220,12 +227,13 @@ ENABLE_PREPROCESSING   = YES
 MACRO_EXPANSION        = YES
 EXPAND_ONLY_PREDEF     = YES
 SEARCH_INCLUDES        = YES
-INCLUDE_PATH           = $(DOXYGEN_SRC_INCLUDE_PATH) .
+INCLUDE_PATH           = $(DOXYGEN_SRC_INCLUDE_PATH) \
+                         .
 INCLUDE_FILE_PATTERNS  = *.h
-PREDEFINED             = "_KERNEL" \
-			 "__FreeBSD__=7" \
-			 "__${TARGET_ARCH}__=1" \
-			 "__${TARGET_ARCH}=1"
+PREDEFINED             = _KERNEL \
+                         __FreeBSD__=9 \
+                         __${TARGET_ARCH}__=1 \
+                         __${TARGET_ARCH}=1
 EXPAND_AS_DEFINED      = 
 SKIP_FUNCTION_MACROS   = YES
 #---------------------------------------------------------------------------
@@ -238,6 +246,7 @@ PERL_PATH              = /usr/bin/perl
 # Configuration options related to the dot tool   
 #---------------------------------------------------------------------------
 CLASS_DIAGRAMS         = NO
+MSCGEN_PATH            = 
 HIDE_UNDOC_RELATIONS   = YES
 HAVE_DOT               = YES
 CLASS_GRAPH            = YES
@@ -248,14 +257,13 @@ TEMPLATE_RELATIONS     = NO
 INCLUDE_GRAPH          = YES
 INCLUDED_BY_GRAPH      = YES
 CALL_GRAPH             = YES
+CALLER_GRAPH           = YES
 GRAPHICAL_HIERARCHY    = YES
 DIRECTORY_GRAPH        = YES
 DOT_IMAGE_FORMAT       = png
 DOT_PATH               = 
 DOTFILE_DIRS           = 
-MAX_DOT_GRAPH_WIDTH    = 1024
-MAX_DOT_GRAPH_HEIGHT   = 1024
-MAX_DOT_GRAPH_DEPTH    = 1000
+DOT_GRAPH_MAX_NODES    = 50
 DOT_TRANSPARENT        = NO
 DOT_MULTI_TARGETS      = YES
 GENERATE_LEGEND        = YES
diff --git a/tools/regression/acltools/00.t b/tools/regression/acltools/00.t
index d2809f42f10..c76b39efb4f 100644
--- a/tools/regression/acltools/00.t
+++ b/tools/regression/acltools/00.t
@@ -1,5 +1,32 @@
 #!/bin/sh
 #
+# Copyright (c) 2008, 2009 Edward Tomasz Napierała 
+# 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$
+#
+
 # This is a wrapper script to run tools-posix.test.
 #
 # If any of the tests fails, here is how to debug it: go to
@@ -9,9 +36,6 @@
 # /usr/src/tools/regression/acltools/run /usr/src/tools/regression/acltools/tools-posix.test
 #
 # Output should be obvious.
-#
-# $FreeBSD$
-#
 
 echo "1..4"
 
@@ -59,4 +83,3 @@ rmdir $MNT
 mdconfig -du $MD
 
 echo "ok 4"
-
diff --git a/tools/regression/acltools/tools-posix.test b/tools/regression/acltools/tools-posix.test
index 9ce94cdb5fd..4741db383fd 100644
--- a/tools/regression/acltools/tools-posix.test
+++ b/tools/regression/acltools/tools-posix.test
@@ -1,11 +1,36 @@
+# Copyright (c) 2008, 2009 Edward Tomasz Napierała 
+# 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$
+#
+
 # This is a tools-level test for POSIX.1e ACL functionality.  Run it as root
 # using ACL-enabled kernel:
 #
 # /usr/src/tools/regression/acltools/run /usr/src/tools/regression/acltools/tools-posix.test
 #
 # WARNING: Creates files in unsafe way.
-#
-# $FreeBSD$
 
 $ whoami
 > root
@@ -13,7 +38,7 @@ $ umask 022
 
 # Smoke test for getfacl(1).
 $ touch xxx
-$ getfacl xxx
+$ getfacl -n xxx
 > # file: xxx
 > # owner: root
 > # group: wheel
@@ -27,7 +52,7 @@ $ getfacl -q xxx
 > other::r--
 
 $ setfacl -m u:42:r,g:43:w xxx
-$ getfacl xxx
+$ getfacl -n xxx
 > # file: xxx
 > # owner: root
 > # group: wheel
@@ -77,9 +102,8 @@ $ getfacl -h lll
 > mask::rwx
 > other::r-x
 
-# XXX: Why doesn't ls(1) print '+' for symbolic links with ACL set?
 $ ls -l lll | cut -d' ' -f1
-> lrwxrwxr-x
+> lrwxrwxr-x+
 
 # Check whether the original file is left untouched.
 $ ls -l xxx | cut -d' ' -f1
@@ -99,8 +123,32 @@ $ getfacl xxx
 > mask::rw-
 > other::r--
 
+$ setfacl -m u:42:r xxx
+$ getfacl -n xxx
+> # file: xxx
+> # owner: root
+> # group: wheel
+> user::rw-
+> user:42:r--
+> group::r--
+> group:43:-w-
+> mask::rw-
+> other::r--
+
+# Test removing entries by number.
+$ setfacl -x 1 xxx
+$ getfacl -n xxx
+> # file: xxx
+> # owner: root
+> # group: wheel
+> user::rw-
+> group::r--
+> group:43:-w-
+> mask::rw-
+> other::r--
+
 $ setfacl -m g:43:r xxx
-$ getfacl xxx
+$ getfacl -n xxx
 > # file: xxx
 > # owner: root
 > # group: wheel
@@ -118,7 +166,7 @@ $ ls -l yyy | cut -d' ' -f1
 # Make sure it does with the "-p" flag.
 $ rm yyy
 $ cp -p xxx yyy
-$ getfacl yyy
+$ getfacl -n yyy
 > # file: yyy
 > # owner: root
 > # group: wheel
@@ -133,7 +181,7 @@ $ rm yyy
 # Test removing entries by...  by example?
 $ setfacl -m u:42:r,g:43:w xxx
 $ setfacl -x u:42: xxx
-$ getfacl xxx
+$ getfacl -n xxx
 > # file: xxx
 > # owner: root
 > # group: wheel
@@ -145,7 +193,7 @@ $ getfacl xxx
 
 # Test setfacl -b.
 $ setfacl -b xxx
-$ getfacl xxx
+$ getfacl -n xxx
 > # file: xxx
 > # owner: root
 > # group: wheel
@@ -158,7 +206,7 @@ $ ls -l xxx | cut -d' ' -f1
 > -rw-r--r--+
 
 $ setfacl -nb xxx
-$ getfacl xxx
+$ getfacl -n xxx
 > # file: xxx
 > # owner: root
 > # group: wheel
@@ -178,7 +226,7 @@ $ ls -l xxx yyy zzz | cut -d' ' -f1
 > -rw-r--r--
 
 $ setfacl -m u:42:x,g:43:w nnn xxx yyy zzz
-> setfacl: stat() of nnn failed: No such file or directory
+> setfacl: nnn: stat() failed: No such file or directory
 
 $ ls -l nnn xxx yyy zzz | cut -d' ' -f1
 > ls: nnn: No such file or directory
@@ -186,8 +234,8 @@ $ ls -l nnn xxx yyy zzz | cut -d' ' -f1
 > -rw-rwxr--+
 > -rw-rwxr--+
 
-$ getfacl -q nnn xxx yyy zzz
-> getfacl: nnn: No such file or directory
+$ getfacl -nq nnn xxx yyy zzz
+> getfacl: nnn: stat() failed: No such file or directory
 > user::rw-
 > user:42:--x
 > group::r--
@@ -210,7 +258,7 @@ $ getfacl -q nnn xxx yyy zzz
 > other::r--
 
 $ setfacl -b nnn xxx yyy zzz
-> setfacl: stat() of nnn failed: No such file or directory
+> setfacl: nnn: stat() failed: No such file or directory
 
 $ ls -l nnn xxx yyy zzz | cut -d' ' -f1
 > ls: nnn: No such file or directory
@@ -219,7 +267,7 @@ $ ls -l nnn xxx yyy zzz | cut -d' ' -f1
 > -rw-r--r--+
 
 $ setfacl -bn nnn xxx yyy zzz
-> setfacl: stat() of nnn failed: No such file or directory
+> setfacl: nnn: stat() failed: No such file or directory
 
 $ ls -l nnn xxx yyy zzz | cut -d' ' -f1
 > ls: nnn: No such file or directory
@@ -233,7 +281,7 @@ $ rm xxx yyy zzz
 $ touch xxx
 $ setfacl -m u:42:rwx,g:43:rwx xxx
 $ chmod 600 xxx
-$ getfacl xxx
+$ getfacl -n xxx
 > # file: xxx
 > # owner: root
 > # group: wheel
@@ -245,7 +293,7 @@ $ getfacl xxx
 > other::---
 
 $ chmod 060 xxx
-$ getfacl xxx
+$ getfacl -n xxx
 > # file: xxx
 > # owner: root
 > # group: wheel
@@ -259,7 +307,7 @@ $ getfacl xxx
 # Test default ACLs.
 $ umask 022
 $ mkdir ddd
-$ getfacl -q ddd
+$ getfacl -qn ddd
 > user::rwx
 > group::r-x
 > other::r-x
@@ -269,7 +317,7 @@ $ ls -l | grep ddd | cut -d' ' -f1
 
 $ getfacl -dq ddd
 $ setfacl -dm u::rwx,g::rx,o::rx,mask::rwx ddd
-$ getfacl -dq ddd
+$ getfacl -dqn ddd
 > user::rwx
 > group::r-x
 > mask::rwx
@@ -281,7 +329,7 @@ $ ls -l | grep ddd | cut -d' ' -f1
 
 $ setfacl -dm g:42:rwx,u:42:r ddd
 $ setfacl -dm g::w ddd
-$ getfacl -dq ddd
+$ getfacl -dqn ddd
 > user::rwx
 > user:42:r--
 > group::-w-
@@ -290,7 +338,7 @@ $ getfacl -dq ddd
 > other::r-x
 
 $ setfacl -dx group:42: ddd
-$ getfacl -dq ddd
+$ getfacl -dqn ddd
 > user::rwx
 > user:42:r--
 > group::-w-
@@ -387,3 +435,19 @@ $ ls -l fff | cut -d' ' -f1
 
 $ rm fff
 
+# Test if we deal properly with device files.
+$ mknod bbb b 1 1
+$ setfacl -m u:42:r,g:43:w bbb
+> setfacl: bbb: acl_get_file() failed: Operation not supported
+$ ls -l bbb | cut -d' ' -f1
+> brw-r--r--
+
+$ rm bbb
+
+$ mknod ccc c 1 1
+$ setfacl -m u:42:r,g:43:w ccc
+> setfacl: ccc: acl_get_file() failed: Operation not supported
+$ ls -l ccc | cut -d' ' -f1
+> crw-r--r--
+
+$ rm ccc
diff --git a/tools/regression/fstest/Makefile b/tools/regression/fstest/Makefile
index ae982b66ed8..13c62e97f7d 100644
--- a/tools/regression/fstest/Makefile
+++ b/tools/regression/fstest/Makefile
@@ -4,7 +4,7 @@ OSTYPE=$(shell uname)
 
 ifeq "${OSTYPE}" "FreeBSD"
 CFLAGS += -D__OS_FreeBSD__
-CFLAGS += -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_LCHFLAGS
+CFLAGS += -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_LCHFLAGS -DHAS_FREEBSD_ACL
 endif
 
 ifeq "${OSTYPE}" "SunOS"
diff --git a/tools/regression/fstest/fstest.c b/tools/regression/fstest/fstest.c
index 798c70222c4..e058e0a20d3 100644
--- a/tools/regression/fstest/fstest.c
+++ b/tools/regression/fstest/fstest.c
@@ -45,6 +45,9 @@
 #define	stat64	stat
 #define	lstat64	lstat
 #endif
+#ifdef HAS_FREEBSD_ACL
+#include 
+#endif
 
 #ifndef ALLPERMS
 #define	ALLPERMS	(S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
@@ -75,7 +78,12 @@ enum action {
 	ACTION_TRUNCATE,
 	ACTION_STAT,
 	ACTION_LSTAT,
-	ACTION_PATHCONF
+	ACTION_PATHCONF,
+#ifdef HAS_FREEBSD_ACL
+	ACTION_PREPENDACL,
+	ACTION_READACL,
+#endif
+	ACTION_WRITE,
 };
 
 #define	TYPE_NONE	0x0000
@@ -118,6 +126,11 @@ static struct syscall_desc syscalls[] = {
 	{ "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
 	{ "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
 	{ "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+#ifdef HAS_FREEBSD_ACL
+	{ "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
+	{ "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } },
+#endif
+	{ "write", ACTION_WRITE, { TYPE_STRING, TYPE_NONE } },
 	{ NULL, -1, { TYPE_NONE } }
 };
 
@@ -397,6 +410,11 @@ call_syscall(struct syscall_desc *scall, char *argv[])
 		char *str;
 		long long num;
 	} args[MAX_ARGS];
+#ifdef HAS_FREEBSD_ACL
+	int entry_id = ACL_FIRST_ENTRY;
+	acl_t acl, newacl;
+	acl_entry_t entry, newentry;
+#endif
 
 	/*
 	 * Verify correctness of the arguments.
@@ -540,6 +558,48 @@ call_syscall(struct syscall_desc *scall, char *argv[])
 		rval = -1;
 		break;
 	    }
+#ifdef HAS_FREEBSD_ACL
+	case ACTION_PREPENDACL:
+		rval = -1;
+
+		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
+		if (acl == NULL)
+			break;
+
+		newacl = acl_from_text(STR(1));
+		if (acl == NULL)
+			break;
+
+		while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
+			entry_id = ACL_NEXT_ENTRY;
+
+			if (acl_create_entry_np(&acl, &entry, 0))
+				break;
+
+			if (acl_copy_entry(entry, newentry))
+				break;
+		}
+
+		rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
+		break;
+
+	case ACTION_READACL:
+		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
+		if (acl == NULL)
+			rval = -1;
+		else
+			rval = 0;
+		break;
+#endif
+
+	case ACTION_WRITE:
+		rval = open(STR(0), O_WRONLY);
+		if (rval < 0)
+			break;
+
+		rval = write(rval, "x", 1);
+		break;
+
 	default:
 		fprintf(stderr, "unsupported syscall\n");
 		exit(1);
diff --git a/tools/regression/fstest/tests/granular/00.t b/tools/regression/fstest/tests/granular/00.t
new file mode 100644
index 00000000000..84533bd0b44
--- /dev/null
+++ b/tools/regression/fstest/tests/granular/00.t
@@ -0,0 +1,110 @@
+#!/bin/sh
+# $FreeBSD$
+
+desc="NFSv4 granular permissions checking - WRITE_DATA vs APPEND_DATA on directories"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..49"
+
+n0=`namegen`
+n1=`namegen`
+n2=`namegen`
+n3=`namegen`
+
+expect 0 mkdir ${n2} 0755
+expect 0 mkdir ${n3} 0777
+cdir=`pwd`
+cd ${n2}
+
+# Tests 2..7 - check out whether root user can do stuff.
+# Can create files?
+expect 0 create ${n0} 0644
+
+# Can create symlinks?
+expect 0 link ${n0} ${n1}
+expect 0 unlink ${n1}
+expect 0 unlink ${n0}
+
+# Can create directories?
+expect 0 mkdir ${n0} 0755
+expect 0 rmdir ${n0}
+
+# Check whether user 65534 is permitted to create and remove
+# files, but not subdirectories.
+expect 0 prependacl . user:65534:write_data::allow,user:65534:append_data::deny
+
+# Can create files?
+expect 0 -u 65534 -g 65534 create ${n0} 0644
+
+# Can create symlinks?
+expect 0 -u 65534 -g 65534 link ${n0} ${n1}
+expect 0 -u 65534 -g 65534 unlink ${n1}
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# Can create directories?
+expect EACCES -u 65534 -g 65534 mkdir ${n0} 0755
+expect ENOENT -u 65534 -g 65534 rmdir ${n0}
+expect 0 mkdir ${n0} 0755
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+# Can move files from other directory?
+expect 0 create ../${n3}/${n1} 0644
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n1} ${n0}
+
+# Can move files from other directory overwriting existing files?
+expect 0 create ../${n3}/${n1} 0644
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n1} ${n0}
+
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# Can move directories from other directory?
+expect 0 mkdir ../${n3}/${n1} 0777
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n1} ${n0}
+
+# Can move directories from other directory overwriting existing directory?
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n1} ${n0}
+expect 0 -u 65534 -g 65534 rmdir ../${n3}/${n1}
+
+# Check whether user 65534 is permitted to create
+# subdirectories, but not files - and to remove neither of them.
+expect 0 prependacl . user:65534:write_data::deny,user:65534:append_data::allow
+
+# Can create files?
+expect EACCES -u 65534 -g 65534 create ${n0} 0644
+
+# Can create symlinks?
+expect 0 create ${n0} 0644
+expect EACCES -u 65534 -g 65534 link ${n0} ${n1}
+expect ENOENT -u 65534 -g 65534 unlink ${n1}
+expect EACCES -u 65534 -g 65534 unlink ${n0}
+expect 0 unlink ${n0}
+
+# Can create directories?
+expect 0 -u 65534 -g 65534 mkdir ${n0} 0755
+expect EACCES -u 65534 -g 65534 rmdir ${n0}
+expect 0 rmdir ${n0}
+
+# Can move files from other directory?
+expect 0 create ../${n3}/${n1} 0644
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n1} ${n0}
+
+# Can move files from other directory overwriting existing files?
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n1} ${n0}
+expect 0 -u 65534 -g 65534 unlink ../${n3}/${n1}
+
+# Can move directories from other directory?
+expect 0 mkdir ../${n3}/${n1} 0777
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n1} ${n0}
+
+# Can move directories from other directory overwriting existing directory?
+expect 0 mkdir ../${n3}/${n1} 0777
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n1} ${n0}
+expect 0 prependacl . user:65534:delete_child::allow
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n1} ${n0}
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+cd ${cdir}
+expect 0 rmdir ${n2}
+expect 0 rmdir ${n3}
diff --git a/tools/regression/fstest/tests/granular/01.t b/tools/regression/fstest/tests/granular/01.t
new file mode 100644
index 00000000000..f1bac1b0214
--- /dev/null
+++ b/tools/regression/fstest/tests/granular/01.t
@@ -0,0 +1,35 @@
+#!/bin/sh
+# $FreeBSD$
+
+desc="NFSv4 granular permissions checking - ACL_READ_ATTRIBUTES and ACL_WRITE_ATTRIBUTES"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..12"
+
+n0=`namegen`
+n1=`namegen`
+n2=`namegen`
+
+expect 0 mkdir ${n2} 0755
+cdir=`pwd`
+cd ${n2}
+
+# Tests 1..12 - check out whether user 65534 is permitted to read attributes.
+expect 0 create ${n0} 0644
+expect 0 lstat ${n0} size
+expect 0 -u 65534 -g 65534 stat ${n0} size
+expect 0 prependacl ${n0} user:65534:read_attributes::deny
+expect 0 lstat ${n0} size
+expect EACCES -u 65534 -g 65534 stat ${n0} size
+expect 0 prependacl ${n0} user:65534:read_attributes::allow
+expect 0 -u 65534 -g 65534 stat ${n0} size
+expect 0 lstat ${n0} size
+expect 0 unlink ${n0}
+
+# Tests 12..12 - check out whether user 65534 is permitted to write attributes.
+# XXX: Check if ACL_WRITE_ATTRIBUTES allows for modifying access times.
+
+cd ${cdir}
+expect 0 rmdir ${n2}
diff --git a/tools/regression/fstest/tests/granular/02.t b/tools/regression/fstest/tests/granular/02.t
new file mode 100644
index 00000000000..80d66547c79
--- /dev/null
+++ b/tools/regression/fstest/tests/granular/02.t
@@ -0,0 +1,142 @@
+#!/bin/sh
+# $FreeBSD$
+
+desc="NFSv4 granular permissions checking - ACL_READ_ACL and ACL_WRITE_ACL"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..83"
+
+n0=`namegen`
+n1=`namegen`
+n2=`namegen`
+
+expect 0 mkdir ${n2} 0755
+cdir=`pwd`
+cd ${n2}
+
+# Check whether user 65534 is permitted to read ACL.
+expect 0 create ${n0} 0644
+expect 0 readacl ${n0}
+expect 0 -u 65534 -g 65534 readacl ${n0}
+expect 0 prependacl ${n0} user:65534:read_acl::deny
+expect 0 readacl ${n0}
+expect EACCES -u 65534 -g 65534 readacl ${n0}
+expect 0 prependacl ${n0} user:65534:read_acl::allow
+expect 0 -u 65534 -g 65534 readacl ${n0}
+expect 0 readacl ${n0}
+expect 0 unlink ${n0}
+
+# Check whether user 65534 is permitted to write ACL.
+expect 0 create ${n0} 0644
+expect EPERM -u 65534 -g 65534 prependacl ${n0} user:65534:read_data::allow
+expect 0 prependacl ${n0} user:65534:write_acl::allow
+expect 0 -u 65534 -g 65534 prependacl ${n0} user:65534:read_data::allow
+expect 0 unlink ${n0}
+
+# Check whether user 65534 is permitted to write mode.
+expect 0 create ${n0} 0755
+expect EPERM -u 65534 -g 65534 chmod ${n0} 0777
+expect 0 prependacl ${n0} user:65534:write_acl::allow
+expect 0 -u 65534 -g 65534 chmod ${n0} 0777
+expect 0 unlink ${n0}
+
+# There is an interesting problem with interaction between ACL_WRITE_ACL
+# and SUID/SGID bits.  In case user does have ACL_WRITE_ACL, but is not
+# a file owner, Solaris does the following:
+# 1. Setting SUID fails with EPERM.
+# 2. Setting SGID succeeds, but mode is not changed.
+# 3. Modifying ACL does not clear SUID nor SGID bits.
+# 4. Writing the file does clear both SUID and SGID bits.
+#
+# What we are doing is the following:
+# 1. Setting SUID or SGID fails with EPERM.
+# 2. Modifying ACL does not clear SUID nor SGID bits.
+# 3. Writing the file does clear both SUID and SGID bits.
+#
+# Check whether user 65534 is denied to write mode with SUID bit.
+expect 0 create ${n0} 0755
+expect EPERM -u 65534 -g 65534 chmod ${n0} 04777
+expect 0 prependacl ${n0} user:65534:write_acl::allow
+expect EPERM -u 65534 -g 65534 chmod ${n0} 04777
+expect 0 unlink ${n0}
+
+# Check whether user 65534 is denied to write mode with SGID bit.
+expect 0 create ${n0} 0755
+expect EPERM -u 65534 -g 65534 chmod ${n0} 02777
+expect 0 prependacl ${n0} user:65534:write_acl::allow
+expect EPERM -u 65534 -g 65534 chmod ${n0} 02777
+expect 0 unlink ${n0}
+
+# Check whether user 65534 is allowed to write mode with sticky bit.
+expect 0 mkdir ${n0} 0755
+expect EPERM -u 65534 -g 65534 chmod ${n0} 01777
+expect 0 prependacl ${n0} user:65534:write_acl::allow
+expect 0 -u 65534 -g 65534 chmod ${n0} 01777
+expect 0 rmdir ${n0}
+
+# Check whether modifying the ACL by not-owner preserves the SUID.
+expect 0 create ${n0} 04755
+expect 0 prependacl ${n0} user:65534:write_acl::allow
+expect 0 -u 65534 -g 65534 prependacl ${n0} user:65534:write_data::allow
+expect 04755 stat ${n0} mode
+expect 0 unlink ${n0}
+
+# Check whether modifying the ACL by not-owner preserves the SGID.
+expect 0 create ${n0} 02755
+expect 0 prependacl ${n0} user:65534:write_acl::allow
+expect 0 -u 65534 -g 65534 prependacl ${n0} user:65534:write_data::allow
+expect 02755 stat ${n0} mode
+expect 0 unlink ${n0}
+
+# Check whether modifying the ACL by not-owner preserves the sticky bit.
+expect 0 mkdir ${n0} 0755
+expect 0 chmod ${n0} 01755
+expect 0 prependacl ${n0} user:65534:write_acl::allow
+expect 0 -u 65534 -g 65534 prependacl ${n0} user:65534:write_data::allow
+expect 01755 stat ${n0} mode
+expect 0 rmdir ${n0}
+
+# Clearing the SUID and SGID bits when being written to by non-owner
+# is checked in chmod/12.t.
+
+# Check whether the file owner is always permitted to get and set
+# ACL and file mode, even if ACL_{READ,WRITE}_ACL would deny it.
+expect 0 chmod . 0777
+expect 0 -u 65534 -g 65534 create ${n0} 0600
+expect 0 -u 65534 -g 65534 prependacl ${n0} user:65534:write_acl::deny
+expect 0 -u 65534 -g 65534 prependacl ${n0} user:65534:read_acl::deny
+expect 0 -u 65534 -g 65534 readacl ${n0}
+expect 0600 -u 65534 -g 65534 stat ${n0} mode
+expect 0 -u 65534 -g 65534 chmod ${n0} 0777
+expect 0 unlink ${n0}
+
+expect 0 -u 65534 -g 65534 mkdir ${n0} 0600
+expect 0 -u 65534 -g 65534 prependacl ${n0} user:65534:write_acl::deny
+expect 0 -u 65534 -g 65534 prependacl ${n0} user:65534:read_acl::deny
+expect 0 -u 65534 -g 65534 readacl ${n0}
+expect 0600 -u 65534 -g 65534 stat ${n0} mode
+expect 0 -u 65534 -g 65534 chmod ${n0} 0777
+expect 0 rmdir ${n0}
+
+# Check whether the root is allowed for these as well.
+expect 0 -u 65534 -g 65534 create ${n0} 0600
+expect 0 prependacl ${n0} everyone@:write_acl::deny
+expect 0 prependacl ${n0} everyone@:read_acl::deny
+expect 0 readacl ${n0}
+expect 0600 stat ${n0} mode
+expect 0 chmod ${n0} 0777
+expect 0 unlink ${n0}
+
+expect 0 -u 65534 -g 65534 mkdir ${n0} 0600
+expect 0 prependacl ${n0} everyone@:write_acl::deny
+expect 0 prependacl ${n0} everyone@:read_acl::deny
+expect 0600 stat ${n0} mode
+expect 0 readacl ${n0}
+expect 0600 stat ${n0} mode
+expect 0 chmod ${n0} 0777
+expect 0 rmdir ${n0}
+
+cd ${cdir}
+expect 0 rmdir ${n2}
diff --git a/tools/regression/fstest/tests/granular/03.t b/tools/regression/fstest/tests/granular/03.t
new file mode 100644
index 00000000000..ec8cebfaa2d
--- /dev/null
+++ b/tools/regression/fstest/tests/granular/03.t
@@ -0,0 +1,132 @@
+#!/bin/sh
+# $FreeBSD$
+
+desc="NFSv4 granular permissions checking - DELETE and DELETE_CHILD"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..65"
+
+n0=`namegen`
+n1=`namegen`
+n2=`namegen`
+n3=`namegen`
+
+expect 0 mkdir ${n2} 0755
+expect 0 mkdir ${n3} 0777
+cdir=`pwd`
+cd ${n2}
+
+# Unlink allowed on writable directory.
+expect 0 create ${n0} 0644
+expect EACCES -u 65534 -g 65534 unlink ${n0}
+expect 0 prependacl . user:65534:write_data::allow
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# Moving file elsewhere allowed on writable directory.
+expect 0 create ${n0} 0644
+expect 0 prependacl . user:65534:write_data::deny
+expect EACCES -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+expect 0 prependacl . user:65534:write_data::allow
+expect 0 -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+
+# Moving file from elsewhere allowed on writable directory.
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# Moving file from elsewhere overwriting local file allowed
+# on writable directory.
+expect 0 create ${n0} 0644
+expect 0 create ../${n3}/${n0} 0644
+expect 0 prependacl . user:65534:write_data::deny
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 prependacl . user:65534:write_data::allow
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# Denied DELETE changes nothing wrt removing.
+expect 0 create ${n0} 0644
+expect 0 prependacl ${n0} user:65534:delete::deny
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# Denied DELETE changes nothing wrt moving elsewhere or from elsewhere.
+expect 0 create ${n0} 0644
+expect 0 -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# DELETE_CHILD denies unlink on writable directory.
+expect 0 create ${n0} 0644
+expect 0 prependacl . user:65534:delete_child::deny
+expect EPERM -u 65534 -g 65534 unlink ${n0}
+expect 0 unlink ${n0}
+
+# DELETE_CHILD denies moving file elsewhere.
+expect 0 create ${n0} 0644
+expect EPERM -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+expect 0 rename ${n0} ../${n3}/${n0}
+
+# DELETE_CHILD does not deny moving file from elsewhere
+# to a writable directory.
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# DELETE_CHILD denies moving file from elsewhere
+# to a writable directory overwriting local file.
+expect 0 create ../${n3}/${n0} 0644
+expect EPERM -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# DELETE allowed on file allows for unlinking, no matter
+# what permissions on containing directory are.
+expect 0 prependacl ${n0} user:65534:delete::allow
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# Same for moving the file elsewhere.
+expect 0 create ${n0} 0644
+expect 0 prependacl ${n0} user:65534:delete::allow
+expect 0 -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+
+# Same for moving the file from elsewhere into a writable
+# directory with DELETE_CHILD denied.
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 unlink ${n0}
+
+# DELETE does not allow for overwriting a file in a unwritable
+# directory with DELETE_CHILD denied.
+expect 0 create ${n0} 0644
+expect 0 create ../${n3}/${n0} 0644
+expect 0 prependacl . user:65534:write_data::deny
+expect 0 prependacl . user:65534:delete_child::deny
+expect EPERM -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 prependacl ${n0} user:65534:delete::allow
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# But it allows for plain deletion.
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# DELETE_CHILD allowed on unwritable directory.
+expect 0 create ${n0} 0644
+expect 0 prependacl . user:65534:delete_child::allow
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+# Moving things elsewhere is allowed.
+expect 0 create ${n0} 0644
+expect 0 -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+
+# Moving things back is not.
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# Even if we're overwriting.
+expect 0 create ${n0} 0644
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# Even if we have DELETE on the existing file.
+expect 0 prependacl ${n0} user:65534:delete::allow
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# Denied DELETE changes nothing wrt removing.
+expect 0 prependacl ${n0} user:65534:delete::deny
+expect 0 -u 65534 -g 65534 unlink ${n0}
+
+cd ${cdir}
+expect 0 rmdir ${n2}
diff --git a/tools/regression/fstest/tests/granular/04.t b/tools/regression/fstest/tests/granular/04.t
new file mode 100644
index 00000000000..9bd55f25023
--- /dev/null
+++ b/tools/regression/fstest/tests/granular/04.t
@@ -0,0 +1,78 @@
+#!/bin/sh
+# $FreeBSD$
+
+desc="NFSv4 granular permissions checking - ACL_WRITE_OWNER"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..52"
+
+n0=`namegen`
+n1=`namegen`
+n2=`namegen`
+
+expect 0 mkdir ${n2} 0755
+cdir=`pwd`
+cd ${n2}
+
+# ACL_WRITE_OWNER permits to set gid to our own only.
+expect 0 create ${n0} 0644
+expect 0,0 lstat ${n0} uid,gid
+expect EPERM -u 65534 -g 65532,65531 chown ${n0} -1 65532
+expect 0,0 lstat ${n0} uid,gid
+expect 0 prependacl ${n0} user:65534:write_owner::allow
+expect EPERM -u 65534 -g 65532,65531 chown ${n0} -1 65530
+expect 0,0 lstat ${n0} uid,gid
+expect 0 -u 65534 -g 65532,65531 chown ${n0} -1 65532
+expect 0,65532 lstat ${n0} uid,gid
+expect 0 unlink ${n0}
+
+# ACL_WRITE_OWNER permits to set uid to our own only.
+expect 0 create ${n0} 0644
+expect 0,0 lstat ${n0} uid,gid
+expect EPERM -u 65534 -g 65532,65531 chown ${n0} 65534 65531
+expect 0,0 lstat ${n0} uid,gid
+expect 0 prependacl ${n0} user:65534:write_owner::allow
+expect EPERM -u 65534 -g 65532,65531 chown ${n0} 65530 65531
+expect 0,0 lstat ${n0} uid,gid
+expect 0 -u 65534 -g 65532,65531 chown ${n0} 65534 65531
+expect 65534,65531 lstat ${n0} uid,gid
+expect 0 unlink ${n0}
+
+# When non-owner calls chown(2) successfully, set-uid and set-gid bits are
+# removed, except when both uid and gid are equal to -1.
+expect 0 create ${n0} 0644
+expect 0 prependacl ${n0} user:65534:write_owner::allow
+expect 0 chmod ${n0} 06555
+expect 06555 lstat ${n0} mode
+expect 0 -u 65534 -g 65533,65532 chown ${n0} 65534 65532
+expect 0555,65534,65532 lstat ${n0} mode,uid,gid
+expect 0 chmod ${n0} 06555
+expect 06555 lstat ${n0} mode
+expect 0 -u 65534 -g 65533,65532 chown ${n0} -1 65533
+expect 0555,65534,65533 lstat ${n0} mode,uid,gid
+expect 0 chmod ${n0} 06555
+expect 06555 lstat ${n0} mode
+expect 0 -u 65534 -g 65533,65532 chown ${n0} -1 -1
+expect 06555,65534,65533 lstat ${n0} mode,uid,gid
+expect 0 unlink ${n0}
+
+expect 0 mkdir ${n0} 0755
+expect 0 prependacl ${n0} user:65534:write_owner::allow
+expect 0 chmod ${n0} 06555
+expect 06555 lstat ${n0} mode
+expect 0 -u 65534 -g 65533,65532 chown ${n0} 65534 65532
+expect 0555,65534,65532 lstat ${n0} mode,uid,gid
+expect 0 chmod ${n0} 06555
+expect 06555 lstat ${n0} mode
+expect 0 -u 65534 -g 65533,65532 chown ${n0} -1 65533
+expect 0555,65534,65533 lstat ${n0} mode,uid,gid
+expect 0 chmod ${n0} 06555
+expect 06555 lstat ${n0} mode
+expect 0 -u 65534 -g 65533,65532 chown ${n0} -1 -1
+expect 06555,65534,65533 lstat ${n0} mode,uid,gid
+expect 0 rmdir ${n0}
+
+cd ${cdir}
+expect 0 rmdir ${n2}
diff --git a/tools/regression/fstest/tests/granular/05.t b/tools/regression/fstest/tests/granular/05.t
new file mode 100644
index 00000000000..7b29774ee02
--- /dev/null
+++ b/tools/regression/fstest/tests/granular/05.t
@@ -0,0 +1,147 @@
+#!/bin/sh
+# $FreeBSD$
+
+desc="NFSv4 granular permissions checking - DELETE and DELETE_CHILD with directories"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..68"
+
+n0=`namegen`
+n1=`namegen`
+n2=`namegen`
+n3=`namegen`
+
+expect 0 mkdir ${n2} 0755
+expect 0 mkdir ${n3} 0777
+cdir=`pwd`
+cd ${n2}
+
+# Unlink allowed on writable directory.
+expect 0 mkdir ${n0} 0755
+expect EACCES -u 65534 -g 65534 rmdir ${n0}
+expect 0 prependacl . user:65534:write_data::allow
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+# Moving directory elsewhere allowed on writable directory.
+expect 0 mkdir ${n0} 0777
+expect 0 prependacl . user:65534:write_data::deny
+expect EACCES -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+expect 0 prependacl . user:65534:write_data::allow
+expect 0 -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+
+# 12
+# Moving directory from elsewhere allowed on writable directory.
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 prependacl . user:65534:append_data::allow
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+# Moving directory from elsewhere overwriting local directory allowed
+# on writable directory.
+expect 0 mkdir ${n0} 0755
+expect 0 mkdir ../${n3}/${n0} 0777
+expect 0 prependacl . user:65534:write_data::deny
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 prependacl . user:65534:write_data::allow
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+# 23
+# Denied DELETE changes nothing wrt removing.
+expect 0 mkdir ${n0} 0755
+expect 0 prependacl ${n0} user:65534:delete::deny
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+# Denied DELETE changes nothing wrt moving elsewhere or from elsewhere.
+expect 0 mkdir ${n0} 0777
+expect 0 -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+# DELETE_CHILD denies unlink on writable directory.
+expect 0 mkdir ${n0} 0755
+expect 0 prependacl . user:65534:delete_child::deny
+expect EPERM -u 65534 -g 65534 rmdir ${n0}
+expect 0 rmdir ${n0}
+
+# 35
+# DELETE_CHILD denies moving directory elsewhere.
+expect 0 mkdir ${n0} 0777
+expect EPERM -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+expect 0 rename ${n0} ../${n3}/${n0}
+
+# DELETE_CHILD does not deny moving directory from elsewhere
+# to a writable directory.
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# DELETE_CHILD denies moving directory from elsewhere
+# to a writable directory overwriting local directory.
+expect 0 mkdir ../${n3}/${n0} 0755
+expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# DELETE allowed on directory allows for unlinking, no matter
+# what permissions on containing directory are.
+expect 0 prependacl ${n0} user:65534:delete::allow
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+# Same for moving the directory elsewhere.
+expect 0 mkdir ${n0} 0777
+expect 0 prependacl ${n0} user:65534:delete::allow
+expect 0 -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+
+# 46
+# Same for moving the directory from elsewhere into a writable
+# directory with DELETE_CHILD denied.
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 rmdir ${n0}
+
+# DELETE does not allow for overwriting a directory in a unwritable
+# directory with DELETE_CHILD denied.
+expect 0 mkdir ${n0} 0755
+expect 0 mkdir ../${n3}/${n0} 0777
+expect 0 prependacl . user:65534:write_data::deny
+expect 0 prependacl . user:65534:delete_child::deny
+expect EPERM -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 prependacl ${n0} user:65534:delete::allow
+# XXX: expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# 54
+# But it allows for plain deletion.
+# XXX: expect 0 -u 65534 -g 65534 rmdir ${n0}
+expect 0 rmdir ${n0}
+
+# DELETE_CHILD allowed on unwritable directory.
+expect 0 mkdir ${n0} 0755
+expect 0 prependacl . user:65534:delete_child::allow
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+# Moving things elsewhere is allowed.
+expect 0 mkdir ${n0} 0777
+expect 0 -u 65534 -g 65534 rename ${n0} ../${n3}/${n0}
+
+# 60
+# Moving things back is not.
+# XXX: expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# Even if we're overwriting.
+# XXX: expect 0 mkdir ${n0} 0755
+expect 0 mkdir ../${n3}/${n0} 0777
+# XXX: expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 mkdir ../${n3}/${n0} 0777
+
+# Even if we have DELETE on the existing directory.
+expect 0 prependacl ${n0} user:65534:delete::allow
+# XXX: expect EACCES -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+expect 0 -u 65534 -g 65534 rename ../${n3}/${n0} ${n0}
+
+# Denied DELETE changes nothing wrt removing.
+expect 0 prependacl ${n0} user:65534:delete::deny
+expect 0 -u 65534 -g 65534 rmdir ${n0}
+
+cd ${cdir}
+expect 0 rmdir ${n2}
diff --git a/tools/regression/poll/Makefile b/tools/regression/poll/Makefile
index 71192a948eb..45f743f17ae 100644
--- a/tools/regression/poll/Makefile
+++ b/tools/regression/poll/Makefile
@@ -3,14 +3,15 @@
 # Nothing yet works with gmake for the path to the sources.
 .PATH: ..
 
-PROG=	pipepoll pipeselect
+PROG=	pipepoll pipeselect sockpoll
 CFLAGS+= -Werror -Wall
 
 all: ${PROG}
 pipepoll: pipepoll.c
 pipeselect: pipeselect.c
+sockpoll: sockpoll.c
 
-pipepoll pipeselect:
+pipepoll pipeselect sockpoll:
 	${CC} ${CFLAGS} ${LDFLAGS} -o $@ $@.c
 
 test: all
diff --git a/tools/regression/priv/Makefile b/tools/regression/priv/Makefile
index 6f494a89bd4..814f5c333db 100644
--- a/tools/regression/priv/Makefile
+++ b/tools/regression/priv/Makefile
@@ -2,6 +2,8 @@
 # $FreeBSD$
 #
 
+.include 
+
 PROG=	priv
 SRCS=	main.c				\
 	priv_acct.c			\
@@ -49,4 +51,8 @@ WARNS=	3
 DPADD+= ${LIBIPSEC}
 LDADD+= -lipsec
 
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+= -DINET6
+.endif
+
 .include 
diff --git a/tools/regression/priv/main.c b/tools/regression/priv/main.c
index 5dd411a22d4..e594c44c4a7 100644
--- a/tools/regression/priv/main.c
+++ b/tools/regression/priv/main.c
@@ -142,20 +142,24 @@ static struct test tests[] = {
 	    priv_netinet_ipsec_policy4_bypass,
 	    priv_netinet_ipsec_policy_bypass_cleanup },
 
+#ifdef INET6
 	{ "priv_netinet_ipsec_policy6_bypass",
 	    priv_netinet_ipsec_policy6_bypass_setup,
 	    priv_netinet_ipsec_policy6_bypass,
 	    priv_netinet_ipsec_policy_bypass_cleanup },
+#endif
 
 	{ "priv_netinet_ipsec_policy4_entrust",
 	    priv_netinet_ipsec_policy4_entrust_setup,
 	    priv_netinet_ipsec_policy4_entrust,
 	    priv_netinet_ipsec_policy_entrust_cleanup },
 
+#ifdef INET6
 	{ "priv_netinet_ipsec_policy6_entrust",
 	    priv_netinet_ipsec_policy6_entrust_setup,
 	    priv_netinet_ipsec_policy6_entrust,
 	    priv_netinet_ipsec_policy_entrust_cleanup },
+#endif
 
 	{ "priv_netinet_raw", priv_netinet_raw_setup, priv_netinet_raw,
 	    priv_netinet_raw_cleanup },
@@ -420,12 +424,23 @@ static void
 enter_jail(const char *test)
 {
 	struct jail j;
+	struct in_addr ia4;
+#ifdef INET6
+	struct in6_addr ia6 = IN6ADDR_LOOPBACK_INIT;
+#endif
 
 	bzero(&j, sizeof(j));
-	j.version = 0;
+	j.version = JAIL_API_VERSION;
 	j.path = "/";
 	j.hostname = "test";
-	j.ip_number = htonl(INADDR_LOOPBACK);
+	j.jailname = "regressions/priv";
+	ia4.s_addr = htonl(INADDR_LOOPBACK);
+	j.ip4s = 1;
+	j.ip4 = &ia4;
+#ifdef INET6
+	j.ip6s = 1;
+	j.ip6 = &ia6;
+#endif
 	if (jail(&j) < 0)
 		err(-1, "test %s: jail", test);
 }
diff --git a/tools/regression/priv/priv_netinet_ipsec.c b/tools/regression/priv/priv_netinet_ipsec.c
index c2014da1d24..a485886b8fe 100644
--- a/tools/regression/priv/priv_netinet_ipsec.c
+++ b/tools/regression/priv/priv_netinet_ipsec.c
@@ -69,6 +69,7 @@ priv_netinet_ipsec_policy_bypass_setup_af(int asroot, int injail,
 			return (-1);
 		}
 		break;
+#ifdef INET6
 	case AF_INET6:
 		sd = socket(AF_INET6, SOCK_DGRAM, 0);
 		if (sd < 0) {
@@ -76,6 +77,7 @@ priv_netinet_ipsec_policy_bypass_setup_af(int asroot, int injail,
 			return (-1);
 		}
 		break;
+#endif
 	default:
 		warnx("%s: unexpected address family", __func__);
 		return (-1);
@@ -92,6 +94,7 @@ priv_netinet_ipsec_policy4_bypass_setup(int asroot, int injail,
 	    AF_INET));
 }
 
+#ifdef INET6
 int
 priv_netinet_ipsec_policy6_bypass_setup(int asroot, int injail,
     struct test *test)
@@ -100,7 +103,7 @@ priv_netinet_ipsec_policy6_bypass_setup(int asroot, int injail,
 	return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test,
 	    AF_INET6));
 }
-
+#endif
 
 
 static int
@@ -121,6 +124,7 @@ priv_netinet_ipsec_policy_entrust_setup_af(int asroot, int injail,
 			return (-1);
 		}
 		break;
+#ifdef INET6
 	case AF_INET6:
 		sd = socket(AF_INET6, SOCK_DGRAM, 0);
 		if (sd < 0) {
@@ -128,6 +132,7 @@ priv_netinet_ipsec_policy_entrust_setup_af(int asroot, int injail,
 			return (-1);
 		}
 		break;
+#endif
 	default:
 		warnx("%s: unexpected address family", __func__);
 		return (-1);
@@ -144,6 +149,7 @@ priv_netinet_ipsec_policy4_entrust_setup(int asroot, int injail,
 	    AF_INET));
 }
 
+#ifdef INET6
 int
 priv_netinet_ipsec_policy6_entrust_setup(int asroot, int injail,
     struct test *test)
@@ -152,7 +158,7 @@ priv_netinet_ipsec_policy6_entrust_setup(int asroot, int injail,
 	return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test,
 	    AF_INET6));
 }
-
+#endif
 
 void
 priv_netinet_ipsec_pfkey(int asroot, int injail, struct test *test)
@@ -196,10 +202,12 @@ priv_netinet_ipsec_policy_bypass_af(int asroot, int injail, struct test *test,
 		level = IPPROTO_IP;
 		optname = IP_IPSEC_POLICY;
 		break;
+#ifdef INET6
 	case AF_INET6:
 		level = IPPROTO_IPV6;
 		optname = IPV6_IPSEC_POLICY;
 		break;
+#endif
 	default:
 		warnx("%s: unexpected address family", __func__);
 		return;
@@ -227,13 +235,14 @@ priv_netinet_ipsec_policy4_bypass(int asroot, int injail, struct test *test)
 	priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET);
 }
 
+#ifdef INET6
 void
 priv_netinet_ipsec_policy6_bypass(int asroot, int injail, struct test *test)
 {
 
 	priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET6);
 }
-
+#endif
 
 static void
 priv_netinet_ipsec_policy_entrust_af(int asroot, int injail, struct test *test,
@@ -246,10 +255,12 @@ priv_netinet_ipsec_policy_entrust_af(int asroot, int injail, struct test *test,
 		level = IPPROTO_IP;
 		optname = IP_IPSEC_POLICY;
 		break;
+#ifdef INET6
 	case AF_INET6:
 		level = IPPROTO_IPV6;
 		optname = IPV6_IPSEC_POLICY;
 		break;
+#endif
 	default:
 		warnx("%s: unexpected address family", __func__);
 		return;
@@ -277,13 +288,14 @@ priv_netinet_ipsec_policy4_entrust(int asroot, int injail, struct test *test)
 	priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET);
 }
 
+#ifdef INET6
 void
 priv_netinet_ipsec_policy6_entrust(int asroot, int injail, struct test *test)
 {
 
 	priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET6);
 }
-
+#endif
 
 void
 priv_netinet_ipsec_policy_bypass_cleanup(int asroot, int injail,
diff --git a/tools/regression/priv/priv_vfs_extattr_system.c b/tools/regression/priv/priv_vfs_extattr_system.c
index 9f8f88718e1..a766a04c793 100644
--- a/tools/regression/priv/priv_vfs_extattr_system.c
+++ b/tools/regression/priv/priv_vfs_extattr_system.c
@@ -80,7 +80,7 @@ priv_vfs_extattr_system(int asroot, int injail, struct test *test)
 	else if (ret == EA_SIZE)
 		error = 0;
 	else
-		err(-1, "priv_vfs_extattr_system: set returned %d", ret);
+		err(-1, "priv_vfs_extattr_system: set returned %zd", ret);
 	if (asroot && injail)
 		expect("priv_vfs_extattr_system(asroot, injail)", error, -1,
 		    EPERM);
diff --git a/tools/tools/ath/athpoke/athpoke.c b/tools/tools/ath/athpoke/athpoke.c
index 82ec550c2be..1749b7b52b7 100644
--- a/tools/tools/ath/athpoke/athpoke.c
+++ b/tools/tools/ath/athpoke/athpoke.c
@@ -39,6 +39,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 typedef struct {
 	HAL_REVS revs;
@@ -64,6 +66,7 @@ main(int argc, char *argv[])
 {
 	struct ath_diag atd;
 	const char *ifname;
+	char *eptr;
 	int c, s;
 
 	s = socket(AF_INET, SOCK_DGRAM, 0);
@@ -102,7 +105,13 @@ main(int argc, char *argv[])
 		if (cp != NULL)
 			*cp++ = '\0';
 		dr = reglookup(argv[0]);
-		reg = (dr != NULL) ? dr->addr : (uint32_t) strtoul(argv[0], NULL, 0);
+		if (dr == NULL) {
+			errno = 0;
+			reg = (uint32_t) strtoul(argv[0], &eptr, 0);
+			if (argv[0] == eptr || eptr[0] != '\0')
+				errx(1, "invalid register \"%s\"", argv[0]);
+		} else
+			reg = dr->addr;
 		if (cp != NULL)
 			regwrite(s, &atd, reg, (uint32_t) strtoul(cp, NULL, 0));
 		printf("%s = %08x\n", argv[0], regread(s, &atd, reg));
diff --git a/tools/tools/vimage/Makefile b/tools/tools/vimage/Makefile
index 82f4f473845..76c76179f76 100644
--- a/tools/tools/vimage/Makefile
+++ b/tools/tools/vimage/Makefile
@@ -10,6 +10,5 @@ CFLAGS+= -I../../../sys
 MAN=	vimage.8
 
 BINDIR?=	/usr/sbin
-NO_SHARED?=	YES
 
 .include 
diff --git a/tools/tools/vimage/vimage.8 b/tools/tools/vimage/vimage.8
index f012af8d698..517a788cda3 100644
--- a/tools/tools/vimage/vimage.8
+++ b/tools/tools/vimage/vimage.8
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2002, 2003 Marko Zec 
+.\" Copyright (c) 2002, 2003 Marko Zec 
 .\" Copyright (c) 2009 University of Zagreb
 .\" Copyright (c) 2009 FreeBSD Foundation
 .\"
@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 6, 2009
+.Dd August 25, 2009
 .Dt VIMAGE 8
 .Os
 .Sh NAME
@@ -35,35 +35,46 @@
 .Nd manage virtual network stacks
 .Sh SYNOPSIS
 .Nm
-.Ar vi_name
-.Op command
-.Nm
-.Fl c
-.Ar vi_name
+.Op Fl c | m
+.Ar vname
+.Op Ar param=value ...
 .Nm
 .Fl d
-.Ar vi_name
+.Ar vname
 .Nm
 .Fl l
-.Op Ar vi_name
+.Op Fl rvj
+.Op Ar vname
 .Nm
 .Fl i
-.Ar vi_name interface
-.Sh DESCRIPTION
+.Ar vname ifname
+.Op Ar newifname
 .Nm
-command is an interm user interface for controlling the virtual network
-stacks in FreeBSD.
+.Ar vi_name
+.Op command ...
+.Sh DESCRIPTION
+The
+.Nm
+utility is an alternative user interface for controlling virtual network
+stacks in FreeBSD, aimed primarily at supporting legacy applications
+which are not yet converted to using
+.Xr jail 8 ,
+.Xr jexec 8 ,
+and
+.Xr jls 8 .
+.
 .Ss Overview
-A virtual image reprepresents an isolated operating environment with its
-own independent network stack instance.  Every process, socket and network
-interface present in the system is always attached to one, and only one,
-virtual image i.e. virtual network stack instance.
-During the system bootup sequence default virtual image is created to
-which all the configured interfaces and user processes are initially
-assigned.
-Assuming that enough system resources and per virtual image privileges
-are provided, the super-user can create and manage a hierarchy of
-subordinated virtual images. The
+A virtual image or vimage is a jail with its own independent network
+stack instance.  Every process, socket and network interface present
+in the system is always attached to one, and only one, virtual network
+stack instance (vnet).
+During system bootup sequence a default vnet
+is created to which all the configured interfaces and user processes
+are initially attached.
+Assuming that enough system resources are
+are available, a user with sufficient privileges can create and manage
+a hierarchy of subordinated virtual images.
+The
 .Nm
 command allows for creation, deletion and monitoring of virtual images,
 as well as for execution of arbitrary processes in a targeted virtual
@@ -71,59 +82,72 @@ image.
 .Ss Invocation
 If invoked with no modifiers, the
 .Nm
-command spawns a new shell process in virtual image 
-.Ar vi_name .
-If provided, the optional arguments following the virtual image name
-.Ar vi_name
-are interpreted as a standard command line issued at a shell,
-otherwise an interactive shell is started in the target virtual image.
+command spawns a new interactive shell in virtual image 
+.Ar vname .
+If optional additional arguments following
+.Ar vname
+are provided, the first of those will be executed in place of the
+interactive shell, and the rest of the arguments will be passed as
+arguments to the executed command.
 .Pp
-The following parameters are available:
+The following modifiers are available:
 .Bl -tag -width indent
 .It Fl c
 Create a new virtual image named
-.So
-.Ar vi_name
-.Sc .
+.Ar vname .
+Additional arguments, if provided, may be used to specify operating
+parameters different from defaults, in format
+.Ar param=value .
+See
+.Xr jail 8
+for an extensive list of available parameters.
+.It Fl m
+Modify the parameters of a virtual image named
+.Ar vname ,
+using the same syntax as with the -c form of the command.
 .It Fl d
 Delete the virtual image 
-.Ar vi_name .
+.Ar vname .
 No processes and/or sockets should exist in the target virtual image
-in order for the delete request to succeed. Non-loopback interfaces
+in order for the delete request to succeed.  Non-loopback interfaces
 residing in the target virtual image will be reassigned to the virtual
 image's parent.
 .It Fl l
 List the properties and statistics for virtual images one level
 below the current one in the hierarchy. If an optional argument
-.Ar vi_name
+.Ar vname
 is provided, only the information regarding the target virtual image
-.Ar vi_name
+.Ar vname
 is displayed.
-.It Fl lr
-List the properties and statistics for all virtual images in
-the hierarchy of subordinated vimages. If an optional argument
-.Ar vi_name
-is provided, the hierarchy will be traversed at and below the
-.Ar vi_name
-level.
+With the optional
+.Op Ar -r
+switch enabled the list will include all virtual images below the
+current level in the vimage hierarchy.
+Enabling the optional
+.Op Ar -v
+or
+.Op Ar -j
+switches results in a more detailed output.
 .It Fl i
-Move the interface
-.Ar interface
+Move interface
+.Ar ifname
 to the target virtual image
-.Ar vi_name .
-If the value of 
-.Ar vi_name
-argument is
-.So ..
+.Ar vname .
+Interfaces will be automatically renamed to
+.So
+ethXX
 .Sc ,
-the interface is returned to the parent of the current virtual image.
+unless an optional argument specifying the desired interface name
+.Op Ar newifname
+is provided.
 .El
 .Sh EXAMPLES
 Create a new virtual image named 
 .So v1
-.Sc :
+.Sc ,
+which is allowed to create and manage an own subhierarchy of vimages:
 .Pp
-.Dl vimage -c v1
+.Dl vimage -c v1 children.max=100
 .Pp
 Execute the
 .So ifconfig
@@ -137,28 +161,35 @@ Move the interface
 .So vlan0
 .Sc to the virtual image
 .So v1
+.Sc while renaming the interface as
+.So
+ve0
 .Sc :
 .Pp
-.Dl vimage -i v1 vlan0
+.Dl vimage -i v1 vlan0 ve0
 .Pp
 Show the status information for virtual image
 .So v1
 .Sc :
 .Pp
-.Dl vimage -l v1
+.Dl vimage -lv v1
 .Sh DIAGNOSTICS
 The
 .Nm
 command exits 0 on success, and >0 if an error occurs.
 .Sh SEE ALSO
 .Xr jail 8
+.Xr jexec 8
+.Xr jls 8
 .Sh BUGS
-If memory allocation failure occurs during the vimage creation, it will remain
-undetected/ignored in the current implementation, thus latently scheduling
-an almost imminent system crash in the future.
+Deletion of vimages / vnets is known to leak kernel memory and fail at
+stopping various timers, hence may lead to system crashes.
 .Sh AUTHOR
 .An "Marko Zec" Aq zec@fer.hr
 .Sh HISTORY
-The
-.Nm
-facility first appeared as a patch against FreeBSD 4.7-RELEASE in 2002.
+Network stack virtualization framework first appeared as a patchset
+against the FreeBSD 4.7 kernel in 2002, and was maintained outside
+of the main FreeBSD tree.
+As a result of a project sponsored by the FreeBSD Foundation and
+Stiching NLNet, integrated virtualized network stack first appeared
+in FreeBSD 8.0.
diff --git a/tools/tools/vimage/vimage.c b/tools/tools/vimage/vimage.c
index e4ab584c4a9..e6655999c50 100644
--- a/tools/tools/vimage/vimage.c
+++ b/tools/tools/vimage/vimage.c
@@ -28,142 +28,292 @@
  */
 
 #include 
-#include 
 #include 
 #include 
 #include 
 
 #include 
 
-#include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
-#define	VI_CREATE		0x00000001
-#define	VI_DESTROY		0x00000002
-#define	VI_SWITCHTO		0x00000008
-#define	VI_IFACE		0x00000010
-#define	VI_GET			0x00000100
-#define	VI_GETNEXT		0x00000200
+typedef enum {
+	VI_SWITCHTO,
+	VI_CREATE,
+	VI_MODIFY,
+	VI_DESTROY,
+	VI_IFMOVE,
+	VI_GET
+} vi_cmd_t;
 
-static int getjail(char *name, int lastjid, int *vnet);
+typedef struct vimage_status {
+	char name[MAXPATHLEN];		/* Must be first field for strcmp(). */
+	char path[MAXPATHLEN];
+	char hostname[MAXPATHLEN];
+	char domainname[MAXPATHLEN];
+	int jid;
+	int parentjid;
+	int vnet;
+	int childcnt;
+	int childmax;
+	int cpuset;
+	int rawsock;
+	int socket_af;
+	int mount;
+} vstat_t;
+
+#define	VST_SIZE_STEP	1024
+#define	MAXPARAMS	32
+
+static int getjail(vstat_t *, int, int);
+
+static char *invocname;
+
+static void
+usage(void)
+{
+
+	fprintf(stderr,
+	    "usage: %s [-c | -m] vname [param=value ...]\n"
+	    "       %s -d vname\n"
+	    "       %s -l[rvj] [vname]\n"
+	    "       %s -i vname ifname [newifname]\n"
+	    "       %s vname [command ...]\n",
+	    invocname, invocname, invocname, invocname, invocname);
+	exit(1);
+}
 
 int
 main(int argc, char **argv)
 {
-	int s;
-	char *shell;
-	int cmd;
-	int jid, vnet;
+	struct jailparam params[MAXPARAMS];
+	char ifname[IFNAMSIZ];
 	struct ifreq ifreq;
-	char name[MAXHOSTNAMELEN];
+	vi_cmd_t newcmd, cmd;
+	int recurse = 0;
+	int verbose = 0;
+	int jid, i, s, namelen;
+	int vst_size, vst_last;
+	vstat_t *vst;
+	char *str;
+	char ch;
 
-	switch (argc) {
+	invocname = argv[0];
 
-	case 1:
-		cmd = 0;
-		break;
-
-	case 2:
-		if (strcmp(argv[1], "-l") == 0)
-			cmd = VI_GETNEXT;
-		else if (strcmp(argv[1], "-lr") == 0)
-			cmd = VI_GETNEXT;
-		else {
-			strcpy(name, argv[1]);
-			cmd = VI_SWITCHTO;
+	newcmd = cmd = VI_SWITCHTO; /* Default if no modifiers specified. */
+	while ((ch = getopt(argc, argv, "cdijlmrv")) != -1) {
+		switch (ch) {
+		case 'c':
+			newcmd = VI_CREATE;
+			break;
+		case 'm':
+			newcmd = VI_MODIFY;
+			break;
+		case 'd':
+			newcmd = VI_DESTROY;
+			break;
+		case 'l':
+			newcmd = VI_GET;
+			break;
+		case 'i':
+			newcmd = VI_IFMOVE;
+			break;
+		case 'r':
+			recurse = 1;
+			break;
+		case 'v':
+			verbose++;
+			break;
+		case 'j':
+			verbose = 2;
+			break;
+		default:
+			usage();
 		}
-		break;
-
-	case 3:
-		strcpy(name, argv[2]);
-		if (strcmp(argv[1], "-l") == 0)
-			cmd = VI_GET;
-		if (strcmp(argv[1], "-c") == 0)
-			cmd = VI_CREATE;
-		if (strcmp(argv[1], "-d") == 0)
-			cmd = VI_DESTROY;
-		break;
-
-	default:
-		strcpy(name, argv[2]);
-		if (strcmp(argv[1], "-c") == 0)
-			cmd = VI_CREATE;
-		if (strcmp(argv[1], "-i") == 0)
-			cmd = VI_IFACE;
+		if (cmd == VI_SWITCHTO || cmd == newcmd)
+			cmd = newcmd;
+		else
+			usage();
 	}
+	argc -= optind;
+	argv += optind;
+
+	if ((cmd != VI_GET && (argc == 0 || recurse != 0 || verbose != 0)) ||
+	    (cmd == VI_IFMOVE && (argc < 2 || argc > 3)) ||
+	    (cmd == VI_MODIFY && argc < 2) || argc >= MAXPARAMS)
+		usage();
 
 	switch (cmd) {
-
 	case VI_GET:
-		jid = getjail(name, -1, &vnet);
-		if (jid < 0)
-			goto abort;
-		printf("%d: %s%s\n", jid, name, vnet ? "" : " (no vnet)");
-		exit(0);
-
-	case VI_GETNEXT:
+		vst_last = 0;
+		vst_size = VST_SIZE_STEP;
+		if ((vst = malloc(vst_size * sizeof(*vst))) == NULL)
+			break;
+		if (argc == 1)
+			namelen = strlen(argv[0]);
+		else
+			namelen = 0;
 		jid = 0;
-		while ((jid = getjail(name, jid, &vnet)) > 0)
-			printf("%d: %s%s\n", jid, name,
-			    vnet ? "" : " (no vnet)");
+		while ((jid = getjail(&vst[vst_last], jid, verbose)) > 0) {
+			/* Skip jails which do not own vnets. */
+			if (vst[vst_last].vnet != 1)
+				continue;
+			/* Skip non-matching vnames / hierarchies. */
+			if (namelen &&
+			    ((strlen(vst[vst_last].name) < namelen ||
+			    strncmp(vst[vst_last].name, argv[0], namelen) != 0)
+			    || (strlen(vst[vst_last].name) > namelen &&
+			    vst[vst_last].name[namelen] != '.')))
+				continue;
+			/* Skip any sub-trees if -r not requested. */
+			if (!recurse &&
+			    (strlen(vst[vst_last].name) < namelen ||
+			    strchr(&vst[vst_last].name[namelen], '.') != NULL))
+				continue;
+			/* Grow vst table if necessary. */
+			if (++vst_last == vst_size) {
+				vst_size += VST_SIZE_STEP;
+				vst = realloc(vst, vst_size * sizeof(*vst));
+				if (vst == NULL)
+					break;
+			}
+		}
+		if (vst == NULL)
+			break;
+		/* Sort: the key is the 1st field in *vst, i.e. vimage name. */
+		qsort(vst, vst_last, sizeof(*vst), (void *) strcmp);
+		for (i = 0; i < vst_last; i++) {
+			if (!verbose) {
+				printf("%s\n", vst[i].name);
+				continue;
+			}
+
+			printf("%s:\n", vst[i].name);
+			printf("    Path: %s\n", vst[i].path);
+			printf("    Hostname: %s\n", vst[i].hostname);
+			printf("    Domainname: %s\n", vst[i].domainname);
+			printf("    Children: %d\n", vst[i].childcnt);
+
+			if (verbose < 2)
+				continue;
+
+			printf("    Children limit: %d\n", vst[i].childmax);
+			printf("    CPUsetID: %d\n", vst[i].cpuset);
+			printf("    JID: %d\n", vst[i].jid);
+			printf("    PJID: %d\n", vst[i].parentjid);
+			printf("    Raw sockets allowed: %d\n", vst[i].rawsock);
+			printf("    All AF allowed: %d\n", vst[i].socket_af);
+			printf("    Mount allowed: %d\n", vst[i].mount);
+		}
+		free(vst);
 		exit(0);
 
-	case VI_IFACE:
-		s = socket(AF_INET, SOCK_DGRAM, 0);
-		if (s == -1)
-			goto abort;
-		jid = jail_getid(name);
-		if (jid < 0)
-			goto abort;
+	case VI_IFMOVE:
+		if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+			break;
+		if ((jid = jail_getid(argv[0])) < 0)
+			break;
 		ifreq.ifr_jid = jid;
-		strncpy(ifreq.ifr_name, argv[3], sizeof(ifreq.ifr_name));
+		strncpy(ifreq.ifr_name, argv[1], sizeof(ifreq.ifr_name));
 		if (ioctl(s, SIOCSIFVNET, (caddr_t)&ifreq) < 0)
-			goto abort;
-		printf("%s@%s\n", ifreq.ifr_name, name);
+			break;
+		close(s);
+		if (argc == 3)
+			snprintf(ifname, sizeof(ifname), "%s", argv[2]);
+		else
+			snprintf(ifname, sizeof(ifname), "eth0");
+		ifreq.ifr_data = ifname;
+		/* Do we need to rename the ifnet? */
+		if (strcmp(ifreq.ifr_name, ifname) != 0) {
+			/* Switch to the context of the target vimage. */
+			if (jail_attach(jid) < 0)
+				break;
+			if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+				break;
+			for (namelen = 0; isalpha(ifname[namelen]); namelen++);
+			i = 0;
+			/* Search for a free ifunit in target vnet.  Unsafe. */
+			while (ioctl(s, SIOCSIFNAME, (caddr_t)&ifreq) < 0) {
+				snprintf(&ifname[namelen],
+				    sizeof(ifname) - namelen, "%d", i);
+				/* Emergency brake. */
+				if (i++ == IF_MAXUNIT)
+					break;
+			}
+		}
+		if (i < IF_MAXUNIT)
+			printf("%s@%s\n", ifname, argv[0]);
+		else
+			printf("%s@%s\n", ifreq.ifr_name, argv[0]);
 		exit(0);
 
 	case VI_CREATE:
-		if (jail_setv(JAIL_CREATE, "name", name, "vnet", NULL,
-		    "host", NULL, "persist", NULL, NULL) < 0)
-			goto abort;
+		if (jail_setv(JAIL_CREATE,
+		    "name", argv[0],
+		    "vnet", NULL,
+		    "host", NULL,
+		    "persist", NULL,
+		    "allow.raw_sockets", "true",
+		    "allow.socket_af", "true",
+		    "allow.mount", "true",
+		    NULL) < 0)
+			break;
+		if (argc == 1)
+			exit(0);
+		/* Not done yet, proceed to apply non-default parameters. */
+
+	case VI_MODIFY:
+		jailparam_init(¶ms[0], "name");
+		jailparam_import(¶ms[0], argv[0]);
+		for (i = 1; i < argc; i++) {
+			for (str = argv[i]; *str != '=' && *str != 0; str++) {
+				/* Do nothing - search for '=' delimeter. */
+			}
+			if (*str == 0)
+				break;
+			*str++ = 0;
+			if (*str == 0)
+				break;
+			jailparam_init(¶ms[i], argv[i]);
+			jailparam_import(¶ms[i], str);
+		}
+		if (i != argc)
+			break;
+		if (jailparam_set(params, i, JAIL_UPDATE) < 0)
+			break;
+		exit(0);
+
+	case VI_DESTROY:
+		if ((jid = jail_getid(argv[0])) < 0)
+			break;
+		if (jail_remove(jid) < 0)
+			break;
 		exit(0);
 
 	case VI_SWITCHTO:
-		jid = jail_getid(name);
-		if (jid < 0)
-			goto abort;
+		if ((jid = jail_getid(argv[0])) < 0)
+			break;
 		if (jail_attach(jid) < 0)
-			goto abort;
-
-		if (argc == 2) {
-			printf("Switched to jail %s\n", argv[1]);
-			if ((shell = getenv("SHELL")) == NULL)
-				execlp("/bin/sh", argv[0], NULL);
+			break;
+		if (argc == 1) {
+			printf("Switched to vimage %s\n", argv[0]);
+			if ((str = getenv("SHELL")) == NULL)
+				execlp("/bin/sh", invocname, NULL);
 			else
-				execlp(shell, argv[0], NULL);
+				execlp(str, invocname, NULL);
 		} else 
-			execvp(argv[2], &argv[2]);
+			execvp(argv[1], &argv[1]);
 		break;
 
-	case VI_DESTROY:
-		jid = jail_getid(name);
-		if (jid < 0)
-			goto abort;
-		if (jail_remove(jid) < 0)
-			goto abort;
-		exit(0);
-
 	default:
-		fprintf(stderr, "usage: %s [-cdilr] vi_name [args]\n",
-		    argv[0]);
-		exit(1);
+		/* Should be unreachable. */
+		break;
 	}
 
-abort:
 	if (jail_errmsg[0])
 		fprintf(stderr, "Error: %s\n", jail_errmsg);
 	else
@@ -172,27 +322,69 @@ abort:
 }
 
 static int
-getjail(char *name, int lastjid, int *vnet)
+getjail(vstat_t *vs, int lastjid, int verbose)
 {
-	struct jailparam params[3];
-	int jid;
+	struct jailparam params[32];	/* Must be > max(psize). */
+	int psize = 0;
 
-	if (lastjid < 0) {
-		jid = jail_getid(name);
-		if (jid < 0)
-			return (jid);
-		jailparam_init(¶ms[0], "jid");
-		jailparam_import_raw(¶ms[0], &jid, sizeof jid);
-	} else {
-		jailparam_init(¶ms[0], "lastjid");
-		jailparam_import_raw(¶ms[0], &lastjid, sizeof lastjid);
-	}
-	jailparam_init(¶ms[1], "name");
-	jailparam_import_raw(¶ms[1], name, MAXHOSTNAMELEN);
-	name[0] = 0;
-	jailparam_init(¶ms[2], "vnet");
-	jailparam_import_raw(¶ms[2], vnet, sizeof(*vnet));
-	jid = jailparam_get(params, 3, 0);
-	jailparam_free(params, 3);
-	return (jid);
+	bzero(params, sizeof(params));
+	bzero(vs, sizeof(*vs));
+
+	jailparam_init(¶ms[psize], "lastjid");
+	jailparam_import_raw(¶ms[psize++], &lastjid, sizeof lastjid);
+
+	jailparam_init(¶ms[psize], "vnet");
+	jailparam_import_raw(¶ms[psize++], &vs->vnet, sizeof(vs->vnet));
+
+	jailparam_init(¶ms[psize], "name");
+	jailparam_import_raw(¶ms[psize++], &vs->name, sizeof(vs->name));
+
+	if (verbose == 0)
+		goto done;
+
+	jailparam_init(¶ms[psize], "path");
+	jailparam_import_raw(¶ms[psize++], &vs->path, sizeof(vs->path));
+
+	jailparam_init(¶ms[psize], "host.hostname");
+	jailparam_import_raw(¶ms[psize++], &vs->hostname,
+	    sizeof(vs->hostname));
+
+	jailparam_init(¶ms[psize], "host.domainname");
+	jailparam_import_raw(¶ms[psize++], &vs->domainname,
+	    sizeof(vs->domainname));
+
+	jailparam_init(¶ms[psize], "children.cur");
+	jailparam_import_raw(¶ms[psize++], &vs->childcnt,
+	    sizeof(vs->childcnt));
+
+	if (verbose == 1)
+		goto done;
+
+	jailparam_init(¶ms[psize], "children.max");
+	jailparam_import_raw(¶ms[psize++], &vs->childmax,
+	    sizeof(vs->childmax));
+
+	jailparam_init(¶ms[psize], "cpuset.id");
+	jailparam_import_raw(¶ms[psize++], &vs->cpuset,
+	    sizeof(vs->cpuset));
+
+	jailparam_init(¶ms[psize], "parent");
+	jailparam_import_raw(¶ms[psize++], &vs->parentjid,
+	    sizeof(vs->parentjid));
+
+	jailparam_init(¶ms[psize], "allow.raw_sockets");
+	jailparam_import_raw(¶ms[psize++], &vs->rawsock,
+	    sizeof(vs->rawsock));
+
+	jailparam_init(¶ms[psize], "allow.socket_af");
+	jailparam_import_raw(¶ms[psize++], &vs->socket_af,
+	    sizeof(vs->socket_af));
+
+	jailparam_init(¶ms[psize], "allow.mount");
+	jailparam_import_raw(¶ms[psize++], &vs->mount, sizeof(vs->mount));
+
+done:
+	vs->jid = jailparam_get(params, psize, 0);
+	jailparam_free(params, psize);
+	return (vs->jid);
 }
diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd
index d729acf224d..a2803377309 100644
--- a/usr.bin/calendar/calendars/calendar.freebsd
+++ b/usr.bin/calendar/calendars/calendar.freebsd
@@ -244,6 +244,7 @@
 09/10	Wesley R. Peters  born in Hartford, Alabama, United States, 1961
 09/12	Weongyo Jeong  born in Haman, Korea, 1980
 09/12	William C. Fumerola II  born in Detroit, Michigan, United States, 1981
+09/15	Dima Panov  born in Khabarovsk, Russian Federation, 1978
 09/17	Maxim Bolotin  born in Rostov-on-Don, Russian Federation, 1976
 09/20	Kevin Lo  born in Taipei, Taiwan, Republic of China, 1972
 09/27	Neil Blakey-Milner  born in Port Elizabeth, South Africa, 1978
diff --git a/usr.bin/ee/Makefile b/usr.bin/ee/Makefile
index 6ce39cf6e35..43f043221a0 100644
--- a/usr.bin/ee/Makefile
+++ b/usr.bin/ee/Makefile
@@ -3,7 +3,7 @@
 .PATH:	${.CURDIR}/../../contrib/ee
 
 CFLAGS+= -DHAS_NCURSES -DHAS_UNISTD -DHAS_STDARG -DHAS_STDLIB \
-	 -DHAS_CTYPE -DHAS_SYS_WAIT
+	 -DHAS_SYS_WAIT
 
 PROG=	ee
 LINKS=	${BINDIR}/ee ${BINDIR}/ree ${BINDIR}/ee ${BINDIR}/edit
diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c
index bfa0a36a9c5..c11d24f8bab 100644
--- a/usr.bin/find/function.c
+++ b/usr.bin/find/function.c
@@ -371,38 +371,48 @@ c_mXXdepth(OPTION *option, char ***argvp)
 int
 f_acl(PLAN *plan __unused, FTSENT *entry)
 {
-	int match, entries;
-	acl_entry_t ae;
 	acl_t facl;
+	acl_type_t acl_type;
+	int acl_supported = 0, ret, trivial;
 
 	if (S_ISLNK(entry->fts_statp->st_mode))
 		return 0;
-	if ((match = pathconf(entry->fts_accpath, _PC_ACL_EXTENDED)) <= 0) {
-		if (match < 0 && errno != EINVAL)
-			warn("%s", entry->fts_accpath);
-	else
-		return 0;
-	}
-	match = 0;
-	if ((facl = acl_get_file(entry->fts_accpath,ACL_TYPE_ACCESS)) != NULL) {
-		if (acl_get_entry(facl, ACL_FIRST_ENTRY, &ae) == 1) {
-			/*
-			 * POSIX.1e requires that ACLs of type ACL_TYPE_ACCESS
-			 * must have at least three entries (owner, group,
-			 * other).
-			 */
-			entries = 1;
-			while (acl_get_entry(facl, ACL_NEXT_ENTRY, &ae) == 1) {
-				if (++entries > 3) {
-					match = 1;
-					break;
-				}
-			}
-		}
-		acl_free(facl);
-	} else
+	ret = pathconf(entry->fts_accpath, _PC_ACL_NFS4);
+	if (ret > 0) {
+		acl_supported = 1;
+		acl_type = ACL_TYPE_NFS4;
+	} else if (ret < 0 && errno != EINVAL) {
 		warn("%s", entry->fts_accpath);
-	return match;
+		return (0);
+	}
+	if (acl_supported == 0) {
+		ret = pathconf(entry->fts_accpath, _PC_ACL_EXTENDED);
+		if (ret > 0) {
+			acl_supported = 1;
+			acl_type = ACL_TYPE_ACCESS;
+		} else if (ret < 0 && errno != EINVAL) {
+			warn("%s", entry->fts_accpath);
+			return (0);
+		}
+	}
+	if (acl_supported == 0)
+		return (0);
+
+	facl = acl_get_file(entry->fts_accpath, acl_type);
+	if (facl == NULL) {
+		warn("%s", entry->fts_accpath);
+		return (0);
+	}
+	ret = acl_is_trivial_np(facl, &trivial);
+	acl_free(facl);
+	if (ret) {
+		warn("%s", entry->fts_accpath);
+		acl_free(facl);
+		return (0);
+	}
+	if (trivial)
+		return (0);
+	return (1);
 }
 
 PLAN *
diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c
index 53561e88e03..f82e964395b 100644
--- a/usr.bin/fstat/fstat.c
+++ b/usr.bin/fstat/fstat.c
@@ -658,7 +658,7 @@ devfs_filestat(struct vnode *vp, struct filestat *fsp)
 		    (void *)devfs_dirent.de_vnode, Pid);
 		return 0;
 	}
-	fsp->fsid = (long)mount.mnt_stat.f_fsid.val[0];
+	fsp->fsid = (long)(uint32_t)mount.mnt_stat.f_fsid.val[0];
 	fsp->fileid = devfs_dirent.de_inode;
 	fsp->mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR;
 	fsp->size = 0;
diff --git a/usr.bin/fstat/zfs.c b/usr.bin/fstat/zfs.c
index 008f1746b0b..96cdff6870a 100644
--- a/usr.bin/fstat/zfs.c
+++ b/usr.bin/fstat/zfs.c
@@ -117,7 +117,7 @@ zfs_filestat(struct vnode *vp, struct filestat *fsp)
 		goto bad;
 	}
 
-	fsp->fsid = (long)mount.mnt_stat.f_fsid.val[0];
+	fsp->fsid = (long)(uint32_t)mount.mnt_stat.f_fsid.val[0];
 	fsp->fileid = *zid;
 	/*
 	 * XXX: Shows up wrong in output, but UFS has this error too. Could
diff --git a/usr.bin/look/look.c b/usr.bin/look/look.c
index e6fd1b8b9e2..7c590c7de08 100644
--- a/usr.bin/look/look.c
+++ b/usr.bin/look/look.c
@@ -140,6 +140,10 @@ main(int argc, char *argv[])
 			err(2, "%s", file);
 		if (sb.st_size > SIZE_T_MAX)
 			errx(2, "%s: %s", file, strerror(EFBIG));
+		if (sb.st_size == 0) {
+			close(fd);
+			continue;
+		}
 		if ((front = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_SHARED, fd, (off_t)0)) == MAP_FAILED)
 			err(2, "%s", file);
 		back = front + sb.st_size;
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index 8be6840d853..51b71c79aa9 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -871,6 +872,47 @@ ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 #undef p1a
 }
 
+/*
+ * Dump ARP statistics structure.
+ */
+void
+arp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+	struct arpstat arpstat, zerostat;
+	size_t len = sizeof(arpstat);
+
+	if (live) {
+		if (zflag)
+			memset(&zerostat, 0, len);
+		if (sysctlbyname("net.link.ether.arp.stats", &arpstat, &len,
+		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+			warn("sysctl: net.link.ether.arp.stats");
+			return;
+		}
+	} else
+		kread(off, &arpstat, len);
+
+	printf("%s:\n", name);
+
+#define	p(f, m) if (arpstat.f || sflag <= 1) \
+    printf(m, arpstat.f, plural(arpstat.f))
+#define	p2(f, m) if (arpstat.f || sflag <= 1) \
+    printf(m, arpstat.f, pluralies(arpstat.f))
+
+	p(txrequests, "\t%lu ARP request%s sent\n");
+	p2(txreplies, "\t%lu ARP repl%s sent\n");
+	p(rxrequests, "\t%lu ARP request%s received\n");
+	p2(rxreplies, "\t%lu ARP repl%s received\n");
+	p(received, "\t%lu ARP packet%s received\n");
+	p(dropped, "\t%lu total packet%s dropped due to no ARP entry\n");
+	p(timeouts, "\t%lu ARP entry%s timed out\n");
+	p(dupips, "\t%lu Duplicate IP%s seen\n");
+#undef p
+#undef p2
+}
+
+
+
 static	const char *icmpnames[ICMP_MAXTYPE + 1] = {
 	"echo reply",			/* RFC 792 */
 	"#1",
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c
index 8b25ff520b5..ebbe1d24fbf 100644
--- a/usr.bin/netstat/main.c
+++ b/usr.bin/netstat/main.c
@@ -184,6 +184,8 @@ static struct nlist nl[] = {
 	{ .n_name = "_sctpstat" },
 #define	N_MFCTABLESIZE	54
 	{ .n_name = "_mfctablesize" },
+#define N_ARPSTAT       55
+	{ .n_name = "_arpstat" },
 	{ .n_name = NULL },
 };
 
@@ -232,6 +234,8 @@ struct protox {
 	  carp_stats,	NULL,		"carp",	1,	0 },
 	{ -1,		N_PFSYNCSTAT,	1,	NULL,
 	  pfsync_stats,	NULL,		"pfsync", 1,	0 },
+	{ -1,		N_ARPSTAT,	1,	NULL,
+	  arp_stats,	NULL,		"arp", 1,	0 },
 	{ -1,		-1,		0,	NULL,
 	  NULL,		NULL,		NULL,	0,	0 }
 };
diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h
index 483bd6c43ef..f834495e32b 100644
--- a/usr.bin/netstat/netstat.h
+++ b/usr.bin/netstat/netstat.h
@@ -75,6 +75,7 @@ void	udp_stats(u_long, const char *, int, int);
 void	sctp_protopr(u_long, const char *, int, int);
 void	sctp_stats(u_long, const char *, int, int);
 #endif
+void	arp_stats(u_long, const char *, int, int);
 void	ip_stats(u_long, const char *, int, int);
 void	icmp_stats(u_long, const char *, int, int);
 void	igmp_stats(u_long, const char *, int, int);
diff --git a/usr.bin/procstat/procstat.1 b/usr.bin/procstat/procstat.1
index a9b32007af8..0fdff9a3c52 100644
--- a/usr.bin/procstat/procstat.1
+++ b/usr.bin/procstat/procstat.1
@@ -351,10 +351,8 @@ may be mechanically parsed.
 .Pp
 The display of open file or memory mapping pathnames is implemented using the
 kernel's name cache.
-It therefore does not work for file systems
-that do not use the name cache, such as
-.Xr devfs 4 ,
-or if the name is not present in the cache due to removal.
+If a file system does not use the name cache, or the path to a file is not in
+the cache, a path will not be displayed.
 .Pp
 .Nm
 currently supports extracting data only from a live kernel, and not from
diff --git a/usr.bin/tar/Makefile b/usr.bin/tar/Makefile
index 10998462d91..22f8ff79517 100644
--- a/usr.bin/tar/Makefile
+++ b/usr.bin/tar/Makefile
@@ -12,7 +12,7 @@ LDADD+= -lcrypto
 .endif
 CFLAGS+=	-DBSDTAR_VERSION_STRING=\"${BSDTAR_VERSION_STRING}\"
 CFLAGS+=	-DPLATFORM_CONFIG_H=\"config_freebsd.h\"
-CFLAGS+=	-I${.CURDIR}
+CFLAGS+=	-I${.CURDIR} -I${.CURDIR}/../../lib/libarchive
 SYMLINKS=	bsdtar ${BINDIR}/tar
 MLINKS=	bsdtar.1 tar.1
 DEBUG_FLAGS=-g
diff --git a/usr.bin/unzip/unzip.1 b/usr.bin/unzip/unzip.1
index 031cf3d2799..b6ee87aa1b5 100644
--- a/usr.bin/unzip/unzip.1
+++ b/usr.bin/unzip/unzip.1
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 30, 2008
+.Dd September 7, 2009
 .Dt UNZIP 1
 .Os
 .Sh NAME
@@ -33,7 +33,7 @@
 .Nd extract files from a ZIP archive
 .Sh SYNOPSIS
 .Nm
-.Op Fl ajLlnoqtu
+.Op Fl aCcfjLlnopqtuv
 .Op Fl d Ar dir
 .Ar zipfile
 .Sh DESCRIPTION
@@ -44,9 +44,22 @@ The following options are available:
 .It Fl a
 When extracting a text file, convert DOS-style line endings to
 Unix-style line endings.
+.It Fl C
+Match file names case-insensitively.
+.It Fl c
+Extract to stdout/screen.
+When extracting files from the zipfile, they are written to stdout.
+This is similar to
+.Fl p ,
+but doesn't suppress normal output.
 .It Fl d Ar dir
 Extract files into the specified directory rather than the current
 directory.
+.It Fl f
+Update existing.
+Extract only files from the zipfile if a file with the same name
+already exists on disk and is older than the former.
+Otherwise, the file is silently skipped.
 .It Fl j
 Ignore directories stored in the zipfile; instead, extract all files
 directly into the extraction directory.
@@ -56,13 +69,19 @@ Convert the names of the extracted files and directories to lowercase.
 List, rather than extract, the contents of the zipfile.
 .It Fl n
 No overwrite.
-When extacting a file from the zipfile, if a file with the same name
+When extracting a file from the zipfile, if a file with the same name
 already exists on disk, the file is silently skipped.
 .It Fl o
 Overwrite.
-When extacting a file from the zipfile, if a file with the same name
+When extracting a file from the zipfile, if a file with the same name
 already exists on disk, the existing file is replaced with the file
 from the zipfile.
+.It Fl p
+Extract to stdout.
+When extracting files from the zipfile, they are written to stdout.
+The normal output is suppressed as if
+.Fl q
+was specified.
 .It Fl q
 Quiet: print less information while extracting.
 .It Fl t
@@ -70,15 +89,25 @@ Test: do not extract anything, but verify the checksum of every file
 in the archive.
 .It Fl u
 Update.
-When extacting a file from the zipfile, if a file with the same name
+When extracting a file from the zipfile, if a file with the same name
 already exists on disk, the existing file is replaced with the file
 from the zipfile if and only if the latter is newer than the former.
 Otherwise, the file is silently skipped.
+.It Fl v
+List verbosely, rather than extract, the contents of the zipfile.
+This differs from
+.Fl l
+by using the long listing.
+Note that most of the data is currently fake and does not reflect the
+content of the archive.
+.It Fl x Ar pattern
+Exclude files matching the pattern
+.Ar pattern .
 .El
 .Pp
 Note that only one of
 .Fl n ,
-.Fl o
+.Fl o ,
 and
 .Fl u
 may be specified.
diff --git a/usr.bin/unzip/unzip.c b/usr.bin/unzip/unzip.c
index 16373f51a1d..f0856a430e3 100644
--- a/usr.bin/unzip/unzip.c
+++ b/usr.bin/unzip/unzip.c
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2009 Joerg Sonnenberger 
  * Copyright (c) 2007-2008 Dag-Erling Coïdan Smørgrav
  * All rights reserved.
  *
@@ -51,15 +52,19 @@
 
 /* command-line options */
 static int		 a_opt;		/* convert EOL */
+static int		 C_opt;		/* match case-insensitively */
+static int		 c_opt;		/* extract to stdout */
 static const char	*d_arg;		/* directory */
+static int		 f_opt;		/* update existing files only */
 static int		 j_opt;		/* junk directories */
 static int		 L_opt;		/* lowercase names */
-static int		 l_opt;		/* list */
 static int		 n_opt;		/* never overwrite */
 static int		 o_opt;		/* always overwrite */
+static int		 p_opt;		/* extract to stdout, quiet */
 static int		 q_opt;		/* quiet */
 static int		 t_opt;		/* test */
 static int		 u_opt;		/* update */
+static int		 v_opt;		/* verbose/list */
 
 /* time when unzip started */
 static time_t		 now;
@@ -70,9 +75,6 @@ static int		 unzip_debug;
 /* running on tty? */
 static int		 tty;
 
-/* error flag for -t */
-static int		 test_failed;
-
 /* convenience macro */
 /* XXX should differentiate between ARCHIVE_{WARN,FAIL,RETRY} */
 #define ac(call)						\
@@ -162,7 +164,6 @@ static void
 info(const char *fmt, ...)
 {
 	va_list ap;
-	int i;
 
 	if (q_opt && !unzip_debug)
 		return;
@@ -171,9 +172,10 @@ info(const char *fmt, ...)
 	va_end(ap);
 	fflush(stdout);
 
-	for (i = 0; fmt[i] != '\0'; ++i)
-		/* nothing */ ;
-	noeol = !(i && fmt[i - 1] == '\n');
+	if (*fmt == '\0')
+		noeol = 1;
+	else
+		noeol = fmt[strlen(fmt) - 1] != '\n';
 }
 
 /* debug message (if unzip_debug) */
@@ -181,7 +183,6 @@ static void
 debug(const char *fmt, ...)
 {
 	va_list ap;
-	int i;
 
 	if (!unzip_debug)
 		return;
@@ -190,9 +191,10 @@ debug(const char *fmt, ...)
 	va_end(ap);
 	fflush(stderr);
 
-	for (i = 0; fmt[i] != '\0'; ++i)
-		/* nothing */ ;
-	noeol = !(i && fmt[i - 1] == '\n');
+	if (*fmt == '\0')
+		noeol = 1;
+	else
+		noeol = fmt[strlen(fmt) - 1] != '\n';
 }
 
 /* duplicate a path name, possibly converting to lower case */
@@ -200,7 +202,7 @@ static char *
 pathdup(const char *path)
 {
 	char *str;
-	int len;
+	size_t i, len;
 
 	len = strlen(path);
 	while (len && path[len - 1] == '/')
@@ -209,8 +211,12 @@ pathdup(const char *path)
 		errno = ENOMEM;
 		error("malloc()");
 	}
-	for (int i = 0; i < len; ++i)
-		str[i] = L_opt ? tolower(path[i]) : path[i];
+	if (L_opt) {
+		for (i = 0; i < len; ++i)
+			str[i] = tolower((unsigned char)path[i]);
+	} else {
+		memcpy(str, path, len);
+	}
 	str[len] = '\0';
 
 	return (str);
@@ -221,7 +227,7 @@ static char *
 pathcat(const char *prefix, const char *path)
 {
 	char *str;
-	int prelen, len;
+	size_t prelen, len;
 
 	prelen = prefix ? strlen(prefix) + 1 : 0;
 	len = strlen(path) + 1;
@@ -257,7 +263,7 @@ static void
 add_pattern(struct pattern_list *list, const char *pattern)
 {
 	struct pattern *entry;
-	int len;
+	size_t len;
 
 	debug("adding pattern '%s'\n", pattern);
 	len = strlen(pattern);
@@ -265,7 +271,6 @@ add_pattern(struct pattern_list *list, const char *pattern)
 		errno = ENOMEM;
 		error("malloc()");
 	}
-	memset(&entry->link, 0, sizeof entry->link);
 	memcpy(entry->pattern, pattern, len + 1);
 	STAILQ_INSERT_TAIL(list, entry, link);
 }
@@ -279,7 +284,7 @@ match_pattern(struct pattern_list *list, const char *str)
 	struct pattern *entry;
 
 	STAILQ_FOREACH(entry, list, link) {
-		if (fnmatch(entry->pattern, str, 0) == 0)
+		if (fnmatch(entry->pattern, str, C_opt ? FNM_CASEFOLD : 0) == 0)
 			return (1);
 	}
 	return (0);
@@ -427,9 +432,9 @@ extract_file(struct archive *a, struct archive_entry *e, const char *path)
 
 	/* look for existing file of same name */
 	if (lstat(path, &sb) == 0) {
-		if (u_opt) {
+		if (u_opt || f_opt) {
 			/* check if up-to-date */
-			if (S_ISREG(sb.st_mode) && sb.st_mtime > mtime)
+			if (S_ISREG(sb.st_mode) && sb.st_mtime >= mtime)
 				return;
 			(void)unlink(path);
 		} else if (o_opt) {
@@ -442,13 +447,16 @@ extract_file(struct archive *a, struct archive_entry *e, const char *path)
 			/* XXX ask user */
 			errorx("not implemented");
 		}
+	} else {
+		if (f_opt)
+			return;
 	}
 
 	if ((fd = open(path, O_RDWR|O_CREAT|O_TRUNC, mode)) < 0)
 		error("open('%s')", path);
 
 	/* loop over file contents and write to disk */
-	info("x %s", path);
+	info(" extracting: %s", path);
 	text = a_opt;
 	warn = 0;
 	cr = 0;
@@ -618,40 +626,172 @@ extract(struct archive *a, struct archive_entry *e)
 	free(pathname);
 }
 
+static void
+extract_stdout(struct archive *a, struct archive_entry *e)
+{
+	char *pathname;
+	mode_t filetype;
+	int cr, text, warn;
+	ssize_t len;
+	unsigned char *p, *q, *end;
+
+	pathname = pathdup(archive_entry_pathname(e));
+	filetype = archive_entry_filetype(e);
+
+	/* I don't think this can happen in a zipfile.. */
+	if (!S_ISDIR(filetype) && !S_ISREG(filetype)) {
+		warningx("skipping non-regular entry '%s'", pathname);
+		ac(archive_read_data_skip(a));
+		free(pathname);
+		return;
+	}
+
+	/* skip directories in -j case */
+	if (S_ISDIR(filetype)) {
+		ac(archive_read_data_skip(a));
+		free(pathname);
+		return;
+	}
+
+	/* apply include / exclude patterns */
+	if (!accept_pathname(pathname)) {
+		ac(archive_read_data_skip(a));
+		free(pathname);
+		return;
+	}
+
+	if (c_opt)
+		info("x %s\n", pathname);
+
+	text = a_opt;
+	warn = 0;
+	cr = 0;
+	for (int n = 0; ; n++) {
+		len = archive_read_data(a, buffer, sizeof buffer);
+
+		if (len < 0)
+			ac(len);
+
+		/* left over CR from previous buffer */
+		if (a_opt && cr) {
+			if (len == 0 || buffer[0] != '\n') {
+				if (fwrite("\r", 1, 1, stderr) != 1)
+					error("write('%s')", pathname);
+			}
+			cr = 0;
+		}
+
+		/* EOF */
+		if (len == 0)
+			break;
+		end = buffer + len;
+
+		/*
+		 * Detect whether this is a text file.  The correct way to
+		 * do this is to check the least significant bit of the
+		 * "internal file attributes" field of the corresponding
+		 * file header in the central directory, but libarchive
+		 * does not read the central directory, so we have to
+		 * guess by looking for non-ASCII characters in the
+		 * buffer.  Hopefully we won't guess wrong.  If we do
+		 * guess wrong, we print a warning message later.
+		 */
+		if (a_opt && n == 0) {
+			for (p = buffer; p < end; ++p) {
+				if (!isascii((unsigned char)*p)) {
+					text = 0;
+					break;
+				}
+			}
+		}
+
+		/* simple case */
+		if (!a_opt || !text) {
+			if (fwrite(buffer, 1, len, stdout) != (size_t)len)
+				error("write('%s')", pathname);
+			continue;
+		}
+
+		/* hard case: convert \r\n to \n (sigh...) */
+		for (p = buffer; p < end; p = q + 1) {
+			for (q = p; q < end; q++) {
+				if (!warn && !isascii(*q)) {
+					warningx("%s may be corrupted due"
+					    " to weak text file detection"
+					    " heuristic", pathname);
+					warn = 1;
+				}
+				if (q[0] != '\r')
+					continue;
+				if (&q[1] == end) {
+					cr = 1;
+					break;
+				}
+				if (q[1] == '\n')
+					break;
+			}
+			if (fwrite(p, 1, q - p, stdout) != (size_t)(q - p))
+				error("write('%s')", pathname);
+		}
+	}
+
+	free(pathname);
+}
+
 /*
  * Print the name of an entry to stdout.
  */
 static void
 list(struct archive *a, struct archive_entry *e)
 {
+	char buf[20];
+	time_t mtime;
 
-	printf("%s\n", archive_entry_pathname(e));
+	mtime = archive_entry_mtime(e);
+	strftime(buf, sizeof(buf), "%m-%d-%g %R", localtime(&mtime));
+
+	if (v_opt == 1) {
+		printf(" %8ju  %s   %s\n",
+		    (uintmax_t)archive_entry_size(e),
+		    buf, archive_entry_pathname(e));
+	} else if (v_opt == 2) {
+		printf("%8ju  Stored  %7ju   0%%  %s  %08x  %s\n",
+		    (uintmax_t)archive_entry_size(e),
+		    (uintmax_t)archive_entry_size(e),
+		    buf,
+		    0U,
+		    archive_entry_pathname(e));
+	}
 	ac(archive_read_data_skip(a));
 }
 
 /*
  * Extract to memory to check CRC
  */
-static void
+static int
 test(struct archive *a, struct archive_entry *e)
 {
 	ssize_t len;
+	int error_count;
 
+	error_count = 0;
 	if (S_ISDIR(archive_entry_filetype(e)))
-		return;
+		return 0;
 
-	info("%s ", archive_entry_pathname(e));
+	info("    testing: %s\t", archive_entry_pathname(e));
 	while ((len = archive_read_data(a, buffer, sizeof buffer)) > 0)
 		/* nothing */;
 	if (len < 0) {
-		info("%s\n", archive_error_string(a));
-		++test_failed;
+		info(" %s\n", archive_error_string(a));
+		++error_count;
 	} else {
-		info("OK\n");
+		info(" OK\n");
 	}
 
 	/* shouldn't be necessary, but it doesn't hurt */
 	ac(archive_read_data_skip(a));
+
+	return error_count;
 }
 
 
@@ -665,6 +805,7 @@ unzip(const char *fn)
 	struct archive *a;
 	struct archive_entry *e;
 	int fd, ret;
+	uintmax_t total_size, file_count, error_count;
 
 	if ((fd = open(fn, O_RDONLY)) < 0)
 		error("%s", fn);
@@ -673,33 +814,69 @@ unzip(const char *fn)
 	ac(archive_read_support_format_zip(a));
 	ac(archive_read_open_fd(a, fd, 8192));
 
+	printf("Archive:  %s\n", fn);
+	if (v_opt == 1) {
+		printf("  Length     Date   Time    Name\n");
+		printf(" --------    ----   ----    ----\n");
+	} else if (v_opt == 2) {
+		printf(" Length   Method    Size  Ratio   Date   Time   CRC-32    Name\n");
+		printf("--------  ------  ------- -----   ----   ----   ------    ----\n");
+	}
+
+	total_size = 0;
+	file_count = 0;
+	error_count = 0;
 	for (;;) {
 		ret = archive_read_next_header(a, &e);
 		if (ret == ARCHIVE_EOF)
 			break;
 		ac(ret);
 		if (t_opt)
-			test(a, e);
-		else if (l_opt)
+			error_count += test(a, e);
+		else if (v_opt)
 			list(a, e);
+		else if (p_opt || c_opt)
+			extract_stdout(a, e);
 		else
 			extract(a, e);
+
+		total_size += archive_entry_size(e);
+		++file_count;
+	}
+
+	if (v_opt == 1) {
+		printf(" --------                   -------\n");
+		printf(" %8ju                   %ju file%s\n",
+		    total_size, file_count, file_count != 1 ? "s" : "");
+	} else if (v_opt == 2) {
+		printf("--------          -------  ---                            -------\n");
+		printf("%8ju          %7ju   0%%                            %ju file%s\n",
+		    total_size, total_size, file_count,
+		    file_count != 1 ? "s" : "");
 	}
 
 	ac(archive_read_close(a));
 	(void)archive_read_finish(a);
+
 	if (close(fd) != 0)
 		error("%s", fn);
 
-	if (t_opt && test_failed)
-		errorx("%d checksum error(s) found.", test_failed);
+	if (t_opt) {
+		if (error_count > 0) {
+			errorx("%d checksum error(s) found.", error_count);
+		}
+		else {
+			printf("No errors detected in compressed data of %s.\n",
+			       fn);
+		}
+	}
 }
 
 static void
 usage(void)
 {
 
-	fprintf(stderr, "usage: unzip [-ajLlnoqtu] [-d dir] zipfile\n");
+	fprintf(stderr, "usage: unzip [-aCcfjLlnopqtuv] [-d dir] [-x pattern] zipfile\n");
 	exit(1);
 }
 
@@ -709,14 +886,23 @@ getopts(int argc, char *argv[])
 	int opt;
 
 	optreset = optind = 1;
-	while ((opt = getopt(argc, argv, "ad:jLlnoqtux:")) != -1)
+	while ((opt = getopt(argc, argv, "aCcd:fjLlnopqtuvx:")) != -1)
 		switch (opt) {
 		case 'a':
 			a_opt = 1;
 			break;
+		case 'C':
+			C_opt = 1;
+			break;
+		case 'c':
+			c_opt = 1;
+			break;
 		case 'd':
 			d_arg = optarg;
 			break;
+		case 'f':
+			f_opt = 1;
+			break;
 		case 'j':
 			j_opt = 1;
 			break;
@@ -724,13 +910,18 @@ getopts(int argc, char *argv[])
 			L_opt = 1;
 			break;
 		case 'l':
-			l_opt = 1;
+			if (v_opt == 0)
+				v_opt = 1;
 			break;
 		case 'n':
 			n_opt = 1;
 			break;
 		case 'o':
 			o_opt = 1;
+			q_opt = 1;
+			break;
+		case 'p':
+			p_opt = 1;
 			break;
 		case 'q':
 			q_opt = 1;
@@ -741,6 +932,9 @@ getopts(int argc, char *argv[])
 		case 'u':
 			u_opt = 1;
 			break;
+		case 'v':
+			v_opt = 2;
+			break;
 		case 'x':
 			add_pattern(&exclude, optarg);
 			break;
diff --git a/usr.bin/w/extern.h b/usr.bin/w/extern.h
index 070d055b061..f3c0045bd93 100644
--- a/usr.bin/w/extern.h
+++ b/usr.bin/w/extern.h
@@ -38,6 +38,6 @@
 extern	int use_ampm;
 
 struct kinfo_proc;
-void	pr_attime(time_t *, time_t *);
+int	pr_attime(time_t *, time_t *);
 int	pr_idle(time_t);
 int	proc_compare(struct kinfo_proc *, struct kinfo_proc *);
diff --git a/usr.bin/w/pr_time.c b/usr.bin/w/pr_time.c
index 9fe0b11df8b..acf6f8c987b 100644
--- a/usr.bin/w/pr_time.c
+++ b/usr.bin/w/pr_time.c
@@ -52,13 +52,14 @@ static const char sccsid[] = "@(#)pr_time.c	8.2 (Berkeley) 4/4/94";
  * pr_attime --
  *	Print the time since the user logged in.
  */
-void
+int
 pr_attime(time_t *started, time_t *now)
 {
-	static char buf[256];
+	static wchar_t buf[256];
 	struct tm tp, tm;
 	time_t diff;
-	char fmt[20];
+	const wchar_t *fmt;
+	int len, width, offset = 0;
 
 	tp = *localtime(started);
 	tm = *localtime(now);
@@ -66,7 +67,7 @@ pr_attime(time_t *started, time_t *now)
 
 	/* If more than a week, use day-month-year. */
 	if (diff > 86400 * 7)
-		(void)strcpy(fmt, "%d%b%y");
+		fmt = L"%d%b%y";
 
 	/* If not today, use day-hour-am/pm. */
 	else if (tm.tm_mday != tp.tm_mday ||
@@ -74,16 +75,26 @@ pr_attime(time_t *started, time_t *now)
 		 tm.tm_year != tp.tm_year) {
 	/* The line below does not take DST into consideration */
 	/* else if (*now / 86400 != *started / 86400) { */
-		(void)strcpy(fmt, use_ampm ? "%a%I%p" : "%a%H");
+		fmt = use_ampm ? L"%a%I%p" : L"%a%H";
 	}
 
 	/* Default is hh:mm{am,pm}. */
 	else {
-		(void)strcpy(fmt, use_ampm ? "%l:%M%p" : "%k:%M");
+		fmt = use_ampm ? L"%l:%M%p" : L"%k:%M";
 	}
 
-	(void)strftime(buf, sizeof(buf), fmt, &tp);
-	(void)wprintf(L"%-7.7s", buf);
+	(void)wcsftime(buf, sizeof(buf), fmt, &tp);
+	len = wcslen(buf);
+	width = wcswidth(buf, len);
+	if (len == width)
+		(void)wprintf(L"%-7.7ls", buf);
+	else if (width < 7)
+		(void)wprintf(L"%ls%.*s", buf, 7 - width, "      ");
+	else {
+		(void)wprintf(L"%ls", buf);
+		offset = width - 7;
+	}
+	return (offset);
 }
 
 /*
diff --git a/usr.bin/w/w.c b/usr.bin/w/w.c
index 379e6a43854..10ec7b04bd2 100644
--- a/usr.bin/w/w.c
+++ b/usr.bin/w/w.c
@@ -137,7 +137,7 @@ main(int argc, char *argv[])
 	struct stat *stp;
 	FILE *ut;
 	time_t touched;
-	int ch, i, nentries, nusers, wcmd, longidle, dropgid;
+	int ch, i, nentries, nusers, wcmd, longidle, longattime, dropgid;
 	const char *memf, *nlistf, *p;
 	char *x_suffix;
 	char buf[MAXHOSTNAMELEN], errbuf[_POSIX2_LINE_MAX];
@@ -406,9 +406,10 @@ main(int argc, char *argv[])
 		    ep->utmp.ut_line : ep->utmp.ut_line + 3,
 		    W_DISPHOSTSIZE, W_DISPHOSTSIZE, *p ? p : "-");
 		t = _time_to_time32(ep->utmp.ut_time);
-		pr_attime(&t, &now);
+		longattime = pr_attime(&t, &now);
 		longidle = pr_idle(ep->idle);
-		(void)printf("%.*s\n", argwidth - longidle, ep->args);
+		(void)printf("%.*s\n", argwidth - longidle - longattime,
+		    ep->args);
 	}
 	(void)kvm_close(kd);
 	exit(0);
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index f57ff3a1daf..160b122571a 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -94,6 +94,7 @@ SUBDIR=	${_ac} \
 	manctl \
 	memcontrol \
 	mergemaster \
+	mfiutil \
 	mixer \
 	${_mld6query} \
 	mlxcontrol \
@@ -103,6 +104,7 @@ SUBDIR=	${_ac} \
 	${_mount_smbfs} \
 	${_moused} \
 	${_mptable} \
+	mptutil \
 	mtest \
 	mtree \
 	${_named} \
diff --git a/usr.sbin/acpi/acpidump/acpi.c b/usr.sbin/acpi/acpidump/acpi.c
index 800655c472c..8a89f108ee4 100644
--- a/usr.sbin/acpi/acpidump/acpi.c
+++ b/usr.sbin/acpi/acpidump/acpi.c
@@ -47,31 +47,36 @@
 #define END_COMMENT	" */\n"
 
 static void	acpi_print_string(char *s, size_t length);
-static void	acpi_print_gas(struct ACPIgas *gas);
-static int	acpi_get_fadt_revision(struct FADTbody *fadt);
-static void	acpi_handle_fadt(struct ACPIsdt *fadt);
+static void	acpi_print_gas(ACPI_GENERIC_ADDRESS *gas);
+static int	acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt);
+static void	acpi_handle_fadt(ACPI_TABLE_HEADER *fadt);
 static void	acpi_print_cpu(u_char cpu_id);
-static void	acpi_print_local_apic(u_char cpu_id, u_char apic_id,
-				      u_int32_t flags);
-static void	acpi_print_io_apic(u_char apic_id, u_int32_t int_base,
-				   u_int64_t apic_addr);
-static void	acpi_print_mps_flags(u_int16_t flags);
-static void	acpi_print_intr(u_int32_t intr, u_int16_t mps_flags);
-static void	acpi_print_apic(struct MADT_APIC *mp);
-static void	acpi_handle_apic(struct ACPIsdt *sdp);
-static void	acpi_handle_hpet(struct ACPIsdt *sdp);
+static void	acpi_print_cpu_uid(uint32_t uid, char *uid_string);
+static void	acpi_print_local_apic(uint32_t apic_id, uint32_t flags);
+static void	acpi_print_io_apic(uint32_t apic_id, uint32_t int_base,
+		    uint64_t apic_addr);
+static void	acpi_print_mps_flags(uint16_t flags);
+static void	acpi_print_intr(uint32_t intr, uint16_t mps_flags);
+static void	acpi_print_local_nmi(u_int lint, uint16_t mps_flags);
+static void	acpi_print_madt(ACPI_SUBTABLE_HEADER *mp);
+static void	acpi_handle_madt(ACPI_TABLE_HEADER *sdp);
+static void	acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp);
+static void	acpi_handle_hpet(ACPI_TABLE_HEADER *sdp);
+static void	acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp);
 static void	acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
 		    uint32_t flags);
-static void	acpi_print_srat_memory(struct SRAT_memory *mp);
-static void	acpi_print_srat(struct SRATentry *srat);
-static void	acpi_handle_srat(struct ACPIsdt *sdp);
-static void	acpi_print_sdt(struct ACPIsdt *sdp);
-static void	acpi_print_fadt(struct ACPIsdt *sdp);
-static void	acpi_print_facs(struct FACSbody *facs);
-static void	acpi_print_dsdt(struct ACPIsdt *dsdp);
-static struct ACPIsdt *acpi_map_sdt(vm_offset_t pa);
-static void	acpi_print_rsd_ptr(struct ACPIrsdp *rp);
-static void	acpi_handle_rsdt(struct ACPIsdt *rsdp);
+static void	acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp);
+static void	acpi_print_srat(ACPI_SUBTABLE_HEADER *srat);
+static void	acpi_handle_srat(ACPI_TABLE_HEADER *sdp);
+static void	acpi_print_sdt(ACPI_TABLE_HEADER *sdp);
+static void	acpi_print_fadt(ACPI_TABLE_HEADER *sdp);
+static void	acpi_print_facs(ACPI_TABLE_FACS *facs);
+static void	acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp);
+static ACPI_TABLE_HEADER *acpi_map_sdt(vm_offset_t pa);
+static void	acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp);
+static void	acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp);
+static void	acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
+		    void (*action)(ACPI_SUBTABLE_HEADER *));
 
 /* Size of an address. 32-bit for ACPI 1.0, 64-bit for ACPI 2.0 and up. */
 static int addr_size;
@@ -92,41 +97,44 @@ acpi_print_string(char *s, size_t length)
 }
 
 static void
-acpi_print_gas(struct ACPIgas *gas)
+acpi_print_gas(ACPI_GENERIC_ADDRESS *gas)
 {
-	switch(gas->address_space_id) {
+	switch(gas->SpaceId) {
 	case ACPI_GAS_MEMORY:
-		printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->address,
-		       gas->bit_offset, gas->bit_width);
+		printf("0x%08lx:%u[%u] (Memory)", (u_long)gas->Address,
+		       gas->BitOffset, gas->BitWidth);
 		break;
 	case ACPI_GAS_IO:
-		printf("0x%02lx:%u[%u] (IO)", (u_long)gas->address,
-		       gas->bit_offset, gas->bit_width);
+		printf("0x%02lx:%u[%u] (IO)", (u_long)gas->Address,
+		       gas->BitOffset, gas->BitWidth);
 		break;
 	case ACPI_GAS_PCI:
-		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->address >> 32),
-		       (uint16_t)((gas->address >> 16) & 0xffff),
-		       (uint16_t)gas->address);
+		printf("%x:%x+0x%x (PCI)", (uint16_t)(gas->Address >> 32),
+		       (uint16_t)((gas->Address >> 16) & 0xffff),
+		       (uint16_t)gas->Address);
 		break;
 	/* XXX How to handle these below? */
 	case ACPI_GAS_EMBEDDED:
-		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->address,
-		       gas->bit_offset, gas->bit_width);
+		printf("0x%x:%u[%u] (EC)", (uint16_t)gas->Address,
+		       gas->BitOffset, gas->BitWidth);
 		break;
 	case ACPI_GAS_SMBUS:
-		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->address,
-		       gas->bit_offset, gas->bit_width);
+		printf("0x%x:%u[%u] (SMBus)", (uint16_t)gas->Address,
+		       gas->BitOffset, gas->BitWidth);
 		break;
+	case ACPI_GAS_CMOS:
+	case ACPI_GAS_PCIBAR:
+	case ACPI_GAS_DATATABLE:
 	case ACPI_GAS_FIXED:
 	default:
-		printf("0x%08lx (?)", (u_long)gas->address);
+		printf("0x%08lx (?)", (u_long)gas->Address);
 		break;
 	}
 }
 
 /* The FADT revision indicates whether we use the DSDT or X_DSDT addresses. */
 static int
-acpi_get_fadt_revision(struct FADTbody *fadt)
+acpi_get_fadt_revision(ACPI_TABLE_FADT *fadt)
 {
 	int fadt_revision;
 
@@ -141,8 +149,8 @@ acpi_get_fadt_revision(struct FADTbody *fadt)
 		 * 32 and 64 bit versions don't match, prefer the 32 bit
 		 * version for all subsequent tables.
 		 */
-		if (fadt->facs_ptr != 0 &&
-		    (fadt->x_facs_ptr & 0xffffffff) != fadt->facs_ptr)
+		if (fadt->Facs != 0 &&
+		    (fadt->XFacs & 0xffffffff) != fadt->Facs)
 			fadt_revision = 1;
 	} else
 		fadt_revision = 1;
@@ -150,34 +158,51 @@ acpi_get_fadt_revision(struct FADTbody *fadt)
 }
 
 static void
-acpi_handle_fadt(struct ACPIsdt *sdp)
+acpi_handle_fadt(ACPI_TABLE_HEADER *sdp)
 {
-	struct ACPIsdt	*dsdp;
-	struct FACSbody	*facs;
-	struct FADTbody *fadt;
+	ACPI_TABLE_HEADER *dsdp;
+	ACPI_TABLE_FACS	*facs;
+	ACPI_TABLE_FADT *fadt;
 	int		fadt_revision;
 
-	fadt = (struct FADTbody *)sdp->body;
+	fadt = (ACPI_TABLE_FADT *)sdp;
 	acpi_print_fadt(sdp);
 
 	fadt_revision = acpi_get_fadt_revision(fadt);
 	if (fadt_revision == 1)
-		facs = (struct FACSbody *)acpi_map_sdt(fadt->facs_ptr);
+		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->Facs);
 	else
-		facs = (struct FACSbody *)acpi_map_sdt(fadt->x_facs_ptr);
-	if (memcmp(facs->signature, "FACS", 4) != 0 || facs->len < 64)
+		facs = (ACPI_TABLE_FACS *)acpi_map_sdt(fadt->XFacs);
+	if (memcmp(facs->Signature, ACPI_SIG_FACS, 4) != 0 || facs->Length < 64)
 		errx(1, "FACS is corrupt");
 	acpi_print_facs(facs);
 
 	if (fadt_revision == 1)
-		dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr);
+		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
 	else
-		dsdp = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr);
-	if (acpi_checksum(dsdp, dsdp->len))
+		dsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
+	if (acpi_checksum(dsdp, dsdp->Length))
 		errx(1, "DSDT is corrupt");
 	acpi_print_dsdt(dsdp);
 }
 
+static void
+acpi_walk_subtables(ACPI_TABLE_HEADER *table, void *first,
+    void (*action)(ACPI_SUBTABLE_HEADER *))
+{
+	ACPI_SUBTABLE_HEADER *subtable;
+	char *end;
+
+	subtable = first;
+	end = (char *)table + table->Length;
+	while ((char *)subtable < end) {
+		printf("\n");
+		action(subtable);
+		subtable = (ACPI_SUBTABLE_HEADER *)((char *)subtable +
+		    subtable->Length);
+	}
+}
+
 static void
 acpi_print_cpu(u_char cpu_id)
 {
@@ -190,219 +215,264 @@ acpi_print_cpu(u_char cpu_id)
 }
 
 static void
-acpi_print_local_apic(u_char cpu_id, u_char apic_id, u_int32_t flags)
+acpi_print_cpu_uid(uint32_t uid, char *uid_string)
 {
-	acpi_print_cpu(cpu_id);
+
+	printf("\tUID=%d", uid);
+	if (uid_string != NULL)
+		printf(" (%s)", uid_string);
+	printf("\n");
+}
+
+static void
+acpi_print_local_apic(uint32_t apic_id, uint32_t flags)
+{
+
 	printf("\tFlags={");
-	if (flags & ACPI_MADT_APIC_LOCAL_FLAG_ENABLED)
+	if (flags & ACPI_MADT_ENABLED)
 		printf("ENABLED");
 	else
 		printf("DISABLED");
 	printf("}\n");
-	printf("\tAPIC ID=%d\n", (u_int)apic_id);
+	printf("\tAPIC ID=%d\n", apic_id);
 }
 
 static void
-acpi_print_io_apic(u_char apic_id, u_int32_t int_base, u_int64_t apic_addr)
+acpi_print_io_apic(uint32_t apic_id, uint32_t int_base, uint64_t apic_addr)
 {
-	printf("\tAPIC ID=%d\n", (u_int)apic_id);
+
+	printf("\tAPIC ID=%d\n", apic_id);
 	printf("\tINT BASE=%d\n", int_base);
-	printf("\tADDR=0x%016jx\n", apic_addr);
+	printf("\tADDR=0x%016jx\n", (uintmax_t)apic_addr);
 }
 
 static void
-acpi_print_mps_flags(u_int16_t flags)
+acpi_print_mps_flags(uint16_t flags)
 {
 
 	printf("\tFlags={Polarity=");
-	switch (flags & MPS_INT_FLAG_POLARITY_MASK) {
-	case MPS_INT_FLAG_POLARITY_CONFORM:
+	switch (flags & ACPI_MADT_POLARITY_MASK) {
+	case ACPI_MADT_POLARITY_CONFORMS:
 		printf("conforming");
 		break;
-	case MPS_INT_FLAG_POLARITY_HIGH:
+	case ACPI_MADT_POLARITY_ACTIVE_HIGH:
 		printf("active-hi");
 		break;
-	case MPS_INT_FLAG_POLARITY_LOW:
+	case ACPI_MADT_POLARITY_ACTIVE_LOW:
 		printf("active-lo");
 		break;
 	default:
-		printf("0x%x", flags & MPS_INT_FLAG_POLARITY_MASK);
+		printf("0x%x", flags & ACPI_MADT_POLARITY_MASK);
 		break;
 	}
 	printf(", Trigger=");
-	switch (flags & MPS_INT_FLAG_TRIGGER_MASK) {
-	case MPS_INT_FLAG_TRIGGER_CONFORM:
+	switch (flags & ACPI_MADT_TRIGGER_MASK) {
+	case ACPI_MADT_TRIGGER_CONFORMS:
 		printf("conforming");
 		break;
-	case MPS_INT_FLAG_TRIGGER_EDGE:
+	case ACPI_MADT_TRIGGER_EDGE:
 		printf("edge");
 		break;
-	case MPS_INT_FLAG_TRIGGER_LEVEL:
+	case ACPI_MADT_TRIGGER_LEVEL:
 		printf("level");
 		break;
 	default:
-		printf("0x%x", (flags & MPS_INT_FLAG_TRIGGER_MASK) >> 2);
+		printf("0x%x", (flags & ACPI_MADT_TRIGGER_MASK) >> 2);
 	}
 	printf("}\n");
 }
 
 static void
-acpi_print_intr(u_int32_t intr, u_int16_t mps_flags)
+acpi_print_intr(uint32_t intr, uint16_t mps_flags)
 {
 
-	printf("\tINTR=%d\n", (u_int)intr);
+	printf("\tINTR=%d\n", intr);
+	acpi_print_mps_flags(mps_flags);
+}
+
+static void
+acpi_print_local_nmi(u_int lint, uint16_t mps_flags)
+{
+
+	printf("\tLINT Pin=%d\n", lint);
 	acpi_print_mps_flags(mps_flags);
 }
 
 const char *apic_types[] = { "Local APIC", "IO APIC", "INT Override", "NMI",
-			     "Local NMI", "Local APIC Override", "IO SAPIC",
-			     "Local SAPIC", "Platform Interrupt" };
-const char *platform_int_types[] = { "PMI", "INIT",
+			     "Local APIC NMI", "Local APIC Override",
+			     "IO SAPIC", "Local SAPIC", "Platform Interrupt",
+			     "Local X2APIC", "Local X2APIC NMI" };
+const char *platform_int_types[] = { "0 (unknown)", "PMI", "INIT",
 				     "Corrected Platform Error" };
 
 static void
-acpi_print_apic(struct MADT_APIC *mp)
+acpi_print_madt(ACPI_SUBTABLE_HEADER *mp)
 {
+	ACPI_MADT_LOCAL_APIC *lapic;
+	ACPI_MADT_IO_APIC *ioapic;
+	ACPI_MADT_INTERRUPT_OVERRIDE *over;
+	ACPI_MADT_NMI_SOURCE *nmi;
+	ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi;
+	ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_over;
+	ACPI_MADT_IO_SAPIC *iosapic;
+	ACPI_MADT_LOCAL_SAPIC *lsapic;
+	ACPI_MADT_INTERRUPT_SOURCE *isrc;
+	ACPI_MADT_LOCAL_X2APIC *x2apic;
+	ACPI_MADT_LOCAL_X2APIC_NMI *x2apic_nmi;
 
-	if (mp->type < sizeof(apic_types) / sizeof(apic_types[0]))
-		printf("\tType=%s\n", apic_types[mp->type]);
+	if (mp->Type < sizeof(apic_types) / sizeof(apic_types[0]))
+		printf("\tType=%s\n", apic_types[mp->Type]);
 	else
-		printf("\tType=%d (unknown)\n", mp->type);
-	switch (mp->type) {
-	case ACPI_MADT_APIC_TYPE_LOCAL_APIC:
-		acpi_print_local_apic(mp->body.local_apic.cpu_id,
-		    mp->body.local_apic.apic_id, mp->body.local_apic.flags);
+		printf("\tType=%d (unknown)\n", mp->Type);
+	switch (mp->Type) {
+	case ACPI_MADT_TYPE_LOCAL_APIC:
+		lapic = (ACPI_MADT_LOCAL_APIC *)mp;
+		acpi_print_cpu(lapic->ProcessorId);
+		acpi_print_local_apic(lapic->Id, lapic->LapicFlags);
 		break;
-	case ACPI_MADT_APIC_TYPE_IO_APIC:
-		acpi_print_io_apic(mp->body.io_apic.apic_id,
-		    mp->body.io_apic.int_base,
-		    mp->body.io_apic.apic_addr);
+	case ACPI_MADT_TYPE_IO_APIC:
+		ioapic = (ACPI_MADT_IO_APIC *)mp;
+		acpi_print_io_apic(ioapic->Id, ioapic->GlobalIrqBase,
+		    ioapic->Address);
 		break;
-	case ACPI_MADT_APIC_TYPE_INT_OVERRIDE:
-		printf("\tBUS=%d\n", (u_int)mp->body.int_override.bus);
-		printf("\tIRQ=%d\n", (u_int)mp->body.int_override.source);
-		acpi_print_intr(mp->body.int_override.intr,
-		    mp->body.int_override.mps_flags);
+	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
+		over = (ACPI_MADT_INTERRUPT_OVERRIDE *)mp;
+		printf("\tBUS=%d\n", (u_int)over->Bus);
+		printf("\tIRQ=%d\n", (u_int)over->SourceIrq);
+		acpi_print_intr(over->GlobalIrq, over->IntiFlags);
 		break;
-	case ACPI_MADT_APIC_TYPE_NMI:
-		acpi_print_intr(mp->body.nmi.intr, mp->body.nmi.mps_flags);
+	case ACPI_MADT_TYPE_NMI_SOURCE:
+		nmi = (ACPI_MADT_NMI_SOURCE *)mp;
+		acpi_print_intr(nmi->GlobalIrq, nmi->IntiFlags);
 		break;
-	case ACPI_MADT_APIC_TYPE_LOCAL_NMI:
-		acpi_print_cpu(mp->body.local_nmi.cpu_id);
-		printf("\tLINT Pin=%d\n", mp->body.local_nmi.lintpin);
-		acpi_print_mps_flags(mp->body.local_nmi.mps_flags);
+	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
+		lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *)mp;
+		acpi_print_cpu(lapic_nmi->ProcessorId);
+		acpi_print_local_nmi(lapic_nmi->Lint, lapic_nmi->IntiFlags);
 		break;
-	case ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE:
+	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
+		lapic_over = (ACPI_MADT_LOCAL_APIC_OVERRIDE *)mp;
 		printf("\tLocal APIC ADDR=0x%016jx\n",
-		    mp->body.local_apic_override.apic_addr);
+		    (uintmax_t)lapic_over->Address);
 		break;
-	case ACPI_MADT_APIC_TYPE_IO_SAPIC:
-		acpi_print_io_apic(mp->body.io_sapic.apic_id,
-		    mp->body.io_sapic.int_base,
-		    mp->body.io_sapic.apic_addr);
+	case ACPI_MADT_TYPE_IO_SAPIC:
+		iosapic = (ACPI_MADT_IO_SAPIC *)mp;
+		acpi_print_io_apic(iosapic->Id, iosapic->GlobalIrqBase,
+		    iosapic->Address);
 		break;
-	case ACPI_MADT_APIC_TYPE_LOCAL_SAPIC:
-		acpi_print_local_apic(mp->body.local_sapic.cpu_id,
-		    mp->body.local_sapic.apic_id, mp->body.local_sapic.flags);
-		printf("\tAPIC EID=%d\n", (u_int)mp->body.local_sapic.apic_eid);
+	case ACPI_MADT_TYPE_LOCAL_SAPIC:
+		lsapic = (ACPI_MADT_LOCAL_SAPIC *)mp;
+		acpi_print_cpu(lsapic->ProcessorId);
+		acpi_print_local_apic(lsapic->Id, lsapic->LapicFlags);
+		printf("\tAPIC EID=%d\n", (u_int)lsapic->Eid);
+		if (mp->Length > __offsetof(ACPI_MADT_LOCAL_SAPIC, Uid))
+			acpi_print_cpu_uid(lsapic->Uid, lsapic->UidString);
 		break;
-	case ACPI_MADT_APIC_TYPE_INT_SRC:
-		printf("\tType=%s\n",
-		    platform_int_types[mp->body.int_src.type]);
-		printf("\tCPU ID=%d\n", (u_int)mp->body.int_src.cpu_id);
-		printf("\tCPU EID=%d\n", (u_int)mp->body.int_src.cpu_id);
-		printf("\tSAPIC Vector=%d\n",
-		    (u_int)mp->body.int_src.sapic_vector);
-		acpi_print_intr(mp->body.int_src.intr,
-		    mp->body.int_src.mps_flags);
+	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
+		isrc = (ACPI_MADT_INTERRUPT_SOURCE *)mp;
+		if (isrc->Type < sizeof(platform_int_types) /
+		    sizeof(platform_int_types[0]))
+			printf("\tType=%s\n", platform_int_types[isrc->Type]);
+		else
+			printf("\tType=%d (unknown)\n", isrc->Type);
+		printf("\tAPIC ID=%d\n", (u_int)isrc->Id);
+		printf("\tAPIC EID=%d\n", (u_int)isrc->Eid);
+		printf("\tSAPIC Vector=%d\n", (u_int)isrc->IoSapicVector);
+		acpi_print_intr(isrc->GlobalIrq, isrc->IntiFlags);
+		break;
+	case ACPI_MADT_TYPE_LOCAL_X2APIC:
+		x2apic = (ACPI_MADT_LOCAL_X2APIC *)mp;
+		acpi_print_cpu_uid(x2apic->Uid, NULL);
+		acpi_print_local_apic(x2apic->LocalApicId, x2apic->LapicFlags);
+		break;
+	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
+		x2apic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *)mp;
+		acpi_print_cpu_uid(x2apic_nmi->Uid, NULL);
+		acpi_print_local_nmi(x2apic_nmi->Lint, x2apic_nmi->IntiFlags);
 		break;
 	}
 }
 
 static void
-acpi_handle_apic(struct ACPIsdt *sdp)
+acpi_handle_madt(ACPI_TABLE_HEADER *sdp)
 {
-	struct MADTbody *madtp;
-	struct MADT_APIC *madt_apicp;
+	ACPI_TABLE_MADT *madt;
 
 	printf(BEGIN_COMMENT);
 	acpi_print_sdt(sdp);
-	madtp = (struct MADTbody *) sdp->body;
-	printf("\tLocal APIC ADDR=0x%08x\n", madtp->lapic_addr);
+	madt = (ACPI_TABLE_MADT *)sdp;
+	printf("\tLocal APIC ADDR=0x%08x\n", madt->Address);
 	printf("\tFlags={");
-	if (madtp->flags & ACPI_APIC_FLAG_PCAT_COMPAT)
+	if (madt->Flags & ACPI_MADT_PCAT_COMPAT)
 		printf("PC-AT");
 	printf("}\n");
-	madt_apicp = (struct MADT_APIC *)madtp->body;
-	while (((uintptr_t)madt_apicp) - ((uintptr_t)sdp) < sdp->len) {
-		printf("\n");
-		acpi_print_apic(madt_apicp);
-		madt_apicp = (struct MADT_APIC *) ((char *)madt_apicp +
-		    madt_apicp->len);
-	}
+	acpi_walk_subtables(sdp, (madt + 1), acpi_print_madt);
 	printf(END_COMMENT);
 }
 
 static void
-acpi_handle_hpet(struct ACPIsdt *sdp)
+acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
 {
-	struct HPETbody *hpetp;
+	ACPI_TABLE_HPET *hpet;
 
 	printf(BEGIN_COMMENT);
 	acpi_print_sdt(sdp);
-	hpetp = (struct HPETbody *) sdp->body;
-	printf("\tHPET Number=%d\n", hpetp->hpet_number);
+	hpet = (ACPI_TABLE_HPET *)sdp;
+	printf("\tHPET Number=%d\n", hpet->Sequence);
 	printf("\tADDR=");
-	acpi_print_gas(&hpetp->genaddr);
-	printf("\tHW Rev=0x%x\n", hpetp->block_hwrev);
-	printf("\tComparitors=%d\n", hpetp->block_comparitors);
-	printf("\tCounter Size=%d\n", hpetp->block_counter_size);
+	acpi_print_gas(&hpet->Address);
+	printf("\tHW Rev=0x%x\n", hpet->Id & ACPI_HPET_ID_HARDWARE_REV_ID);
+	printf("\tComparators=%d\n", (hpet->Id & ACPI_HPET_ID_COMPARATORS) >>
+	    8);
+	printf("\tCounter Size=%d\n", hpet->Id & ACPI_HPET_ID_COUNT_SIZE_CAP ?
+	    1 : 0);
 	printf("\tLegacy IRQ routing capable={");
-	if (hpetp->block_legacy_capable)
+	if (hpet->Id & ACPI_HPET_ID_LEGACY_CAPABLE)
 		printf("TRUE}\n");
 	else
 		printf("FALSE}\n");
-	printf("\tPCI Vendor ID=0x%04x\n", hpetp->block_pcivendor);
-	printf("\tMinimal Tick=%d\n", hpetp->clock_tick);
+	printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
+	printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
 	printf(END_COMMENT);
 }
 
 static void
-acpi_handle_ecdt(struct ACPIsdt *sdp)
+acpi_handle_ecdt(ACPI_TABLE_HEADER *sdp)
 {
-	struct ECDTbody *ecdt;
+	ACPI_TABLE_ECDT *ecdt;
 
 	printf(BEGIN_COMMENT);
 	acpi_print_sdt(sdp);
-	ecdt = (struct ECDTbody *) sdp->body;
+	ecdt = (ACPI_TABLE_ECDT *)sdp;
 	printf("\tEC_CONTROL=");
-	acpi_print_gas(&ecdt->ec_control);
+	acpi_print_gas(&ecdt->Control);
 	printf("\n\tEC_DATA=");
-	acpi_print_gas(&ecdt->ec_data);
-	printf("\n\tUID=%#x, ", ecdt->uid);
-	printf("GPE_BIT=%#x\n", ecdt->gpe_bit);
-	printf("\tEC_ID=%s\n", ecdt->ec_id);
+	acpi_print_gas(&ecdt->Data);
+	printf("\n\tUID=%#x, ", ecdt->Uid);
+	printf("GPE_BIT=%#x\n", ecdt->Gpe);
+	printf("\tEC_ID=%s\n", ecdt->Id);
 	printf(END_COMMENT);
 }
 
 static void
-acpi_handle_mcfg(struct ACPIsdt *sdp)
+acpi_handle_mcfg(ACPI_TABLE_HEADER *sdp)
 {
-	struct MCFGbody *mcfg;
-	u_int i, e;
+	ACPI_TABLE_MCFG *mcfg;
+	ACPI_MCFG_ALLOCATION *alloc;
+	u_int i, entries;
 
 	printf(BEGIN_COMMENT);
 	acpi_print_sdt(sdp);
-	mcfg = (struct MCFGbody *) sdp->body;
-
-	e = (sdp->len - ((caddr_t)&mcfg->s[0] - (caddr_t)sdp)) /
-	    sizeof(*mcfg->s);
-	for (i = 0; i < e; i++, mcfg++) {
+	mcfg = (ACPI_TABLE_MCFG *)sdp;
+	entries = (sdp->Length - sizeof(ACPI_TABLE_MCFG)) /
+	    sizeof(ACPI_MCFG_ALLOCATION);
+	alloc = (ACPI_MCFG_ALLOCATION *)(mcfg + 1);
+	for (i = 0; i < entries; i++, alloc++) {
 		printf("\n");
-		printf("\tBase Address=0x%016jx\n", mcfg->s[i].baseaddr);
-		printf("\tSegment Group=0x%04x\n", mcfg->s[i].seg_grp);
-		printf("\tStart Bus=%d\n", mcfg->s[i].start);
-		printf("\tEnd Bus=%d\n", mcfg->s[i].end);
+		printf("\tBase Address=0x%016jx\n", alloc->Address);
+		printf("\tSegment Group=0x%04x\n", alloc->PciSegment);
+		printf("\tStart Bus=%d\n", alloc->StartBusNumber);
+		printf("\tEnd Bus=%d\n", alloc->EndBusNumber);
 	}
 	printf(END_COMMENT);
 }
@@ -423,108 +493,109 @@ acpi_print_srat_cpu(uint32_t apic_id, uint32_t proximity_domain,
 }
 
 static void
-acpi_print_srat_memory(struct SRAT_memory *mp)
+acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
 {
 
 	printf("\tFlags={");
-	if (mp->flags & ACPI_SRAT_MEM_ENABLED)
+	if (mp->Flags & ACPI_SRAT_MEM_ENABLED)
 		printf("ENABLED");
 	else
 		printf("DISABLED");
-	if (mp->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
+	if (mp->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
 		printf(",HOT_PLUGGABLE");
-	if (mp->flags & ACPI_SRAT_MEM_NON_VOLATILE)
+	if (mp->Flags & ACPI_SRAT_MEM_NON_VOLATILE)
 		printf(",NON_VOLATILE");
 	printf("}\n");
-	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->base_address);
-	printf("\tLength=0x%016jx\n", (uintmax_t)mp->length);
-	printf("\tProximity Domain=%d\n", mp->proximity_domain);
+	printf("\tBase Address=0x%016jx\n", (uintmax_t)mp->BaseAddress);
+	printf("\tLength=0x%016jx\n", (uintmax_t)mp->Length);
+	printf("\tProximity Domain=%d\n", mp->ProximityDomain);
 }
 
 const char *srat_types[] = { "CPU", "Memory", "X2APIC" };
 
 static void
-acpi_print_srat(struct SRATentry *srat)
+acpi_print_srat(ACPI_SUBTABLE_HEADER *srat)
 {
+	ACPI_SRAT_CPU_AFFINITY *cpu;
+	ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
 
-	if (srat->type < sizeof(srat_types) / sizeof(srat_types[0]))
-		printf("\tType=%s\n", srat_types[srat->type]);
+	if (srat->Type < sizeof(srat_types) / sizeof(srat_types[0]))
+		printf("\tType=%s\n", srat_types[srat->Type]);
 	else
-		printf("\tType=%d (unknown)\n", srat->type);
-	switch (srat->type) {
+		printf("\tType=%d (unknown)\n", srat->Type);
+	switch (srat->Type) {
 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
-		acpi_print_srat_cpu(srat->body.cpu.apic_id,
-		    srat->body.cpu.proximity_domain_hi[2] << 24 |
-		    srat->body.cpu.proximity_domain_hi[1] << 16 |
-		    srat->body.cpu.proximity_domain_hi[0] << 0 |
-		    srat->body.cpu.proximity_domain_lo, srat->body.cpu.flags);
+		cpu = (ACPI_SRAT_CPU_AFFINITY *)srat;
+		acpi_print_srat_cpu(cpu->ApicId,
+		    cpu->ProximityDomainHi[2] << 24 |
+		    cpu->ProximityDomainHi[1] << 16 |
+		    cpu->ProximityDomainHi[0] << 0 |
+		    cpu->ProximityDomainLo, cpu->Flags);
 		break;
 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
-		acpi_print_srat_memory(&srat->body.mem);
+		acpi_print_srat_memory((ACPI_SRAT_MEM_AFFINITY *)srat);
 		break;
 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
-		acpi_print_srat_cpu(srat->body.x2apic.apic_id,
-		    srat->body.x2apic.proximity_domain,
-		    srat->body.x2apic.flags);
+		x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *)srat;
+		acpi_print_srat_cpu(x2apic->ApicId, x2apic->ProximityDomain,
+		    x2apic->Flags);
 		break;
 	}
 }
 
 static void
-acpi_handle_srat(struct ACPIsdt *sdp)
+acpi_handle_srat(ACPI_TABLE_HEADER *sdp)
 {
-	struct SRATbody *sratp;
-	struct SRATentry *entry;
+	ACPI_TABLE_SRAT *srat;
 
 	printf(BEGIN_COMMENT);
 	acpi_print_sdt(sdp);
-	sratp = (struct SRATbody *)sdp->body;
-	printf("\tTable Revision=%d\n", sratp->table_revision);
-	entry = sratp->body;
-	while (((uintptr_t)entry) - ((uintptr_t)sdp) < sdp->len) {
-		printf("\n");
-		acpi_print_srat(entry);
-		entry = (struct SRATentry *)((char *)entry + entry->len);
-	}
+	srat = (ACPI_TABLE_SRAT *)sdp;
+	printf("\tTable Revision=%d\n", srat->TableRevision);
+	acpi_walk_subtables(sdp, (srat + 1), acpi_print_srat);
 	printf(END_COMMENT);
 }
 
 static void
-acpi_print_sdt(struct ACPIsdt *sdp)
+acpi_print_sdt(ACPI_TABLE_HEADER *sdp)
 {
 	printf("  ");
-	acpi_print_string(sdp->signature, 4);
+	acpi_print_string(sdp->Signature, ACPI_NAME_SIZE);
 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
-	       sdp->len, sdp->rev, sdp->check);
+	       sdp->Length, sdp->Revision, sdp->Checksum);
 	printf("\tOEMID=");
-	acpi_print_string(sdp->oemid, 6);
+	acpi_print_string(sdp->OemId, ACPI_OEM_ID_SIZE);
 	printf(", OEM Table ID=");
-	acpi_print_string(sdp->oemtblid, 8);
-	printf(", OEM Revision=0x%x,\n", sdp->oemrev);
+	acpi_print_string(sdp->OemTableId, ACPI_OEM_TABLE_ID_SIZE);
+	printf(", OEM Revision=0x%x,\n", sdp->OemRevision);
 	printf("\tCreator ID=");
-	acpi_print_string(sdp->creator, 4);
-	printf(", Creator Revision=0x%x\n", sdp->crerev);
+	acpi_print_string(sdp->AslCompilerId, ACPI_NAME_SIZE);
+	printf(", Creator Revision=0x%x\n", sdp->AslCompilerRevision);
 }
 
 static void
-acpi_print_rsdt(struct ACPIsdt *rsdp)
+acpi_print_rsdt(ACPI_TABLE_HEADER *rsdp)
 {
+	ACPI_TABLE_RSDT *rsdt;
+	ACPI_TABLE_XSDT *xsdt;
 	int	i, entries;
 	u_long	addr;
 
+	rsdt = (ACPI_TABLE_RSDT *)rsdp;
+	xsdt = (ACPI_TABLE_XSDT *)rsdp;
 	printf(BEGIN_COMMENT);
 	acpi_print_sdt(rsdp);
-	entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size;
+	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
 	printf("\tEntries={ ");
 	for (i = 0; i < entries; i++) {
 		if (i > 0)
 			printf(", ");
 		switch (addr_size) {
 		case 4:
-			addr = le32dec((char*)rsdp->body + i * addr_size);
+			addr = le32toh(rsdt->TableOffsetEntry[i]);
 			break;
 		case 8:
-			addr = le64dec((char*)rsdp->body + i * addr_size);
+			addr = le64toh(xsdt->TableOffsetEntry[i]);
 			break;
 		default:
 			addr = 0;
@@ -542,138 +613,147 @@ static const char *acpi_pm_profiles[] = {
 };
 
 static void
-acpi_print_fadt(struct ACPIsdt *sdp)
+acpi_print_fadt(ACPI_TABLE_HEADER *sdp)
 {
-	struct FADTbody *fadt;
+	ACPI_TABLE_FADT *fadt;
 	const char *pm;
 	char	    sep;
 
-	fadt = (struct FADTbody *)sdp->body;
+	fadt = (ACPI_TABLE_FADT *)sdp;
 	printf(BEGIN_COMMENT);
 	acpi_print_sdt(sdp);
-	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->facs_ptr,
-	       fadt->dsdt_ptr);
-	printf("\tINT_MODEL=%s\n", fadt->int_model ? "APIC" : "PIC");
-	if (fadt->pm_profile >= sizeof(acpi_pm_profiles) / sizeof(char *))
+	printf(" \tFACS=0x%x, DSDT=0x%x\n", fadt->Facs,
+	       fadt->Dsdt);
+	printf("\tINT_MODEL=%s\n", fadt->Model ? "APIC" : "PIC");
+	if (fadt->PreferredProfile >= sizeof(acpi_pm_profiles) / sizeof(char *))
 		pm = "Reserved";
 	else
-		pm = acpi_pm_profiles[fadt->pm_profile];
-	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->pm_profile);
-	printf("\tSCI_INT=%d\n", fadt->sci_int);
-	printf("\tSMI_CMD=0x%x, ", fadt->smi_cmd);
-	printf("ACPI_ENABLE=0x%x, ", fadt->acpi_enable);
-	printf("ACPI_DISABLE=0x%x, ", fadt->acpi_disable);
-	printf("S4BIOS_REQ=0x%x\n", fadt->s4biosreq);
-	printf("\tPSTATE_CNT=0x%x\n", fadt->pstate_cnt);
+		pm = acpi_pm_profiles[fadt->PreferredProfile];
+	printf("\tPreferred_PM_Profile=%s (%d)\n", pm, fadt->PreferredProfile);
+	printf("\tSCI_INT=%d\n", fadt->SciInterrupt);
+	printf("\tSMI_CMD=0x%x, ", fadt->SmiCommand);
+	printf("ACPI_ENABLE=0x%x, ", fadt->AcpiEnable);
+	printf("ACPI_DISABLE=0x%x, ", fadt->AcpiDisable);
+	printf("S4BIOS_REQ=0x%x\n", fadt->S4BiosRequest);
+	printf("\tPSTATE_CNT=0x%x\n", fadt->PstateControl);
 	printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
-	       fadt->pm1a_evt_blk,
-	       fadt->pm1a_evt_blk + fadt->pm1_evt_len - 1);
-	if (fadt->pm1b_evt_blk != 0)
+	       fadt->Pm1aEventBlock,
+	       fadt->Pm1aEventBlock + fadt->Pm1EventLength - 1);
+	if (fadt->Pm1bEventBlock != 0)
 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
-		       fadt->pm1b_evt_blk,
-		       fadt->pm1b_evt_blk + fadt->pm1_evt_len - 1);
+		       fadt->Pm1bEventBlock,
+		       fadt->Pm1bEventBlock + fadt->Pm1EventLength - 1);
 	printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
-	       fadt->pm1a_cnt_blk,
-	       fadt->pm1a_cnt_blk + fadt->pm1_cnt_len - 1);
-	if (fadt->pm1b_cnt_blk != 0)
+	       fadt->Pm1aControlBlock,
+	       fadt->Pm1aControlBlock + fadt->Pm1ControlLength - 1);
+	if (fadt->Pm1bControlBlock != 0)
 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
-		       fadt->pm1b_cnt_blk,
-		       fadt->pm1b_cnt_blk + fadt->pm1_cnt_len - 1);
-	if (fadt->pm2_cnt_blk != 0)
+		       fadt->Pm1bControlBlock,
+		       fadt->Pm1bControlBlock + fadt->Pm1ControlLength - 1);
+	if (fadt->Pm2ControlBlock != 0)
 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
-		       fadt->pm2_cnt_blk,
-		       fadt->pm2_cnt_blk + fadt->pm2_cnt_len - 1);
+		       fadt->Pm2ControlBlock,
+		       fadt->Pm2ControlBlock + fadt->Pm2ControlLength - 1);
 	printf("\tPM_TMR_BLK=0x%x-0x%x\n",
-	       fadt->pm_tmr_blk,
-	       fadt->pm_tmr_blk + fadt->pm_tmr_len - 1);
-	if (fadt->gpe0_blk != 0)
+	       fadt->PmTimerBlock,
+	       fadt->PmTimerBlock + fadt->PmTimerLength - 1);
+	if (fadt->Gpe0Block != 0)
 		printf("\tGPE0_BLK=0x%x-0x%x\n",
-		       fadt->gpe0_blk,
-		       fadt->gpe0_blk + fadt->gpe0_len - 1);
-	if (fadt->gpe1_blk != 0)
+		       fadt->Gpe0Block,
+		       fadt->Gpe0Block + fadt->Gpe0BlockLength - 1);
+	if (fadt->Gpe1Block != 0)
 		printf("\tGPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
-		       fadt->gpe1_blk,
-		       fadt->gpe1_blk + fadt->gpe1_len - 1,
-		       fadt->gpe1_base);
-	if (fadt->cst_cnt != 0)
-		printf("\tCST_CNT=0x%x\n", fadt->cst_cnt);
+		       fadt->Gpe1Block,
+		       fadt->Gpe1Block + fadt->Gpe1BlockLength - 1,
+		       fadt->Gpe1Base);
+	if (fadt->CstControl != 0)
+		printf("\tCST_CNT=0x%x\n", fadt->CstControl);
 	printf("\tP_LVL2_LAT=%d us, P_LVL3_LAT=%d us\n",
-	       fadt->p_lvl2_lat, fadt->p_lvl3_lat);
+	       fadt->C2Latency, fadt->C3Latency);
 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
-	       fadt->flush_size, fadt->flush_stride);
+	       fadt->FlushSize, fadt->FlushStride);
 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
-	       fadt->duty_off, fadt->duty_width);
+	       fadt->DutyOffset, fadt->DutyWidth);
 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
-	       fadt->day_alrm, fadt->mon_alrm, fadt->century);
+	       fadt->DayAlarm, fadt->MonthAlarm, fadt->Century);
 
 #define PRINTFLAG(var, flag) do {			\
-	if ((var) & FADT_FLAG_## flag) {		\
+	if ((var) & ACPI_FADT_## flag) {		\
 		printf("%c%s", sep, #flag); sep = ',';	\
 	}						\
 } while (0)
 
 	printf("\tIAPC_BOOT_ARCH=");
 	sep = '{';
-	PRINTFLAG(fadt->iapc_boot_arch, LEGACY_DEV);
-	PRINTFLAG(fadt->iapc_boot_arch, 8042);
-	if (fadt->iapc_boot_arch != 0)
+	PRINTFLAG(fadt->BootFlags, LEGACY_DEVICES);
+	PRINTFLAG(fadt->BootFlags, 8042);
+	PRINTFLAG(fadt->BootFlags, NO_VGA);
+	PRINTFLAG(fadt->BootFlags, NO_MSI);
+	PRINTFLAG(fadt->BootFlags, NO_ASPM);
+	if (fadt->BootFlags != 0)
 		printf("}");
 	printf("\n");
 
 	printf("\tFlags=");
 	sep = '{';
-	PRINTFLAG(fadt->flags, WBINVD);
-	PRINTFLAG(fadt->flags, WBINVD_FLUSH);
-	PRINTFLAG(fadt->flags, PROC_C1);
-	PRINTFLAG(fadt->flags, P_LVL2_UP);
-	PRINTFLAG(fadt->flags, PWR_BUTTON);
-	PRINTFLAG(fadt->flags, SLP_BUTTON);
-	PRINTFLAG(fadt->flags, FIX_RTC);
-	PRINTFLAG(fadt->flags, RTC_S4);
-	PRINTFLAG(fadt->flags, TMR_VAL_EXT);
-	PRINTFLAG(fadt->flags, DCK_CAP);
-	PRINTFLAG(fadt->flags, RESET_REG);
-	PRINTFLAG(fadt->flags, SEALED_CASE);
-	PRINTFLAG(fadt->flags, HEADLESS);
-	PRINTFLAG(fadt->flags, CPU_SW_SLP);
-	if (fadt->flags != 0)
+	PRINTFLAG(fadt->Flags, WBINVD);
+	PRINTFLAG(fadt->Flags, WBINVD_FLUSH);
+	PRINTFLAG(fadt->Flags, C1_SUPPORTED);
+	PRINTFLAG(fadt->Flags, C2_MP_SUPPORTED);
+	PRINTFLAG(fadt->Flags, POWER_BUTTON);
+	PRINTFLAG(fadt->Flags, SLEEP_BUTTON);
+	PRINTFLAG(fadt->Flags, FIXED_RTC);
+	PRINTFLAG(fadt->Flags, S4_RTC_WAKE);
+	PRINTFLAG(fadt->Flags, 32BIT_TIMER);
+	PRINTFLAG(fadt->Flags, DOCKING_SUPPORTED);
+	PRINTFLAG(fadt->Flags, RESET_REGISTER);
+	PRINTFLAG(fadt->Flags, SEALED_CASE);
+	PRINTFLAG(fadt->Flags, HEADLESS);
+	PRINTFLAG(fadt->Flags, SLEEP_TYPE);
+	PRINTFLAG(fadt->Flags, PCI_EXPRESS_WAKE);
+	PRINTFLAG(fadt->Flags, PLATFORM_CLOCK);
+	PRINTFLAG(fadt->Flags, S4_RTC_VALID);
+	PRINTFLAG(fadt->Flags, REMOTE_POWER_ON);
+	PRINTFLAG(fadt->Flags, APIC_CLUSTER);
+	PRINTFLAG(fadt->Flags, APIC_PHYSICAL);
+	if (fadt->Flags != 0)
 		printf("}\n");
 
 #undef PRINTFLAG
 
-	if (fadt->flags & FADT_FLAG_RESET_REG) {
+	if (fadt->Flags & ACPI_FADT_RESET_REGISTER) {
 		printf("\tRESET_REG=");
-		acpi_print_gas(&fadt->reset_reg);
-		printf(", RESET_VALUE=%#x\n", fadt->reset_value);
+		acpi_print_gas(&fadt->ResetRegister);
+		printf(", RESET_VALUE=%#x\n", fadt->ResetValue);
 	}
 	if (acpi_get_fadt_revision(fadt) > 1) {
-		printf("\tX_FACS=0x%08lx, ", (u_long)fadt->x_facs_ptr);
-		printf("X_DSDT=0x%08lx\n", (u_long)fadt->x_dsdt_ptr);
+		printf("\tX_FACS=0x%08lx, ", (u_long)fadt->XFacs);
+		printf("X_DSDT=0x%08lx\n", (u_long)fadt->XDsdt);
 		printf("\tX_PM1a_EVT_BLK=");
-		acpi_print_gas(&fadt->x_pm1a_evt_blk);
-		if (fadt->x_pm1b_evt_blk.address != 0) {
+		acpi_print_gas(&fadt->XPm1aEventBlock);
+		if (fadt->XPm1bEventBlock.Address != 0) {
 			printf("\n\tX_PM1b_EVT_BLK=");
-			acpi_print_gas(&fadt->x_pm1b_evt_blk);
+			acpi_print_gas(&fadt->XPm1bEventBlock);
 		}
 		printf("\n\tX_PM1a_CNT_BLK=");
-		acpi_print_gas(&fadt->x_pm1a_cnt_blk);
-		if (fadt->x_pm1b_cnt_blk.address != 0) {
+		acpi_print_gas(&fadt->XPm1aControlBlock);
+		if (fadt->XPm1bControlBlock.Address != 0) {
 			printf("\n\tX_PM1b_CNT_BLK=");
-			acpi_print_gas(&fadt->x_pm1b_cnt_blk);
+			acpi_print_gas(&fadt->XPm1bControlBlock);
 		}
-		if (fadt->x_pm1b_cnt_blk.address != 0) {
+		if (fadt->XPm2ControlBlock.Address != 0) {
 			printf("\n\tX_PM2_CNT_BLK=");
-			acpi_print_gas(&fadt->x_pm2_cnt_blk);
+			acpi_print_gas(&fadt->XPm2ControlBlock);
 		}
 		printf("\n\tX_PM_TMR_BLK=");
-		acpi_print_gas(&fadt->x_pm_tmr_blk);
-		if (fadt->x_gpe0_blk.address != 0) {
+		acpi_print_gas(&fadt->XPmTimerBlock);
+		if (fadt->XGpe0Block.Address != 0) {
 			printf("\n\tX_GPE0_BLK=");
-			acpi_print_gas(&fadt->x_gpe0_blk);
+			acpi_print_gas(&fadt->XGpe0Block);
 		}
-		if (fadt->x_gpe1_blk.address != 0) {
+		if (fadt->XGpe1Block.Address != 0) {
 			printf("\n\tX_GPE1_BLK=");
-			acpi_print_gas(&fadt->x_gpe1_blk);
+			acpi_print_gas(&fadt->XGpe1Block);
 		}
 		printf("\n");
 	}
@@ -682,38 +762,38 @@ acpi_print_fadt(struct ACPIsdt *sdp)
 }
 
 static void
-acpi_print_facs(struct FACSbody *facs)
+acpi_print_facs(ACPI_TABLE_FACS *facs)
 {
 	printf(BEGIN_COMMENT);
-	printf("  FACS:\tLength=%u, ", facs->len);
-	printf("HwSig=0x%08x, ", facs->hw_sig);
-	printf("Firm_Wake_Vec=0x%08x\n", facs->firm_wake_vec);
+	printf("  FACS:\tLength=%u, ", facs->Length);
+	printf("HwSig=0x%08x, ", facs->HardwareSignature);
+	printf("Firm_Wake_Vec=0x%08x\n", facs->FirmwareWakingVector);
 
 	printf("\tGlobal_Lock=");
-	if (facs->global_lock != 0) {
-		if (facs->global_lock & FACS_FLAG_LOCK_PENDING)
+	if (facs->GlobalLock != 0) {
+		if (facs->GlobalLock & ACPI_GLOCK_PENDING)
 			printf("PENDING,");
-		if (facs->global_lock & FACS_FLAG_LOCK_OWNED)
+		if (facs->GlobalLock & ACPI_GLOCK_OWNED)
 			printf("OWNED");
 	}
 	printf("\n");
 
 	printf("\tFlags=");
-	if (facs->flags & FACS_FLAG_S4BIOS_F)
+	if (facs->Flags & ACPI_FACS_S4_BIOS_PRESENT)
 		printf("S4BIOS");
 	printf("\n");
 
-	if (facs->x_firm_wake_vec != 0) {
+	if (facs->XFirmwareWakingVector != 0) {
 		printf("\tX_Firm_Wake_Vec=%08lx\n",
-		       (u_long)facs->x_firm_wake_vec);
+		       (u_long)facs->XFirmwareWakingVector);
 	}
-	printf("\tVersion=%u\n", facs->version);
+	printf("\tVersion=%u\n", facs->Version);
 
 	printf(END_COMMENT);
 }
 
 static void
-acpi_print_dsdt(struct ACPIsdt *dsdp)
+acpi_print_dsdt(ACPI_TABLE_HEADER *dsdp)
 {
 	printf(BEGIN_COMMENT);
 	acpi_print_sdt(dsdp);
@@ -723,8 +803,8 @@ acpi_print_dsdt(struct ACPIsdt *dsdp)
 int
 acpi_checksum(void *p, size_t length)
 {
-	u_int8_t	*bp;
-	u_int8_t	sum;
+	uint8_t *bp;
+	uint8_t sum;
 
 	bp = p;
 	sum = 0;
@@ -734,71 +814,77 @@ acpi_checksum(void *p, size_t length)
 	return (sum);
 }
 
-static struct ACPIsdt *
+static ACPI_TABLE_HEADER *
 acpi_map_sdt(vm_offset_t pa)
 {
-	struct	ACPIsdt *sp;
+	ACPI_TABLE_HEADER *sp;
 
-	sp = acpi_map_physical(pa, sizeof(struct ACPIsdt));
-	sp = acpi_map_physical(pa, sp->len);
+	sp = acpi_map_physical(pa, sizeof(ACPI_TABLE_HEADER));
+	sp = acpi_map_physical(pa, sp->Length);
 	return (sp);
 }
 
 static void
-acpi_print_rsd_ptr(struct ACPIrsdp *rp)
+acpi_print_rsd_ptr(ACPI_TABLE_RSDP *rp)
 {
 	printf(BEGIN_COMMENT);
 	printf("  RSD PTR: OEM=");
-	acpi_print_string(rp->oem, 6);
-	printf(", ACPI_Rev=%s (%d)\n", rp->revision < 2 ? "1.0x" : "2.0x",
-	       rp->revision);
-	if (rp->revision < 2) {
-		printf("\tRSDT=0x%08x, cksum=%u\n", rp->rsdt_addr, rp->sum);
+	acpi_print_string(rp->OemId, ACPI_OEM_ID_SIZE);
+	printf(", ACPI_Rev=%s (%d)\n", rp->Revision < 2 ? "1.0x" : "2.0x",
+	       rp->Revision);
+	if (rp->Revision < 2) {
+		printf("\tRSDT=0x%08x, cksum=%u\n", rp->RsdtPhysicalAddress,
+		    rp->Checksum);
 	} else {
 		printf("\tXSDT=0x%08lx, length=%u, cksum=%u\n",
-		    (u_long)rp->xsdt_addr, rp->length, rp->xsum);
+		    (u_long)rp->XsdtPhysicalAddress, rp->Length,
+		    rp->ExtendedChecksum);
 	}
 	printf(END_COMMENT);
 }
 
 static void
-acpi_handle_rsdt(struct ACPIsdt *rsdp)
+acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
 {
-	struct ACPIsdt *sdp;
+	ACPI_TABLE_HEADER *sdp;
+	ACPI_TABLE_RSDT *rsdt;
+	ACPI_TABLE_XSDT *xsdt;
 	vm_offset_t addr;
 	int entries, i;
 
 	acpi_print_rsdt(rsdp);
-	entries = (rsdp->len - SIZEOF_SDT_HDR) / addr_size;
+	rsdt = (ACPI_TABLE_RSDT *)rsdp;
+	xsdt = (ACPI_TABLE_XSDT *)rsdp;
+	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
 	for (i = 0; i < entries; i++) {
 		switch (addr_size) {
 		case 4:
-			addr = le32dec((char*)rsdp->body + i * addr_size);
+			addr = le32toh(rsdt->TableOffsetEntry[i]);
 			break;
 		case 8:
-			addr = le64dec((char*)rsdp->body + i * addr_size);
+			addr = le64toh(xsdt->TableOffsetEntry[i]);
 			break;
 		default:
 			assert((addr = 0));
 		}
 
-		sdp = (struct ACPIsdt *)acpi_map_sdt(addr);
-		if (acpi_checksum(sdp, sdp->len)) {
+		sdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
+		if (acpi_checksum(sdp, sdp->Length)) {
 			warnx("RSDT entry %d (sig %.4s) is corrupt", i,
-			    sdp->signature);
+			    sdp->Signature);
 			continue;
 		}
-		if (!memcmp(sdp->signature, "FACP", 4))
+		if (!memcmp(sdp->Signature, ACPI_SIG_FADT, 4))
 			acpi_handle_fadt(sdp);
-		else if (!memcmp(sdp->signature, "APIC", 4))
-			acpi_handle_apic(sdp);
-		else if (!memcmp(sdp->signature, "HPET", 4))
+		else if (!memcmp(sdp->Signature, ACPI_SIG_MADT, 4))
+			acpi_handle_madt(sdp);
+		else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4))
 			acpi_handle_hpet(sdp);
-		else if (!memcmp(sdp->signature, "ECDT", 4))
+		else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4))
 			acpi_handle_ecdt(sdp);
-		else if (!memcmp(sdp->signature, "MCFG", 4))
+		else if (!memcmp(sdp->Signature, ACPI_SIG_MCFG, 4))
 			acpi_handle_mcfg(sdp);
-		else if (!memcmp(sdp->signature, "SRAT", 4))
+		else if (!memcmp(sdp->Signature, ACPI_SIG_SRAT, 4))
 			acpi_handle_srat(sdp);
 		else {
 			printf(BEGIN_COMMENT);
@@ -808,11 +894,11 @@ acpi_handle_rsdt(struct ACPIsdt *rsdp)
 	}
 }
 
-struct ACPIsdt *
+ACPI_TABLE_HEADER *
 sdt_load_devmem(void)
 {
-	struct	ACPIrsdp *rp;
-	struct	ACPIsdt *rsdp;
+	ACPI_TABLE_RSDP *rp;
+	ACPI_TABLE_HEADER *rsdp;
 
 	rp = acpi_find_rsd_ptr();
 	if (!rp)
@@ -820,16 +906,16 @@ sdt_load_devmem(void)
 
 	if (tflag)
 		acpi_print_rsd_ptr(rp);
-	if (rp->revision < 2) {
-		rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->rsdt_addr);
-		if (memcmp(rsdp->signature, "RSDT", 4) != 0 ||
-		    acpi_checksum(rsdp, rsdp->len) != 0)
+	if (rp->Revision < 2) {
+		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->RsdtPhysicalAddress);
+		if (memcmp(rsdp->Signature, "RSDT", 4) != 0 ||
+		    acpi_checksum(rsdp, rsdp->Length) != 0)
 			errx(1, "RSDT is corrupted");
 		addr_size = sizeof(uint32_t);
 	} else {
-		rsdp = (struct ACPIsdt *)acpi_map_sdt(rp->xsdt_addr);
-		if (memcmp(rsdp->signature, "XSDT", 4) != 0 ||
-		    acpi_checksum(rsdp, rsdp->len) != 0)
+		rsdp = (ACPI_TABLE_HEADER *)acpi_map_sdt(rp->XsdtPhysicalAddress);
+		if (memcmp(rsdp->Signature, "XSDT", 4) != 0 ||
+		    acpi_checksum(rsdp, rsdp->Length) != 0)
 			errx(1, "XSDT is corrupted");
 		addr_size = sizeof(uint64_t);
 	}
@@ -838,37 +924,39 @@ sdt_load_devmem(void)
 
 /* Write the DSDT to a file, concatenating any SSDTs (if present). */
 static int
-write_dsdt(int fd, struct ACPIsdt *rsdt, struct ACPIsdt *dsdt)
+write_dsdt(int fd, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdt)
 {
-	struct ACPIsdt sdt;
-	struct ACPIsdt *ssdt;
+	ACPI_TABLE_HEADER sdt;
+	ACPI_TABLE_HEADER *ssdt;
 	uint8_t sum;
 
 	/* Create a new checksum to account for the DSDT and any SSDTs. */
 	sdt = *dsdt;
 	if (rsdt != NULL) {
-		sdt.check = 0;
-		sum = acpi_checksum(dsdt->body, dsdt->len - SIZEOF_SDT_HDR);
-		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
+		sdt.Checksum = 0;
+		sum = acpi_checksum(dsdt + 1, dsdt->Length -
+		    sizeof(ACPI_TABLE_HEADER));
+		ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, NULL);
 		while (ssdt != NULL) {
-			sdt.len += ssdt->len - SIZEOF_SDT_HDR;
-			sum += acpi_checksum(ssdt->body,
-			    ssdt->len - SIZEOF_SDT_HDR);
-			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
+			sdt.Length += ssdt->Length - sizeof(ACPI_TABLE_HEADER);
+			sum += acpi_checksum(ssdt + 1,
+			    ssdt->Length - sizeof(ACPI_TABLE_HEADER));
+			ssdt = sdt_from_rsdt(rsdt, ACPI_SIG_SSDT, ssdt);
 		}
-		sum += acpi_checksum(&sdt, SIZEOF_SDT_HDR);
-		sdt.check -= sum;
+		sum += acpi_checksum(&sdt, sizeof(ACPI_TABLE_HEADER));
+		sdt.Checksum -= sum;
 	}
 
 	/* Write out the DSDT header and body. */
-	write(fd, &sdt, SIZEOF_SDT_HDR);
-	write(fd, dsdt->body, dsdt->len - SIZEOF_SDT_HDR);
+	write(fd, &sdt, sizeof(ACPI_TABLE_HEADER));
+	write(fd, dsdt + 1, dsdt->Length - sizeof(ACPI_TABLE_HEADER));
 
 	/* Write out any SSDTs (if present.) */
 	if (rsdt != NULL) {
 		ssdt = sdt_from_rsdt(rsdt, "SSDT", NULL);
 		while (ssdt != NULL) {
-			write(fd, ssdt->body, ssdt->len - SIZEOF_SDT_HDR);
+			write(fd, ssdt + 1, ssdt->Length -
+			    sizeof(ACPI_TABLE_HEADER));
 			ssdt = sdt_from_rsdt(rsdt, "SSDT", ssdt);
 		}
 	}
@@ -876,7 +964,7 @@ write_dsdt(int fd, struct ACPIsdt *rsdt, struct ACPIsdt *dsdt)
 }
 
 void
-dsdt_save_file(char *outfile, struct ACPIsdt *rsdt, struct ACPIsdt *dsdp)
+dsdt_save_file(char *outfile, ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
 {
 	int	fd;
 	mode_t	mode;
@@ -893,7 +981,7 @@ dsdt_save_file(char *outfile, struct ACPIsdt *rsdt, struct ACPIsdt *dsdp)
 }
 
 void
-aml_disassemble(struct ACPIsdt *rsdt, struct ACPIsdt *dsdp)
+aml_disassemble(ACPI_TABLE_HEADER *rsdt, ACPI_TABLE_HEADER *dsdp)
 {
 	char buf[PATH_MAX], tmpstr[PATH_MAX];
 	const char *tmpdir;
@@ -949,40 +1037,44 @@ aml_disassemble(struct ACPIsdt *rsdt, struct ACPIsdt *dsdp)
 }
 
 void
-sdt_print_all(struct ACPIsdt *rsdp)
+sdt_print_all(ACPI_TABLE_HEADER *rsdp)
 {
 	acpi_handle_rsdt(rsdp);
 }
 
 /* Fetch a table matching the given signature via the RSDT. */
-struct ACPIsdt *
-sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig, struct ACPIsdt *last)
+ACPI_TABLE_HEADER *
+sdt_from_rsdt(ACPI_TABLE_HEADER *rsdp, const char *sig, ACPI_TABLE_HEADER *last)
 {
-	struct ACPIsdt *sdt;
+	ACPI_TABLE_HEADER *sdt;
+	ACPI_TABLE_RSDT *rsdt;
+	ACPI_TABLE_XSDT *xsdt;
 	vm_offset_t addr;
 	int entries, i;
 
-	entries = (rsdt->len - SIZEOF_SDT_HDR) / addr_size;
+	rsdt = (ACPI_TABLE_RSDT *)rsdp;
+	xsdt = (ACPI_TABLE_XSDT *)rsdp;
+	entries = (rsdp->Length - sizeof(ACPI_TABLE_HEADER)) / addr_size;
 	for (i = 0; i < entries; i++) {
 		switch (addr_size) {
 		case 4:
-			addr = le32dec((char*)rsdt->body + i * addr_size);
+			addr = le32toh(rsdt->TableOffsetEntry[i]);
 			break;
 		case 8:
-			addr = le64dec((char*)rsdt->body + i * addr_size);
+			addr = le64toh(xsdt->TableOffsetEntry[i]);
 			break;
 		default:
 			assert((addr = 0));
 		}
-		sdt = (struct ACPIsdt *)acpi_map_sdt(addr);
+		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(addr);
 		if (last != NULL) {
 			if (sdt == last)
 				last = NULL;
 			continue;
 		}
-		if (memcmp(sdt->signature, sig, strlen(sig)))
+		if (memcmp(sdt->Signature, sig, strlen(sig)))
 			continue;
-		if (acpi_checksum(sdt, sdt->len))
+		if (acpi_checksum(sdt, sdt->Length))
 			errx(1, "RSDT entry %d is corrupt", i);
 		return (sdt);
 	}
@@ -990,17 +1082,17 @@ sdt_from_rsdt(struct ACPIsdt *rsdt, const char *sig, struct ACPIsdt *last)
 	return (NULL);
 }
 
-struct ACPIsdt *
-dsdt_from_fadt(struct FADTbody *fadt)
+ACPI_TABLE_HEADER *
+dsdt_from_fadt(ACPI_TABLE_FADT *fadt)
 {
-	struct	ACPIsdt	*sdt;
+	ACPI_TABLE_HEADER	*sdt;
 
-	/* Use the DSDT address if it is version 1, otherwise use X_DSDT. */
+	/* Use the DSDT address if it is version 1, otherwise use XDSDT. */
 	if (acpi_get_fadt_revision(fadt) == 1)
-		sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->dsdt_ptr);
+		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->Dsdt);
 	else
-		sdt = (struct ACPIsdt *)acpi_map_sdt(fadt->x_dsdt_ptr);
-	if (acpi_checksum(sdt, sdt->len))
+		sdt = (ACPI_TABLE_HEADER *)acpi_map_sdt(fadt->XDsdt);
+	if (acpi_checksum(sdt, sdt->Length))
 		errx(1, "DSDT is corrupt\n");
 	return (sdt);
 }
diff --git a/usr.sbin/acpi/acpidump/acpi_user.c b/usr.sbin/acpi/acpidump/acpi_user.c
index d9d9c2417db..f0c47b41735 100644
--- a/usr.sbin/acpi/acpidump/acpi_user.c
+++ b/usr.sbin/acpi/acpidump/acpi_user.c
@@ -94,40 +94,43 @@ acpi_user_find_mapping(vm_offset_t pa, size_t size)
 	return (map);
 }
 
-static struct ACPIrsdp *
+static ACPI_TABLE_RSDP *
 acpi_get_rsdp(u_long addr)
 {
-	struct ACPIrsdp rsdp;
+	ACPI_TABLE_RSDP rsdp;
 	size_t len;
 
 	/* Read in the table signature and check it. */
 	pread(acpi_mem_fd, &rsdp, 8, addr);
-	if (memcmp(rsdp.signature, "RSD PTR ", 8))
+	if (memcmp(rsdp.Signature, "RSD PTR ", 8))
 		return (NULL);
 
 	/* Read the entire table. */
 	pread(acpi_mem_fd, &rsdp, sizeof(rsdp), addr);
 
-	/* Run the checksum only over the version 1 header. */
-	if (acpi_checksum(&rsdp, 20))
+	/* Check the standard checksum. */
+	if (acpi_checksum(&rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0)
+		return (NULL);
+
+	/* Check extended checksum if table version >= 2. */
+	if (rsdp.Revision >= 2 &&
+	    acpi_checksum(&rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)
 		return (NULL);
 
 	/* If the revision is 0, assume a version 1 length. */
-	if (rsdp.revision == 0)
-		len = 20;
+	if (rsdp.Revision == 0)
+		len = ACPI_RSDP_REV0_SIZE;
 	else
-		len = rsdp.length;
-
-	/* XXX Should handle ACPI 2.0 RSDP extended checksum here. */
+		len = rsdp.Length;
 
 	return (acpi_map_physical(addr, len));
 }
 
-static struct ACPIrsdp *
+static ACPI_TABLE_RSDP *
 acpi_scan_rsd_ptr(void)
 {
 #if defined(__amd64__) || defined(__i386__)
-	struct ACPIrsdp *rsdp;
+	ACPI_TABLE_RSDP *rsdp;
 	u_long		addr, end;
 
 	/*
@@ -137,15 +140,15 @@ acpi_scan_rsd_ptr(void)
 	 * 1. EBDA (1 KB area addressed by the 16 bit pointer at 0x40E
 	 * 2. High memory (0xE0000 - 0xFFFFF)
 	 */
-	addr = RSDP_EBDA_PTR;
+	addr = ACPI_EBDA_PTR_LOCATION;
 	pread(acpi_mem_fd, &addr, sizeof(uint16_t), addr);
 	addr <<= 4;
-	end = addr + RSDP_EBDA_SIZE;
+	end = addr + ACPI_EBDA_WINDOW_SIZE;
 	for (; addr < end; addr += 16)
 		if ((rsdp = acpi_get_rsdp(addr)) != NULL)
 			return (rsdp);
-	addr = RSDP_HI_START;
-	end = addr + RSDP_HI_SIZE;
+	addr = ACPI_HI_RSDP_WINDOW_BASE;
+	end = addr + ACPI_HI_RSDP_WINDOW_SIZE;
 	for (; addr < end; addr += 16)
 		if ((rsdp = acpi_get_rsdp(addr)) != NULL)
 			return (rsdp);
@@ -156,10 +159,10 @@ acpi_scan_rsd_ptr(void)
 /*
  * Public interfaces
  */
-struct ACPIrsdp *
+ACPI_TABLE_RSDP *
 acpi_find_rsd_ptr(void)
 {
-	struct ACPIrsdp *rsdp;
+	ACPI_TABLE_RSDP *rsdp;
 	char		buf[20];
 	u_long		addr;
 	size_t		len;
@@ -191,10 +194,10 @@ acpi_map_physical(vm_offset_t pa, size_t size)
 	return (map->va + (pa - map->pa));
 }
 
-struct ACPIsdt *
+ACPI_TABLE_HEADER *
 dsdt_load_file(char *infile)
 {
-	struct ACPIsdt	*sdt;
+	ACPI_TABLE_HEADER *sdt;
 	uint8_t		*dp;
 	struct stat	 sb;
 
@@ -210,8 +213,9 @@ dsdt_load_file(char *infile)
 	if (dp == NULL)
 		errx(1, "mmap %s", infile);
 
-	sdt = (struct ACPIsdt *)dp;
-	if (strncmp(dp, "DSDT", 4) != 0 || acpi_checksum(sdt, sdt->len) != 0)
+	sdt = (ACPI_TABLE_HEADER *)dp;
+	if (strncmp(dp, ACPI_SIG_DSDT, 4) != 0 ||
+	    acpi_checksum(sdt, sdt->Length) != 0)
 		return (NULL);
 
 	return (sdt);
diff --git a/usr.sbin/acpi/acpidump/acpidump.c b/usr.sbin/acpi/acpidump/acpidump.c
index a601ac26163..38844b63873 100644
--- a/usr.sbin/acpi/acpidump/acpidump.c
+++ b/usr.sbin/acpi/acpidump/acpidump.c
@@ -54,9 +54,9 @@ usage(const char *progname)
 int
 main(int argc, char *argv[])
 {
+	ACPI_TABLE_HEADER *rsdt, *sdt;
 	char	c, *progname;
 	char	*dsdt_input_file, *dsdt_output_file;
-	struct	ACPIsdt *rsdt, *sdt;
 
 	dsdt_input_file = dsdt_output_file = NULL;
 	progname = argv[0];
@@ -117,8 +117,8 @@ main(int argc, char *argv[])
 
 	/* Translate RSDT to DSDT pointer */
 	if (dsdt_input_file == NULL) {
-		sdt = sdt_from_rsdt(rsdt, "FACP", NULL);
-		sdt = dsdt_from_fadt((struct FADTbody *)sdt->body);
+		sdt = sdt_from_rsdt(rsdt, ACPI_SIG_FADT, NULL);
+		sdt = dsdt_from_fadt((ACPI_TABLE_FADT *)sdt);
 	} else {
 		sdt = rsdt;
 		rsdt = NULL;
diff --git a/usr.sbin/acpi/acpidump/acpidump.h b/usr.sbin/acpi/acpidump/acpidump.h
index 8eca6a8b6bb..c75cabd34f6 100644
--- a/usr.sbin/acpi/acpidump/acpidump.h
+++ b/usr.sbin/acpi/acpidump/acpidump.h
@@ -28,368 +28,55 @@
  */
 
 #ifndef _ACPIDUMP_H_
-#define _ACPIDUMP_H_
+#define	_ACPIDUMP_H_
 
-/* Generic Address structure */
-struct ACPIgas {
-	u_int8_t	address_space_id;
-#define ACPI_GAS_MEMORY		0
-#define ACPI_GAS_IO		1
-#define ACPI_GAS_PCI		2
-#define ACPI_GAS_EMBEDDED	3
-#define ACPI_GAS_SMBUS		4
-#define ACPI_GAS_FIXED		0x7f
-	u_int8_t	bit_width;
-	u_int8_t	bit_offset;
-	u_int8_t	_reserved;
-	u_int64_t	address;
-} __packed;
+#include 
+#include 
+#include 
 
-/* Root System Description Pointer */
-struct ACPIrsdp {
-	u_char		signature[8];
-	u_char		sum;
-	u_char		oem[6];
-	u_char		revision;
-	u_int32_t	rsdt_addr;
-	u_int32_t	length;
-	u_int64_t	xsdt_addr;
-	u_char		xsum;
-	u_char		_reserved_[3];
-} __packed;
+/* GAS address space ID constants. */
+#define	ACPI_GAS_MEMORY		0
+#define	ACPI_GAS_IO		1
+#define	ACPI_GAS_PCI		2
+#define	ACPI_GAS_EMBEDDED	3
+#define	ACPI_GAS_SMBUS		4
+#define	ACPI_GAS_CMOS		5
+#define	ACPI_GAS_PCIBAR		6
+#define	ACPI_GAS_DATATABLE	7
+#define	ACPI_GAS_FIXED		0x7f
 
-/* System Description Table */
-struct ACPIsdt {
-	u_char		signature[4];
-	u_int32_t	len;
-	u_char		rev;
-	u_char		check;
-	u_char		oemid[6];
-	u_char		oemtblid[8];
-	u_int32_t	oemrev;
-	u_char		creator[4];
-	u_int32_t	crerev;
-#define SIZEOF_SDT_HDR 36	/* struct size except body */
-	u_int32_t	body[1];/* This member should be casted */
-} __packed;
-
-/* Fixed ACPI Description Table (body) */
-struct FADTbody {
-	u_int32_t	facs_ptr;
-	u_int32_t	dsdt_ptr;
-	u_int8_t	int_model;
-#define ACPI_FADT_INTMODEL_PIC	0	/* Standard PC-AT PIC */
-#define ACPI_FADT_INTMODEL_APIC	1	/* Multiple APIC */
-	u_int8_t	pm_profile;
-	u_int16_t	sci_int;
-	u_int32_t	smi_cmd;
-	u_int8_t	acpi_enable;
-	u_int8_t	acpi_disable;
-	u_int8_t	s4biosreq;
-	u_int8_t	pstate_cnt;
-	u_int32_t	pm1a_evt_blk;
-	u_int32_t	pm1b_evt_blk;
-	u_int32_t	pm1a_cnt_blk;
-	u_int32_t	pm1b_cnt_blk;
-	u_int32_t	pm2_cnt_blk;
-	u_int32_t	pm_tmr_blk;
-	u_int32_t	gpe0_blk;
-	u_int32_t	gpe1_blk;
-	u_int8_t	pm1_evt_len;
-	u_int8_t	pm1_cnt_len;
-	u_int8_t	pm2_cnt_len;
-	u_int8_t	pm_tmr_len;
-	u_int8_t	gpe0_len;
-	u_int8_t	gpe1_len;
-	u_int8_t	gpe1_base;
-	u_int8_t	cst_cnt;
-	u_int16_t	p_lvl2_lat;
-	u_int16_t	p_lvl3_lat;
-	u_int16_t	flush_size;
-	u_int16_t	flush_stride;
-	u_int8_t	duty_off;
-	u_int8_t	duty_width;
-	u_int8_t	day_alrm;
-	u_int8_t	mon_alrm;
-	u_int8_t	century;
-	u_int16_t	iapc_boot_arch;
-#define FADT_FLAG_LEGACY_DEV	1	/* System has legacy devices */
-#define FADT_FLAG_8042		2	/* 8042 keyboard controller */
-	u_char		reserved4[1];
-	u_int32_t	flags;
-#define FADT_FLAG_WBINVD	1	/* WBINVD is correctly supported */
-#define FADT_FLAG_WBINVD_FLUSH	2	/* WBINVD flushes caches */
-#define FADT_FLAG_PROC_C1	4	/* C1 power state supported */
-#define FADT_FLAG_P_LVL2_UP	8	/* C2 power state works on SMP */
-#define FADT_FLAG_PWR_BUTTON	16	/* Power button uses control method */
-#define FADT_FLAG_SLP_BUTTON	32	/* Sleep button uses control method */
-#define FADT_FLAG_FIX_RTC	64	/* RTC wakeup not supported */
-#define FADT_FLAG_RTC_S4	128	/* RTC can wakeup from S4 state */
-#define FADT_FLAG_TMR_VAL_EXT	256	/* TMR_VAL is 32bit */
-#define FADT_FLAG_DCK_CAP	512	/* Can support docking */
-#define FADT_FLAG_RESET_REG	1024	/* Supports RESET_REG */
-#define FADT_FLAG_SEALED_CASE	2048	/* Case cannot be opened */
-#define FADT_FLAG_HEADLESS	4096	/* No monitor */
-#define FADT_FLAG_CPU_SW_SLP	8192	/* Supports CPU software sleep */
-	struct ACPIgas	reset_reg;
-	u_int8_t	reset_value;
-	u_int8_t	reserved5[3];
-	u_int64_t	x_facs_ptr;
-	u_int64_t	x_dsdt_ptr;
-	struct ACPIgas	x_pm1a_evt_blk;
-	struct ACPIgas	x_pm1b_evt_blk;
-	struct ACPIgas	x_pm1a_cnt_blk;
-	struct ACPIgas	x_pm1b_cnt_blk;
-	struct ACPIgas	x_pm2_cnt_blk;
-	struct ACPIgas	x_pm_tmr_blk;
-	struct ACPIgas	x_gpe0_blk;
-	struct ACPIgas	x_gpe1_blk;
-} __packed;
-
-/* Firmware ACPI Control Structure */
-struct FACSbody {
-	u_char		signature[4];
-	u_int32_t	len;
-	u_int32_t	hw_sig;
-	/*
-	 * NOTE This should be filled with physical address below 1MB!!
-	 * sigh....
-	 */
-	u_int32_t	firm_wake_vec;
-	u_int32_t	global_lock;
-#define FACS_FLAG_LOCK_PENDING	1	/* 5.2.6.1 Global Lock */
-#define FACS_FLAG_LOCK_OWNED	2
-	u_int32_t	flags;
-#define FACS_FLAG_S4BIOS_F	1	/* Supports S4BIOS_SEQ */
-	u_int64_t	x_firm_wake_vec;
-	u_int8_t	version;
-	char		reserved[31];
-} __packed;
-
-struct MADT_local_apic {
-	u_char		cpu_id;
-	u_char		apic_id;
-	u_int32_t	flags;
-#define	ACPI_MADT_APIC_LOCAL_FLAG_ENABLED	1
-} __packed;
-
-struct MADT_io_apic {
-	u_char		apic_id;
-	u_char		reserved;
-	u_int32_t	apic_addr;
-	u_int32_t	int_base;
-} __packed;
-
-struct MADT_int_override {
-	u_char		bus;
-	u_char		source;
-	u_int32_t	intr;
-	u_int16_t	mps_flags;
-#define	MPS_INT_FLAG_POLARITY_MASK	0x3
-#define	MPS_INT_FLAG_POLARITY_CONFORM	0x0
-#define	MPS_INT_FLAG_POLARITY_HIGH	0x1
-#define	MPS_INT_FLAG_POLARITY_LOW	0x3
-#define	MPS_INT_FLAG_TRIGGER_MASK	0xc
-#define	MPS_INT_FLAG_TRIGGER_CONFORM	0x0
-#define	MPS_INT_FLAG_TRIGGER_EDGE	0x4
-#define	MPS_INT_FLAG_TRIGGER_LEVEL	0xc
-} __packed;
-
-struct MADT_nmi {
-	u_int16_t	mps_flags;
-	u_int32_t	intr;
-} __packed;
-
-struct MADT_local_nmi {
-	u_char		cpu_id;
-	u_int16_t	mps_flags;
-	u_char		lintpin;
-} __packed;
-
-struct MADT_local_apic_override {
-	u_char		reserved[2];
-	u_int64_t	apic_addr;
-} __packed;
-
-struct MADT_io_sapic {
-	u_char		apic_id;
-	u_char		reserved;
-	u_int32_t	int_base;
-	u_int64_t	apic_addr;
-} __packed;
-
-struct MADT_local_sapic {
-	u_char		cpu_id;
-	u_char		apic_id;
-	u_char		apic_eid;
-	u_char		reserved[3];
-	u_int32_t	flags;
-} __packed;
-
-struct MADT_int_src {
-	u_int16_t	mps_flags;
-	u_char		type;
-#define	ACPI_MADT_APIC_INT_SOURCE_PMI	1
-#define	ACPI_MADT_APIC_INT_SOURCE_INIT	2
-#define	ACPI_MADT_APIC_INT_SOURCE_CPEI	3	/* Corrected Platform Error */
-	u_char		cpu_id;
-	u_char		cpu_eid;
-	u_char		sapic_vector;
-	u_int32_t	intr;
-	u_char		reserved[4];
-} __packed;
-
-struct MADT_APIC {
-	u_char		type;
-#define	ACPI_MADT_APIC_TYPE_LOCAL_APIC	0
-#define	ACPI_MADT_APIC_TYPE_IO_APIC	1
-#define	ACPI_MADT_APIC_TYPE_INT_OVERRIDE 2
-#define	ACPI_MADT_APIC_TYPE_NMI		3
-#define	ACPI_MADT_APIC_TYPE_LOCAL_NMI	4
-#define	ACPI_MADT_APIC_TYPE_LOCAL_OVERRIDE 5
-#define	ACPI_MADT_APIC_TYPE_IO_SAPIC	6
-#define	ACPI_MADT_APIC_TYPE_LOCAL_SAPIC	7
-#define	ACPI_MADT_APIC_TYPE_INT_SRC	8
-	u_char		len;
-	union {
-		struct MADT_local_apic local_apic;
-		struct MADT_io_apic io_apic;
-		struct MADT_int_override int_override;
-		struct MADT_nmi nmi;
-		struct MADT_local_nmi local_nmi;
-		struct MADT_local_apic_override local_apic_override;
-		struct MADT_io_sapic io_sapic;
-		struct MADT_local_sapic local_sapic;
-		struct MADT_int_src int_src;
-	} body;
-} __packed;
-
-struct MADTbody {
-	u_int32_t	lapic_addr;
-	u_int32_t	flags;
-#define	ACPI_APIC_FLAG_PCAT_COMPAT 1	/* System has dual-8259 setup. */
-	u_char		body[1];
-} __packed;
-
-struct HPETbody {
-	u_int32_t	block_hwrev:8,
-			block_comparitors:5,
-			block_counter_size:1,
-			:1,
-			block_legacy_capable:1,
-			block_pcivendor:16;
-	struct ACPIgas  genaddr;
-	u_int8_t	hpet_number;
-	u_int16_t	clock_tick __packed;
-} __packed;
-
-/* Embedded Controller Description Table */
-struct ECDTbody {
-	struct ACPIgas	ec_control;	/* Control register */
-	struct ACPIgas	ec_data;	/* Data register */
-	uint32_t	uid;		/* Same value as _UID in namespace */
-	uint8_t		gpe_bit;	/* GPE bit for the EC */
-	u_char		ec_id[1];	/* Variable length name string */
-} __packed;
-
-/* Memory Mapped PCI config space base allocation structure */
-struct MCFGbody {
-	uint8_t		rsvd[8];
-	struct {
-		uint64_t	baseaddr;	/* Base Address */
-		uint16_t	seg_grp;	/* Segment group number */
-		uint8_t		start;		/* Starting bus number */
-		uint8_t		end;		/* Ending bus number */
-		uint8_t		rsvd[4];	/* Reserved */
-	} s[1] __packed;
-} __packed;
-
-/* System Resource Affinity Table */
-struct SRAT_cpu {
-	uint8_t		proximity_domain_lo;
-	uint8_t		apic_id;
-	uint32_t	flags;
-#define	ACPI_SRAT_CPU_ENABLED		0x00000001
-	uint8_t		sapic_eid;
-	uint8_t		proximity_domain_hi[3];
-	uint32_t	reserved;
-} __packed;
-
-struct SRAT_memory {
-	uint32_t	proximity_domain;
-	uint16_t	reserved;
-	uint64_t	base_address;
-	uint64_t	length;
-	uint32_t	reserved1;
-	uint32_t	flags;
-#define	ACPI_SRAT_MEM_ENABLED		0x00000001
-#define	ACPI_SRAT_MEM_HOT_PLUGGABLE	0x00000002
-#define	ACPI_SRAT_MEM_NON_VOLATILE	0x00000002
-	uint64_t	reserved2;
-} __packed;
-
-struct SRAT_x2apic {
-	uint16_t	reserved;
-	uint32_t	proximity_domain;
-	uint32_t	apic_id;
-	uint32_t	flags;
-} __packed;
-
-struct SRATentry {
-	uint8_t		type;
-#define	ACPI_SRAT_TYPE_CPU_AFFINITY		0
-#define	ACPI_SRAT_TYPE_MEMORY_AFFINITY		1
-#define	ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY	2
-	uint8_t		len;
-	union {
-		struct SRAT_cpu cpu;
-		struct SRAT_memory mem;
-		struct SRAT_x2apic x2apic;
-	} body;
-} __packed;
-
-struct SRATbody {
-	uint32_t	table_revision;
-	uint64_t	reserved;
-	struct SRATentry body[0];
-} __packed;
-	
-/*
- * Addresses to scan on ia32 for the RSD PTR.  According to section 5.2.2
- * of the ACPI spec, we only consider two regions for the base address:
- * 1. EBDA (1 KB area addressed to by 16 bit pointer at 0x40E)
- * 2. High memory (0xE0000 - 0xFFFFF)
- */
-#define RSDP_EBDA_PTR	0x40E
-#define RSDP_EBDA_SIZE	0x400
-#define RSDP_HI_START	0xE0000
-#define RSDP_HI_SIZE	0x20000
+/* Subfields in the HPET Id member. */
+#define	ACPI_HPET_ID_HARDWARE_REV_ID	0x000000ff
+#define	ACPI_HPET_ID_COMPARATORS	0x00001f00
+#define	ACPI_HPET_ID_COUNT_SIZE_CAP	0x00002000
+#define	ACPI_HPET_ID_LEGACY_CAPABLE	0x00008000
+#define	ACPI_HPET_ID_PCI_VENDOR_ID	0xffff0000
 
 /* Find and map the RSD PTR structure and return it for parsing */
-struct ACPIsdt  *sdt_load_devmem(void);
+ACPI_TABLE_HEADER *sdt_load_devmem(void);
 
 /*
  * Load the DSDT from a previous save file.  Note that other tables are
  * not saved (i.e. FADT)
  */
-struct ACPIsdt  *dsdt_load_file(char *);
+ACPI_TABLE_HEADER *dsdt_load_file(char *);
 
 /* Save the DSDT to a file */
-void		 dsdt_save_file(char *, struct ACPIsdt *, struct ACPIsdt *);
+void	 dsdt_save_file(char *, ACPI_TABLE_HEADER *, ACPI_TABLE_HEADER *);
 
 /* Print out as many fixed tables as possible, given the RSD PTR */
-void		 sdt_print_all(struct ACPIsdt *);
+void	 sdt_print_all(ACPI_TABLE_HEADER *);
 
 /* Disassemble the AML in the DSDT */
-void		 aml_disassemble(struct ACPIsdt *, struct ACPIsdt *);
+void	 aml_disassemble(ACPI_TABLE_HEADER *, ACPI_TABLE_HEADER *);
 
 /* Routines for accessing tables in physical memory */
-struct ACPIrsdp	*acpi_find_rsd_ptr(void);
-void		*acpi_map_physical(vm_offset_t, size_t);
-struct ACPIsdt	*sdt_from_rsdt(struct ACPIsdt *, const char *,
-    struct ACPIsdt *);
-struct ACPIsdt	*dsdt_from_fadt(struct FADTbody *);
-int		 acpi_checksum(void *, size_t);
+ACPI_TABLE_RSDP *acpi_find_rsd_ptr(void);
+void	*acpi_map_physical(vm_offset_t, size_t);
+ACPI_TABLE_HEADER *sdt_from_rsdt(ACPI_TABLE_HEADER *, const char *,
+	    ACPI_TABLE_HEADER *);
+ACPI_TABLE_HEADER *dsdt_from_fadt(ACPI_TABLE_FADT *);
+int	 acpi_checksum(void *, size_t);
 
 /* Command line flags */
 extern int	dflag;
diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c
index e585ba0fecd..8a3410fd8f8 100644
--- a/usr.sbin/arp/arp.c
+++ b/usr.sbin/arp/arp.c
@@ -120,7 +120,7 @@ main(int argc, char *argv[])
 	int aflag = 0;	/* do it for all entries */
 
 	while ((ch = getopt(argc, argv, "andfsSi:")) != -1)
-		switch((char)ch) {
+		switch(ch) {
 		case 'a':
 			aflag = 1;
 			break;
diff --git a/usr.sbin/diskinfo/diskinfo.c b/usr.sbin/diskinfo/diskinfo.c
index 48b019b1a14..7ecf7cb4f32 100644
--- a/usr.sbin/diskinfo/diskinfo.c
+++ b/usr.sbin/diskinfo/diskinfo.c
@@ -104,9 +104,6 @@ main(int argc, char **argv)
 		error = ioctl(fd, DIOCGFWHEADS, &fwheads);
 		if (error)
 			fwheads = 0;
-		error = ioctl(fd, DIOCGIDENT, ident);
-		if (error)
-			ident[0] = '\0';
 		if (!opt_v) {
 			printf("%s", argv[i]);
 			printf("\t%u", sectorsize);
@@ -133,7 +130,7 @@ main(int argc, char **argv)
 				printf("\t%-12u\t# Heads according to firmware.\n", fwheads);
 				printf("\t%-12u\t# Sectors according to firmware.\n", fwsectors);
 			} 
-			if (ident[0] != '\0')
+			if (ioctl(fd, DIOCGIDENT, ident) == 0)
 				printf("\t%-12s\t# Disk ident.\n", ident);
 		}
 		printf("\n");
diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh
index 331ef101494..2eacca8d2fb 100644
--- a/usr.sbin/freebsd-update/freebsd-update.sh
+++ b/usr.sbin/freebsd-update/freebsd-update.sh
@@ -88,7 +88,7 @@ EOF
 CONFIGOPTIONS="KEYPRINT WORKDIR SERVERNAME MAILTO ALLOWADD ALLOWDELETE
     KEEPMODIFIEDMETADATA COMPONENTS IGNOREPATHS UPDATEIFUNMODIFIED
     BASEDIR VERBOSELEVEL TARGETRELEASE STRICTCOMPONENTS MERGECHANGES
-    IDSIGNOREPATHS"
+    IDSIGNOREPATHS BACKUPKERNEL BACKUPKERNELDIR BACKUPKERNELSYMBOLFILES"
 
 # Set all the configuration options to "".
 nullconfig () {
@@ -308,6 +308,70 @@ config_VerboseLevel () {
 	fi
 }
 
+config_BackupKernel () {
+	if [ -z ${BACKUPKERNEL} ]; then
+		case $1 in
+		[Yy][Ee][Ss])
+			BACKUPKERNEL=yes
+			;;
+		[Nn][Oo])
+			BACKUPKERNEL=no
+			;;
+		*)
+			return 1
+			;;
+		esac
+	else
+		return 1
+	fi
+}
+
+config_BackupKernelDir () {
+	if [ -z ${BACKUPKERNELDIR} ]; then
+		if [ -z "$1" ]; then
+			echo "BackupKernelDir set to empty dir"
+			return 1
+		fi
+
+		# We check for some paths which would be extremely odd
+		# to use, but which could cause a lot of problems if
+		# used.
+		case $1 in
+		/|/bin|/boot|/etc|/lib|/libexec|/sbin|/usr|/var)
+			echo "BackupKernelDir set to invalid path $1"
+			return 1
+			;;
+		/*)
+			BACKUPKERNELDIR=$1
+			;;
+		*)
+			echo "BackupKernelDir ($1) is not an absolute path"
+			return 1
+			;;
+		esac
+	else
+		return 1
+	fi
+}
+
+config_BackupKernelSymbolFiles () {
+	if [ -z ${BACKUPKERNELSYMBOLFILES} ]; then
+		case $1 in
+		[Yy][Ee][Ss])
+			BACKUPKERNELSYMBOLFILES=yes
+			;;
+		[Nn][Oo])
+			BACKUPKERNELSYMBOLFILES=no
+			;;
+		*)
+			return 1
+			;;
+		esac
+	else
+		return 1
+	fi
+}
+
 # Handle one line of configuration
 configline () {
 	if [ $# -eq 0 ]; then
@@ -461,6 +525,9 @@ default_params () {
 	config_BaseDir /
 	config_VerboseLevel stats
 	config_StrictComponents no
+	config_BackupKernel yes
+	config_BackupKernelDir /boot/kernel.old
+	config_BackupKernelSymbolFiles no
 
 	# Merge these defaults into the earlier-configured settings
 	mergeconfig
@@ -665,6 +732,14 @@ install_check_params () {
 		echo "Re-run '$0 fetch'."
 		exit 1
 	fi
+
+	# Figure out what directory contains the running kernel
+	BOOTFILE=`sysctl -n kern.bootfile`
+	KERNELDIR=${BOOTFILE%/kernel}
+	if ! [ -d ${KERNELDIR} ]; then
+		echo "Cannot identify running kernel"
+		exit 1
+	fi
 }
 
 # Perform sanity checks and set some final parameters in
@@ -2494,6 +2569,88 @@ install_unschg () {
 	rm filelist
 }
 
+# Decide which directory name to use for kernel backups.
+backup_kernel_finddir () {
+	CNT=0
+	while true ; do
+		# Pathname does not exist, so it is OK use that name
+		# for backup directory.
+		if [ ! -e $BACKUPKERNELDIR ]; then
+			return 0
+		fi
+
+		# If directory do exist, we only use if it has our
+		# marker file.
+		if [ -d $BACKUPKERNELDIR -a \
+			-e $BACKUPKERNELDIR/.freebsd-update ]; then
+			return 0
+		fi
+
+		# We could not use current directory name, so add counter to
+		# the end and try again.
+		CNT=$((CNT + 1))
+		if [ $CNT -gt 9 ]; then
+			echo "Could not find valid backup dir ($BACKUPKERNELDIR)"
+			exit 1
+		fi
+		BACKUPKERNELDIR="`echo $BACKUPKERNELDIR | sed -Ee 's/[0-9]\$//'`"
+		BACKUPKERNELDIR="${BACKUPKERNELDIR}${CNT}"
+	done
+}
+
+# Backup the current kernel using hardlinks, if not disabled by user.
+# Since we delete all files in the directory used for previous backups
+# we create a marker file called ".freebsd-update" in the directory so
+# we can determine on the next run that the directory was created by
+# freebsd-update and we then do not accidentally remove user files in
+# the unlikely case that the user has created a directory with a
+# conflicting name.
+backup_kernel () {
+	# Only make kernel backup is so configured.
+	if [ $BACKUPKERNEL != yes ]; then
+		return 0
+	fi
+
+	# Decide which directory name to use for kernel backups.
+	backup_kernel_finddir
+
+	# Remove old kernel backup files.  If $BACKUPKERNELDIR was
+	# "not ours", backup_kernel_finddir would have exited, so
+	# deleting the directory content is as safe as we can make it.
+	if [ -d $BACKUPKERNELDIR ]; then
+		rm -f $BACKUPKERNELDIR/*
+	fi
+
+	# Create directory for backup if it doesn't exist.
+	mkdir -p $BACKUPKERNELDIR
+
+	# Mark the directory as having been created by freebsd-update.
+	touch $BACKUPKERNELDIR/.freebsd-update
+	if [ $? -ne 0 ]; then
+		echo "Could not create kernel backup directory"
+		exit 1
+	fi
+
+	# Disable pathname expansion to be sure *.symbols is not
+	# expanded.
+	set -f
+
+	# Use find to ignore symbol files, unless disabled by user.
+	if [ $BACKUPKERNELSYMBOLFILES = yes ]; then
+		FINDFILTER=""
+	else
+		FINDFILTER=-"a ! -name *.symbols"
+	fi
+
+	# Backup all the kernel files using hardlinks.
+	find $KERNELDIR -type f $FINDFILTER | \
+		sed -Ee "s,($KERNELDIR)/?(.*),\1/\2 ${BACKUPKERNELDIR}/\2," | \
+		xargs -n 2 cp -pl
+
+	# Re-enable patchname expansion.
+	set +f
+}
+
 # Install new files
 install_from_index () {
 	# First pass: Do everything apart from setting file flags.  We
@@ -2575,6 +2732,9 @@ install_files () {
 		grep -E '^/boot/' $1/INDEX-OLD > INDEX-OLD
 		grep -E '^/boot/' $1/INDEX-NEW > INDEX-NEW
 
+		# Backup current kernel before installing a new one
+		backup_kernel || return 1
+
 		# Install new files
 		install_from_index INDEX-NEW || return 1
 
diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c
index 65a0386a92a..9831f842ed3 100644
--- a/usr.sbin/iostat/iostat.c
+++ b/usr.sbin/iostat/iostat.c
@@ -586,7 +586,7 @@ main(int argc, char **argv)
 		}
 
 		if (xflag == 0 && Tflag > 0)
-			printf("%4.0Lf%5.0Lf", cur.tk_nin / etime,
+			printf("%4.0Lf %5.0Lf", cur.tk_nin / etime,
 			    cur.tk_nout / etime);
 
 		devstats(hflag, etime, havelast);
@@ -674,7 +674,7 @@ phdr(void)
 		return;
 
 	if (Tflag > 0)
-		(void)printf("      tty");
+		(void)printf("       tty");
 	for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){
 		int di;
 		if ((dev_select[i].selected != 0)
@@ -696,7 +696,7 @@ phdr(void)
 		(void)printf("\n");
 
 	if (Tflag > 0)
-		(void)printf(" tin tout");
+		(void)printf(" tin  tout");
 
 	for (i=0, printed = 0;(i < num_devices) && (printed < maxshowdevs);i++){
 		if ((dev_select[i].selected != 0)
@@ -741,7 +741,7 @@ devstats(int perf_select, long double etime, int havelast)
 	if (xflag > 0) {
 		printf("                        extended device statistics  ");
 		if (Tflag > 0)
-			printf("     tty ");
+			printf("      tty ");
 		if (Cflag > 0)
 			printf("           cpu ");
 		printf("\n");
@@ -754,7 +754,7 @@ devstats(int perf_select, long double etime, int havelast)
 		"device     r/i   w/i    kr/i    kw/i wait svc_t  %%b  "
 			    );
 		if (Tflag > 0)
-			printf("tin tout ");
+			printf("tin  tout ");
 		if (Cflag > 0)
 			printf("us ni sy in id ");
 		printf("\n");
@@ -895,7 +895,7 @@ devstats(int perf_select, long double etime, int havelast)
 		 */
 		printf("%52s","");
 		if (Tflag > 0)
-			printf("%4.0Lf%5.0Lf", cur.tk_nin / etime,
+			printf("%4.0Lf %5.0Lf", cur.tk_nin / etime,
 			    cur.tk_nout / etime);
 		if (Cflag > 0)
 			cpustats();
diff --git a/usr.sbin/jls/jls.c b/usr.sbin/jls/jls.c
index 8c8b981d82f..0661ee3fa43 100644
--- a/usr.sbin/jls/jls.c
+++ b/usr.sbin/jls/jls.c
@@ -359,7 +359,7 @@ print_jail(int pflags, int jflags)
 				    ipbuf, sizeof(ipbuf)) == NULL)
 					err(1, "inet_ntop");
 				else
-					printf("%6s  %-15.15s\n", "", ipbuf);
+					printf("%6s  %s\n", "", ipbuf);
 		}
 	} else if (pflags & PRINT_DEFAULT)
 		printf("%6d  %-15.15s %-29.29s %.74s\n",
diff --git a/usr.sbin/kbdcontrol/kbdcontrol.c b/usr.sbin/kbdcontrol/kbdcontrol.c
index c800233d445..bbeb75871e0 100644
--- a/usr.sbin/kbdcontrol/kbdcontrol.c
+++ b/usr.sbin/kbdcontrol/kbdcontrol.c
@@ -55,6 +55,8 @@ __FBSDID("$FreeBSD$");
 #define PASTE		0xa3		/* paste from cut-paste buffer */
 #endif
 
+#define	SPECIAL		0x80000000
+
 char ctrl_names[32][4] = {
 	"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
 	"bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ",
@@ -180,77 +182,77 @@ get_entry(void)
 {
 	switch ((token = yylex())) {
 	case TNOP:
-		return NOP | 0x100;
+		return NOP | SPECIAL;
 	case TLSH:
-		return LSH | 0x100;
+		return LSH | SPECIAL;
 	case TRSH:
-		return RSH | 0x100;
+		return RSH | SPECIAL;
 	case TCLK:
-		return CLK | 0x100;
+		return CLK | SPECIAL;
 	case TNLK:
-		return NLK | 0x100;
+		return NLK | SPECIAL;
 	case TSLK:
-		return SLK | 0x100;
+		return SLK | SPECIAL;
 	case TBTAB:
-		return BTAB | 0x100;
+		return BTAB | SPECIAL;
 	case TLALT:
-		return LALT | 0x100;
+		return LALT | SPECIAL;
 	case TLCTR:
-		return LCTR | 0x100;
+		return LCTR | SPECIAL;
 	case TNEXT:
-		return NEXT | 0x100;
+		return NEXT | SPECIAL;
 	case TPREV:
-		return PREV | 0x100;
+		return PREV | SPECIAL;
 	case TRCTR:
-		return RCTR | 0x100;
+		return RCTR | SPECIAL;
 	case TRALT:
-		return RALT | 0x100;
+		return RALT | SPECIAL;
 	case TALK:
-		return ALK | 0x100;
+		return ALK | SPECIAL;
 	case TASH:
-		return ASH | 0x100;
+		return ASH | SPECIAL;
 	case TMETA:
-		return META | 0x100;
+		return META | SPECIAL;
 	case TRBT:
-		return RBT | 0x100;
+		return RBT | SPECIAL;
 	case TDBG:
-		return DBG | 0x100;
+		return DBG | SPECIAL;
 	case TSUSP:
-		return SUSP | 0x100;
+		return SUSP | SPECIAL;
 	case TSPSC:
-		return SPSC | 0x100;
+		return SPSC | SPECIAL;
 	case TPANIC:
-		return PNC | 0x100;
+		return PNC | SPECIAL;
 	case TLSHA:
-		return LSHA | 0x100;
+		return LSHA | SPECIAL;
 	case TRSHA:
-		return RSHA | 0x100;
+		return RSHA | SPECIAL;
 	case TLCTRA:
-		return LCTRA | 0x100;
+		return LCTRA | SPECIAL;
 	case TRCTRA:
-		return RCTRA | 0x100;
+		return RCTRA | SPECIAL;
 	case TLALTA:
-		return LALTA | 0x100;
+		return LALTA | SPECIAL;
 	case TRALTA:
-		return RALTA | 0x100;
+		return RALTA | SPECIAL;
 	case THALT:
-		return HALT | 0x100;
+		return HALT | SPECIAL;
 	case TPDWN:
-		return PDWN | 0x100;
+		return PDWN | SPECIAL;
 	case TPASTE:
-		return PASTE | 0x100;
+		return PASTE | SPECIAL;
 	case TACC:
 		if (ACC(number) > L_ACC)
 			return -1;
-		return ACC(number) | 0x100;
+		return ACC(number) | SPECIAL;
 	case TFUNC:
 		if (F(number) > L_FN)
 			return -1;
-		return F(number) | 0x100;
+		return F(number) | SPECIAL;
 	case TSCRN:
 		if (S(number) > L_SCR)
 			return -1;
-		return S(number) | 0x100;
+		return S(number) | SPECIAL;
 	case TLET:
 		return (unsigned char)letter;
 	case TNUM:
@@ -310,9 +312,9 @@ get_key_definition_line(keymap_t *map)
 	for (i=0; ikey[scancode].spcl |= (0x80 >> i);
-		map->key[scancode].map[i] = def & 0xFF;
+		map->key[scancode].map[i] = def & ~SPECIAL;
 	}
 	/* get lock state key def */
 	if ((token = yylex()) != TFLAG)
@@ -386,101 +388,101 @@ get_accent_definition_line(accentmap_t *map)
 void
 print_entry(FILE *fp, int value)
 {
-	int val = value & 0xFF;
+	int val = value & ~SPECIAL;
 
 	switch (value) {
-	case NOP | 0x100:
+	case NOP | SPECIAL:
 		fprintf(fp, " nop   ");
 		break;
-	case LSH | 0x100:
+	case LSH | SPECIAL:
 		fprintf(fp, " lshift");
 		break;
-	case RSH | 0x100:
+	case RSH | SPECIAL:
 		fprintf(fp, " rshift");
 		break;
-	case CLK | 0x100:
+	case CLK | SPECIAL:
 		fprintf(fp, " clock ");
 		break;
-	case NLK | 0x100:
+	case NLK | SPECIAL:
 		fprintf(fp, " nlock ");
 		break;
-	case SLK | 0x100:
+	case SLK | SPECIAL:
 		fprintf(fp, " slock ");
 		break;
-	case BTAB | 0x100:
+	case BTAB | SPECIAL:
 		fprintf(fp, " btab  ");
 		break;
-	case LALT | 0x100:
+	case LALT | SPECIAL:
 		fprintf(fp, " lalt  ");
 		break;
-	case LCTR | 0x100:
+	case LCTR | SPECIAL:
 		fprintf(fp, " lctrl ");
 		break;
-	case NEXT | 0x100:
+	case NEXT | SPECIAL:
 		fprintf(fp, " nscr  ");
 		break;
-	case PREV | 0x100:
+	case PREV | SPECIAL:
 		fprintf(fp, " pscr  ");
 		break;
-	case RCTR | 0x100:
+	case RCTR | SPECIAL:
 		fprintf(fp, " rctrl ");
 		break;
-	case RALT | 0x100:
+	case RALT | SPECIAL:
 		fprintf(fp, " ralt  ");
 		break;
-	case ALK | 0x100:
+	case ALK | SPECIAL:
 		fprintf(fp, " alock ");
 		break;
-	case ASH | 0x100:
+	case ASH | SPECIAL:
 		fprintf(fp, " ashift");
 		break;
-	case META | 0x100:
+	case META | SPECIAL:
 		fprintf(fp, " meta  ");
 		break;
-	case RBT | 0x100:
+	case RBT | SPECIAL:
 		fprintf(fp, " boot  ");
 		break;
-	case DBG | 0x100:
+	case DBG | SPECIAL:
 		fprintf(fp, " debug ");
 		break;
-	case SUSP | 0x100:
+	case SUSP | SPECIAL:
 		fprintf(fp, " susp  ");
 		break;
-	case SPSC | 0x100:
+	case SPSC | SPECIAL:
 		fprintf(fp, " saver ");
 		break;
-	case PNC | 0x100:
+	case PNC | SPECIAL:
 		fprintf(fp, " panic ");
 		break;
-	case LSHA | 0x100:
+	case LSHA | SPECIAL:
 		fprintf(fp, " lshifta");
 		break;
-	case RSHA | 0x100:
+	case RSHA | SPECIAL:
 		fprintf(fp, " rshifta");
 		break;
-	case LCTRA | 0x100:
+	case LCTRA | SPECIAL:
 		fprintf(fp, " lctrla");
 		break;
-	case RCTRA | 0x100:
+	case RCTRA | SPECIAL:
 		fprintf(fp, " rctrla");
 		break;
-	case LALTA | 0x100:
+	case LALTA | SPECIAL:
 		fprintf(fp, " lalta ");
 		break;
-	case RALTA | 0x100:
+	case RALTA | SPECIAL:
 		fprintf(fp, " ralta ");
 		break;
-	case HALT | 0x100:
+	case HALT | SPECIAL:
 		fprintf(fp, " halt  ");
 		break;
-	case PDWN | 0x100:
+	case PDWN | SPECIAL:
 		fprintf(fp, " pdwn  ");
 		break;
-	case PASTE | 0x100:
+	case PASTE | SPECIAL:
 		fprintf(fp, " paste ");
 		break;
 	default:
-		if (value & 0x100) {
+		if (value & SPECIAL) {
 		 	if (val >= F_FN && val <= L_FN)
 				fprintf(fp, " fkey%02d", val - F_FN + 1);
 		 	else if (val >= F_SCR && val <= L_SCR)
@@ -521,7 +523,7 @@ print_key_definition_line(FILE *fp, int scancode, struct keyent_t *key)
 	/* print key definitions */
 	for (i=0; ispcl & (0x80 >> i))
-			print_entry(fp, key->map[i] | 0x100);
+			print_entry(fp, key->map[i] | SPECIAL);
 		else
 			print_entry(fp, key->map[i]);
 	}
@@ -587,8 +589,8 @@ print_accent_definition_line(FILE *fp, int accent, struct acc_t *key)
 void
 dump_entry(int value)
 {
-	if (value & 0x100) {
-		value &= 0x00ff;
+	if (value & SPECIAL) {
+		value &= ~SPECIAL;
 		switch (value) {
 		case NOP:
 			printf("  NOP, ");
@@ -719,7 +721,7 @@ dump_key_definition(char *name, keymap_t *keymap)
 		printf("/*%02x*/{{", i);
 		for (j = 0; j < NUM_STATES; j++) {
 			if (keymap->key[i].spcl & (0x80 >> j))
-				dump_entry(keymap->key[i].map[j] | 0x100);
+				dump_entry(keymap->key[i].map[j] | SPECIAL);
 			else
 				dump_entry(keymap->key[i].map[j]);
 		}
diff --git a/usr.sbin/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile
new file mode 100644
index 00000000000..03ded032958
--- /dev/null
+++ b/usr.sbin/mfiutil/Makefile
@@ -0,0 +1,18 @@
+# $FreeBSD$
+PROG=	mfiutil
+
+SRCS=	mfiutil.c mfi_cmd.c mfi_config.c mfi_drive.c mfi_evt.c mfi_flash.c \
+	mfi_patrol.c mfi_show.c mfi_volume.c
+MAN8=	mfiutil.8
+
+CFLAGS+= -fno-builtin-strftime
+WARNS?=3
+
+LDADD=	-lutil
+
+# Here be dragons
+.ifdef DEBUG
+CFLAGS+= -DDEBUG
+.endif
+
+.include 
diff --git a/usr.sbin/mfiutil/mfi_cmd.c b/usr.sbin/mfiutil/mfi_cmd.c
new file mode 100644
index 00000000000..abc8312aa22
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_cmd.c
@@ -0,0 +1,351 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mfiutil.h"
+#include 
+
+static const char *mfi_status_codes[] = {
+	"Command completed succesfully",
+	"Invalid command",
+	"Invalid DMCD opcode",
+	"Invalid parameter",
+	"Invalid Sequence Number",
+	"Abort isn't possible for the requested command",
+	"Application 'host' code not found",
+	"Application in use",
+	"Application not initialized",
+	"Array index invalid",
+	"Array row not empty",
+	"Configuration resource conflict",
+	"Device not found",
+	"Drive too small",
+	"Flash memory allocation failed",
+	"Flash download already in progress",
+	"Flash operation failed",
+	"Bad flash image",
+	"Incomplete flash image",
+	"Flash not open",
+	"Flash not started",
+	"Flush failed",
+	"Specified application doesn't have host-resident code",
+	"Volume consistency check in progress",
+	"Volume initialization in progress",
+	"Volume LBA out of range",
+	"Maximum number of volumes are already configured",
+	"Volume is not OPTIMAL",
+	"Volume rebuild in progress",
+	"Volume reconstruction in progress",
+	"Volume RAID level is wrong for requested operation",
+	"Too many spares assigned",
+	"Scratch memory not available",
+	"Error writing MFC data to SEEPROM",
+	"Required hardware is missing",
+	"Item not found",
+	"Volume drives are not within an enclosure",
+	"Drive clear in progress",
+	"Drive type mismatch (SATA vs SAS)",
+	"Patrol read disabled",
+	"Invalid row index",
+	"SAS Config - Invalid action",
+	"SAS Config - Invalid data",
+	"SAS Config - Invalid page",
+	"SAS Config - Invalid type",
+	"SCSI command completed with error",
+	"SCSI I/O request failed",
+	"SCSI RESERVATION_CONFLICT",
+	"One or more flush operations during shutdown failed",
+	"Firmware time is not set",
+	"Wrong firmware or drive state",
+	"Volume is offline",
+	"Peer controller rejected request",
+	"Unable to inform peer of communication changes",
+	"Volume reservation already in progress",
+	"I2C errors were detected",
+	"PCI errors occurred during XOR/DMA operation",
+	"Diagnostics failed",
+	"Unable to process command as boot messages are pending",
+	"Foreign configuration is incomplete"
+};
+
+const char *
+mfi_status(u_int status_code)
+{
+	static char buffer[16];
+
+	if (status_code == MFI_STAT_INVALID_STATUS)
+		return ("Invalid status");
+	if (status_code < sizeof(mfi_status_codes) / sizeof(char *))
+		return (mfi_status_codes[status_code]);
+	snprintf(buffer, sizeof(buffer), "Status: 0x%02x", status_code);
+	return (buffer);
+}
+
+const char *
+mfi_raid_level(uint8_t primary_level, uint8_t secondary_level)
+{
+	static char buf[16];
+
+	switch (primary_level) {
+	case DDF_RAID0:
+		return ("RAID-0");
+	case DDF_RAID1:
+		if (secondary_level != 0)
+			return ("RAID-10");
+		else
+			return ("RAID-1");
+	case DDF_RAID1E:
+		return ("RAID-1E");
+	case DDF_RAID3:
+		return ("RAID-3");
+	case DDF_RAID5:
+		if (secondary_level != 0)
+			return ("RAID-50");
+		else
+			return ("RAID-5");
+	case DDF_RAID5E:
+		return ("RAID-5E");
+	case DDF_RAID5EE:
+		return ("RAID-5EE");
+	case DDF_RAID6:
+		if (secondary_level != 0)
+			return ("RAID-60");
+		else
+			return ("RAID-6");
+	case DDF_JBOD:
+		return ("JBOD");
+	case DDF_CONCAT:
+		return ("CONCAT");
+	default:
+		sprintf(buf, "LVL 0x%02x", primary_level);
+		return (buf);
+	}
+}
+
+static int
+mfi_query_disk(int fd, uint8_t target_id, struct mfi_query_disk *info)
+{
+
+	bzero(info, sizeof(*info));
+	info->array_id = target_id;
+	if (ioctl(fd, MFIIO_QUERY_DISK, info) < 0)
+		return (-1);
+	if (!info->present) {
+		errno = ENXIO;
+		return (-1);
+	}
+	return (0);
+}
+
+const char *
+mfi_volume_name(int fd, uint8_t target_id)
+{
+	static struct mfi_query_disk info;
+	static char buf[4];
+
+	if (mfi_query_disk(fd, target_id, &info) < 0) {
+		snprintf(buf, sizeof(buf), "%d", target_id);
+		return (buf);
+	}
+	return (info.devname);
+}
+
+int
+mfi_volume_busy(int fd, uint8_t target_id)
+{
+	struct mfi_query_disk info;
+
+	/* Assume it isn't mounted if we can't get information. */
+	if (mfi_query_disk(fd, target_id, &info) < 0)
+		return (0);
+	return (info.open != 0);
+}
+
+/*
+ * Check if the running kernel supports changing the RAID
+ * configuration of the mfi controller.
+ */
+int
+mfi_reconfig_supported(void)
+{
+	char mibname[64];
+	size_t len;
+	int dummy;
+
+	len = sizeof(dummy);
+	snprintf(mibname, sizeof(mibname), "dev.mfi.%d.delete_busy_volumes",
+	    mfi_unit);
+	return (sysctlbyname(mibname, &dummy, &len, NULL, 0) == 0);
+}
+
+int
+mfi_lookup_volume(int fd, const char *name, uint8_t *target_id)
+{
+	struct mfi_query_disk info;
+	struct mfi_ld_list list;
+	char *cp;
+	long val;
+	u_int i;
+
+	/* If it's a valid number, treat it as a raw target ID. */
+	val = strtol(name, &cp, 0);
+	if (*cp == '\0') {
+		*target_id = val;
+		return (0);
+	}
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_LIST, &list, sizeof(list),
+	    NULL, 0, NULL) < 0)
+		return (-1);	
+
+	for (i = 0; i < list.ld_count; i++) {
+		if (mfi_query_disk(fd, list.ld_list[i].ld.v.target_id,
+		    &info) < 0)
+			continue;
+		if (strcmp(name, info.devname) == 0) {
+			*target_id = list.ld_list[i].ld.v.target_id;
+			return (0);
+		}
+	}
+	errno = EINVAL;
+	return (-1);
+}
+
+int
+mfi_dcmd_command(int fd, uint32_t opcode, void *buf, size_t bufsize,
+    uint8_t *mbox, size_t mboxlen, uint8_t *statusp)
+{
+	struct mfi_ioc_passthru ioc;
+	struct mfi_dcmd_frame *dcmd;
+	int r;
+
+	if ((mbox != NULL && (mboxlen == 0 || mboxlen > MFI_MBOX_SIZE)) ||
+	    (mbox == NULL && mboxlen != 0)) {
+		errno = EINVAL;
+		return (-1);
+	}
+
+	bzero(&ioc, sizeof(ioc));
+	dcmd = &ioc.ioc_frame;
+	if (mbox)
+		bcopy(mbox, dcmd->mbox, mboxlen);
+	dcmd->header.cmd = MFI_CMD_DCMD;
+	dcmd->header.timeout = 0;
+	dcmd->header.flags = 0;
+	dcmd->header.data_len = bufsize;
+	dcmd->opcode = opcode;
+
+	ioc.buf = buf;
+	ioc.buf_size = bufsize;
+	r = ioctl(fd, MFIIO_PASSTHRU, &ioc);
+	if (r < 0)
+		return (r);
+
+	if (statusp != NULL)
+		*statusp = dcmd->header.cmd_status;
+	else if (dcmd->header.cmd_status != MFI_STAT_OK) {
+		warnx("Command failed: %s",
+		    mfi_status(dcmd->header.cmd_status));
+		errno = EIO;
+		return (-1);
+	}
+	return (0);
+}
+
+int
+mfi_ctrl_get_info(int fd, struct mfi_ctrl_info *info, uint8_t *statusp)
+{
+
+	return (mfi_dcmd_command(fd, MFI_DCMD_CTRL_GETINFO, info,
+	    sizeof(struct mfi_ctrl_info), NULL, 0, statusp));
+}
+
+int
+mfi_open(int unit)
+{
+	char path[MAXPATHLEN];
+
+	snprintf(path, sizeof(path), "/dev/mfi%d", unit);
+	return (open(path, O_RDWR));
+}
+
+void
+mfi_display_progress(const char *label, struct mfi_progress *prog)
+{
+	uint seconds;
+
+	printf("%s: %.2f%% complete, after %ds", label,
+	    (float)prog->progress * 100 / 0xffff, prog->elapsed_seconds);
+	if (prog->elapsed_seconds > 10) {
+		printf(" finished in ");
+		seconds = (0x10000 * (uint32_t)prog->elapsed_seconds) /
+		    prog->progress - prog->elapsed_seconds;
+		if (seconds > 3600)
+			printf("%u:", seconds / 3600);
+		if (seconds > 60) {
+			seconds %= 3600;
+			printf("%02u:%02u", seconds / 60, seconds % 60);
+		} else
+			printf("%us", seconds);
+	}
+	printf("\n");
+}
+
+int
+mfi_table_handler(struct mfiutil_command **start, struct mfiutil_command **end,
+    int ac, char **av)
+{
+	struct mfiutil_command **cmd;
+
+	if (ac < 2) {
+		warnx("The %s command requires a sub-command.", av[0]);
+		return (EINVAL);
+	}
+	for (cmd = start; cmd < end; cmd++) {
+		if (strcmp((*cmd)->name, av[1]) == 0)
+			return ((*cmd)->handler(ac - 1, av + 1));
+	}
+
+	warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
+	return (ENOENT);
+}
diff --git a/usr.sbin/mfiutil/mfi_config.c b/usr.sbin/mfiutil/mfi_config.c
new file mode 100644
index 00000000000..6152d21f582
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_config.c
@@ -0,0 +1,1164 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#include 
+#ifdef DEBUG
+#include 
+#endif
+#include 
+#include 
+#include 
+#ifdef DEBUG
+#include 
+#endif
+#include 
+#include 
+#include 
+#include 
+#include "mfiutil.h"
+
+#ifdef DEBUG
+static void	dump_config(int fd, struct mfi_config_data *config);
+#endif
+
+static int	add_spare(int ac, char **av);
+static int	remove_spare(int ac, char **av);
+
+#define powerof2(x)    ((((x)-1)&(x))==0)
+
+static long
+dehumanize(const char *value)
+{
+        char    *vtp;
+        long    iv;
+ 
+        if (value == NULL)
+                return (0);
+        iv = strtoq(value, &vtp, 0);
+        if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) {
+                return (0);
+        }
+        switch (vtp[0]) {
+        case 't': case 'T':
+                iv *= 1024;
+        case 'g': case 'G':
+                iv *= 1024;
+        case 'm': case 'M':
+                iv *= 1024;
+        case 'k': case 'K':
+                iv *= 1024;
+        case '\0':
+                break;
+        default:
+                return (0);
+        }
+        return (iv);
+}
+int
+mfi_config_read(int fd, struct mfi_config_data **configp)
+{
+	struct mfi_config_data *config;
+	uint32_t config_size;
+
+	/*
+	 * Keep fetching the config in a loop until we have a large enough
+	 * buffer to hold the entire configuration.
+	 */
+	config = NULL;
+	config_size = 1024;
+fetch:
+	config = reallocf(config, config_size);
+	if (config == NULL)
+		return (-1);
+	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_READ, config,
+	    config_size, NULL, 0, NULL) < 0)
+		return (-1);
+
+	if (config->size > config_size) {
+		config_size = config->size;
+		goto fetch;
+	}
+
+	*configp = config;
+	return (0);
+}
+
+static struct mfi_array *
+mfi_config_lookup_array(struct mfi_config_data *config, uint16_t array_ref)
+{
+	struct mfi_array *ar;
+	char *p;
+	int i;
+
+	p = (char *)config->array;
+	for (i = 0; i < config->array_count; i++) {
+		ar = (struct mfi_array *)p;
+		if (ar->array_ref == array_ref)
+			return (ar);
+		p += config->array_size;
+	}
+
+	return (NULL);
+}
+
+static struct mfi_ld_config *
+mfi_config_lookup_volume(struct mfi_config_data *config, uint8_t target_id)
+{
+	struct mfi_ld_config *ld;
+	char *p;
+	int i;
+
+	p = (char *)config->array + config->array_count * config->array_size;
+	for (i = 0; i < config->log_drv_count; i++) {
+		ld = (struct mfi_ld_config *)p;
+		if (ld->properties.ld.v.target_id == target_id)
+			return (ld);
+		p += config->log_drv_size;
+	}
+
+	return (NULL);
+}
+
+static int
+clear_config(int ac, char **av)
+{
+	struct mfi_ld_list list;
+	int ch, fd;
+	u_int i;
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (!mfi_reconfig_supported()) {
+		warnx("The current mfi(4) driver does not support "
+		    "configuration changes.");
+		return (EOPNOTSUPP);
+	}
+
+	if (mfi_ld_get_list(fd, &list, NULL) < 0) {
+		warn("Failed to get volume list");
+		return (errno);
+	}
+
+	for (i = 0; i < list.ld_count; i++) {
+		if (mfi_volume_busy(fd, list.ld_list[i].ld.v.target_id)) {
+			warnx("Volume %s is busy and cannot be deleted",
+			    mfi_volume_name(fd, list.ld_list[i].ld.v.target_id));
+			return (EBUSY);
+		}
+	}
+
+	printf(
+	    "Are you sure you wish to clear the configuration on mfi%u? [y/N] ",
+	    mfi_unit);
+	ch = getchar();
+	if (ch != 'y' && ch != 'Y') {
+		printf("\nAborting\n");
+		return (0);
+	}
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_CLEAR, NULL, 0, NULL, 0, NULL) < 0) {
+		warn("Failed to clear configuration");
+		return (errno);
+	}
+
+	printf("mfi%d: Configuration cleared\n", mfi_unit);
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, clear, clear_config);
+
+#define	MFI_ARRAY_SIZE		288
+#define	MAX_DRIVES_PER_ARRAY						\
+	((MFI_ARRAY_SIZE - sizeof(struct mfi_array)) / 8)
+
+#define	RT_RAID0	0
+#define	RT_RAID1	1
+#define	RT_RAID5	2
+#define	RT_RAID6	3
+#define	RT_JBOD		4
+#define	RT_CONCAT	5
+#define	RT_RAID10	6
+#define	RT_RAID50	7
+#define	RT_RAID60	8
+
+static int
+compare_int(const void *one, const void *two)
+{
+	int first, second;
+
+	first = *(const int *)one;
+	second = *(const int *)two;
+
+	return (first - second);
+}
+
+static struct raid_type_entry {
+	const char *name;
+	int	raid_type;
+} raid_type_table[] = {
+	{ "raid0",	RT_RAID0 },
+	{ "raid-0",	RT_RAID0 },
+	{ "raid1",	RT_RAID1 },
+	{ "raid-1",	RT_RAID1 },
+	{ "mirror",	RT_RAID1 },
+	{ "raid5",	RT_RAID5 },
+	{ "raid-5",	RT_RAID5 },
+	{ "raid6",	RT_RAID6 },
+	{ "raid-6",	RT_RAID6 },
+	{ "jbod",	RT_JBOD },
+	{ "concat",	RT_CONCAT },
+	{ "raid10",	RT_RAID10 },
+	{ "raid1+0",	RT_RAID10 },
+	{ "raid-10",	RT_RAID10 },
+	{ "raid-1+0",	RT_RAID10 },
+	{ "raid50",	RT_RAID50 },
+	{ "raid5+0",	RT_RAID50 },
+	{ "raid-50",	RT_RAID50 },
+	{ "raid-5+0",	RT_RAID50 },
+	{ "raid60",	RT_RAID60 },
+	{ "raid6+0",	RT_RAID60 },
+	{ "raid-60",	RT_RAID60 },
+	{ "raid-6+0",	RT_RAID60 },
+	{ NULL,		0 },
+};
+
+struct config_id_state {
+	int	array_count;
+	int	log_drv_count;
+	int	*arrays;
+	int	*volumes;
+	uint16_t array_ref;
+	uint8_t	target_id;
+};
+
+struct array_info {
+	int	drive_count;
+	struct mfi_pd_info *drives;
+	struct mfi_array *array;
+};
+
+/* Parse a comma-separated list of drives for an array. */
+static int
+parse_array(int fd, int raid_type, char *array_str, struct array_info *info)
+{
+	struct mfi_pd_info *pinfo;
+	uint16_t device_id;
+	char *cp;
+	u_int count;
+	int error;
+
+	cp = array_str;
+	for (count = 0; cp != NULL; count++) {
+		cp = strchr(cp, ',');
+		if (cp != NULL) {
+			cp++;
+			if (*cp == ',') {
+				warnx("Invalid drive list '%s'", array_str);
+				return (EINVAL);
+			}
+		}
+	}
+
+	/* Validate the number of drives for this array. */
+	if (count >= MAX_DRIVES_PER_ARRAY) {
+		warnx("Too many drives for a single array: max is %zu",
+		    MAX_DRIVES_PER_ARRAY);
+		return (EINVAL);
+	}
+	switch (raid_type) {
+	case RT_RAID1:
+	case RT_RAID10:
+		if (count % 2 != 0) {
+			warnx("RAID1 and RAID10 require an even number of "
+			    "drives in each array");
+			return (EINVAL);
+		}
+		break;
+	case RT_RAID5:
+	case RT_RAID50:
+		if (count < 3) {
+			warnx("RAID5 and RAID50 require at least 3 drives in "
+			    "each array");
+			return (EINVAL);
+		}
+		break;
+	case RT_RAID6:
+	case RT_RAID60:
+		if (count < 4) {
+			warnx("RAID6 and RAID60 require at least 4 drives in "
+			    "each array");
+			return (EINVAL);
+		}
+		break;
+	}
+
+	/* Validate each drive. */
+	info->drives = calloc(count, sizeof(struct mfi_pd_info));
+	info->drive_count = count;
+	for (pinfo = info->drives; (cp = strsep(&array_str, ",")) != NULL;
+	     pinfo++) {
+		error = mfi_lookup_drive(fd, cp, &device_id);
+		if (error)
+			return (error);
+
+		if (mfi_pd_get_info(fd, device_id, pinfo, NULL) < 0) {
+			warn("Failed to fetch drive info for drive %s", cp);
+			return (errno);
+		}
+
+		if (pinfo->fw_state != MFI_PD_STATE_UNCONFIGURED_GOOD) {
+			warnx("Drive %u is not available", device_id);
+			return (EINVAL);
+		}
+	}
+
+	return (0);
+}
+
+/*
+ * Find the next free array ref assuming that 'array_ref' is the last
+ * one used.  'array_ref' should be 0xffff for the initial test.
+ */
+static uint16_t
+find_next_array(struct config_id_state *state)
+{
+	int i;
+
+	/* Assume the current one is used. */
+	state->array_ref++;
+
+	/* Find the next free one. */
+	for (i = 0; i < state->array_count; i++)
+		if (state->arrays[i] == state->array_ref)
+			state->array_ref++;
+	return (state->array_ref);
+}
+
+/*
+ * Find the next free volume ID assuming that 'target_id' is the last
+ * one used.  'target_id' should be 0xff for the initial test.
+ */
+static uint8_t
+find_next_volume(struct config_id_state *state)
+{
+	int i;
+
+	/* Assume the current one is used. */
+	state->target_id++;
+
+	/* Find the next free one. */
+	for (i = 0; i < state->log_drv_count; i++)
+		if (state->volumes[i] == state->target_id)
+			state->target_id++;
+	return (state->target_id);
+}
+
+/* Populate an array with drives. */
+static void
+build_array(int fd, char *arrayp, struct array_info *array_info,
+    struct config_id_state *state, int verbose)
+{
+	struct mfi_array *ar = (struct mfi_array *)arrayp;
+	int i;
+
+	ar->size = array_info->drives[0].coerced_size;
+	ar->num_drives = array_info->drive_count;
+	ar->array_ref = find_next_array(state);
+	for (i = 0; i < array_info->drive_count; i++) {
+		if (verbose)
+			printf("Adding drive %u to array %u\n",
+			    array_info->drives[i].ref.v.device_id,
+			    ar->array_ref);
+		if (ar->size > array_info->drives[i].coerced_size)
+			ar->size = array_info->drives[i].coerced_size;
+		ar->pd[i].ref = array_info->drives[i].ref;
+		ar->pd[i].fw_state = MFI_PD_STATE_ONLINE;
+	}
+	array_info->array = ar;
+}
+
+/*
+ * Create a volume that spans one or more arrays.
+ */
+static void
+build_volume(char *volumep, int narrays, struct array_info *arrays,
+    int raid_type, long stripe_size, struct config_id_state *state, int verbose)
+{
+	struct mfi_ld_config *ld = (struct mfi_ld_config *)volumep;
+	struct mfi_array *ar;
+	int i;
+
+	/* properties */
+	ld->properties.ld.v.target_id = find_next_volume(state);
+	ld->properties.ld.v.seq = 0;
+	ld->properties.default_cache_policy = MR_LD_CACHE_ALLOW_WRITE_CACHE |
+	    MR_LD_CACHE_WRITE_BACK;
+	ld->properties.access_policy = MFI_LD_ACCESS_RW;
+	ld->properties.disk_cache_policy = MR_PD_CACHE_UNCHANGED;
+	ld->properties.current_cache_policy = MR_LD_CACHE_ALLOW_WRITE_CACHE |
+	    MR_LD_CACHE_WRITE_BACK;
+	ld->properties.no_bgi = 0;
+
+	/* params */
+	switch (raid_type) {
+	case RT_RAID0:
+	case RT_JBOD:
+		ld->params.primary_raid_level = DDF_RAID0;
+		ld->params.raid_level_qualifier = 0;
+		ld->params.secondary_raid_level = 0;
+		break;
+	case RT_RAID1:
+		ld->params.primary_raid_level = DDF_RAID1;
+		ld->params.raid_level_qualifier = 0;
+		ld->params.secondary_raid_level = 0;
+		break;
+	case RT_RAID5:
+		ld->params.primary_raid_level = DDF_RAID5;
+		ld->params.raid_level_qualifier = 3;
+		ld->params.secondary_raid_level = 0;
+		break;
+	case RT_RAID6:
+		ld->params.primary_raid_level = DDF_RAID6;
+		ld->params.raid_level_qualifier = 3;
+		ld->params.secondary_raid_level = 0;
+		break;
+	case RT_CONCAT:
+		ld->params.primary_raid_level = DDF_CONCAT;
+		ld->params.raid_level_qualifier = 0;
+		ld->params.secondary_raid_level = 0;
+		break;
+	case RT_RAID10:
+		ld->params.primary_raid_level = DDF_RAID1;
+		ld->params.raid_level_qualifier = 0;
+		ld->params.secondary_raid_level = 3; /* XXX? */
+		break;
+	case RT_RAID50:
+		/*
+		 * XXX: This appears to work though the card's BIOS
+		 * complains that the configuration is foreign.  The
+		 * BIOS setup does not allow for creation of RAID-50
+		 * or RAID-60 arrays.  The only nested array
+		 * configuration it allows for is RAID-10.
+		 */
+		ld->params.primary_raid_level = DDF_RAID5;
+		ld->params.raid_level_qualifier = 3;
+		ld->params.secondary_raid_level = 3; /* XXX? */
+		break;
+	case RT_RAID60:
+		ld->params.primary_raid_level = DDF_RAID6;
+		ld->params.raid_level_qualifier = 3;
+		ld->params.secondary_raid_level = 3; /* XXX? */
+		break;
+	}
+
+	/*
+	 * Stripe size is encoded as (2 ^ N) * 512 = stripe_size.  Use
+	 * ffs() to simulate log2(stripe_size).
+	 */
+	ld->params.stripe_size = ffs(stripe_size) - 1 - 9;
+	ld->params.num_drives = arrays[0].array->num_drives;
+	ld->params.span_depth = narrays;
+	ld->params.state = MFI_LD_STATE_OPTIMAL;
+	ld->params.init_state = MFI_LD_PARAMS_INIT_NO;
+	ld->params.is_consistent = 0;
+
+	/* spans */
+	for (i = 0; i < narrays; i++) {
+		ar = arrays[i].array;
+		if (verbose)
+			printf("Adding array %u to volume %u\n", ar->array_ref,
+			    ld->properties.ld.v.target_id);
+		ld->span[i].start_block = 0;
+		ld->span[i].num_blocks = ar->size;
+		ld->span[i].array_ref = ar->array_ref;
+	}
+}
+
+static int
+create_volume(int ac, char **av)
+{
+	struct mfi_config_data *config;
+	struct mfi_array *ar;
+	struct mfi_ld_config *ld;
+	struct config_id_state state;
+	size_t config_size;
+	char *p, *cfg_arrays, *cfg_volumes;
+	int error, fd, i, raid_type;
+	int narrays, nvolumes, arrays_per_volume;
+	struct array_info *arrays;
+	long stripe_size;
+#ifdef DEBUG
+	int dump;
+#endif
+	int ch, verbose;
+
+	/*
+	 * Backwards compat.  Map 'create volume' to 'create' and
+	 * 'create spare' to 'add'.
+	 */
+	if (ac > 1) {
+		if (strcmp(av[1], "volume") == 0) {
+			av++;
+			ac--;
+		} else if (strcmp(av[1], "spare") == 0) {
+			av++;
+			ac--;
+			return (add_spare(ac, av));
+		}
+	}
+
+	if (ac < 2) {
+		warnx("create volume: volume type required");
+		return (EINVAL);
+	}
+
+	
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (!mfi_reconfig_supported()) {
+		warnx("The current mfi(4) driver does not support "
+		    "configuration changes.");
+		return (EOPNOTSUPP);
+	}
+
+	/* Lookup the RAID type first. */
+	raid_type = -1;
+	for (i = 0; raid_type_table[i].name != NULL; i++)
+		if (strcasecmp(raid_type_table[i].name, av[1]) == 0) {
+			raid_type = raid_type_table[i].raid_type;
+			break;
+		}
+
+	if (raid_type == -1) {
+		warnx("Unknown or unsupported volume type %s", av[1]);
+		return (EINVAL);
+	}
+
+	/* Parse any options. */
+	optind = 2;
+#ifdef DEBUG
+	dump = 0;
+#endif
+	verbose = 0;
+	stripe_size = 64 * 1024;
+
+	while ((ch = getopt(ac, av, "ds:v")) != -1) {
+		switch (ch) {
+#ifdef DEBUG
+		case 'd':
+			dump = 1;
+			break;
+#endif
+		case 's':
+			stripe_size = dehumanize(optarg);
+			if ((stripe_size < 512) || (!powerof2(stripe_size)))
+				stripe_size = 64 * 1024;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case '?':
+		default:
+			return (EINVAL);
+		}
+	}
+	ac -= optind;
+	av += optind;
+
+	/* Parse all the arrays. */
+	narrays = ac;
+	if (narrays == 0) {
+		warnx("At least one drive list is required");
+		return (EINVAL);
+	}
+	switch (raid_type) {
+	case RT_RAID0:
+	case RT_RAID1:
+	case RT_RAID5:
+	case RT_RAID6:
+	case RT_CONCAT:
+		if (narrays != 1) {
+			warnx("Only one drive list can be specified");
+			return (EINVAL);
+		}
+		break;
+	case RT_RAID10:
+	case RT_RAID50:
+	case RT_RAID60:
+		if (narrays < 1) {
+			warnx("RAID10, RAID50, and RAID60 require at least "
+			    "two drive lists");
+			return (EINVAL);
+		}
+		if (narrays > MFI_MAX_SPAN_DEPTH) {
+			warnx("Volume spans more than %d arrays",
+			    MFI_MAX_SPAN_DEPTH);
+			return (EINVAL);
+		}
+		break;
+	}
+	arrays = calloc(narrays, sizeof(*arrays));
+	for (i = 0; i < narrays; i++) {
+		error = parse_array(fd, raid_type, av[i], &arrays[i]);
+		if (error)
+			return (error);
+	}
+
+	switch (raid_type) {
+	case RT_RAID10:
+	case RT_RAID50:
+	case RT_RAID60:
+		for (i = 1; i < narrays; i++) {
+			if (arrays[i].drive_count != arrays[0].drive_count) {
+				warnx("All arrays must contain the same "
+				    "number of drives");
+				return (EINVAL);
+			}
+		}
+		break;
+	}
+
+	/*
+	 * Fetch the current config and build sorted lists of existing
+	 * array and volume identifiers.
+	 */
+	if (mfi_config_read(fd, &config) < 0) {
+		warn("Failed to read configuration");
+		return (errno);
+	}
+	p = (char *)config->array;
+	state.array_ref = 0xffff;
+	state.target_id = 0xff;
+	state.array_count = config->array_count;
+	if (config->array_count > 0) {
+		state.arrays = calloc(config->array_count, sizeof(int));
+		for (i = 0; i < config->array_count; i++) {
+			ar = (struct mfi_array *)p;
+			state.arrays[i] = ar->array_ref;
+			p += config->array_size;
+		}
+		qsort(state.arrays, config->array_count, sizeof(int),
+		    compare_int);
+	} else
+		state.arrays = NULL;
+	state.log_drv_count = config->log_drv_count;
+	if (config->log_drv_count) {
+		state.volumes = calloc(config->log_drv_count, sizeof(int));
+		for (i = 0; i < config->log_drv_count; i++) {
+			ld = (struct mfi_ld_config *)p;
+			state.volumes[i] = ld->properties.ld.v.target_id;
+			p += config->log_drv_size;
+		}
+		qsort(state.volumes, config->log_drv_count, sizeof(int),
+		    compare_int);
+	} else
+		state.volumes = NULL;
+	free(config);
+
+	/* Determine the size of the configuration we will build. */
+	switch (raid_type) {
+	case RT_RAID0:
+	case RT_RAID1:
+	case RT_RAID5:
+	case RT_RAID6:
+	case RT_CONCAT:
+	case RT_JBOD:
+		/* Each volume spans a single array. */
+		nvolumes = narrays;
+		break;
+	case RT_RAID10:
+	case RT_RAID50:
+	case RT_RAID60:
+		/* A single volume spans multiple arrays. */
+		nvolumes = 1;
+		break;
+	default:
+		/* Pacify gcc. */
+		abort();
+	}
+
+	config_size = sizeof(struct mfi_config_data) +
+	    sizeof(struct mfi_ld_config) * nvolumes + MFI_ARRAY_SIZE * narrays;
+	config = calloc(1, config_size);
+	config->size = config_size;
+	config->array_count = narrays;
+	config->array_size = MFI_ARRAY_SIZE;	/* XXX: Firmware hardcode */
+	config->log_drv_count = nvolumes;
+	config->log_drv_size = sizeof(struct mfi_ld_config);
+	config->spares_count = 0;
+	config->spares_size = 40;		/* XXX: Firmware hardcode */
+	cfg_arrays = (char *)config->array;
+	cfg_volumes = cfg_arrays + config->array_size * narrays;
+
+	/* Build the arrays. */
+	for (i = 0; i < narrays; i++) {
+		build_array(fd, cfg_arrays, &arrays[i], &state, verbose);
+		cfg_arrays += config->array_size;
+	}
+
+	/* Now build the volume(s). */
+	arrays_per_volume = narrays / nvolumes;
+	for (i = 0; i < nvolumes; i++) {
+		build_volume(cfg_volumes, arrays_per_volume,
+		    &arrays[i * arrays_per_volume], raid_type, stripe_size,
+		    &state, verbose);
+		cfg_volumes += config->log_drv_size;
+	}
+
+#ifdef DEBUG
+	if (dump)
+		dump_config(fd, config);
+	else
+#endif
+
+	/* Send the new config to the controller. */
+	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_ADD, config, config_size,
+	    NULL, 0, NULL) < 0) {
+		warn("Failed to add volume");
+		return (errno);
+	}
+
+	/* Clean up. */
+	free(config);
+	if (state.log_drv_count > 0)
+		free(state.volumes);
+	if (state.array_count > 0)
+		free(state.arrays);
+	for (i = 0; i < narrays; i++)
+		free(arrays[i].drives);
+	free(arrays);
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, create, create_volume);
+
+static int
+delete_volume(int ac, char **av)
+{
+	struct mfi_ld_info info;
+	int fd;
+	uint8_t target_id, mbox[4];
+
+	/*
+	 * Backwards compat.  Map 'delete volume' to 'delete' and
+	 * 'delete spare' to 'remove'.
+	 */
+	if (ac > 1) {
+		if (strcmp(av[1], "volume") == 0) {
+			av++;
+			ac--;
+		} else if (strcmp(av[1], "spare") == 0) {
+			av++;
+			ac--;
+			return (remove_spare(ac, av));
+		}
+	}
+
+	if (ac != 2) {
+		warnx("delete volume: volume required");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (!mfi_reconfig_supported()) {
+		warnx("The current mfi(4) driver does not support "
+		    "configuration changes.");
+		return (EOPNOTSUPP);
+	}
+
+	if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
+		warn("Invalid volume %s", av[1]);
+		return (errno);
+	}
+
+	if (mfi_ld_get_info(fd, target_id, &info, NULL) < 0) {
+		warn("Failed to get info for volume %d", target_id);
+		return (errno);
+	}
+
+	if (mfi_volume_busy(fd, target_id)) {
+		warnx("Volume %s is busy and cannot be deleted",
+		    mfi_volume_name(fd, target_id));
+		return (EBUSY);
+	}
+
+	mbox_store_ldref(mbox, &info.ld_config.properties.ld);
+	if (mfi_dcmd_command(fd, MFI_DCMD_LD_DELETE, NULL, 0, mbox,
+	    sizeof(mbox), NULL) < 0) {
+		warn("Failed to delete volume");
+		return (errno);
+	}
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, delete, delete_volume);
+
+static int
+add_spare(int ac, char **av)
+{
+	struct mfi_pd_info info;
+	struct mfi_config_data *config;
+	struct mfi_array *ar;
+	struct mfi_ld_config *ld;
+	struct mfi_spare *spare;
+	uint16_t device_id;
+	uint8_t target_id;
+	char *p;
+	int error, fd, i;
+
+	if (ac < 2) {
+		warnx("add spare: drive required");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	error = mfi_lookup_drive(fd, av[1], &device_id);
+	if (error)
+		return (error);
+
+	if (mfi_pd_get_info(fd, device_id, &info, NULL) < 0) {
+		warn("Failed to fetch drive info");
+		return (errno);
+	}
+
+	if (info.fw_state != MFI_PD_STATE_UNCONFIGURED_GOOD) {
+		warnx("Drive %u is not available", device_id);
+		return (EINVAL);
+	}
+
+	if (ac > 2) {
+		if (mfi_lookup_volume(fd, av[2], &target_id) < 0) {
+			warn("Invalid volume %s", av[2]);
+			return (errno);
+		}
+	}
+
+	if (mfi_config_read(fd, &config) < 0) {
+		warn("Failed to read configuration");
+		return (errno);
+	}
+
+	spare = malloc(sizeof(struct mfi_spare) + sizeof(uint16_t) *
+	    config->array_count);
+	bzero(spare, sizeof(struct mfi_spare));
+	spare->ref = info.ref;
+
+	if (ac == 2) {
+		/* Global spare backs all arrays. */
+		p = (char *)config->array;
+		for (i = 0; i < config->array_count; i++) {
+			ar = (struct mfi_array *)p;
+			if (ar->size > info.coerced_size) {
+				warnx("Spare isn't large enough for array %u",
+				    ar->array_ref);
+				return (EINVAL);
+			}
+			p += config->array_size;
+		}
+		spare->array_count = 0;
+	} else  {
+		/*
+		 * Dedicated spares only back the arrays for a
+		 * specific volume.
+		 */
+		ld = mfi_config_lookup_volume(config, target_id);
+		if (ld == NULL) {
+			warnx("Did not find volume %d", target_id);
+			return (EINVAL);
+		}
+
+		spare->spare_type |= MFI_SPARE_DEDICATED;
+		spare->array_count = ld->params.span_depth;
+		for (i = 0; i < ld->params.span_depth; i++) {
+			ar = mfi_config_lookup_array(config,
+			    ld->span[i].array_ref);
+			if (ar == NULL) {
+				warnx("Missing array; inconsistent config?");
+				return (ENXIO);
+			}
+			if (ar->size > info.coerced_size) {
+				warnx("Spare isn't large enough for array %u",
+				    ar->array_ref);
+				return (EINVAL);
+			}				
+			spare->array_ref[i] = ar->array_ref;
+		}
+	}
+	free(config);
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_MAKE_SPARE, spare,
+	    sizeof(struct mfi_spare) + sizeof(uint16_t) * spare->array_count,
+	    NULL, 0, NULL) < 0) {
+		warn("Failed to assign spare");
+		return (errno);
+	}
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, add, add_spare);
+
+static int
+remove_spare(int ac, char **av)
+{
+	struct mfi_pd_info info;
+	int error, fd;
+	uint16_t device_id;
+	uint8_t mbox[4];
+
+	if (ac != 2) {
+		warnx("remove spare: drive required");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	error = mfi_lookup_drive(fd, av[1], &device_id);
+	if (error)
+		return (error);
+
+	/* Get the info for this drive. */
+	if (mfi_pd_get_info(fd, device_id, &info, NULL) < 0) {
+		warn("Failed to fetch info for drive %u", device_id);
+		return (errno);
+	}
+
+	if (info.fw_state != MFI_PD_STATE_HOT_SPARE) {
+		warnx("Drive %u is not a hot spare", device_id);
+		return (EINVAL);
+	}
+
+	mbox_store_pdref(mbox, &info.ref);
+	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_REMOVE_SPARE, NULL, 0, mbox,
+	    sizeof(mbox), NULL) < 0) {
+		warn("Failed to delete spare");
+		return (errno);
+	}
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, remove, remove_spare);
+
+#ifdef DEBUG
+/* Display raw data about a config. */
+static void
+dump_config(int fd, struct mfi_config_data *config)
+{
+	struct mfi_array *ar;
+	struct mfi_ld_config *ld;
+	struct mfi_spare *sp;
+	struct mfi_pd_info pinfo;
+	uint16_t device_id;
+	char *p;
+	int i, j;
+
+	printf(
+	    "mfi%d Configuration (Debug): %d arrays, %d volumes, %d spares\n",
+	    mfi_unit, config->array_count, config->log_drv_count,
+	    config->spares_count);
+	printf("  array size: %u\n", config->array_size);
+	printf("  volume size: %u\n", config->log_drv_size);
+	printf("  spare size: %u\n", config->spares_size);
+	p = (char *)config->array;
+
+	for (i = 0; i < config->array_count; i++) {
+		ar = (struct mfi_array *)p;
+		printf("    array %u of %u drives:\n", ar->array_ref,
+		    ar->num_drives);
+		printf("      size = %ju\n", (uintmax_t)ar->size);
+		for (j = 0; j < ar->num_drives; j++) {
+			device_id = ar->pd[j].ref.device_id;
+			if (device_id == 0xffff)
+				printf("        drive MISSING\n");
+			else {
+				printf("        drive %u %s\n", device_id,
+				    mfi_pdstate(ar->pd[j].fw_state));
+				if (mfi_pd_get_info(fd, device_id, &pinfo,
+				    NULL) >= 0) {
+					printf("          raw size: %ju\n",
+					    (uintmax_t)pinfo.raw_size);
+					printf("          non-coerced size: %ju\n",
+					    (uintmax_t)pinfo.non_coerced_size);
+					printf("          coerced size: %ju\n",
+					    (uintmax_t)pinfo.coerced_size);
+				}
+			}
+		}
+		p += config->array_size;
+	}
+
+	for (i = 0; i < config->log_drv_count; i++) {
+		ld = (struct mfi_ld_config *)p;
+		printf("    volume %s ",
+		    mfi_volume_name(fd, ld->properties.ld.v.target_id));
+		printf("%s %s",
+		    mfi_raid_level(ld->params.primary_raid_level,
+			ld->params.secondary_raid_level),
+		    mfi_ldstate(ld->params.state));
+		if (ld->properties.name[0] != '\0')
+			printf(" <%s>", ld->properties.name);
+		printf("\n");
+		printf("      primary raid level: %u\n",
+		    ld->params.primary_raid_level);
+		printf("      raid level qualifier: %u\n",
+		    ld->params.raid_level_qualifier);
+		printf("      secondary raid level: %u\n",
+		    ld->params.secondary_raid_level);
+		printf("      stripe size: %u\n", ld->params.stripe_size);
+		printf("      num drives: %u\n", ld->params.num_drives);
+		printf("      init state: %u\n", ld->params.init_state);
+		printf("      consistent: %u\n", ld->params.is_consistent);
+		printf("      no bgi: %u\n", ld->properties.no_bgi);
+		printf("      spans:\n");
+		for (j = 0; j < ld->params.span_depth; j++) {
+			printf("        array %u @ ", ld->span[j].array_ref);
+			printf("%ju : %ju\n",
+			    (uintmax_t)ld->span[j].start_block,
+			    (uintmax_t)ld->span[j].num_blocks);
+		}
+		p += config->log_drv_size;
+	}
+
+	for (i = 0; i < config->spares_count; i++) {
+		sp = (struct mfi_spare *)p;
+		printf("    %s spare %u ",
+		    sp->spare_type & MFI_SPARE_DEDICATED ? "dedicated" :
+		    "global", sp->ref.device_id);
+		printf("%s", mfi_pdstate(MFI_PD_STATE_HOT_SPARE));
+		printf(" backs:\n");
+		for (j = 0; j < sp->array_count; j++)
+			printf("        array %u\n", sp->array_ref[j]);
+		p += config->spares_size;
+	}
+}
+
+static int
+debug_config(int ac, char **av)
+{
+	struct mfi_config_data *config;
+	int fd;
+
+	if (ac != 1) {
+		warnx("debug: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	/* Get the config from the controller. */
+	if (mfi_config_read(fd, &config) < 0) {
+		warn("Failed to get config");
+		return (errno);
+	}
+
+	/* Dump out the configuration. */
+	dump_config(fd, config);
+	free(config);
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, debug, debug_config);
+
+static int
+dump(int ac, char **av)
+{
+	struct mfi_config_data *config;
+	char buf[64];
+	size_t len;
+	int fd;
+
+	if (ac != 1) {
+		warnx("dump: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	/* Get the stashed copy of the last dcmd from the driver. */
+	snprintf(buf, sizeof(buf), "dev.mfi.%d.debug_command", mfi_unit);
+	if (sysctlbyname(buf, NULL, &len, NULL, 0) < 0) {
+		warn("Failed to read debug command");
+		if (errno == ENOENT)
+			errno = EOPNOTSUPP;
+		return (errno);
+	}
+
+	config = malloc(len);
+	if (sysctlbyname(buf, config, &len, NULL, 0) < 0) {
+		warn("Failed to read debug command");
+		return (errno);
+	}
+	dump_config(fd, config);
+	free(config);
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, dump, dump);
+#endif
diff --git a/usr.sbin/mfiutil/mfi_drive.c b/usr.sbin/mfiutil/mfi_drive.c
new file mode 100644
index 00000000000..104422814ea
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_drive.c
@@ -0,0 +1,625 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mfiutil.h"
+
+MFI_TABLE(top, drive);
+
+const char *
+mfi_pdstate(enum mfi_pd_state state)
+{
+	static char buf[16];
+
+	switch (state) {
+	case MFI_PD_STATE_UNCONFIGURED_GOOD:
+		return ("UNCONFIGURED GOOD");
+	case MFI_PD_STATE_UNCONFIGURED_BAD:
+		return ("UNCONFIGURED BAD");
+	case MFI_PD_STATE_HOT_SPARE:
+		return ("HOT SPARE");
+	case MFI_PD_STATE_OFFLINE:
+		return ("OFFLINE");
+	case MFI_PD_STATE_FAILED:
+		return ("FAILED");
+	case MFI_PD_STATE_REBUILD:
+		return ("REBUILD");
+	case MFI_PD_STATE_ONLINE:
+		return ("ONLINE");
+	default:
+		sprintf(buf, "PSTATE 0x%04x", state);
+		return (buf);
+	}
+}
+
+int
+mfi_lookup_drive(int fd, char *drive, uint16_t *device_id)
+{
+	struct mfi_pd_list *list;
+	uint8_t encl, slot;
+	long val;
+	u_int i;
+	char *cp;
+
+	/* Look for a raw device id first. */
+	val = strtol(drive, &cp, 0);
+	if (*cp == '\0') {
+		if (val < 0 || val >= 0xffff)
+			goto bad;
+		*device_id = val;
+		return (0);
+	}
+
+	/* Support for MegaCli style [Exx]:Syy notation. */
+	if (toupper(drive[0]) == 'E' || toupper(drive[0]) == 'S') {
+		if (drive[1] == '\0')
+			goto bad;
+		cp = drive;
+		if (toupper(drive[0]) == 'E') {
+			cp++;			/* Eat 'E' */
+			val = strtol(cp, &cp, 0);
+			if (val < 0 || val > 0xff || *cp != ':')
+				goto bad;
+			encl = val;
+			cp++;			/* Eat ':' */
+			if (toupper(*cp) != 'S')
+				goto bad;
+		} else
+			encl = 0xff;
+		cp++;				/* Eat 'S' */
+		if (*cp == '\0')
+			goto bad;
+		val = strtol(cp, &cp, 0);
+		if (val < 0 || val > 0xff || *cp != '\0')
+			goto bad;
+		slot = val;
+
+		if (mfi_pd_get_list(fd, &list, NULL) < 0) {
+			warn("Failed to fetch drive list");
+			return (errno);
+		}
+
+		for (i = 0; i < list->count; i++) {
+			if (list->addr[i].scsi_dev_type != 0)
+				continue;
+
+			if (((encl == 0xff &&
+			    list->addr[i].encl_device_id == 0xffff) ||
+			    list->addr[i].encl_index == encl) &&
+			    list->addr[i].slot_number == slot) {
+				*device_id = list->addr[i].device_id;
+				free(list);
+				return (0);
+			}
+		}
+		free(list);
+		warnx("Unknown drive %s", drive);
+		return (EINVAL);
+	}
+
+bad:
+	warnx("Invalid drive number %s", drive);
+	return (EINVAL);
+}
+
+static void
+mbox_store_device_id(uint8_t *mbox, uint16_t device_id)
+{
+
+	mbox[0] = device_id & 0xff;
+	mbox[1] = device_id >> 8;
+}
+
+void
+mbox_store_pdref(uint8_t *mbox, union mfi_pd_ref *ref)
+{
+
+	mbox[0] = ref->v.device_id & 0xff;
+	mbox[1] = ref->v.device_id >> 8;
+	mbox[2] = ref->v.seq_num & 0xff;
+	mbox[3] = ref->v.seq_num >> 8;
+}
+
+int
+mfi_pd_get_list(int fd, struct mfi_pd_list **listp, uint8_t *statusp)
+{
+	struct mfi_pd_list *list;
+	uint32_t list_size;
+
+	/*
+	 * Keep fetching the list in a loop until we have a large enough
+	 * buffer to hold the entire list.
+	 */
+	list = NULL;
+	list_size = 1024;
+fetch:
+	list = reallocf(list, list_size);
+	if (list == NULL)
+		return (-1);
+	if (mfi_dcmd_command(fd, MFI_DCMD_PD_GET_LIST, list, list_size, NULL,
+	    0, statusp) < 0) {
+		free(list);
+		return (-1);
+	}
+
+	if (list->size > list_size) {
+		list_size = list->size;
+		goto fetch;
+	}
+
+	*listp = list;
+	return (0);
+}
+
+int
+mfi_pd_get_info(int fd, uint16_t device_id, struct mfi_pd_info *info,
+    uint8_t *statusp)
+{
+	uint8_t mbox[2];
+
+	mbox_store_device_id(&mbox[0], device_id);
+	return (mfi_dcmd_command(fd, MFI_DCMD_PD_GET_INFO, info,
+	    sizeof(struct mfi_pd_info), mbox, 2, statusp));
+}
+
+static void
+cam_strvis(char *dst, const char *src, int srclen, int dstlen)
+{
+
+	/* Trim leading/trailing spaces, nulls. */
+	while (srclen > 0 && src[0] == ' ')
+		src++, srclen--;
+	while (srclen > 0
+	    && (src[srclen-1] == ' ' || src[srclen-1] == '\0'))
+		srclen--;
+
+	while (srclen > 0 && dstlen > 1) {
+		char *cur_pos = dst;
+
+		if (*src < 0x20) {
+			/* SCSI-II Specifies that these should never occur. */
+			/* non-printable character */
+			if (dstlen > 4) {
+				*cur_pos++ = '\\';
+				*cur_pos++ = ((*src & 0300) >> 6) + '0';
+				*cur_pos++ = ((*src & 0070) >> 3) + '0';
+				*cur_pos++ = ((*src & 0007) >> 0) + '0';
+			} else {
+				*cur_pos++ = '?';
+			}
+		} else {
+			/* normal character */
+			*cur_pos++ = *src;
+		}
+		src++;
+		srclen--;
+		dstlen -= cur_pos - dst;
+		dst = cur_pos;
+	}
+	*dst = '\0';
+}
+
+/* Borrowed heavily from scsi_all.c:scsi_print_inquiry(). */
+const char *
+mfi_pd_inq_string(struct mfi_pd_info *info)
+{
+	struct scsi_inquiry_data *inq_data;
+	char vendor[16], product[48], revision[16], rstr[12], serial[SID_VENDOR_SPECIFIC_0_SIZE];
+	static char inq_string[64];
+
+	inq_data = (struct scsi_inquiry_data *)info->inquiry_data;
+	if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data))
+		return (NULL);
+	if (SID_TYPE(inq_data) != T_DIRECT)
+		return (NULL);
+	if (SID_QUAL(inq_data) != SID_QUAL_LU_CONNECTED)
+		return (NULL);
+
+	cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
+	    sizeof(vendor));
+	cam_strvis(product, inq_data->product, sizeof(inq_data->product),
+	    sizeof(product));
+	cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
+	    sizeof(revision));
+	cam_strvis(serial, (char *)inq_data->vendor_specific0, sizeof(inq_data->vendor_specific0),
+	    sizeof(serial));
+
+	/* Hack for SATA disks, no idea how to tell speed. */
+	if (strcmp(vendor, "ATA") == 0) {
+		snprintf(inq_string, sizeof(inq_string), "<%s %s serial=%s> SATA",
+		    product, revision, serial);
+		return (inq_string);
+	}
+
+	switch (SID_ANSI_REV(inq_data)) {
+	case SCSI_REV_CCS:
+		strcpy(rstr, "SCSI-CCS");
+		break;
+	case 5:
+		strcpy(rstr, "SAS");
+		break;
+	default:
+		snprintf(rstr, sizeof (rstr), "SCSI-%d",
+		    SID_ANSI_REV(inq_data));
+		break;
+	}
+	snprintf(inq_string, sizeof(inq_string), "<%s %s %s serial=%s> %s", vendor,
+	    product, revision, serial, rstr);
+	return (inq_string);
+}
+
+/* Helper function to set a drive to a given state. */
+static int
+drive_set_state(char *drive, uint16_t new_state)
+{
+	struct mfi_pd_info info;
+	uint16_t device_id;
+	uint8_t mbox[6];
+	int error, fd;
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	error = mfi_lookup_drive(fd, drive, &device_id);
+	if (error)
+		return (error);
+
+	/* Get the info for this drive. */
+	if (mfi_pd_get_info(fd, device_id, &info, NULL) < 0) {
+		warn("Failed to fetch info for drive %u", device_id);
+		return (errno);
+	}
+
+	/* Try to change the state. */
+	if (info.fw_state == new_state) {
+		warnx("Drive %u is already in the desired state", device_id);
+		return (EINVAL);
+	}
+
+	mbox_store_pdref(&mbox[0], &info.ref);
+	mbox[4] = new_state & 0xff;
+	mbox[5] = new_state >> 8;
+	if (mfi_dcmd_command(fd, MFI_DCMD_PD_STATE_SET, NULL, 0, mbox, 6,
+	    NULL) < 0) {
+		warn("Failed to set drive %u to %s", device_id,
+		    mfi_pdstate(new_state));
+		return (errno);
+	}
+
+	close(fd);
+
+	return (0);
+}
+
+static int
+fail_drive(int ac, char **av)
+{
+
+	if (ac != 2) {
+		warnx("fail: %s", ac > 2 ? "extra arguments" :
+		    "drive required");
+		return (EINVAL);
+	}
+
+	return (drive_set_state(av[1], MFI_PD_STATE_FAILED));
+}
+MFI_COMMAND(top, fail, fail_drive);
+
+static int
+good_drive(int ac, char **av)
+{
+
+	if (ac != 2) {
+		warnx("good: %s", ac > 2 ? "extra arguments" :
+		    "drive required");
+		return (EINVAL);
+	}
+
+	return (drive_set_state(av[1], MFI_PD_STATE_UNCONFIGURED_GOOD));
+}
+MFI_COMMAND(top, good, good_drive);
+
+static int
+rebuild_drive(int ac, char **av)
+{
+
+	if (ac != 2) {
+		warnx("rebuild: %s", ac > 2 ? "extra arguments" :
+		    "drive required");
+		return (EINVAL);
+	}
+
+	return (drive_set_state(av[1], MFI_PD_STATE_REBUILD));
+}
+MFI_COMMAND(top, rebuild, rebuild_drive);
+
+static int
+start_rebuild(int ac, char **av)
+{
+	struct mfi_pd_info info;
+	uint16_t device_id;
+	uint8_t mbox[4];
+	int error, fd;
+
+	if (ac != 2) {
+		warnx("start rebuild: %s", ac > 2 ? "extra arguments" :
+		    "drive required");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	error = mfi_lookup_drive(fd, av[1], &device_id);
+	if (error)
+		return (error);
+
+	/* Get the info for this drive. */
+	if (mfi_pd_get_info(fd, device_id, &info, NULL) < 0) {
+		warn("Failed to fetch info for drive %u", device_id);
+		return (errno);
+	}
+
+	/* Check the state, must be REBUILD. */
+	if (info.fw_state != MFI_PD_STATE_REBUILD) {
+		warn("Drive %d is not in the REBUILD state", device_id);
+		return (EINVAL);
+	}
+
+	/* Start the rebuild. */
+	mbox_store_pdref(&mbox[0], &info.ref);
+	if (mfi_dcmd_command(fd, MFI_DCMD_PD_REBUILD_START, NULL, 0, mbox, 4,
+	    NULL) < 0) {
+		warn("Failed to start rebuild on drive %u", device_id);
+		return (errno);
+	}
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(start, rebuild, start_rebuild);
+
+static int
+abort_rebuild(int ac, char **av)
+{
+	struct mfi_pd_info info;
+	uint16_t device_id;
+	uint8_t mbox[4];
+	int error, fd;
+
+	if (ac != 2) {
+		warnx("abort rebuild: %s", ac > 2 ? "extra arguments" :
+		    "drive required");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	error = mfi_lookup_drive(fd, av[1], &device_id);
+	if (error)
+		return (error);
+
+	/* Get the info for this drive. */
+	if (mfi_pd_get_info(fd, device_id, &info, NULL) < 0) {
+		warn("Failed to fetch info for drive %u", device_id);
+		return (errno);
+	}
+
+	/* Check the state, must be REBUILD. */
+	if (info.fw_state != MFI_PD_STATE_REBUILD) {
+		warn("Drive %d is not in the REBUILD state", device_id);
+		return (EINVAL);
+	}
+
+	/* Abort the rebuild. */
+	mbox_store_pdref(&mbox[0], &info.ref);
+	if (mfi_dcmd_command(fd, MFI_DCMD_PD_REBUILD_ABORT, NULL, 0, mbox, 4,
+	    NULL) < 0) {
+		warn("Failed to abort rebuild on drive %u", device_id);
+		return (errno);
+	}
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(abort, rebuild, abort_rebuild);
+
+static int
+drive_progress(int ac, char **av)
+{
+	struct mfi_pd_info info;
+	uint16_t device_id;
+	int error, fd;
+
+	if (ac != 2) {
+		warnx("drive progress: %s", ac > 2 ? "extra arguments" :
+		    "drive required");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	error = mfi_lookup_drive(fd, av[1], &device_id);
+	if (error)
+		return (error);
+
+	/* Get the info for this drive. */
+	if (mfi_pd_get_info(fd, device_id, &info, NULL) < 0) {
+		warn("Failed to fetch info for drive %u", device_id);
+		return (errno);
+	}
+	close(fd);
+
+	/* Display any of the active events. */
+	if (info.prog_info.active & MFI_PD_PROGRESS_REBUILD)
+		mfi_display_progress("Rebuild", &info.prog_info.rbld);
+	if (info.prog_info.active & MFI_PD_PROGRESS_PATROL)
+		mfi_display_progress("Patrol Read", &info.prog_info.patrol);
+	if (info.prog_info.active & MFI_PD_PROGRESS_CLEAR)
+		mfi_display_progress("Clear", &info.prog_info.clear);
+	if ((info.prog_info.active & (MFI_PD_PROGRESS_REBUILD |
+	    MFI_PD_PROGRESS_PATROL | MFI_PD_PROGRESS_CLEAR)) == 0)
+		printf("No activity in progress for drive %u.\n", device_id);
+
+	return (0);
+}
+MFI_COMMAND(drive, progress, drive_progress);
+
+static int
+drive_clear(int ac, char **av)
+{
+	struct mfi_pd_info info;
+	uint32_t opcode;
+	uint16_t device_id;
+	uint8_t mbox[4];
+	char *s1;
+	int error, fd;
+
+	if (ac != 3) {
+		warnx("drive clear: %s", ac > 3 ? "extra arguments" :
+		    "drive and action requires");
+		return (EINVAL);
+	}
+
+	for (s1 = av[2]; *s1 != '\0'; s1++)
+		*s1 = tolower(*s1);
+	if (strcmp(av[2], "start") == 0)
+		opcode = MFI_DCMD_PD_CLEAR_START;
+	else if ((strcmp(av[2], "stop") == 0) || (strcmp(av[2], "abort") == 0))
+		opcode = MFI_DCMD_PD_CLEAR_ABORT;
+	else {
+		warnx("drive clear: invalid action, must be 'start' or 'stop'\n");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	error = mfi_lookup_drive(fd, av[1], &device_id);
+	if (error)
+		return (error);
+
+	/* Get the info for this drive. */
+	if (mfi_pd_get_info(fd, device_id, &info, NULL) < 0) {
+		warn("Failed to fetch info for drive %u", device_id);
+		return (errno);
+	}
+
+	mbox_store_pdref(&mbox[0], &info.ref);
+	if (mfi_dcmd_command(fd, opcode, NULL, 0, mbox, 4, NULL) < 0) {
+		warn("Failed to %s clear on drive %u",
+		    opcode == MFI_DCMD_PD_CLEAR_START ? "start" : "stop",
+		    device_id);
+		return (errno);
+	}
+
+	close(fd);
+	return (0);
+}
+MFI_COMMAND(drive, clear, drive_clear);
+
+static int
+drive_locate(int ac, char **av)
+{
+	uint16_t device_id;
+	uint32_t opcode;
+	int error, fd;
+	uint8_t mbox[4];
+
+	if (ac != 3) {
+		warnx("locate: %s", ac > 3 ? "extra arguments" :
+		    "drive and state required");
+		return (EINVAL);
+	}
+
+	if (strcasecmp(av[2], "on") == 0 || strcasecmp(av[2], "start") == 0)
+		opcode = MFI_DCMD_PD_LOCATE_START;
+	else if (strcasecmp(av[2], "off") == 0 ||
+	    strcasecmp(av[2], "stop") == 0)
+		opcode = MFI_DCMD_PD_LOCATE_STOP;
+	else {
+		warnx("locate: invalid state %s", av[2]);
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	error = mfi_lookup_drive(fd, av[1], &device_id);
+	if (error)
+		return (error);
+
+
+	mbox_store_device_id(&mbox[0], device_id);
+	mbox[2] = 0;
+	mbox[3] = 0;
+	if (mfi_dcmd_command(fd, opcode, NULL, 0, mbox, 4, NULL) < 0) {
+		warn("Failed to %s locate on drive %u",
+		    opcode == MFI_DCMD_PD_LOCATE_START ? "start" : "stop",
+		    device_id);
+		return (errno);
+	}
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, locate, drive_locate);
diff --git a/usr.sbin/mfiutil/mfi_evt.c b/usr.sbin/mfiutil/mfi_evt.c
new file mode 100644
index 00000000000..d553dae086e
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_evt.c
@@ -0,0 +1,667 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#include 
+#include 
+#include 
+//#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mfiutil.h"
+
+static int
+mfi_event_get_info(int fd, struct mfi_evt_log_state *info, uint8_t *statusp)
+{
+
+	return (mfi_dcmd_command(fd, MFI_DCMD_CTRL_EVENT_GETINFO, info,
+	    sizeof(struct mfi_evt_log_state), NULL, 0, statusp));
+}
+
+static int
+mfi_get_events(int fd, struct mfi_evt_list *list, int num_events,
+    union mfi_evt filter, uint32_t start_seq, uint8_t *statusp)
+{
+	uint32_t mbox[2];
+	size_t size;
+
+	mbox[0] = start_seq;
+	mbox[1] = filter.word;
+	size = sizeof(struct mfi_evt_list) + sizeof(struct mfi_evt_detail) *
+	    (num_events - 1);
+	return (mfi_dcmd_command(fd, MFI_DCMD_CTRL_EVENT_GET, list, size,
+	    (uint8_t *)&mbox, sizeof(mbox), statusp));
+}
+
+static int
+show_logstate(int ac, char **av)
+{
+	struct mfi_evt_log_state info;
+	int fd;
+
+	if (ac != 1) {
+		warnx("show logstate: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_event_get_info(fd, &info, NULL) < 0) {
+		warn("Failed to get event log info");
+		return (errno);
+	}
+
+	printf("mfi%d Event Log Sequence Numbers:\n", mfi_unit);
+	printf("  Newest Seq #: %u\n", info.newest_seq_num);
+	printf("  Oldest Seq #: %u\n", info.oldest_seq_num);
+	printf("   Clear Seq #: %u\n", info.clear_seq_num);
+	printf("Shutdown Seq #: %u\n", info.shutdown_seq_num);
+	printf("    Boot Seq #: %u\n", info.boot_seq_num);
+	
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(show, logstate, show_logstate);
+
+static int
+parse_seq(struct mfi_evt_log_state *info, char *arg, uint32_t *seq)
+{
+	char *cp;
+	long val;
+
+	if (strcasecmp(arg, "newest") == 0) {
+		*seq = info->newest_seq_num;
+		return (0);
+	}
+	if (strcasecmp(arg, "oldest") == 0) {
+		*seq = info->oldest_seq_num;
+		return (0);
+	}
+	if (strcasecmp(arg, "clear") == 0) {
+		*seq = info->clear_seq_num;
+		return (0);
+	}
+	if (strcasecmp(arg, "shutdown") == 0) {
+		*seq = info->shutdown_seq_num;
+		return (0);
+	}
+	if (strcasecmp(arg, "boot") == 0) {
+		*seq = info->boot_seq_num;
+		return (0);
+	}
+	val = strtol(arg, &cp, 0);
+	if (*cp != '\0' || val < 0) {
+		errno = EINVAL;
+		return (-1);
+	}
+	*seq = val;
+	return (0);
+}
+
+static int
+parse_locale(char *arg, uint16_t *locale)
+{
+	char *cp;
+	long val;
+
+	if (strncasecmp(arg, "vol", 3) == 0 || strcasecmp(arg, "ld") == 0) {
+		*locale = MFI_EVT_LOCALE_LD;
+		return (0);
+	}
+	if (strncasecmp(arg, "drive", 5) == 0 || strcasecmp(arg, "pd") == 0) {
+		*locale = MFI_EVT_LOCALE_PD;
+		return (0);
+	}
+	if (strncasecmp(arg, "encl", 4) == 0) {
+		*locale = MFI_EVT_LOCALE_ENCL;
+		return (0);
+	}
+	if (strncasecmp(arg, "batt", 4) == 0 ||
+	    strncasecmp(arg, "bbu", 3) == 0) {
+		*locale = MFI_EVT_LOCALE_BBU;
+		return (0);
+	}
+	if (strcasecmp(arg, "sas") == 0) {
+		*locale = MFI_EVT_LOCALE_SAS;
+		return (0);
+	}
+	if (strcasecmp(arg, "ctrl") == 0 || strncasecmp(arg, "cont", 4) == 0) {
+		*locale = MFI_EVT_LOCALE_CTRL;
+		return (0);
+	}
+	if (strcasecmp(arg, "config") == 0) {
+		*locale = MFI_EVT_LOCALE_CONFIG;
+		return (0);
+	}
+	if (strcasecmp(arg, "cluster") == 0) {
+		*locale = MFI_EVT_LOCALE_CLUSTER;
+		return (0);
+	}
+	if (strcasecmp(arg, "all") == 0) {
+		*locale = MFI_EVT_LOCALE_ALL;
+		return (0);
+	}
+	val = strtol(arg, &cp, 0);
+	if (*cp != '\0' || val < 0 || val > 0xffff) {
+		errno = EINVAL;
+		return (-1);
+	}
+	*locale = val;
+	return (0);
+}
+
+static int
+parse_class(char *arg, int8_t *class)
+{
+	char *cp;
+	long val;
+
+	if (strcasecmp(arg, "debug") == 0) {
+		*class = MFI_EVT_CLASS_DEBUG;
+		return (0);
+	}
+	if (strncasecmp(arg, "prog", 4) == 0) {
+		*class = MFI_EVT_CLASS_PROGRESS;
+		return (0);
+	}
+	if (strncasecmp(arg, "info", 4) == 0) {
+		*class = MFI_EVT_CLASS_INFO;
+		return (0);
+	}
+	if (strncasecmp(arg, "warn", 4) == 0) {
+		*class = MFI_EVT_CLASS_WARNING;
+		return (0);
+	}
+	if (strncasecmp(arg, "crit", 4) == 0) {
+		*class = MFI_EVT_CLASS_CRITICAL;
+		return (0);
+	}
+	if (strcasecmp(arg, "fatal") == 0) {
+		*class = MFI_EVT_CLASS_FATAL;
+		return (0);
+	}
+	if (strcasecmp(arg, "dead") == 0) {
+		*class = MFI_EVT_CLASS_DEAD;
+		return (0);
+	}
+	val = strtol(arg, &cp, 0);
+	if (*cp != '\0' || val < -128 || val > 127) {
+		errno = EINVAL;
+		return (-1);
+	}
+	*class = val;
+	return (0);
+}
+
+/*
+ * The timestamp is the number of seconds since 00:00 Jan 1, 2000.  If
+ * the bits in 24-31 are all set, then it is the number of seconds since
+ * boot.
+ */
+static const char *
+format_timestamp(uint32_t timestamp)
+{
+	static char buffer[32];
+	static time_t base;
+	time_t t;
+	struct tm tm;
+
+	if ((timestamp & 0xff000000) == 0xff000000) {
+		snprintf(buffer, sizeof(buffer), "boot + %us", timestamp &
+		    0x00ffffff);
+		return (buffer);
+	}
+
+	if (base == 0) {
+		/* Compute 00:00 Jan 1, 2000 offset. */
+		bzero(&tm, sizeof(tm));
+		tm.tm_mday = 1;
+		tm.tm_year = (2000 - 1900);
+		base = mktime(&tm);
+	}
+	if (base == -1) {
+		snprintf(buffer, sizeof(buffer), "%us", timestamp);
+		return (buffer);
+	}
+	t = base + timestamp;
+	strftime(buffer, sizeof(buffer), "%+", localtime(&t));
+	return (buffer);
+}
+
+static const char *
+format_locale(uint16_t locale)
+{
+	static char buffer[8];
+
+	switch (locale) {
+	case MFI_EVT_LOCALE_LD:
+		return ("VOLUME");
+	case MFI_EVT_LOCALE_PD:
+		return ("DRIVE");
+	case MFI_EVT_LOCALE_ENCL:
+		return ("ENCL");
+	case MFI_EVT_LOCALE_BBU:
+		return ("BATTERY");
+	case MFI_EVT_LOCALE_SAS:
+		return ("SAS");
+	case MFI_EVT_LOCALE_CTRL:
+		return ("CTRL");
+	case MFI_EVT_LOCALE_CONFIG:
+		return ("CONFIG");
+	case MFI_EVT_LOCALE_CLUSTER:
+		return ("CLUSTER");
+	case MFI_EVT_LOCALE_ALL:
+		return ("ALL");
+	default:
+		snprintf(buffer, sizeof(buffer), "0x%04x", locale);
+		return (buffer);
+	}
+}
+
+static const char *
+format_class(int8_t class)
+{
+	static char buffer[6];
+
+	switch (class) {
+	case MFI_EVT_CLASS_DEBUG:
+		return ("debug");
+	case MFI_EVT_CLASS_PROGRESS:
+		return ("progress");
+	case MFI_EVT_CLASS_INFO:
+		return ("info");
+	case MFI_EVT_CLASS_WARNING:
+		return ("WARN");
+	case MFI_EVT_CLASS_CRITICAL:
+		return ("CRIT");
+	case MFI_EVT_CLASS_FATAL:
+		return ("FATAL");
+	case MFI_EVT_CLASS_DEAD:
+		return ("DEAD");
+	default:
+		snprintf(buffer, sizeof(buffer), "%d", class);
+		return (buffer);
+	}
+}
+
+/* Simulates %D from kernel printf(9). */
+static void
+simple_hex(void *ptr, size_t length, const char *separator)
+{
+	unsigned char *cp;
+	u_int i;
+
+	if (length == 0)
+		return;
+	cp = ptr;
+	printf("%02x", cp[0]);
+	for (i = 1; i < length; i++)
+		printf("%s%02x", separator, cp[i]);
+}
+
+static const char *
+pdrive_location(struct mfi_evt_pd *pd)
+{
+	static char buffer[16];
+
+	if (pd->enclosure_index == 0)
+		snprintf(buffer, sizeof(buffer), "%02d(s%d)", pd->device_id,
+		    pd->slot_number);
+	else
+		snprintf(buffer, sizeof(buffer), "%02d(e%d/s%d)", pd->device_id,
+		    pd->enclosure_index, pd->slot_number);
+	return (buffer);
+}
+
+static const char *
+volume_name(int fd, struct mfi_evt_ld *ld)
+{
+
+	return (mfi_volume_name(fd, ld->target_id));
+}
+
+/* Ripped from sys/dev/mfi/mfi.c. */
+static void
+mfi_decode_evt(int fd, struct mfi_evt_detail *detail, int verbose)
+{
+
+	printf("%5d (%s/%s/%s) - ", detail->seq, format_timestamp(detail->time),
+	    format_locale(detail->class.members.locale),
+	    format_class(detail->class.members.class));
+	switch (detail->arg_type) {
+	case MR_EVT_ARGS_NONE:
+		break;
+	case MR_EVT_ARGS_CDB_SENSE:
+		if (verbose) {
+			printf("PD %s CDB ",
+			    pdrive_location(&detail->args.cdb_sense.pd)
+			    );
+			simple_hex(detail->args.cdb_sense.cdb,
+			    detail->args.cdb_sense.cdb_len, ":");
+			printf(" Sense ");
+			simple_hex(detail->args.cdb_sense.sense,
+			    detail->args.cdb_sense.sense_len, ":");
+			printf(":\n ");
+		}
+		break;
+	case MR_EVT_ARGS_LD:
+		printf("VOL %s event: ", volume_name(fd, &detail->args.ld));
+		break;
+	case MR_EVT_ARGS_LD_COUNT:
+		printf("VOL %s", volume_name(fd, &detail->args.ld_count.ld));
+		if (verbose) {
+			printf(" count %lld: ",
+			    (long long)detail->args.ld_count.count);
+		}
+		printf(": ");
+		break;
+	case MR_EVT_ARGS_LD_LBA:
+		printf("VOL %s", volume_name(fd, &detail->args.ld_count.ld));
+		if (verbose) {
+			printf(" lba %lld",
+			    (long long)detail->args.ld_lba.lba);
+		}
+		printf(": ");
+		break;
+	case MR_EVT_ARGS_LD_OWNER:
+		printf("VOL %s", volume_name(fd, &detail->args.ld_count.ld));
+		if (verbose) {
+			printf(" owner changed: prior %d, new %d",
+			    detail->args.ld_owner.pre_owner,
+			    detail->args.ld_owner.new_owner);
+		}
+		printf(": ");
+		break;
+	case MR_EVT_ARGS_LD_LBA_PD_LBA:
+		printf("VOL %s", volume_name(fd, &detail->args.ld_count.ld));
+		if (verbose) {
+			printf(" lba %lld, physical drive PD %s lba %lld",
+			    (long long)detail->args.ld_lba_pd_lba.ld_lba,
+			    pdrive_location(&detail->args.ld_lba_pd_lba.pd),
+			    (long long)detail->args.ld_lba_pd_lba.pd_lba);
+		}
+		printf(": ");
+		break;
+	case MR_EVT_ARGS_LD_PROG:
+		printf("VOL %s", volume_name(fd, &detail->args.ld_prog.ld));
+		if (verbose) {
+			printf(" progress %d%% in %ds",
+			    detail->args.ld_prog.prog.progress/655,
+			    detail->args.ld_prog.prog.elapsed_seconds);
+		}
+		printf(": ");
+		break;
+	case MR_EVT_ARGS_LD_STATE:
+		printf("VOL %s", volume_name(fd, &detail->args.ld_prog.ld));
+		if (verbose) {
+			printf(" state prior %s new %s",
+			    mfi_ldstate(detail->args.ld_state.prev_state),
+			    mfi_ldstate(detail->args.ld_state.new_state));
+		}
+		printf(": ");
+		break;
+	case MR_EVT_ARGS_LD_STRIP:
+		printf("VOL %s", volume_name(fd, &detail->args.ld_prog.ld));
+		if (verbose) {
+			printf(" strip %lld",
+			    (long long)detail->args.ld_strip.strip);
+		}
+		printf(": ");
+		break;
+	case MR_EVT_ARGS_PD:
+		if (verbose) {
+			printf("PD %s event: ",
+			    pdrive_location(&detail->args.pd));
+		}
+		break;
+	case MR_EVT_ARGS_PD_ERR:
+		if (verbose) {
+			printf("PD %s err %d: ",
+			    pdrive_location(&detail->args.pd_err.pd),
+			    detail->args.pd_err.err);
+		}
+		break;
+	case MR_EVT_ARGS_PD_LBA:
+		if (verbose) {
+			printf("PD %s lba %lld: ",
+			    pdrive_location(&detail->args.pd_lba.pd),
+			    (long long)detail->args.pd_lba.lba);
+		}
+		break;
+	case MR_EVT_ARGS_PD_LBA_LD:
+		if (verbose) {
+			printf("PD %s lba %lld VOL %s: ",
+			    pdrive_location(&detail->args.pd_lba_ld.pd),
+			    (long long)detail->args.pd_lba.lba,
+			    volume_name(fd, &detail->args.pd_lba_ld.ld));
+		}
+		break;
+	case MR_EVT_ARGS_PD_PROG:
+		if (verbose) {
+			printf("PD %s progress %d%% seconds %ds: ",
+			    pdrive_location(&detail->args.pd_prog.pd),
+			    detail->args.pd_prog.prog.progress/655,
+			    detail->args.pd_prog.prog.elapsed_seconds);
+		}
+		break;
+	case MR_EVT_ARGS_PD_STATE:
+		if (verbose) {
+			printf("PD %s state prior %s new %s: ",
+			    pdrive_location(&detail->args.pd_prog.pd),
+			    mfi_pdstate(detail->args.pd_state.prev_state),
+			    mfi_pdstate(detail->args.pd_state.new_state));
+		}
+		break;
+	case MR_EVT_ARGS_PCI:
+		if (verbose) {
+			printf("PCI 0x%04x 0x%04x 0x%04x 0x%04x: ",
+			    detail->args.pci.venderId,
+			    detail->args.pci.deviceId,
+			    detail->args.pci.subVenderId,
+			    detail->args.pci.subDeviceId);
+		}
+		break;
+	case MR_EVT_ARGS_RATE:
+		if (verbose) {
+			printf("Rebuild rate %d: ", detail->args.rate);
+		}
+		break;
+	case MR_EVT_ARGS_TIME:
+		if (verbose) {
+			printf("Adapter time %s; %d seconds since power on: ",
+			    format_timestamp(detail->args.time.rtc),
+			    detail->args.time.elapsedSeconds);
+		}
+		break;
+	case MR_EVT_ARGS_ECC:
+		if (verbose) {
+			printf("Adapter ECC %x,%x: %s: ",
+			    detail->args.ecc.ecar,
+			    detail->args.ecc.elog,
+			    detail->args.ecc.str);
+		}
+		break;
+	default:
+		if (verbose) {
+			printf("Type %d: ", detail->arg_type);
+		}
+		break;
+	}
+	printf("%s\n", detail->description);
+}
+
+static int
+show_events(int ac, char **av)
+{
+	struct mfi_evt_log_state info;
+	struct mfi_evt_list *list;
+	union mfi_evt filter;
+	long val;
+	char *cp;
+	ssize_t size;
+	uint32_t seq, start, stop;
+	uint8_t status;
+	int ch, fd, num_events, verbose;
+	u_int i;
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_event_get_info(fd, &info, NULL) < 0) {
+		warn("Failed to get event log info");
+		return (errno);
+	}
+
+	/* Default settings. */
+	num_events = 15;
+	filter.members.reserved = 0;
+	filter.members.locale = MFI_EVT_LOCALE_ALL;
+	filter.members.class = MFI_EVT_CLASS_WARNING;
+	start = info.boot_seq_num;
+	stop = info.newest_seq_num;
+	verbose = 0;
+
+	/* Parse any options. */
+	optind = 1;
+	while ((ch = getopt(ac, av, "c:l:n:v")) != -1) {
+		switch (ch) {
+		case 'c':
+			if (parse_class(optarg, &filter.members.class) < 0) {
+				warn("Error parsing event class");
+				return (errno);
+			}
+			break;
+		case 'l':
+			if (parse_locale(optarg, &filter.members.locale) < 0) {
+				warn("Error parsing event locale");
+				return (errno);
+			}
+			break;
+		case 'n':
+			val = strtol(optarg, &cp, 0);
+			if (*cp != '\0' || val <= 0) {
+				warnx("Invalid event count");
+				return (EINVAL);
+			}
+			num_events = val;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case '?':
+		default:
+			return (EINVAL);
+		}
+	}
+	ac -= optind;
+	av += optind;
+
+	/* Determine buffer size and validate it. */
+	size = sizeof(struct mfi_evt_list) + sizeof(struct mfi_evt_detail) *
+	    (num_events - 1);
+	if (size > getpagesize()) {
+		warnx("Event count is too high");
+		return (EINVAL);
+	}
+
+	/* Handle optional start and stop sequence numbers. */
+	if (ac > 2) {
+		warnx("show events: extra arguments");
+		return (EINVAL);
+	}
+	if (ac > 0 && parse_seq(&info, av[0], &start) < 0) {
+		warn("Error parsing starting sequence number");
+		return (errno);
+	}
+	if (ac > 1 && parse_seq(&info, av[1], &stop) < 0) {
+		warn("Error parsing ending sequence number");
+		return (errno);
+	}
+
+	list = malloc(size);
+	for (seq = start;;) {
+		if (mfi_get_events(fd, list, num_events, filter, seq,
+		    &status) < 0) {
+			warn("Failed to fetch events");
+			return (errno);
+		}
+		if (status == MFI_STAT_NOT_FOUND) {
+			if (seq == start)
+				warnx("No matching events found");
+			break;
+		}
+		if (status != MFI_STAT_OK) {
+			warnx("Error fetching events: %s", mfi_status(status));
+			return (EIO);
+		}
+
+		for (i = 0; i < list->count; i++) {
+			/*
+			 * If this event is newer than 'stop_seq' then
+			 * break out of the loop.  Note that the log
+			 * is a circular buffer so we have to handle
+			 * the case that our stop point is earlier in
+			 * the buffer than our start point.
+			 */
+			if (list->event[i].seq >= stop) {
+				if (start <= stop)
+					break;
+				else if (list->event[i].seq < start)
+					break;
+			}
+			mfi_decode_evt(fd, &list->event[i], verbose);
+		}
+
+		/*
+		 * XXX: If the event's seq # is the end of the buffer
+		 * then this probably won't do the right thing.  We
+		 * need to know the size of the buffer somehow.
+		 */
+		seq = list->event[list->count - 1].seq + 1;
+			
+	}
+
+	free(list);
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(show, events, show_events);
diff --git a/usr.sbin/mfiutil/mfi_flash.c b/usr.sbin/mfiutil/mfi_flash.c
new file mode 100644
index 00000000000..5dd93f14f0e
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_flash.c
@@ -0,0 +1,199 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mfiutil.h"
+
+#define	FLASH_BUF_SIZE	(64 * 1024)
+
+int fw_name_width, fw_version_width, fw_date_width, fw_time_width;
+
+static void
+scan_firmware(struct mfi_info_component *comp)
+{
+	int len;
+
+	len = strlen(comp->name);
+	if (fw_name_width < len)
+		fw_name_width = len;
+	len = strlen(comp->version);
+	if (fw_version_width < len)
+		fw_version_width = len;
+	len = strlen(comp->build_date);
+	if (fw_date_width < len)
+		fw_date_width = len;
+	len = strlen(comp->build_time);
+	if (fw_time_width < len)
+		fw_time_width = len;
+}
+
+static void
+display_firmware(struct mfi_info_component *comp)
+{
+
+	printf("%-*s  %-*s  %-*s  %-*s\n", fw_name_width, comp->name,
+	    fw_version_width, comp->version, fw_date_width, comp->build_date,
+	    fw_time_width, comp->build_time);
+}
+
+static void
+display_pending_firmware(int fd)
+{
+	struct mfi_ctrl_info info;
+	struct mfi_info_component header;
+	u_int i;
+
+	if (mfi_ctrl_get_info(fd, &info, NULL) < 0) {
+		warn("Failed to get controller info");
+		return;
+	}
+
+	printf("mfi%d Pending Firmware Images:\n", mfi_unit);
+	strcpy(header.name, "Name");
+	strcpy(header.version, "Version");
+	strcpy(header.build_date, "Date");
+	strcpy(header.build_time, "Time");
+	scan_firmware(&header);
+	if (info.pending_image_component_count > 8)
+		info.pending_image_component_count = 8;
+	for (i = 0; i < info.pending_image_component_count; i++)
+		scan_firmware(&info.pending_image_component[i]);
+	display_firmware(&header);
+	for (i = 0; i < info.pending_image_component_count; i++)
+		display_firmware(&info.pending_image_component[i]);
+}
+
+static void
+mbox_store_word(uint8_t *mbox, uint32_t val)
+{
+
+	mbox[0] = val & 0xff;
+	mbox[1] = val >> 8 & 0xff;
+	mbox[2] = val >> 16 & 0xff;
+	mbox[3] = val >> 24;
+}
+
+static int
+flash_adapter(int ac, char **av)
+{
+	struct mfi_progress dummy;
+	off_t offset;
+	size_t nread;
+	char *buf;
+	struct stat sb;
+	int fd, flash;
+	uint8_t mbox[4], status;
+
+	if (ac != 2) {
+		warnx("flash: Firmware file required");
+		return (EINVAL);
+	}
+
+	flash = open(av[1], O_RDONLY);
+	if (flash < 0) {
+		warn("flash: Failed to open %s", av[1]);
+		return (errno);
+	}
+
+	if (fstat(flash, &sb) < 0) {
+		warn("fstat(%s)", av[1]);
+		return (errno);
+	}
+	if (sb.st_size % 1024 != 0 || sb.st_size > 0x7fffffff) {
+		warnx("Invalid flash file size");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	/* First, ask the firmware to allocate space for the flash file. */
+	mbox_store_word(mbox, sb.st_size);
+	mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_OPEN, NULL, 0, mbox, 4, &status);
+	if (status != MFI_STAT_OK) {
+		warnx("Failed to alloc flash memory: %s", mfi_status(status));
+		return (EIO);
+	}
+
+	/* Upload the file 64k at a time. */
+	buf = malloc(FLASH_BUF_SIZE);
+	offset = 0;
+	while (sb.st_size > 0) {
+		nread = read(flash, buf, FLASH_BUF_SIZE);
+		if (nread <= 0 || nread % 1024 != 0) {
+			warnx("Bad read from flash file");
+			mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0,
+			    NULL, 0, NULL);
+			return (ENXIO);
+		}
+
+		mbox_store_word(mbox, offset);
+		mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_DOWNLOAD, buf, nread,
+		    mbox, 4, &status);
+		if (status != MFI_STAT_OK) {
+			warnx("Flash download failed: %s", mfi_status(status));
+			mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_CLOSE, NULL, 0,
+			    NULL, 0, NULL);
+			return (ENXIO);
+		}
+		sb.st_size -= nread;
+		offset += nread;
+	}
+	close(flash);
+
+	/* Kick off the flash. */
+	printf("WARNING: Firmware flash in progress, do not reboot machine... ");
+	fflush(stdout);
+	mfi_dcmd_command(fd, MFI_DCMD_FLASH_FW_FLASH, &dummy, sizeof(dummy),
+	    NULL, 0, &status);
+	if (status != MFI_STAT_OK) {
+		printf("failed:\n\t%s\n", mfi_status(status));
+		return (ENXIO);
+	}
+	printf("finished\n");
+	display_pending_firmware(fd);
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, flash, flash_adapter);
diff --git a/usr.sbin/mfiutil/mfi_patrol.c b/usr.sbin/mfiutil/mfi_patrol.c
new file mode 100644
index 00000000000..b8da2ae4bb9
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_patrol.c
@@ -0,0 +1,305 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mfiutil.h"
+
+static char *
+adapter_time(time_t now, uint32_t at_now, uint32_t at)
+{
+	time_t t;
+
+	t = (now - at_now) + at;
+	return (ctime(&t));
+}
+
+static void
+mfi_get_time(int fd, uint32_t *at)
+{
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_TIME_SECS_GET, at, sizeof(*at), NULL,
+	    0, NULL) < 0) {
+		warn("Couldn't fetch adapter time");
+		at = 0;
+	}
+}
+
+static int
+patrol_get_props(int fd, struct mfi_pr_properties *prop)
+{
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_PR_GET_PROPERTIES, prop,
+	    sizeof(*prop), NULL, 0, NULL) < 0) {
+		warn("Failed to get patrol read properties");
+		return (-1);
+	}
+	return (0);
+}
+
+static int
+show_patrol(int ac, char **av)
+{
+	struct mfi_pr_properties prop;
+	struct mfi_pr_status status;
+	struct mfi_pd_list *list;
+	struct mfi_pd_info info;
+	char label[16];
+	time_t now;
+	uint32_t at;
+	int fd;
+	u_int i;
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	time(&now);
+	mfi_get_time(fd, &at);
+	if (patrol_get_props(fd, &prop) < 0)
+		return (errno);
+	printf("Operation Mode: ");
+	switch (prop.op_mode) {
+	case MFI_PR_OPMODE_AUTO:
+		printf("auto\n");
+		break;
+	case MFI_PR_OPMODE_MANUAL:
+		printf("manual\n");
+		break;
+	case MFI_PR_OPMODE_DISABLED:
+		printf("disabled\n");
+		break;
+	default:
+		printf("??? (%02x)\n", prop.op_mode);
+		break;
+	}
+	if (prop.op_mode == MFI_PR_OPMODE_AUTO) {
+		if (at != 0 && prop.next_exec)
+			printf("    Next Run Starts: %s", adapter_time(now, at,
+			    prop.next_exec));
+		if (prop.exec_freq == 0xffffffff)
+			printf("    Runs Execute Continuously\n");
+		else if (prop.exec_freq != 0)
+			printf("    Runs Start Every %u seconds\n",
+			    prop.exec_freq);
+	}
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_PR_GET_STATUS, &status,
+	    sizeof(status), NULL, 0, NULL) < 0) {
+		warn("Failed to get patrol read properties");
+		return (errno);
+	}
+	printf("Runs Completed: %u\n", status.num_iteration);
+	printf("Current State: ");
+	switch (status.state) {
+	case MFI_PR_STATE_STOPPED:
+		printf("stopped\n");
+		break;
+	case MFI_PR_STATE_READY:
+		printf("ready\n");
+		break;
+	case MFI_PR_STATE_ACTIVE:
+		printf("active\n");
+		break;
+	case MFI_PR_STATE_ABORTED:
+		printf("aborted\n");
+		break;
+	default:
+		printf("??? (%02x)\n", status.state);
+		break;
+	}
+	if (status.state == MFI_PR_STATE_ACTIVE) {
+		if (mfi_pd_get_list(fd, &list, NULL) < 0) {
+			warn("Failed to get drive list");
+			return (errno);
+		}
+
+		for (i = 0; i < list->count; i++) {
+			if (list->addr[i].scsi_dev_type != 0)
+				continue;
+
+			if (mfi_pd_get_info(fd, list->addr[i].device_id, &info,
+			    NULL) < 0) {
+				warn("Failed to fetch info for drive %u",
+				    list->addr[i].device_id);
+				return (errno);
+			}
+			if (info.prog_info.active & MFI_PD_PROGRESS_PATROL) {
+				snprintf(label, sizeof(label), "    Drive %u",
+				    list->addr[i].device_id);
+				mfi_display_progress(label,
+				    &info.prog_info.patrol);
+			}
+		}
+	}
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(show, patrol, show_patrol);
+
+static int
+start_patrol(int ac, char **av)
+{
+	int fd;
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_PR_START, NULL, 0, NULL, 0, NULL) <
+	    0) {
+		warn("Failed to start patrol read");
+		return (errno);
+	}
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(start, patrol, start_patrol);
+
+static int
+stop_patrol(int ac, char **av)
+{
+	int fd;
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_PR_STOP, NULL, 0, NULL, 0, NULL) <
+	    0) {
+		warn("Failed to stop patrol read");
+		return (errno);
+	}
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(stop, patrol, stop_patrol);
+
+static int
+patrol_config(int ac, char **av)
+{
+	struct mfi_pr_properties prop;
+	long val;
+	time_t now;
+	uint32_t at, next_exec, exec_freq;
+	char *cp;
+	uint8_t op_mode;
+	int fd;
+
+	exec_freq = 0;	/* GCC too stupid */
+	next_exec = 0;
+	if (ac < 2) {
+		warnx("patrol: command required");
+		return (EINVAL);
+	}
+	if (strcasecmp(av[1], "auto") == 0) {
+		op_mode = MFI_PR_OPMODE_AUTO;
+		if (ac > 2) {
+			if (strcasecmp(av[2], "continously") == 0)
+				exec_freq = 0xffffffff;
+			else {
+				val = strtol(av[2], &cp, 0);
+				if (*cp != '\0') {
+					warnx("patrol: Invalid interval %s",
+					    av[2]);
+					return (EINVAL);
+				}
+				exec_freq = val;
+			}
+		}
+		if (ac > 3) {
+			val = strtol(av[3], &cp, 0);
+			if (*cp != '\0' || val < 0) {
+				warnx("patrol: Invalid start time %s", av[3]);
+				return (EINVAL);
+			}
+			next_exec = val;
+		}
+	} else if (strcasecmp(av[1], "manual") == 0)
+		op_mode = MFI_PR_OPMODE_MANUAL;
+	else if (strcasecmp(av[1], "disable") == 0)
+		op_mode = MFI_PR_OPMODE_DISABLED;
+	else {
+		warnx("patrol: Invalid command %s", av[1]);
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (patrol_get_props(fd, &prop) < 0)
+		return (errno);
+	prop.op_mode = op_mode;
+	if (op_mode == MFI_PR_OPMODE_AUTO) {
+		if (ac > 2)
+			prop.exec_freq = exec_freq;
+		if (ac > 3) {
+			time(&now);
+			mfi_get_time(fd, &at);
+			if (at == 0)
+				return (ENXIO);
+			prop.next_exec = at + next_exec;
+			printf("Starting next patrol read at %s",
+			    adapter_time(now, at, prop.next_exec));
+		}
+	}
+	if (mfi_dcmd_command(fd, MFI_DCMD_PR_SET_PROPERTIES, &prop,
+	    sizeof(prop), NULL, 0, NULL) < 0) {
+		warn("Failed to set patrol read properties");
+		return (errno);
+	}
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, patrol, patrol_config);
diff --git a/usr.sbin/mfiutil/mfi_show.c b/usr.sbin/mfiutil/mfi_show.c
new file mode 100644
index 00000000000..abd11107077
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_show.c
@@ -0,0 +1,560 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mfiutil.h"
+
+MFI_TABLE(top, show);
+
+static void
+format_stripe(char *buf, size_t buflen, uint8_t stripe)
+{
+
+	humanize_number(buf, buflen, (1 << stripe) * 512, "", HN_AUTOSCALE,  
+	    HN_B | HN_NOSPACE);
+}
+
+static int
+show_adapter(int ac, char **av)
+{
+	struct mfi_ctrl_info info;
+	char stripe[5];
+	int fd, comma;
+
+	if (ac != 1) {
+		warnx("show adapter: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_ctrl_get_info(fd, &info, NULL) < 0) {
+		warn("Failed to get controller info");
+		return (errno);
+	}
+	printf("mfi%d Adapter:\n", mfi_unit);
+	printf("    Product Name: %.80s\n", info.product_name);
+	printf("   Serial Number: %.32s\n", info.serial_number);
+	if (info.package_version[0] != '\0')
+		printf("        Firmware: %s\n", info.package_version);
+	printf("     RAID Levels:");
+#ifdef DEBUG
+	printf(" (%#x)", info.raid_levels);
+#endif
+	comma = 0;
+	if (info.raid_levels & MFI_INFO_RAID_0) {
+		printf(" JBOD, RAID0");
+		comma = 1;
+	}
+	if (info.raid_levels & MFI_INFO_RAID_1) {
+		printf("%s RAID1", comma ? "," : "");
+		comma = 1;
+	}
+	if (info.raid_levels & MFI_INFO_RAID_5) {
+		printf("%s RAID5", comma ? "," : "");
+		comma = 1;
+	}
+	if (info.raid_levels & MFI_INFO_RAID_1E) {
+		printf("%s RAID1E", comma ? "," : "");
+		comma = 1;
+	}
+	if (info.raid_levels & MFI_INFO_RAID_6) {
+		printf("%s RAID6", comma ? "," : "");
+		comma = 1;
+	}
+	if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) ==
+	    (MFI_INFO_RAID_0 | MFI_INFO_RAID_1)) {
+		printf("%s RAID10", comma ? "," : "");
+		comma = 1;
+	}
+	if ((info.raid_levels & (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) ==
+	    (MFI_INFO_RAID_0 | MFI_INFO_RAID_5)) {
+		printf("%s RAID50", comma ? "," : "");
+		comma = 1;
+	}
+	printf("\n");
+	printf("  Battery Backup: ");
+	if (info.hw_present & MFI_INFO_HW_BBU)
+		printf("present\n");
+	else
+		printf("not present\n");
+	if (info.hw_present & MFI_INFO_HW_NVRAM)
+		printf("           NVRAM: %uK\n", info.nvram_size);
+	printf("  Onboard Memory: %uM\n", info.memory_size);
+	format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.min);
+	printf("  Minimum Stripe: %s\n", stripe);
+	format_stripe(stripe, sizeof(stripe), info.stripe_sz_ops.max);
+	printf("  Maximum Stripe: %s\n", stripe);
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(show, adapter, show_adapter);
+
+static int
+show_battery(int ac, char **av)
+{
+	struct mfi_bbu_capacity_info cap;
+	struct mfi_bbu_design_info design;
+	uint8_t status;
+	int fd;
+
+	if (ac != 1) {
+		warnx("show battery: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_CAPACITY_INFO, &cap,
+	    sizeof(cap), NULL, 0, &status) < 0) {
+		if (status == MFI_STAT_NO_HW_PRESENT) {
+			printf("mfi%d: No battery present\n", mfi_unit);
+			return (0);
+		}
+		warn("Failed to get capacity info");
+		return (errno);
+	}
+
+	if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_DESIGN_INFO, &design,
+	    sizeof(design), NULL, 0, NULL) < 0) {
+		warn("Failed to get design info");
+		return (errno);
+	}
+
+	printf("mfi%d: Battery State:\n", mfi_unit);
+	printf(" Manufacture Date: %d/%d/%d\n", design.mfg_date >> 5 & 0x0f,
+	    design.mfg_date & 0x1f, design.mfg_date >> 9 & 0xffff);
+	printf("    Serial Number: %d\n", design.serial_number);
+	printf("     Manufacturer: %s\n", design.mfg_name);
+	printf("            Model: %s\n", design.device_name);
+	printf("        Chemistry: %s\n", design.device_chemistry);
+	printf("  Design Capacity: %d mAh\n", design.design_capacity);
+	printf("   Design Voltage: %d mV\n", design.design_voltage);
+	printf("   Current Charge: %d%%\n", cap.relative_charge);
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(show, battery, show_battery);
+
+static void
+print_ld(struct mfi_ld_info *info, int state_len)
+{
+	struct mfi_ld_params *params = &info->ld_config.params;
+	const char *level;
+	char size[6], stripe[5];
+
+	humanize_number(size, sizeof(size), info->size * 512,
+	    "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+	format_stripe(stripe, sizeof(stripe),
+	    info->ld_config.params.stripe_size);
+	level = mfi_raid_level(params->primary_raid_level,
+	    params->secondary_raid_level);
+	if (state_len > 0)
+		printf("(%6s) %-8s %6s %-*s", size, level, stripe, state_len,
+		    mfi_ldstate(params->state));
+	else
+		printf("(%s) %s %s %s", size, level, stripe,
+		    mfi_ldstate(params->state));
+}
+
+static void
+print_pd(struct mfi_pd_info *info, int state_len, int location)
+{
+	const char *s;
+	char buf[6];
+
+	humanize_number(buf, sizeof(buf), info->raw_size * 512, "",
+	    HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL);
+	printf("(%6s) ", buf);
+	if (state_len > 0)
+		printf("%-*s", state_len, mfi_pdstate(info->fw_state));
+	else
+		printf("%s", mfi_pdstate(info->fw_state));
+	s = mfi_pd_inq_string(info);
+	if (s != NULL)
+		printf(" %s", s);
+	if (!location)
+		return;
+	if (info->encl_device_id == 0xffff)
+		printf(" slot %d", info->slot_number);
+	else if (info->encl_device_id == info->ref.v.device_id)
+		printf(" enclosure %d", info->encl_index);
+	else
+		printf(" enclosure %d, slot %d", info->encl_index,
+		    info->slot_number);
+}
+
+static int
+show_config(int ac, char **av)
+{
+	struct mfi_config_data *config;
+	struct mfi_array *ar;
+	struct mfi_ld_config *ld;
+	struct mfi_spare *sp;
+	struct mfi_ld_info linfo;
+	struct mfi_pd_info pinfo;
+	uint16_t device_id;
+	char *p;
+	int fd, i, j;
+
+	if (ac != 1) {
+		warnx("show config: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	/* Get the config from the controller. */
+	if (mfi_config_read(fd, &config) < 0) {
+		warn("Failed to get config");
+		return (errno);
+	}
+
+	/* Dump out the configuration. */
+	printf("mfi%d Configuration: %d arrays, %d volumes, %d spares\n",
+	    mfi_unit, config->array_count, config->log_drv_count,
+	    config->spares_count);
+	p = (char *)config->array;
+
+	for (i = 0; i < config->array_count; i++) {
+		ar = (struct mfi_array *)p;
+		printf("    array %u of %u drives:\n", ar->array_ref,
+		    ar->num_drives);
+		for (j = 0; j < ar->num_drives; j++) {
+			device_id = ar->pd[j].ref.v.device_id;
+			if (device_id == 0xffff)
+				printf("        drive MISSING\n");
+			else {
+				printf("        drive %u ", device_id);
+				if (mfi_pd_get_info(fd, device_id, &pinfo,
+				    NULL) < 0)
+					printf("%s",
+					    mfi_pdstate(ar->pd[j].fw_state));
+				else
+					print_pd(&pinfo, -1, 1);
+				printf("\n");
+			}
+		}
+		p += config->array_size;
+	}
+
+	for (i = 0; i < config->log_drv_count; i++) {
+		ld = (struct mfi_ld_config *)p;
+		printf("    volume %s ",
+		    mfi_volume_name(fd, ld->properties.ld.v.target_id));
+		if (mfi_ld_get_info(fd, ld->properties.ld.v.target_id, &linfo,
+		    NULL) < 0) {
+			printf("%s %s",
+			    mfi_raid_level(ld->params.primary_raid_level,
+				ld->params.secondary_raid_level),
+			    mfi_ldstate(ld->params.state));
+		} else
+			print_ld(&linfo, -1);
+		if (ld->properties.name[0] != '\0')
+			printf(" <%s>", ld->properties.name);
+		printf(" spans:\n");
+		for (j = 0; j < ld->params.span_depth; j++)
+			printf("        array %u\n", ld->span[j].array_ref);
+		p += config->log_drv_size;
+	}
+
+	for (i = 0; i < config->spares_count; i++) {
+		sp = (struct mfi_spare *)p;
+		printf("    %s spare %u ",
+		    sp->spare_type & MFI_SPARE_DEDICATED ? "dedicated" :
+		    "global", sp->ref.v.device_id);
+		if (mfi_pd_get_info(fd, sp->ref.v.device_id, &pinfo, NULL) < 0)
+			printf("%s", mfi_pdstate(MFI_PD_STATE_HOT_SPARE));
+		else
+			print_pd(&pinfo, -1, 1);
+		if (sp->spare_type & MFI_SPARE_DEDICATED) {
+			printf(" backs:\n");
+			for (j = 0; j < sp->array_count; j++)
+				printf("        array %u\n", sp->array_ref[j]);
+		} else
+			printf("\n");
+		p += config->spares_size;
+	}
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(show, config, show_config);
+
+static int
+show_volumes(int ac, char **av)
+{
+	struct mfi_ld_list list;
+	struct mfi_ld_info info;
+	u_int i, len, state_len;
+	int fd;
+
+	if (ac != 1) {
+		warnx("show volumes: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	/* Get the logical drive list from the controller. */
+	if (mfi_ld_get_list(fd, &list, NULL) < 0) {
+		warn("Failed to get volume list");
+		return (errno);
+	}
+
+	/* List the volumes. */
+	printf("mfi%d Volumes:\n", mfi_unit);
+	state_len = strlen("State");
+	for (i = 0; i < list.ld_count; i++) {
+		len = strlen(mfi_ldstate(list.ld_list[i].state));
+		if (len > state_len)
+			state_len = len;
+	}
+	printf("  Id     Size    Level   Stripe ");
+	len = state_len - strlen("State");
+	for (i = 0; i < (len + 1) / 2; i++)
+		printf(" ");
+	printf("State");
+	for (i = 0; i < len / 2; i++)
+		printf(" ");
+	printf("  Cache   Name\n");
+	for (i = 0; i < list.ld_count; i++) {
+		if (mfi_ld_get_info(fd, list.ld_list[i].ld.v.target_id, &info,
+		    NULL) < 0) {
+			warn("Failed to get info for volume %d",
+			    list.ld_list[i].ld.v.target_id);
+			return (errno);
+		}
+		printf("%6s ",
+		    mfi_volume_name(fd, list.ld_list[i].ld.v.target_id));
+		print_ld(&info, state_len);
+		switch (info.ld_config.properties.current_cache_policy &
+		    (MR_LD_CACHE_ALLOW_WRITE_CACHE |
+		    MR_LD_CACHE_ALLOW_READ_CACHE)) {
+		case 0:
+			printf(" Disabled");
+			break;
+		case MR_LD_CACHE_ALLOW_READ_CACHE:
+			printf(" Reads   ");
+			break;
+		case MR_LD_CACHE_ALLOW_WRITE_CACHE:
+			printf(" Writes  ");
+			break;
+		case MR_LD_CACHE_ALLOW_WRITE_CACHE |
+		    MR_LD_CACHE_ALLOW_READ_CACHE:
+			printf(" Enabled ");
+			break;
+		}
+		if (info.ld_config.properties.name[0] != '\0')
+			printf(" <%s>", info.ld_config.properties.name);
+		printf("\n");
+	}
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(show, volumes, show_volumes);
+
+static int
+show_drives(int ac, char **av)
+{
+	struct mfi_pd_list *list;
+	struct mfi_pd_info info;
+	u_int i, len, state_len;
+	int fd;
+
+	if (ac != 1) {
+		warnx("show drives: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_pd_get_list(fd, &list, NULL) < 0) {
+		warn("Failed to get drive list");
+		return (errno);
+	}
+
+	/* Walk the list of drives to determine width of state column. */
+	state_len = 0;
+	for (i = 0; i < list->count; i++) {
+		if (list->addr[i].scsi_dev_type != 0)
+			continue;
+
+		if (mfi_pd_get_info(fd, list->addr[i].device_id, &info,
+		    NULL) < 0) {
+			warn("Failed to fetch info for drive %u",
+			    list->addr[i].device_id);
+			return (errno);
+		}
+		len = strlen(mfi_pdstate(info.fw_state));
+		if (len > state_len)
+			state_len = len;
+	}
+
+	/* List the drives. */
+	printf("mfi%d Physical Drives:\n", mfi_unit);
+	for (i = 0; i < list->count; i++) {
+
+		/* Skip non-hard disks. */
+		if (list->addr[i].scsi_dev_type != 0)
+			continue;
+
+		/* Fetch details for this drive. */
+		if (mfi_pd_get_info(fd, list->addr[i].device_id, &info,
+		    NULL) < 0) {
+			warn("Failed to fetch info for drive %u",
+			    list->addr[i].device_id);
+			return (errno);
+		}
+
+		print_pd(&info, state_len, 1);
+		printf("\n");
+	}
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(show, drives, show_drives);
+
+int fw_name_width, fw_version_width, fw_date_width, fw_time_width;
+
+static void
+scan_firmware(struct mfi_info_component *comp)
+{
+	int len;
+
+	len = strlen(comp->name);
+	if (fw_name_width < len)
+		fw_name_width = len;
+	len = strlen(comp->version);
+	if (fw_version_width < len)
+		fw_version_width = len;
+	len = strlen(comp->build_date);
+	if (fw_date_width < len)
+		fw_date_width = len;
+	len = strlen(comp->build_time);
+	if (fw_time_width < len)
+		fw_time_width = len;
+}
+
+static void
+display_firmware(struct mfi_info_component *comp, const char *tag)
+{
+
+	printf("%-*s  %-*s  %-*s  %-*s  %s\n", fw_name_width, comp->name,
+	    fw_version_width, comp->version, fw_date_width, comp->build_date,
+	    fw_time_width, comp->build_time, tag);
+}
+
+static int
+show_firmware(int ac, char **av)
+{
+	struct mfi_ctrl_info info;
+	struct mfi_info_component header;
+	int fd;
+	u_int i;
+
+	if (ac != 1) {
+		warnx("show drives: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_ctrl_get_info(fd, &info, NULL) < 0) {
+		warn("Failed to get controller info");
+		return (errno);
+	}
+
+	if (info.package_version[0] != '\0')
+		printf("mfi%d Firmware Package Version: %s\n", mfi_unit,
+		    info.package_version);
+	printf("mfi%d Firmware Images:\n", mfi_unit);
+	strcpy(header.name, "Name");
+	strcpy(header.version, "Version");
+	strcpy(header.build_date, "Date");
+	strcpy(header.build_time, "Time");
+	scan_firmware(&header);
+	if (info.image_component_count > 8)
+		info.image_component_count = 8;
+	for (i = 0; i < info.image_component_count; i++)
+		scan_firmware(&info.image_component[i]);
+	if (info.pending_image_component_count > 8)
+		info.pending_image_component_count = 8;
+	for (i = 0; i < info.pending_image_component_count; i++)
+		scan_firmware(&info.pending_image_component[i]);
+	display_firmware(&header, "Status");
+	for (i = 0; i < info.image_component_count; i++)
+		display_firmware(&info.image_component[i], "active");
+	for (i = 0; i < info.pending_image_component_count; i++)
+		display_firmware(&info.pending_image_component[i], "pending");
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(show, firmware, show_firmware);
diff --git a/usr.sbin/mfiutil/mfi_volume.c b/usr.sbin/mfiutil/mfi_volume.c
new file mode 100644
index 00000000000..b3f4a7656c3
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_volume.c
@@ -0,0 +1,412 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mfiutil.h"
+
+MFI_TABLE(top, volume);
+
+const char *
+mfi_ldstate(enum mfi_ld_state state)
+{
+	static char buf[16];
+
+	switch (state) {
+	case MFI_LD_STATE_OFFLINE:
+		return ("OFFLINE");
+	case MFI_LD_STATE_PARTIALLY_DEGRADED:
+		return ("PARTIALLY DEGRADED");
+	case MFI_LD_STATE_DEGRADED:
+		return ("DEGRADED");
+	case MFI_LD_STATE_OPTIMAL:
+		return ("OPTIMAL");
+	default:
+		sprintf(buf, "LSTATE 0x%02x", state);
+		return (buf);
+	}
+}
+
+void
+mbox_store_ldref(uint8_t *mbox, union mfi_ld_ref *ref)
+{
+
+	mbox[0] = ref->v.target_id;
+	mbox[1] = ref->v.reserved;
+	mbox[2] = ref->v.seq & 0xff;
+	mbox[3] = ref->v.seq >> 8;
+}
+
+int
+mfi_ld_get_list(int fd, struct mfi_ld_list *list, uint8_t *statusp)
+{
+
+	return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_LIST, list,
+		sizeof(struct mfi_ld_list), NULL, 0, statusp));
+}
+
+int
+mfi_ld_get_info(int fd, uint8_t target_id, struct mfi_ld_info *info,
+    uint8_t *statusp)
+{
+	uint8_t mbox[1];
+
+	mbox[0] = target_id;
+	return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_INFO, info,
+	    sizeof(struct mfi_ld_info), mbox, 1, statusp));
+}
+
+static int
+mfi_ld_get_props(int fd, uint8_t target_id, struct mfi_ld_props *props)
+{
+	uint8_t mbox[1];
+
+	mbox[0] = target_id;
+	return (mfi_dcmd_command(fd, MFI_DCMD_LD_GET_PROP, props,
+	    sizeof(struct mfi_ld_props), mbox, 1, NULL));
+}
+
+static int
+mfi_ld_set_props(int fd, struct mfi_ld_props *props)
+{
+	uint8_t mbox[4];
+
+	mbox_store_ldref(mbox, &props->ld);
+	return (mfi_dcmd_command(fd, MFI_DCMD_LD_SET_PROP, props,
+	    sizeof(struct mfi_ld_props), mbox, 4, NULL));
+}
+
+static int
+update_cache_policy(int fd, struct mfi_ld_props *props, uint8_t new_policy,
+    uint8_t mask)
+{
+	uint8_t changes, policy;
+
+	policy = (props->default_cache_policy & ~mask) | new_policy;
+	if (policy == props->default_cache_policy)
+		return (0);
+	changes = policy ^ props->default_cache_policy;
+	if (changes & MR_LD_CACHE_ALLOW_WRITE_CACHE)
+		printf("%s caching of I/O writes\n",
+		    policy & MR_LD_CACHE_ALLOW_WRITE_CACHE ? "Enabling" :
+		    "Disabling");
+	if (changes & MR_LD_CACHE_ALLOW_READ_CACHE)
+		printf("%s caching of I/O reads\n",
+		    policy & MR_LD_CACHE_ALLOW_READ_CACHE ? "Enabling" :
+		    "Disabling");
+	if (changes & MR_LD_CACHE_WRITE_BACK)
+		printf("Setting write cache policy to %s\n",
+		    policy & MR_LD_CACHE_WRITE_BACK ? "write-back" :
+		    "write-through");
+	if (changes & (MR_LD_CACHE_READ_AHEAD | MR_LD_CACHE_READ_ADAPTIVE))
+		printf("Setting read ahead policy to %s\n",
+		    policy & MR_LD_CACHE_READ_AHEAD ?
+		    (policy & MR_LD_CACHE_READ_ADAPTIVE ?
+		    "adaptive" : "always") : "none");
+
+	props->default_cache_policy = policy;
+	if (mfi_ld_set_props(fd, props) < 0) {
+		warn("Failed to set volume properties");
+		return (errno);
+	}
+	return (0);
+}
+
+static int
+volume_cache(int ac, char **av)
+{
+	struct mfi_ld_props props;
+	int error, fd;
+	uint8_t target_id, policy;
+
+	if (ac < 2) {
+		warnx("cache: volume required");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
+		warn("Invalid volume: %s", av[1]);
+		return (errno);
+	}
+
+	if (mfi_ld_get_props(fd, target_id, &props) < 0) {
+		warn("Failed to fetch volume properties");
+		return (errno);
+	}
+
+	if (ac == 2) {
+		printf("mfi%u volume %s cache settings:\n", mfi_unit,
+		    mfi_volume_name(fd, target_id));
+		printf("      I/O caching: ");
+		switch (props.default_cache_policy &
+		    (MR_LD_CACHE_ALLOW_WRITE_CACHE |
+		    MR_LD_CACHE_ALLOW_READ_CACHE)) {
+		case 0:
+			printf("disabled\n");
+			break;
+		case MR_LD_CACHE_ALLOW_WRITE_CACHE:
+			printf("writes\n");
+			break;
+		case MR_LD_CACHE_ALLOW_READ_CACHE:
+			printf("reads\n");
+			break;
+		case MR_LD_CACHE_ALLOW_WRITE_CACHE |
+		    MR_LD_CACHE_ALLOW_READ_CACHE:
+			printf("writes and reads\n");
+			break;
+		}
+		printf("    write caching: %s\n",
+		    props.default_cache_policy & MR_LD_CACHE_WRITE_BACK ?
+		    "write-back" : "write-through");
+		printf("       read ahead: %s\n",
+		    props.default_cache_policy & MR_LD_CACHE_READ_AHEAD ?
+		    (props.default_cache_policy & MR_LD_CACHE_READ_ADAPTIVE ?
+		    "adaptive" : "always") : "none");
+		printf("drive write cache: ");
+		switch (props.disk_cache_policy) {
+		case MR_PD_CACHE_UNCHANGED:
+			printf("default\n");
+			break;
+		case MR_PD_CACHE_ENABLE:
+			printf("enabled\n");
+			break;
+		case MR_PD_CACHE_DISABLE:
+			printf("disabled\n");
+			break;
+		default:
+			printf("??? %d\n", props.disk_cache_policy);
+			break;
+		}
+		if (props.default_cache_policy != props.current_cache_policy)
+			printf("Cache Disabled Due to Dead Battery\n");
+		error = 0;
+	} else {
+		if (strcmp(av[2], "all") == 0 || strcmp(av[2], "enable") == 0)
+			error = update_cache_policy(fd, &props,
+			    MR_LD_CACHE_ALLOW_READ_CACHE |
+			    MR_LD_CACHE_ALLOW_WRITE_CACHE,
+			    MR_LD_CACHE_ALLOW_READ_CACHE |
+			    MR_LD_CACHE_ALLOW_WRITE_CACHE);
+		else if (strcmp(av[2], "none") == 0 ||
+		    strcmp(av[2], "disable") == 0)
+			error = update_cache_policy(fd, &props, 0,
+			    MR_LD_CACHE_ALLOW_READ_CACHE |
+			    MR_LD_CACHE_ALLOW_WRITE_CACHE);
+		else if (strcmp(av[2], "reads") == 0)
+			error = update_cache_policy(fd, &props,
+			    MR_LD_CACHE_ALLOW_READ_CACHE,
+			    MR_LD_CACHE_ALLOW_READ_CACHE |
+			    MR_LD_CACHE_ALLOW_WRITE_CACHE);
+		else if (strcmp(av[2], "writes") == 0)
+			error = update_cache_policy(fd, &props,
+			    MR_LD_CACHE_ALLOW_WRITE_CACHE,
+			    MR_LD_CACHE_ALLOW_READ_CACHE |
+			    MR_LD_CACHE_ALLOW_WRITE_CACHE);
+		else if (strcmp(av[2], "write-back") == 0)
+			error = update_cache_policy(fd, &props,
+			    MR_LD_CACHE_WRITE_BACK,
+			    MR_LD_CACHE_WRITE_BACK);
+		else if (strcmp(av[2], "write-through") == 0)
+			error = update_cache_policy(fd, &props, 0,
+			    MR_LD_CACHE_WRITE_BACK);
+		else if (strcmp(av[2], "read-ahead") == 0) {
+			if (ac < 4) {
+				warnx("cache: read-ahead setting required");
+				return (EINVAL);
+			}
+			if (strcmp(av[3], "none") == 0)
+				policy = 0;
+			else if (strcmp(av[3], "always") == 0)
+				policy = MR_LD_CACHE_READ_AHEAD;
+			else if (strcmp(av[3], "adaptive") == 0)
+				policy = MR_LD_CACHE_READ_AHEAD |
+				    MR_LD_CACHE_READ_ADAPTIVE;
+			else {
+				warnx("cache: invalid read-ahead setting");
+				return (EINVAL);
+			}
+			error = update_cache_policy(fd, &props, policy,
+			    MR_LD_CACHE_READ_AHEAD |
+			    MR_LD_CACHE_READ_ADAPTIVE);
+		} else if (strcmp(av[2], "write-cache") == 0) {
+			if (ac < 4) {
+				warnx("cache: write-cache setting required");
+				return (EINVAL);
+			}
+			if (strcmp(av[3], "enable") == 0)
+				policy = MR_PD_CACHE_ENABLE;
+			else if (strcmp(av[3], "disable") == 0)
+				policy = MR_PD_CACHE_DISABLE;
+			else if (strcmp(av[3], "default") == 0)
+				policy = MR_PD_CACHE_UNCHANGED;
+			else {
+				warnx("cache: invalid write-cache setting");
+				return (EINVAL);
+			}
+			error = 0;
+			if (policy != props.disk_cache_policy) {
+				switch (policy) {
+				case MR_PD_CACHE_ENABLE:
+					printf("Enabling write-cache on physical drives\n");
+					break;
+				case MR_PD_CACHE_DISABLE:
+					printf("Disabling write-cache on physical drives\n");
+					break;
+				case MR_PD_CACHE_UNCHANGED:
+					printf("Using default write-cache setting on physical drives\n");
+					break;
+				}
+				props.disk_cache_policy = policy;
+				if (mfi_ld_set_props(fd, &props) < 0) {
+					warn("Failed to set volume properties");
+					error = errno;
+				}
+			}
+		} else {
+			warnx("cache: Invalid command");
+			return (EINVAL);
+		}
+	}
+	close(fd);
+
+	return (error);
+}
+MFI_COMMAND(top, cache, volume_cache);
+
+static int
+volume_name(int ac, char **av)
+{
+	struct mfi_ld_props props;
+	int fd;
+	uint8_t target_id;
+
+	if (ac != 3) {
+		warnx("name: volume and name required");
+		return (EINVAL);
+	}
+
+	if (strlen(av[2]) >= sizeof(props.name)) {
+		warnx("name: new name is too long");
+		return (ENOSPC);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
+		warn("Invalid volume: %s", av[1]);
+		return (errno);
+	}
+
+	if (mfi_ld_get_props(fd, target_id, &props) < 0) {
+		warn("Failed to fetch volume properties");
+		return (errno);
+	}
+
+	printf("mfi%u volume %s name changed from \"%s\" to \"%s\"\n", mfi_unit,
+	    mfi_volume_name(fd, target_id), props.name, av[2]);
+	bzero(props.name, sizeof(props.name));
+	strcpy(props.name, av[2]);
+	if (mfi_ld_set_props(fd, &props) < 0) {
+		warn("Failed to set volume properties");
+		return (errno);
+	}
+
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(top, name, volume_name);
+
+static int
+volume_progress(int ac, char **av)
+{
+	struct mfi_ld_info info;
+	int fd;
+	uint8_t target_id;
+
+	if (ac != 2) {
+		warnx("volume progress: %s", ac > 2 ? "extra arguments" :
+		    "volume required");
+		return (EINVAL);
+	}
+
+	fd = mfi_open(mfi_unit);
+	if (fd < 0) {
+		warn("mfi_open");
+		return (errno);
+	}
+
+	if (mfi_lookup_volume(fd, av[1], &target_id) < 0) {
+		warn("Invalid volume: %s", av[1]);
+		return (errno);
+	}
+
+	/* Get the info for this drive. */
+	if (mfi_ld_get_info(fd, target_id, &info, NULL) < 0) {
+		warn("Failed to fetch info for volume %s",
+		    mfi_volume_name(fd, target_id));
+		return (errno);
+	}
+
+	/* Display any of the active events. */
+	if (info.progress.active & MFI_LD_PROGRESS_CC)
+		mfi_display_progress("Consistency Check", &info.progress.cc);
+	if (info.progress.active & MFI_LD_PROGRESS_BGI)
+		mfi_display_progress("Background Init", &info.progress.bgi);
+	if (info.progress.active & MFI_LD_PROGRESS_FGI)
+		mfi_display_progress("Foreground Init", &info.progress.fgi);
+	if (info.progress.active & MFI_LD_PROGRESS_RECON)
+		mfi_display_progress("Reconstruction", &info.progress.recon);
+	if ((info.progress.active & (MFI_LD_PROGRESS_CC | MFI_LD_PROGRESS_BGI |
+	    MFI_LD_PROGRESS_FGI | MFI_LD_PROGRESS_RECON)) == 0)
+		printf("No activity in progress for volume %s.\n",
+		    mfi_volume_name(fd, target_id));
+	close(fd);
+
+	return (0);
+}
+MFI_COMMAND(volume, progress, volume_progress);
diff --git a/usr.sbin/mfiutil/mfiutil.8 b/usr.sbin/mfiutil/mfiutil.8
new file mode 100644
index 00000000000..e6026d653d4
--- /dev/null
+++ b/usr.sbin/mfiutil/mfiutil.8
@@ -0,0 +1,566 @@
+.\" Copyright (c) 2008, 2009 Yahoo!, Inc.
+.\" 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.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\"    products derived from this software without specific prior written
+.\"    permission.
+.\"
+.\" 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$
+.\"
+.Dd August 16, 2009
+.Dt MFIUTIL 8
+.Os
+.Sh NAME
+.Nm mfiutil
+.Nd Utility for managing LSI MegaRAID SAS controllers
+.Sh SYNOPSIS
+.Nm
+.Cm version
+.Nm
+.Op Fl u Ar unit
+.Cm show adapter
+.Nm
+.Op Fl u Ar unit
+.Cm show battery
+.Nm
+.Op Fl u Ar unit
+.Cm show config
+.Nm
+.Op Fl u Ar unit
+.Cm show drives
+.Nm
+.Op Fl u Ar unit
+.Cm show events
+.Op Fl c Ar class
+.Op Fl l Ar locale
+.Op Fl n Ar count
+.Op Fl v
+.Op Ar start Op Ar stop
+.Nm
+.Op Fl u Ar unit
+.Cm show firmware
+.Nm
+.Op Fl u Ar unit
+.Cm show logstate
+.Nm
+.Op Fl u Ar unit
+.Cm show patrol
+.Nm
+.Op Fl u Ar unit
+.Cm show volumes
+.Nm
+.Op Fl u Ar unit
+.Cm fail Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm good Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm rebuild Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm drive progress Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm drive clear Ar drive Brq "start | stop"
+.Nm
+.Op Fl u Ar unit
+.Cm start rebuild Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm abort rebuild Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm locate Ar drive Brq "on | off"
+.Nm
+.Op Fl u Ar unit
+.Cm cache Ar volume Op Ar setting Op Ar value
+.Nm
+.Op Fl u Ar unit
+.Cm name Ar volume Ar name
+.Nm
+.Op Fl u Ar unit
+.Cm volume progress Ar volume
+.Nm
+.Op Fl u Ar unit
+.Cm clear
+.Nm
+.Op Fl u Ar unit
+.Cm create Ar type
+.Op Fl v
+.Op Fl s Ar stripe_size
+.Ar drive Ns Op \&, Ns Ar drive Ns Op ",..."
+.Op Ar drive Ns Op \&, Ns Ar drive Ns Op ",..."
+.Nm
+.Op Fl u Ar unit
+.Cm delete Ar volume
+.Nm
+.Op Fl u Ar unit
+.Cm add Ar drive Op Ar volume
+.Nm
+.Op Fl u Ar unit
+.Cm remove Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm start patrol
+.Nm
+.Op Fl u Ar unit
+.Cm stop patrol
+.Nm
+.Op Fl u Ar unit
+.Cm patrol Ar command Op Ar interval Op Ar start
+.Nm
+.Op Fl u Ar unit
+.Cm flash Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility can be used to display or modify various parameters on LSI
+MegaRAID SAS RAID controllers.
+Each invocation of
+.Nm
+consists of zero or more global options followed by a command.
+Commands may support additional optional or required arguments after the
+command.
+.Pp
+Currently one global option is supported:
+.Bl -tag -width indent
+.It Fl u Ar unit
+.Ar unit
+specifies the unit of the controller to work with.
+If no unit is specified,
+then unit 0 is used.
+.El
+.Pp
+Volumes may be specified in two forms.
+First,
+a volume may be identified by its target ID.
+Second,
+on the volume may be specified by the corresponding
+.Em mfidX
+device,
+such as
+.Em mfid0 .
+.Pp
+Drives may be specified in two forms.
+First,
+a drive may be identified by its device ID.
+The device ID for configured drives can be found in
+.Cm show config .
+Second,
+a drive may be identified by its location as
+.Sm off
+.Op E Ar xx Ns \&:
+.Li S Ns Ar yy
+.Sm on
+where
+.Ar xx
+is the enclosure
+and
+.Ar yy
+is the slot for each drive as displayed in
+.Cm show drives .
+.Pp
+The
+.Nm
+utility supports several different groups of commands.
+The first group of commands provide information about the controller,
+the volumes it manages, and the drives it controls.
+The second group of commands are used to manage the physical drives
+attached to the controller.
+The third group of commands are used to manage the logical volumes
+managed by the controller.
+The fourth group of commands are used to manage the drive configuration for
+the controller.
+The fifth group of commands are used to manage controller-wide operations.
+.Pp
+The informational commands include:
+.Bl -tag -width indent
+.It Cm version
+Displays the version of
+.Nm .
+.It Cm show adapter
+Displays information about the RAID controller such as the model number.
+.It Cm show battery
+Displays information about the battery from the battery backup unit.
+.It Cm show config
+Displays the volume and drive configuration for the controller.
+Each array is listed along with the physical drives the array is built from.
+Each volume is listed along with the arrays that the volume spans.
+If any hot spare drives are configured, then they are listed as well.
+.It Cm show drives
+Lists all of the physical drives attached to the controller.
+.It Xo Cm show events
+.Op Fl c Ar class
+.Op Fl l Ar locale
+.Op Fl n Ar count
+.Op Fl v
+.Op Ar start Op Ar stop
+.Xc
+Display entries from the controller's event log.
+The controller maintains a circular buffer of events.
+Each event is tagged with a class and locale.
+.Pp
+The
+.Ar class
+parameter limits the output to entries at the specified class or higher.
+The default class is
+.Dq warn .
+The available classes from lowest priority to highest are:
+.Bl -tag -width -indent
+.It Cm debug
+Debug messages.
+.It Cm progress
+Periodic progress updates for long-running operations such as background
+initializations, array rebuilds, or patrol reads.
+.It Cm info
+Informational messages such as drive insertions and volume creations.
+.It Cm warn
+Indicates that some component may be close to failing.
+.It Cm crit
+A component has failed, but no data is lost.
+For example, a volume becoming degraded due to a drive failure.
+.It Cm fatal
+A component has failed resulting in data loss.
+.It Cm dead
+The controller itself has died.
+.El
+.Pp
+The
+.Ar locale
+parameter limits the output to entries for the specified part of the controller.
+The default locale is
+.Dq all .
+The available locales are
+.Dq volume ,
+.Dq drive ,
+.Dq enclousure ,
+.Dq battery ,
+.Dq sas ,
+.Dq controller ,
+.Dq config ,
+.Dq cluster ,
+and
+.Dq all .
+.Pp
+The
+.Ar count
+parameter is a debugging aid that specifies the number of events to fetch from
+the controller for each low-level request.
+The default is 15 events.
+.Pp
+By default, matching event log entries from the previous shutdown up to the
+present are displayed.  This range can be adjusted via the
+.Ar start
+and
+.Ar stop
+parameters.
+Each of these parameters can either be specified as a log entry number or as
+one of the following aliases:
+.Bl -tag -width -indent
+.It Cm newest
+The newest entry in the event log.
+.It Cm oldest
+The oldest entry in the event log.
+.It Cm clear
+The first entry since the event log was cleared.
+.It Cm shutdown
+The entry in the event log corresponding to the last time the controller was
+cleanly shut down.
+.It Cm boot
+The entry in the event log corresponding to the most recent boot.
+.El
+.It Cm show firmware
+Lists all of the firmware images present on the controller.
+.It Cm show logstate
+Display the various sequence numbers associated with the event log.
+.It Cm show patrol
+Display the status of the controller's patrol read operation.
+.It Cm show volumes
+Lists all of the logical volumes managed by the controller.
+.El
+.Pp
+The physical drive management commands include:
+.Bl -tag -width indent
+.It Cm fail Ar drive
+Mark
+.Ar drive
+as failed.
+.Ar Drive
+must be an online drive that is part of an array.
+.It Cm good Ar drive
+Mark
+.Ar drive
+as an unconfigured good drive.
+.Ar Drive
+must not be part of an existing array.
+.It Cm rebuild Ar drive
+Mark a failed
+.Ar drive
+that is still part of an array as a good drive suitable for a rebuild.
+The firmware should kick off an array rebuild on its own if a failed drive
+is marked as a rebuild drive.
+.It Cm drive progress Ar drive
+Report the current progress and estimated completion time of drive operations
+such as rebuilds or patrol reads.
+.It Cm drive clear Ar drive Brq "start | stop"
+Start or stop the writing of all 0x00 characters to a drive.
+.It Cm start rebuild Ar drive
+Manually start a rebuild on
+.Ar drive .
+.It Cm abort rebuild Ar drive
+Abort an in-progress rebuild operation on
+.Ar drive .
+It can be resumed with the
+.Cm start rebuild
+command.
+.It Cm locate Ar drive Brq "on | off"
+Change the state of the external LED associated with
+.Ar drive .
+.El
+.Pp
+The logical volume management commands include:
+.Bl -tag -width indent
+.It Cm cache Ar volume Op Ar setting Op Ar value
+If no
+.Ar setting
+argument is supplied, then the current cache policy for
+.Ar volume
+is displayed;
+otherwise,
+the cache policy for
+.Ar volume
+is modified.
+The optional
+.Ar setting
+argument can be one of the following values:
+.Bl -tag -width indent
+.It Cm enable
+Enable caching for both read and write I/O operations.
+.It Cm disable
+Disable caching for both read and write I/O operations.
+.It Cm reads
+Enable caching only for read I/O operations.
+.It Cm writes
+Enable caching only for write I/O operations.
+.It Cm write-back
+Use write-back policy for cached writes.
+.It Cm write-through
+Use write-through policy for cached writes.
+.It Cm read-ahead Op Ar value
+Set the read ahead policy for cached reads.
+The
+.Ar value
+argument can be set to either
+.Dq none ,
+.Dq adaptive ,
+or
+.Dq always .
+.It Cm write-cache Op Ar value
+Control the write caches on the physical drives backing
+.Ar volume .
+The
+.Ar value
+argument can be set to either
+.Dq disable ,
+.Dq enable ,
+or
+.Dq default .
+.Pp
+In general this setting should be left disabled to avoid data loss when the
+physical drives lose power.
+The battery backup of the RAID controller does not save data in the write
+caches of the physical drives.
+.El
+.It Cm name Ar volume Ar name
+Sets the name of
+.Ar volume
+to
+.Ar name .
+.It Cm volume progress Ar volume
+Report the current progress and estimated completion time of volume operations
+such as consistency checks and initializations.
+.El
+.Pp
+The configuration commands include:
+.Bl -tag -width indent
+.It Cm clear
+Delete the entire configuration including all volumes, arrays, and spares.
+.It Xo Cm create Ar type
+.Op Fl v
+.Op Fl s Ar stripe_size
+.Ar drive Ns Op \&, Ns Ar drive Ns Op ",..."
+.Op Ar drive Ns Op \&, Ns Ar drive Ns Op ",..."
+.Xc
+Create a new volume.
+The
+.Ar type
+specifies the type of volume to create.
+Currently supported types include:
+.Bl -tag -width indent
+.It Cm jbod
+Creates a RAID0 volume for each drive specified.
+Each drive must be specified as a separate argument.
+.It Cm raid0
+Creates one RAID0 volume spanning the drives listed in the single drive list.
+.It Cm raid1
+Creates one RAID1 volume spanning the drives listed in the single drive list.
+.It Cm raid5
+Creates one RAID5 volume spanning the drives listed in the single drive list.
+.It Cm raid6
+Creates one RAID6 volume spanning the drives listed in the single drive list.
+.It Cm raid10
+Creates one RAID10 volume spanning multiple RAID1 arrays.
+The drives for each RAID1 array are specified as a single drive list.
+.It Cm raid50
+Creates one RAID50 volume spanning multiple RAID5 arrays.
+The drives for each RAID5 array are specified as a single drive list.
+.It Cm raid60
+Creates one RAID60 volume spanning multiple RAID6 arrays.
+The drives for each RAID6 array are specified as a single drive list.
+.It Cm concat
+Creates a single volume by concatenating all of the drives in the single drive
+list.
+.El
+.Pp
+.Sy Note:
+Not all volume types are supported by all controllers.
+.Pp
+If the
+.Fl v
+flag is specified after
+.Ar type ,
+then more verbose output will be enabled.
+Currently this just provides notification as drives are added to arrays and
+arrays to volumes when building the configuration.
+.Pp
+The
+.Fl s
+.Ar stripe_size
+parameter allows the stripe size of the array to be set.
+By default a stripe size of 64K is used.
+Valid values are 512 through 1M, though the MFI firmware may reject some
+values.
+.It Cm delete Ar volume
+Delete the volume
+.Ar volume .
+.It Cm add Ar drive Op Ar volume
+Mark
+.Ar drive
+as a hot spare.
+.Ar Drive
+must be in the unconfigured good state.
+If
+.Ar volume
+is specified,
+then the hot spare will be dedicated to arrays backing that volume.
+Otherwise,
+.Ar drive
+will be used as a global hot spare backing all arrays for this controller.
+Note that
+.Ar drive
+must be as large as the smallest drive in all of the arrays it is going to
+back.
+.It Cm remove Ar drive
+Remove the hot spare
+.Ar drive
+from service.
+It will be placed in the unconfigured good state.
+.El
+.Pp
+The controller management commands include:
+.Bl -tag -width indent
+.It Cm patrol Ar command Op Ar interval Op Ar start
+Set the patrol read operation mode.
+The
+.Ar command
+argument can be one of the following values:
+.Bl -tag -width indent
+.It Cm disable
+Disable patrol reads.
+.It Cm auto
+Enable periodic patrol reads initiated by the firmware.
+The optional
+.Ar interval
+argument specifies the interval in seconds between patrol reads.
+If patrol reads should be run continously,
+then
+.Ar interval
+should consist of the word
+.Dq continuously .
+The optional
+.Ar start
+argument specifies a non-negative, relative start time for the next patrol read.
+If an interval or start time is not specified,
+then the existing setting will be used.
+.It Cm manual
+Enable manual patrol reads that are only initiated by the user.
+.El
+.It Cm start patrol
+Start a patrol read operation.
+.It Cm stop patrol
+Stop a currently running patrol read operation.
+.It Cm flash Ar file
+Updates the flash on the controller with the firmware stored in
+.Ar file .
+A reboot is required for the new firmware to take effect.
+.El
+.Sh EXAMPLES
+Configure the cache for volume mfid0 to cache only writes:
+.Pp
+.Dl Nm Cm cache mfid0 writes
+.Dl Nm Cm cache mfid0 write-back
+.Pp
+Create a RAID5 array spanning the first four disks in the second enclosure:
+.Pp
+.Dl Nm Cm create raid5 e1:s0,e1:s1,e1:s2,e1:s4
+.Pp
+Configure the first three disks on a controller as JBOD:
+.Pp
+.Dl Nm Cm create jbod 0 1 2
+.Pp
+Create a RAID10 volume that spans two arrays each of which contains two disks
+from two different enclosures:
+.Pp
+.Dl Nm Cm create raid10 e1:s0,e1:s1 e2:s0,e2:s1
+.Pp
+Add drive with the device ID of 4 as a global hot spare:
+.Pp
+.Dl Nm Cm add 4
+.Pp
+Add the drive in slot 2 in the main chassis as a hot spare for volume mfid0:
+.Pp
+.Dl Nm Cm add s2 mfid0
+.Pp
+Configure the adapter to run periodic patrol reads once a week with the first
+patrol read starting in 5 minutes:
+.Pp
+.Dl Nm Cm patrol auto 604800 300
+.Pp
+.Sh SEE ALSO
+.Xr mfi 4
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 8.0 .
diff --git a/usr.sbin/mfiutil/mfiutil.c b/usr.sbin/mfiutil/mfiutil.c
new file mode 100644
index 00000000000..d091fb63177
--- /dev/null
+++ b/usr.sbin/mfiutil/mfiutil.c
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mfiutil.h"
+
+SET_DECLARE(MFI_DATASET(top), struct mfiutil_command);
+
+MFI_TABLE(top, start);
+MFI_TABLE(top, stop);
+MFI_TABLE(top, abort);
+
+int mfi_unit;
+
+static void
+usage(void)
+{
+
+	fprintf(stderr, "usage: mfiutil [-u unit]  ...\n\n");
+	fprintf(stderr, "Commands include:\n");
+	fprintf(stderr, "    version\n");
+	fprintf(stderr, "    show adapter              - display controller information\n");
+	fprintf(stderr, "    show battery              - display battery information\n");
+	fprintf(stderr, "    show config               - display RAID configuration\n");
+	fprintf(stderr, "    show drives               - list physical drives\n");
+	fprintf(stderr, "    show events               - display event log\n");
+	fprintf(stderr, "    show firmware             - list firmware images\n");
+	fprintf(stderr, "    show volumes              - list logical volumes\n");
+	fprintf(stderr, "    show patrol               - display patrol read status\n");
+	fprintf(stderr, "    fail               - fail a physical drive\n");
+	fprintf(stderr, "    good               - mark a bad physical drive as good\n");
+	fprintf(stderr, "    rebuild            - mark failed drive ready for rebuild\n");
+	fprintf(stderr, "    drive progress     - display status of active operations\n");
+	fprintf(stderr, "    drive clear   - clear a drive with all 0x00\n");
+	fprintf(stderr, "    start rebuild \n");
+	fprintf(stderr, "    abort rebuild \n");
+	fprintf(stderr, "    locate     - toggle drive LED\n");
+	fprintf(stderr, "    cache  [command [setting]]\n");
+	fprintf(stderr, "    name  \n");
+	fprintf(stderr, "    volume progress   - display status of active operations\n");
+	fprintf(stderr, "    clear                     - clear volume configuration\n");
+	fprintf(stderr, "    create  [-v] [,[,...]] [[,[,...]]\n");
+	fprintf(stderr, "    delete \n");
+	fprintf(stderr, "    add  [volume]      - add a hot spare\n");
+	fprintf(stderr, "    remove             - remove a hot spare\n");
+	fprintf(stderr, "    patrol  [interval [start]]\n");
+	fprintf(stderr, "    start patrol              - start a patrol read\n");
+	fprintf(stderr, "    stop patrol               - stop a patrol read\n");
+	fprintf(stderr, "    flash \n");
+#ifdef DEBUG
+	fprintf(stderr, "    debug                     - debug 'show config'\n");
+	fprintf(stderr, "    dump                      - display 'saved' config\n");
+#endif
+	exit(1);
+}
+
+static int
+version(int ac, char **av)
+{
+
+	printf("mfiutil version 1.0.13");
+#ifdef DEBUG
+	printf(" (DEBUG)");
+#endif
+	printf("\n");
+	return (0);
+}
+MFI_COMMAND(top, version, version);
+
+int
+main(int ac, char **av)
+{
+	struct mfiutil_command **cmd;
+	int ch;
+
+	while ((ch = getopt(ac, av, "u:")) != -1) {
+		switch (ch) {
+		case 'u':
+			mfi_unit = atoi(optarg);
+			break;
+		case '?':
+			usage();
+		}
+	}
+
+	av += optind;
+	ac -= optind;
+
+	/* getopt() eats av[0], so we can't use mfi_table_handler() directly. */
+	if (ac == 0)
+		usage();
+
+	SET_FOREACH(cmd, MFI_DATASET(top)) {
+		if (strcmp((*cmd)->name, av[0]) == 0) {
+			(*cmd)->handler(ac, av);
+			return (0);
+		}
+	}
+	warnx("Unknown command %s.", av[0]);
+	return (0);
+}
diff --git a/usr.sbin/mfiutil/mfiutil.h b/usr.sbin/mfiutil/mfiutil.h
new file mode 100644
index 00000000000..b080b5004e3
--- /dev/null
+++ b/usr.sbin/mfiutil/mfiutil.h
@@ -0,0 +1,147 @@
+/*-
+ * Copyright (c) 2008, 2009 Yahoo!, Inc.
+ * 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.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * 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$
+ */
+
+#ifndef __MFIUTIL_H__
+#define	__MFIUTIL_H__
+
+#include 
+#include 
+
+#include 
+
+/* 4.x compat */
+#ifndef SET_DECLARE
+
+/*  */
+#define	__used
+#define	__section(x)	__attribute__((__section__(x)))
+
+/*  */
+#undef __MAKE_SET
+#undef DATA_SET
+
+#define __MAKE_SET(set, sym)						\
+	static void const * const __set_##set##_sym_##sym 		\
+	__section("set_" #set) __used = &sym
+
+#define DATA_SET(set, sym)	__MAKE_SET(set, sym)
+
+#define SET_DECLARE(set, ptype)						\
+	extern ptype *__CONCAT(__start_set_,set);			\
+	extern ptype *__CONCAT(__stop_set_,set)
+
+#define SET_BEGIN(set)							\
+	(&__CONCAT(__start_set_,set))
+#define SET_LIMIT(set)							\
+	(&__CONCAT(__stop_set_,set))
+
+#define	SET_FOREACH(pvar, set)						\
+	for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++)
+
+int	humanize_number(char *_buf, size_t _len, int64_t _number,
+	    const char *_suffix, int _scale, int _flags);
+
+/* humanize_number(3) */
+#define HN_DECIMAL		0x01
+#define HN_NOSPACE		0x02
+#define HN_B			0x04
+#define HN_DIVISOR_1000		0x08
+
+#define HN_GETSCALE		0x10
+#define HN_AUTOSCALE		0x20
+
+#endif
+
+/* Constants for DDF RAID levels. */
+#define	DDF_RAID0		0x00
+#define	DDF_RAID1		0x01
+#define	DDF_RAID3		0x03
+#define	DDF_RAID5		0x05
+#define	DDF_RAID6		0x06
+#define	DDF_RAID1E		0x11
+#define	DDF_JBOD		0x0f
+#define	DDF_CONCAT		0x1f
+#define	DDF_RAID5E		0x15
+#define	DDF_RAID5EE		0x25
+
+struct mfiutil_command {
+	const char *name;
+	int (*handler)(int ac, char **av);
+};
+
+#define	MFI_DATASET(name)	mfiutil_ ## name ## _table
+
+#define	MFI_COMMAND(set, name, function)				\
+	static struct mfiutil_command function ## _mfiutil_command =	\
+	{ #name, function };						\
+	DATA_SET(MFI_DATASET(set), function ## _mfiutil_command)
+
+#define	MFI_TABLE(set, name)						\
+	SET_DECLARE(MFI_DATASET(name), struct mfiutil_command);		\
+									\
+	static int							\
+	mfiutil_ ## name ## _table_handler(int ac, char **av)		\
+	{								\
+		return (mfi_table_handler(SET_BEGIN(MFI_DATASET(name)), \
+		    SET_LIMIT(MFI_DATASET(name)), ac, av));		\
+	}								\
+	MFI_COMMAND(set, name, mfiutil_ ## name ## _table_handler)
+
+extern int mfi_unit;
+
+void	mbox_store_ldref(uint8_t *mbox, union mfi_ld_ref *ref);
+void	mbox_store_pdref(uint8_t *mbox, union mfi_pd_ref *ref);
+void	mfi_display_progress(const char *label, struct mfi_progress *prog);
+int	mfi_table_handler(struct mfiutil_command **start,
+    struct mfiutil_command **end, int ac, char **av);
+const char *mfi_raid_level(uint8_t primary_level, uint8_t secondary_level);
+const char *mfi_ldstate(enum mfi_ld_state state);
+const char *mfi_pdstate(enum mfi_pd_state state);
+const char *mfi_pd_inq_string(struct mfi_pd_info *info);
+const char *mfi_volume_name(int fd, uint8_t target_id);
+int	mfi_volume_busy(int fd, uint8_t target_id);
+int	mfi_config_read(int fd, struct mfi_config_data **configp);
+int	mfi_lookup_drive(int fd, char *drive, uint16_t *device_id);
+int	mfi_lookup_volume(int fd, const char *name, uint8_t *target_id);
+int	mfi_dcmd_command(int fd, uint32_t opcode, void *buf, size_t bufsize,
+    uint8_t *mbox, size_t mboxlen, uint8_t *statusp);
+int	mfi_open(int unit);
+int	mfi_ctrl_get_info(int fd, struct mfi_ctrl_info *info, uint8_t *statusp);
+int	mfi_ld_get_info(int fd, uint8_t target_id, struct mfi_ld_info *info,
+    uint8_t *statusp);
+int	mfi_ld_get_list(int fd, struct mfi_ld_list *list, uint8_t *statusp);
+int	mfi_pd_get_info(int fd, uint16_t device_id, struct mfi_pd_info *info,
+    uint8_t *statusp);
+int	mfi_pd_get_list(int fd, struct mfi_pd_list **listp, uint8_t *statusp);
+int	mfi_reconfig_supported(void);
+const char *mfi_status(u_int status_code);
+
+#endif /* !__MFIUTIL_H__ */
diff --git a/usr.sbin/mptutil/Makefile b/usr.sbin/mptutil/Makefile
new file mode 100644
index 00000000000..4abf66e4657
--- /dev/null
+++ b/usr.sbin/mptutil/Makefile
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+PROG=	mptutil
+SRCS=	mptutil.c mpt_cam.c mpt_cmd.c mpt_config.c mpt_drive.c mpt_evt.c \
+	mpt_show.c mpt_volume.c
+#	mpt_flash.c
+MAN=	mptutil.8
+
+WARNS?= 3
+
+DPADD+=	${LIBCAM} ${LIBUTIL}
+LDADD+=	-lcam -lutil
+
+# Here be dragons
+.ifdef DEBUG
+CFLAGS+= -DDEBUG
+.endif
+
+.include 
diff --git a/usr.sbin/mptutil/mpt_cam.c b/usr.sbin/mptutil/mpt_cam.c
new file mode 100644
index 00000000000..0d20c7db601
--- /dev/null
+++ b/usr.sbin/mptutil/mpt_cam.c
@@ -0,0 +1,569 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin 
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include 
+__RCSID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "mptutil.h"
+
+static int xptfd;
+
+static int
+xpt_open(void)
+{
+
+	if (xptfd == 0)
+		xptfd = open(XPT_DEVICE, O_RDWR);
+	return (xptfd);
+}
+
+int
+mpt_query_disk(U8 VolumeBus, U8 VolumeID, struct mpt_query_disk *qd)
+{
+	struct bus_match_pattern *b;
+	struct periph_match_pattern *p;
+	struct periph_match_result *r;
+	union ccb ccb;
+	size_t bufsize;
+	int i;
+
+	/* mpt(4) only handles devices on bus 0. */
+	if (VolumeBus != 0)
+		return (ENXIO);
+
+	if (xpt_open() < 0)
+		return (ENXIO);
+
+	bzero(&ccb, sizeof(ccb));
+
+	ccb.ccb_h.func_code = XPT_DEV_MATCH;
+	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
+	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
+	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
+
+	bufsize = sizeof(struct dev_match_result) * 5;
+	ccb.cdm.num_matches = 0;
+	ccb.cdm.match_buf_len = bufsize;
+	ccb.cdm.matches = calloc(1, bufsize);
+
+	bufsize = sizeof(struct dev_match_pattern) * 2;
+	ccb.cdm.num_patterns = 2;
+	ccb.cdm.pattern_buf_len = bufsize;
+	ccb.cdm.patterns = calloc(1, bufsize);
+
+	/* Match mptX bus 0. */
+	ccb.cdm.patterns[0].type = DEV_MATCH_BUS;
+	b = &ccb.cdm.patterns[0].pattern.bus_pattern;
+	snprintf(b->dev_name, sizeof(b->dev_name), "mpt");
+	b->unit_number = mpt_unit;
+	b->bus_id = 0;
+	b->flags = BUS_MATCH_NAME | BUS_MATCH_UNIT | BUS_MATCH_BUS_ID;
+
+	/* Look for a "da" device at the specified target and lun. */
+	ccb.cdm.patterns[1].type = DEV_MATCH_PERIPH;
+	p = &ccb.cdm.patterns[1].pattern.periph_pattern;
+	snprintf(p->periph_name, sizeof(p->periph_name), "da");
+	p->target_id = VolumeID;
+	p->flags = PERIPH_MATCH_NAME | PERIPH_MATCH_TARGET;
+
+	if (ioctl(xptfd, CAMIOCOMMAND, &ccb) < 0) {
+		i = errno;
+		free(ccb.cdm.matches);
+		free(ccb.cdm.patterns);
+		return (i);
+	}
+	free(ccb.cdm.patterns);
+
+	if (((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) ||
+	    (ccb.cdm.status != CAM_DEV_MATCH_LAST)) {
+		warnx("mpt_query_disk got CAM error %#x, CDM error %d\n",
+		    ccb.ccb_h.status, ccb.cdm.status);
+		free(ccb.cdm.matches);
+		return (EIO);
+	}
+
+	/*
+	 * We should have exactly 2 matches, 1 for the bus and 1 for
+	 * the peripheral.  However, if we only have 1 match and it is
+	 * for the bus, don't print an error message and return
+	 * ENOENT.
+	 */
+	if (ccb.cdm.num_matches == 1 &&
+	    ccb.cdm.matches[0].type == DEV_MATCH_BUS) {
+		free(ccb.cdm.matches);
+		return (ENOENT);
+	}
+	if (ccb.cdm.num_matches != 2) {
+		warnx("mpt_query_disk got %d matches, expected 2",
+		    ccb.cdm.num_matches);
+		free(ccb.cdm.matches);
+		return (EIO);
+	}
+	if (ccb.cdm.matches[0].type != DEV_MATCH_BUS ||
+	    ccb.cdm.matches[1].type != DEV_MATCH_PERIPH) {
+		warnx("mpt_query_disk got wrong CAM matches");
+		free(ccb.cdm.matches);
+		return (EIO);
+	}
+
+	/* Copy out the data. */
+	r = &ccb.cdm.matches[1].result.periph_result;
+	snprintf(qd->devname, sizeof(qd->devname), "%s%d", r->periph_name,
+	    r->unit_number);
+	free(ccb.cdm.matches);
+
+	return (0);
+}
+
+static int
+periph_is_volume(CONFIG_PAGE_IOC_2 *ioc2, struct periph_match_result *r)
+{
+	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
+	int i;
+
+	if (ioc2 == NULL)
+		return (0);
+	vol = ioc2->RaidVolume;
+	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
+		if (vol->VolumeBus == 0 && vol->VolumeID == r->target_id)
+			return (1);
+	}
+	return (0);
+}
+
+/* Much borrowed from scsireadcapacity() in src/sbin/camcontrol/camcontrol.c. */
+static int
+fetch_scsi_capacity(struct cam_device *dev, struct mpt_standalone_disk *disk)
+{
+	struct scsi_read_capacity_data rcap;
+	struct scsi_read_capacity_data_long rcaplong;
+	union ccb *ccb;
+	int error;
+
+	ccb = cam_getccb(dev);
+	if (ccb == NULL)
+		return (ENOMEM);
+
+	/* Zero the rest of the ccb. */
+	bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio) -
+	    sizeof(struct ccb_hdr));
+
+	scsi_read_capacity(&ccb->csio, 1, NULL, MSG_SIMPLE_Q_TAG, &rcap,
+	    SSD_FULL_SIZE, 5000);
+
+	/* Disable freezing the device queue */
+	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+	if (cam_send_ccb(dev, ccb) < 0) {
+		error = errno;
+		cam_freeccb(ccb);
+		return (error);
+	}
+
+	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+		cam_freeccb(ccb);
+		return (EIO);
+	}
+	cam_freeccb(ccb);
+
+	/*
+	 * A last block of 2^32-1 means that the true capacity is over 2TB,
+	 * and we need to issue the long READ CAPACITY to get the real
+	 * capacity.  Otherwise, we're all set.
+	 */
+	if (scsi_4btoul(rcap.addr) != 0xffffffff) {
+		disk->maxlba = scsi_4btoul(rcap.addr);
+		return (0);
+	}
+
+	/* Zero the rest of the ccb. */
+	bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio) -
+	    sizeof(struct ccb_hdr));
+
+	scsi_read_capacity_16(&ccb->csio, 1, NULL, MSG_SIMPLE_Q_TAG, 0, 0, 0,
+	    &rcaplong, SSD_FULL_SIZE, 5000);
+
+	/* Disable freezing the device queue */
+	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+	if (cam_send_ccb(dev, ccb) < 0) {
+		error = errno;
+		cam_freeccb(ccb);
+		return (error);
+	}
+
+	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+		cam_freeccb(ccb);
+		return (EIO);
+	}
+	cam_freeccb(ccb);
+
+	disk->maxlba = scsi_8btou64(rcaplong.addr);
+	return (0);
+}
+
+/* Borrowed heavily from scsi_all.c:scsi_print_inquiry(). */
+static void
+format_scsi_inquiry(struct mpt_standalone_disk *disk,
+    struct scsi_inquiry_data *inq_data)
+{
+	char vendor[16], product[48], revision[16], rstr[12];
+
+	if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data))
+		return;
+	if (SID_TYPE(inq_data) != T_DIRECT)
+		return;
+	if (SID_QUAL(inq_data) != SID_QUAL_LU_CONNECTED)
+		return;
+
+	cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
+	    sizeof(vendor));
+	cam_strvis(product, inq_data->product, sizeof(inq_data->product),
+	    sizeof(product));
+	cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
+	    sizeof(revision));
+
+	/* Hack for SATA disks, no idea how to tell speed. */
+	if (strcmp(vendor, "ATA") == 0) {
+		snprintf(disk->inqstring, sizeof(disk->inqstring),
+		    "<%s %s> SATA", product, revision);
+		return;
+	}
+
+	switch (SID_ANSI_REV(inq_data)) {
+	case SCSI_REV_CCS:
+		strcpy(rstr, "SCSI-CCS");
+		break;
+	case 5:
+		strcpy(rstr, "SAS");
+		break;
+	default:
+		snprintf(rstr, sizeof (rstr), "SCSI-%d",
+		    SID_ANSI_REV(inq_data));
+		break;
+	}
+	snprintf(disk->inqstring, sizeof(disk->inqstring), "<%s %s %s> %s",
+	    vendor, product, revision, rstr);
+}
+
+/* Much borrowed from scsiinquiry() in src/sbin/camcontrol/camcontrol.c. */
+static int
+fetch_scsi_inquiry(struct cam_device *dev, struct mpt_standalone_disk *disk)
+{
+	struct scsi_inquiry_data *inq_buf;
+	union ccb *ccb;
+	int error;
+
+	ccb = cam_getccb(dev);
+	if (ccb == NULL)
+		return (ENOMEM);
+
+	/* Zero the rest of the ccb. */
+	bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio) -
+	    sizeof(struct ccb_hdr));
+
+	inq_buf = calloc(1, sizeof(*inq_buf));
+	if (inq_buf == NULL) {
+		cam_freeccb(ccb);
+		return (ENOMEM);
+	}
+	scsi_inquiry(&ccb->csio, 1, NULL, MSG_SIMPLE_Q_TAG, (void *)inq_buf,
+	    SHORT_INQUIRY_LENGTH, 0, 0, SSD_FULL_SIZE, 5000);
+
+	/* Disable freezing the device queue */
+	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+	if (cam_send_ccb(dev, ccb) < 0) {
+		error = errno;
+		free(inq_buf);
+		cam_freeccb(ccb);
+		return (error);
+	}
+
+	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+		free(inq_buf);
+		cam_freeccb(ccb);
+		return (EIO);
+	}
+
+	cam_freeccb(ccb);
+	format_scsi_inquiry(disk, inq_buf);
+	free(inq_buf);
+	return (0);
+}
+
+int
+mpt_fetch_disks(int fd, int *ndisks, struct mpt_standalone_disk **disksp)
+{
+	CONFIG_PAGE_IOC_2 *ioc2;
+	struct mpt_standalone_disk *disks;
+	struct bus_match_pattern *b;
+	struct periph_match_pattern *p;
+	struct periph_match_result *r;
+	struct cam_device *dev;
+	union ccb ccb;
+	size_t bufsize;
+	u_int i;
+	int count;
+
+	if (xpt_open() < 0)
+		return (ENXIO);
+
+	for (count = 100;; count+= 100) {
+		/* Try to fetch 'count' disks in one go. */
+		bzero(&ccb, sizeof(ccb));
+
+		ccb.ccb_h.func_code = XPT_DEV_MATCH;
+
+		bufsize = sizeof(struct dev_match_result) * (count + 2);
+		ccb.cdm.num_matches = 0;
+		ccb.cdm.match_buf_len = bufsize;
+		ccb.cdm.matches = calloc(1, bufsize);
+
+		bufsize = sizeof(struct dev_match_pattern) * 2;
+		ccb.cdm.num_patterns = 2;
+		ccb.cdm.pattern_buf_len = bufsize;
+		ccb.cdm.patterns = calloc(1, bufsize);
+
+		/* Match mptX bus 0. */
+		ccb.cdm.patterns[0].type = DEV_MATCH_BUS;
+		b = &ccb.cdm.patterns[0].pattern.bus_pattern;
+		snprintf(b->dev_name, sizeof(b->dev_name), "mpt");
+		b->unit_number = mpt_unit;
+		b->bus_id = 0;
+		b->flags = BUS_MATCH_NAME | BUS_MATCH_UNIT | BUS_MATCH_BUS_ID;
+
+		/* Match any "da" peripherals. */
+		ccb.cdm.patterns[1].type = DEV_MATCH_PERIPH;
+		p = &ccb.cdm.patterns[1].pattern.periph_pattern;
+		snprintf(p->periph_name, sizeof(p->periph_name), "da");
+		p->flags = PERIPH_MATCH_NAME;
+
+		if (ioctl(xptfd, CAMIOCOMMAND, &ccb) < 0) {
+			i = errno;
+			free(ccb.cdm.matches);
+			free(ccb.cdm.patterns);
+			return (i);
+		}
+		free(ccb.cdm.patterns);
+
+		/* Check for CCB errors. */
+		if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+			free(ccb.cdm.matches);
+			return (EIO);
+		}
+
+		/* If we need a longer list, try again. */
+		if (ccb.cdm.status == CAM_DEV_MATCH_MORE) {
+			free(ccb.cdm.matches);
+			continue;
+		}
+
+		/* If we got an error, abort. */
+		if (ccb.cdm.status != CAM_DEV_MATCH_LAST) {
+			free(ccb.cdm.matches);
+			return (EIO);
+		}
+		break;
+	}
+
+	/*
+	 * We should have N + 1 matches, 1 for the bus and 1 for each
+	 * "da" device.
+	 */
+	if (ccb.cdm.num_matches < 1) {
+		warnx("mpt_fetch_disks didn't get any matches");
+		free(ccb.cdm.matches);
+		return (EIO);
+	}
+	if (ccb.cdm.matches[0].type != DEV_MATCH_BUS) {
+		warnx("mpt_fetch_disks got wrong CAM matches");
+		free(ccb.cdm.matches);
+		return (EIO);
+	}
+	for (i = 1; i < ccb.cdm.num_matches; i++) {
+		if (ccb.cdm.matches[i].type != DEV_MATCH_PERIPH) {
+			warnx("mpt_fetch_disks got wrong CAM matches");
+			free(ccb.cdm.matches);
+			return (EIO);
+		}
+	}
+
+	/* Shortcut if we don't have any "da" devices. */
+	if (ccb.cdm.num_matches == 1) {
+		free(ccb.cdm.matches);
+		*ndisks = 0;
+		*disksp = NULL;
+		return (0);
+	}
+
+	/*
+	 * Some of the "da" peripherals may be for RAID volumes, so
+	 * fetch the IOC 2 page (list of RAID volumes) so we can
+	 * exclude them from the list.
+	 */
+	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
+	disks = calloc(ccb.cdm.num_matches, sizeof(*disks));
+	count = 0;
+	for (i = 1; i < ccb.cdm.num_matches; i++) {
+		r = &ccb.cdm.matches[i].result.periph_result;
+		if (periph_is_volume(ioc2, r))
+			continue;
+		disks[count].bus = 0;
+		disks[count].target = r->target_id;
+		snprintf(disks[count].devname, sizeof(disks[count].devname),
+		    "%s%d", r->periph_name, r->unit_number);
+
+		dev = cam_open_device(disks[count].devname, O_RDWR);
+		if (dev != NULL) {
+			fetch_scsi_capacity(dev, &disks[count]);
+			fetch_scsi_inquiry(dev, &disks[count]);
+			cam_close_device(dev);
+		}
+		count++;
+	}
+	free(ccb.cdm.matches);
+	free(ioc2);
+
+	*ndisks = count;
+	*disksp = disks;
+	return (0);
+}
+
+/*
+ * Instruct the mpt(4) device to rescan its busses to find new devices
+ * such as disks whose RAID physdisk page was removed or volumes that
+ * were created.  If id is -1, the entire bus is rescanned.
+ * Otherwise, only devices at the specified ID are rescanned.  If bus
+ * is -1, then all busses are scanned instead of the specified bus.
+ * Note that currently, only bus 0 is supported.
+ */
+int
+mpt_rescan_bus(int bus, int id)
+{
+	struct bus_match_pattern *b;
+	union ccb ccb;
+	path_id_t path_id;
+	size_t bufsize;
+
+	/* mpt(4) only handles devices on bus 0. */
+	if (bus != -1 && bus != 0)
+		return (EINVAL);
+
+	if (xpt_open() < 0)
+		return (ENXIO);
+
+	/* First, find the path id of bus 0 for this mpt controller. */
+	bzero(&ccb, sizeof(ccb));
+
+	ccb.ccb_h.func_code = XPT_DEV_MATCH;
+
+	bufsize = sizeof(struct dev_match_result) * 1;
+	ccb.cdm.num_matches = 0;
+	ccb.cdm.match_buf_len = bufsize;
+	ccb.cdm.matches = calloc(1, bufsize);
+
+	bufsize = sizeof(struct dev_match_pattern) * 1;
+	ccb.cdm.num_patterns = 1;
+	ccb.cdm.pattern_buf_len = bufsize;
+	ccb.cdm.patterns = calloc(1, bufsize);
+
+	/* Match mptX bus 0. */
+	ccb.cdm.patterns[0].type = DEV_MATCH_BUS;
+	b = &ccb.cdm.patterns[0].pattern.bus_pattern;
+	snprintf(b->dev_name, sizeof(b->dev_name), "mpt");
+	b->unit_number = mpt_unit;
+	b->bus_id = 0;
+	b->flags = BUS_MATCH_NAME | BUS_MATCH_UNIT | BUS_MATCH_BUS_ID;
+
+	if (ioctl(xptfd, CAMIOCOMMAND, &ccb) < 0) {
+		free(ccb.cdm.matches);
+		free(ccb.cdm.patterns);
+		return (errno);
+	}
+	free(ccb.cdm.patterns);
+
+	if (((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) ||
+	    (ccb.cdm.status != CAM_DEV_MATCH_LAST)) {
+		warnx("mpt_rescan_bus got CAM error %#x, CDM error %d\n",
+		    ccb.ccb_h.status, ccb.cdm.status);
+		free(ccb.cdm.matches);
+		return (EIO);
+	}
+
+	/* We should have exactly 1 match for the bus. */
+	if (ccb.cdm.num_matches != 1 ||
+	    ccb.cdm.matches[0].type != DEV_MATCH_BUS) {
+		free(ccb.cdm.matches);
+		return (ENOENT);
+	}
+	path_id = ccb.cdm.matches[0].result.bus_result.path_id;
+	free(ccb.cdm.matches);
+
+	/* Now perform the actual rescan. */
+	ccb.ccb_h.path_id = path_id;
+	if (id == -1) {
+		ccb.ccb_h.func_code = XPT_SCAN_BUS;
+		ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
+		ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
+		ccb.ccb_h.timeout = 5000;
+	} else {
+		ccb.ccb_h.func_code = XPT_SCAN_LUN;
+		ccb.ccb_h.target_id = id;
+		ccb.ccb_h.target_lun = 0;
+	}
+	ccb.crcn.flags = CAM_FLAG_NONE;
+
+	/* Run this at a low priority. */
+	ccb.ccb_h.pinfo.priority = 5;
+
+	if (ioctl(xptfd, CAMIOCOMMAND, &ccb) == -1)
+		return (errno);
+
+	if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+		warnx("mpt_rescan_bus rescan got CAM error %#x\n",
+		    ccb.ccb_h.status & CAM_STATUS_MASK);
+		return (EIO);
+	}
+
+	return (0);
+}
diff --git a/usr.sbin/mptutil/mpt_cmd.c b/usr.sbin/mptutil/mpt_cmd.c
new file mode 100644
index 00000000000..2d6000c7731
--- /dev/null
+++ b/usr.sbin/mptutil/mpt_cmd.c
@@ -0,0 +1,639 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin 
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include 
+__RCSID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mptutil.h"
+
+static const char *mpt_ioc_status_codes[] = {
+	"Success",				/* 0x0000 */
+	"Invalid function",
+	"Busy",
+	"Invalid scatter-gather list",
+	"Internal error",
+	"Reserved",
+	"Insufficient resources",
+	"Invalid field",
+	"Invalid state",			/* 0x0008 */
+	"Operation state not supported",
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,					/* 0x0010 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,					/* 0x0018 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"Invalid configuration action",		/* 0x0020 */
+	"Invalid configuration type",
+	"Invalid configuration page",
+	"Invalid configuration data",
+	"No configuration defaults",
+	"Unable to commit configuration change",
+	NULL,
+	NULL,
+	NULL,					/* 0x0028 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,					/* 0x0030 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,					/* 0x0038 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"Recovered SCSI error",			/* 0x0040 */
+	"Invalid SCSI bus",
+	"Invalid SCSI target ID",
+	"SCSI device not there",
+	"SCSI data overrun",
+	"SCSI data underrun",
+	"SCSI I/O error",
+	"SCSI protocol error",
+	"SCSI task terminated",			/* 0x0048 */
+	"SCSI residual mismatch",
+	"SCSI task management failed",
+	"SCSI I/O controller terminated",
+	"SCSI external controller terminated",
+	"EEDP guard error",
+	"EEDP reference tag error",
+	"EEDP application tag error",
+	NULL,					/* 0x0050 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,					/* 0x0058 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"SCSI target priority I/O",		/* 0x0060 */
+	"Invalid SCSI target port",
+	"Invalid SCSI target I/O index",
+	"SCSI target aborted",
+	"No connection retryable",
+	"No connection",
+	"FC aborted",
+	"Invalid FC receive ID",
+	"FC did invalid",			/* 0x0068 */
+	"FC node logged out",
+	"Transfer count mismatch",
+	"STS data not set",
+	"FC exchange canceled",
+	"Data offset error",
+	"Too much write data",
+	"IU too short",
+	"ACK NAK timeout",			/* 0x0070 */
+	"NAK received",
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,					/* 0x0078 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"LAN device not found",			/* 0x0080 */
+	"LAN device failure",
+	"LAN transmit error",
+	"LAN transmit aborted",
+	"LAN receive error",
+	"LAN receive aborted",
+	"LAN partial packet",
+	"LAN canceled",
+	NULL,					/* 0x0088 */
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"SAS SMP request failed",		/* 0x0090 */
+	"SAS SMP data overrun",
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"Inband aborted",			/* 0x0098 */
+	"No inband connection",
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"Diagnostic released",			/* 0x00A0 */
+};
+
+static const char *mpt_raid_action_status_codes[] = {
+	"Success",
+	"Invalid action",
+	"Failure",
+	"Operation in progress",
+};
+
+const char *
+mpt_ioc_status(U16 IOCStatus)
+{
+	static char buffer[16];
+
+	IOCStatus &= MPI_IOCSTATUS_MASK;
+	if (IOCStatus < sizeof(mpt_ioc_status_codes) / sizeof(char *) &&
+	    mpt_ioc_status_codes[IOCStatus] != NULL)
+		return (mpt_ioc_status_codes[IOCStatus]);
+	snprintf(buffer, sizeof(buffer), "Status: 0x%04x", IOCStatus);
+	return (buffer);
+}
+
+const char *
+mpt_raid_status(U16 ActionStatus)
+{
+	static char buffer[16];
+
+	if (ActionStatus < sizeof(mpt_raid_action_status_codes) /
+	    sizeof(char *))
+		return (mpt_raid_action_status_codes[ActionStatus]);
+	snprintf(buffer, sizeof(buffer), "Status: 0x%04x", ActionStatus);
+	return (buffer);
+}
+
+const char *
+mpt_raid_level(U8 VolumeType)
+{
+	static char buf[16];
+
+	switch (VolumeType) {
+	case MPI_RAID_VOL_TYPE_IS:
+		return ("RAID-0");
+	case MPI_RAID_VOL_TYPE_IM:
+		return ("RAID-1");
+	case MPI_RAID_VOL_TYPE_IME:
+		return ("RAID-1E");
+	case MPI_RAID_VOL_TYPE_RAID_5:
+		return ("RAID-5");
+	case MPI_RAID_VOL_TYPE_RAID_6:
+		return ("RAID-6");
+	case MPI_RAID_VOL_TYPE_RAID_10:
+		return ("RAID-10");
+	case MPI_RAID_VOL_TYPE_RAID_50:
+		return ("RAID-50");
+	default:
+		sprintf(buf, "LVL 0x%02x", VolumeType);
+		return (buf);
+	}
+}
+
+const char *
+mpt_volume_name(U8 VolumeBus, U8 VolumeID)
+{
+	static struct mpt_query_disk info;
+	static char buf[16];
+
+	if (mpt_query_disk(VolumeBus, VolumeID, &info) != 0) {
+		/*
+		 * We only print out the bus number if it is non-zero
+		 * since mpt(4) only supports devices on bus zero
+		 * anyway.
+		 */
+		if (VolumeBus == 0)
+			snprintf(buf, sizeof(buf), "%d", VolumeID);
+		else
+			snprintf(buf, sizeof(buf), "%d:%d", VolumeBus,
+			    VolumeID);
+		return (buf);
+	}
+	return (info.devname);
+}
+
+int
+mpt_lookup_volume(int fd, const char *name, U8 *VolumeBus, U8 *VolumeID)
+{
+	CONFIG_PAGE_IOC_2 *ioc2;
+	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
+	struct mpt_query_disk info;
+	char *cp;
+	long bus, id;
+	int i;
+
+	/*
+	 * Check for a raw [:] string.  If the bus is not
+	 * specified, assume bus 0.
+	 */
+	bus = strtol(name, &cp, 0);
+	if (*cp == ':') {
+		id = strtol(cp + 1, &cp, 0);
+		if (*cp == '\0') {
+			if (bus < 0 || bus > 0xff || id < 0 || id > 0xff) {
+				errno = EINVAL;
+				return (-1);
+			}
+			*VolumeBus = bus;
+			*VolumeID = id;
+			return (0);
+		}
+	} else if (*cp == '\0') {
+		if (bus < 0 || bus > 0xff) {
+			errno = EINVAL;
+			return (-1);
+		}
+		*VolumeBus = 0;
+		*VolumeID = bus;
+		return (0);
+	}
+
+	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
+	if (ioc2 == NULL)
+		return (-1);
+
+	vol = ioc2->RaidVolume;
+	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
+		if (mpt_query_disk(vol->VolumeBus, vol->VolumeID, &info) != 0)
+			continue;
+		if (strcmp(name, info.devname) == 0) {
+			*VolumeBus = vol->VolumeBus;
+			*VolumeID = vol->VolumeID;
+			free(ioc2);
+			return (0);
+		}
+	}
+	free(ioc2);
+	errno = EINVAL;
+	return (-1);
+}
+
+int
+mpt_read_config_page_header(int fd, U8 PageType, U8 PageNumber, U32 PageAddress,
+    CONFIG_PAGE_HEADER *header, U16 *IOCStatus)
+{
+	struct mpt_cfg_page_req req;
+
+	if (IOCStatus != NULL)
+		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
+	bzero(&req, sizeof(req));
+	req.header.PageType = PageType;
+	req.header.PageNumber = PageNumber;
+	req.page_address = PageAddress;
+	if (ioctl(fd, MPTIO_READ_CFG_HEADER, &req) < 0)
+		return (-1);
+	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
+		if (IOCStatus != NULL)
+			*IOCStatus = req.ioc_status;
+		else
+			warnx("Reading config page header failed: %s",
+			    mpt_ioc_status(req.ioc_status));
+		errno = EIO;
+		return (-1);
+	}
+	*header = req.header;
+	return (0);
+}
+
+void *
+mpt_read_config_page(int fd, U8 PageType, U8 PageNumber, U32 PageAddress,
+    U16 *IOCStatus)
+{
+	struct mpt_cfg_page_req req;
+	void *buf;
+	int save_errno;
+
+	if (IOCStatus != NULL)
+		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
+	bzero(&req, sizeof(req));
+	req.header.PageType = PageType;
+	req.header.PageNumber = PageNumber;
+	req.page_address = PageAddress;
+	if (ioctl(fd, MPTIO_READ_CFG_HEADER, &req) < 0)
+		return (NULL);
+	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
+		if (IOCStatus != NULL)
+			*IOCStatus = req.ioc_status;
+		else
+			warnx("Reading config page header failed: %s",
+			    mpt_ioc_status(req.ioc_status));
+		errno = EIO;
+		return (NULL);
+	}
+	req.len = req.header.PageLength * 4;
+	buf = malloc(req.len);
+	req.buf = buf;
+	bcopy(&req.header, buf, sizeof(req.header));
+	if (ioctl(fd, MPTIO_READ_CFG_PAGE, &req) < 0) {
+		save_errno = errno;
+		free(buf);
+		errno = save_errno;
+		return (NULL);
+	}
+	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
+		if (IOCStatus != NULL)
+			*IOCStatus = req.ioc_status;
+		else
+			warnx("Reading config page failed: %s",
+			    mpt_ioc_status(req.ioc_status));
+		free(buf);
+		errno = EIO;
+		return (NULL);
+	}
+	return (buf);
+}
+
+void *
+mpt_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion,
+    U8 PageNumber, U32 PageAddress, U16 *IOCStatus)
+{
+	struct mpt_ext_cfg_page_req req;
+	void *buf;
+	int save_errno;
+
+	if (IOCStatus != NULL)
+		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
+	bzero(&req, sizeof(req));
+	req.header.PageVersion = PageVersion;
+	req.header.PageNumber = PageNumber;
+	req.header.ExtPageType = ExtPageType;
+	req.page_address = PageAddress;
+	if (ioctl(fd, MPTIO_READ_EXT_CFG_HEADER, &req) < 0)
+		return (NULL);
+	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
+		if (IOCStatus != NULL)
+			*IOCStatus = req.ioc_status;
+		else
+			warnx("Reading extended config page header failed: %s",
+			    mpt_ioc_status(req.ioc_status));
+		errno = EIO;
+		return (NULL);
+	}
+	req.len = req.header.ExtPageLength * 4;
+	buf = malloc(req.len);
+	req.buf = buf;
+	bcopy(&req.header, buf, sizeof(req.header));
+	if (ioctl(fd, MPTIO_READ_EXT_CFG_PAGE, &req) < 0) {
+		save_errno = errno;
+		free(buf);
+		errno = save_errno;
+		return (NULL);
+	}
+	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
+		if (IOCStatus != NULL)
+			*IOCStatus = req.ioc_status;
+		else
+			warnx("Reading extended config page failed: %s",
+			    mpt_ioc_status(req.ioc_status));
+		free(buf);
+		errno = EIO;
+		return (NULL);
+	}
+	return (buf);
+}
+
+int
+mpt_write_config_page(int fd, void *buf, U16 *IOCStatus)
+{
+	CONFIG_PAGE_HEADER *hdr;
+	struct mpt_cfg_page_req req;
+
+	if (IOCStatus != NULL)
+		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
+	bzero(&req, sizeof(req));
+	req.buf = buf;
+	hdr = buf;
+	req.len = hdr->PageLength * 4;
+	if (ioctl(fd, MPTIO_WRITE_CFG_PAGE, &req) < 0)
+		return (-1);
+	if (!IOC_STATUS_SUCCESS(req.ioc_status)) {
+		if (IOCStatus != NULL) {
+			*IOCStatus = req.ioc_status;
+			return (0);
+		}
+		warnx("Writing config page failed: %s",
+		    mpt_ioc_status(req.ioc_status));
+		errno = EIO;
+		return (-1);
+	}
+	return (0);
+}
+
+int
+mpt_raid_action(int fd, U8 Action, U8 VolumeBus, U8 VolumeID, U8 PhysDiskNum,
+    U32 ActionDataWord, void *buf, int len, RAID_VOL0_STATUS *VolumeStatus,
+    U32 *ActionData, int datalen, U16 *IOCStatus, U16 *ActionStatus, int write)
+{
+	struct mpt_raid_action raid_act;
+
+	if (IOCStatus != NULL)
+		*IOCStatus = MPI_IOCSTATUS_SUCCESS;
+	if (datalen < 0 || (unsigned)datalen > sizeof(raid_act.action_data)) {
+		errno = EINVAL;
+		return (-1);
+	}
+	bzero(&raid_act, sizeof(raid_act));
+	raid_act.action = Action;
+	raid_act.volume_bus = VolumeBus;
+	raid_act.volume_id = VolumeID;
+	raid_act.phys_disk_num = PhysDiskNum;
+	raid_act.action_data_word = ActionDataWord;
+	if (buf != NULL && len != 0) {
+		raid_act.buf = buf;
+		raid_act.len = len;
+		raid_act.write = write;
+	}
+
+	if (ioctl(fd, MPTIO_RAID_ACTION, &raid_act) < 0)
+		return (-1);
+
+	if (!IOC_STATUS_SUCCESS(raid_act.ioc_status)) {
+		if (IOCStatus != NULL) {
+			*IOCStatus = raid_act.ioc_status;
+			return (0);
+		}
+		warnx("RAID action failed: %s",
+		    mpt_ioc_status(raid_act.ioc_status));
+		errno = EIO;
+		return (-1);
+	}
+
+	if (ActionStatus != NULL)
+		*ActionStatus = raid_act.action_status;
+	if (raid_act.action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS) {
+		if (ActionStatus != NULL)
+			return (0);
+		warnx("RAID action failed: %s",
+		    mpt_raid_status(raid_act.action_status));
+		errno = EIO;
+		return (-1);
+	}
+
+	if (VolumeStatus != NULL)
+		*((U32 *)VolumeStatus) = raid_act.volume_status;
+	if (ActionData != NULL)
+		bcopy(raid_act.action_data, ActionData, datalen);
+	return (0);
+}
+
+int
+mpt_open(int unit)
+{
+	char path[MAXPATHLEN];
+
+	snprintf(path, sizeof(path), "/dev/mpt%d", unit);
+	return (open(path, O_RDWR));
+}
+
+int
+mpt_table_handler(struct mptutil_command **start, struct mptutil_command **end,
+    int ac, char **av)
+{
+	struct mptutil_command **cmd;
+
+	if (ac < 2) {
+		warnx("The %s command requires a sub-command.", av[0]);
+		return (EINVAL);
+	}
+	for (cmd = start; cmd < end; cmd++) {
+		if (strcmp((*cmd)->name, av[1]) == 0)
+			return ((*cmd)->handler(ac - 1, av + 1));
+	}
+
+	warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
+	return (ENOENT);
+}
+
+#ifdef DEBUG
+void
+hexdump(const void *ptr, int length, const char *hdr, int flags)
+{
+	int i, j, k;
+	int cols;
+	const unsigned char *cp;
+	char delim;
+
+	if ((flags & HD_DELIM_MASK) != 0)
+		delim = (flags & HD_DELIM_MASK) >> 8;
+	else
+		delim = ' ';
+
+	if ((flags & HD_COLUMN_MASK) != 0)
+		cols = flags & HD_COLUMN_MASK;
+	else
+		cols = 16;
+
+	cp = ptr;
+	for (i = 0; i < length; i+= cols) {
+		if (hdr != NULL)
+			printf("%s", hdr);
+
+		if ((flags & HD_OMIT_COUNT) == 0)
+			printf("%04x  ", i);
+
+		if ((flags & HD_OMIT_HEX) == 0) {
+			for (j = 0; j < cols; j++) {
+				k = i + j;
+				if (k < length)
+					printf("%c%02x", delim, cp[k]);
+				else
+					printf("   ");
+			}
+		}
+
+		if ((flags & HD_OMIT_CHARS) == 0) {
+			printf("  |");
+			for (j = 0; j < cols; j++) {
+				k = i + j;
+				if (k >= length)
+					printf(" ");
+				else if (cp[k] >= ' ' && cp[k] <= '~')
+					printf("%c", cp[k]);
+				else
+					printf(".");
+			}
+			printf("|");
+		}
+		printf("\n");
+	}
+}
+#endif
diff --git a/usr.sbin/mptutil/mpt_config.c b/usr.sbin/mptutil/mpt_config.c
new file mode 100644
index 00000000000..3874df30137
--- /dev/null
+++ b/usr.sbin/mptutil/mpt_config.c
@@ -0,0 +1,1160 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin 
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include 
+__RCSID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#ifdef DEBUG
+#include 
+#endif
+#include 
+#include 
+#include 
+#include 
+#include "mptutil.h"
+
+#ifdef DEBUG
+static void	dump_config(CONFIG_PAGE_RAID_VOL_0 *vol);
+#endif
+
+#define powerof2(x)    ((((x)-1)&(x))==0)
+
+static long
+dehumanize(const char *value)
+{
+        char    *vtp;
+        long    iv;
+ 
+        if (value == NULL)
+                return (0);
+        iv = strtoq(value, &vtp, 0);
+        if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) {
+                return (0);
+        }
+        switch (vtp[0]) {
+        case 't': case 'T':
+                iv *= 1024;
+        case 'g': case 'G':
+                iv *= 1024;
+        case 'm': case 'M':
+                iv *= 1024;
+        case 'k': case 'K':
+                iv *= 1024;
+        case '\0':
+                break;
+        default:
+                return (0);
+        }
+        return (iv);
+}
+
+/*
+ * Lock the volume by opening its /dev device read/write.  This will
+ * only work if nothing else has it opened (including mounts).  We
+ * leak the fd on purpose since this application is not long-running.
+ */
+int
+mpt_lock_volume(U8 VolumeBus, U8 VolumeID)
+{
+	char path[MAXPATHLEN];
+	struct mpt_query_disk qd;
+	int error, vfd;
+
+	error = mpt_query_disk(VolumeBus, VolumeID, &qd);
+	if (error == ENOENT)
+		/*
+		 * This means there isn't a CAM device associated with
+		 * the volume, and thus it is already implicitly
+		 * locked, so just return.
+		 */
+		return (0);
+	if (error) {
+		errno = error;
+		warn("Unable to lookup volume device name");
+		return (-1);
+	}
+	snprintf(path, sizeof(path), "%s%s", _PATH_DEV, qd.devname);
+	vfd = open(path, O_RDWR);
+	if (vfd < 0) {
+		warn("Unable to lock volume %s", qd.devname);
+		return (-1);
+	}
+	return (0);
+}
+
+static int
+mpt_lock_physdisk(struct mpt_standalone_disk *disk)
+{
+	char path[MAXPATHLEN];
+	int dfd;
+
+	snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk->devname);
+	dfd = open(path, O_RDWR);
+	if (dfd < 0) {
+		warn("Unable to lock disk %s", disk->devname);
+		return (-1);
+	}
+	return (0);
+}
+
+static int
+mpt_lookup_standalone_disk(const char *name, struct mpt_standalone_disk *disks,
+    int ndisks, int *index)
+{
+	char *cp;
+	long bus, id;
+	int i;
+
+	/* Check for a raw : string. */
+	bus = strtol(name, &cp, 0);
+	if (*cp == ':') {
+		id = strtol(cp + 1, &cp, 0);
+		if (*cp == '\0') {
+			if (bus < 0 || bus > 0xff || id < 0 || id > 0xff) {
+				errno = EINVAL;
+				return (-1);
+			}
+			for (i = 0; i < ndisks; i++) {
+				if (disks[i].bus == (U8)bus &&
+				    disks[i].target == (U8)id) {
+					*index = i;
+					return (0);
+				}
+			}
+			errno = ENOENT;
+			return (-1);
+		}
+	}
+
+	if (name[0] == 'd' && name[1] == 'a') {
+		for (i = 0; i < ndisks; i++) {
+			if (strcmp(name, disks[i].devname) == 0) {
+				*index = i;
+				return (0);
+			}
+		}
+		errno = ENOENT;
+		return (-1);
+	}
+
+	errno = EINVAL;
+	return (-1);
+}
+
+/*
+ * Mark a standalone disk as being a physical disk.
+ */
+static int
+mpt_create_physdisk(int fd, struct mpt_standalone_disk *disk, U8 *PhysDiskNum)
+{
+	CONFIG_PAGE_HEADER header;
+	CONFIG_PAGE_RAID_PHYS_DISK_0 *config_page;
+	U32 ActionData;
+
+	if (mpt_read_config_page_header(fd, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK,
+	    0, 0, &header, NULL) < 0)
+		return (-1);
+	if (header.PageVersion > MPI_RAIDPHYSDISKPAGE0_PAGEVERSION) {
+		warnx("Unsupported RAID physdisk page 0 version %d",
+		    header.PageVersion);
+		errno = EOPNOTSUPP;
+		return (-1);
+	}		
+	config_page = calloc(1, sizeof(CONFIG_PAGE_RAID_PHYS_DISK_0));
+	config_page->Header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
+	config_page->Header.PageNumber = 0;
+	config_page->Header.PageLength = sizeof(CONFIG_PAGE_RAID_PHYS_DISK_0) /
+	    4;
+	config_page->PhysDiskIOC = 0;	/* XXX */
+	config_page->PhysDiskBus = disk->bus;
+	config_page->PhysDiskID = disk->target;
+
+	/* XXX: Enclosure info for PhysDiskSettings? */
+	if (mpt_raid_action(fd, MPI_RAID_ACTION_CREATE_PHYSDISK, 0, 0, 0, 0,
+	    config_page, sizeof(CONFIG_PAGE_RAID_PHYS_DISK_0), NULL,
+	    &ActionData, sizeof(ActionData), NULL, NULL, 1) < 0)
+		return (-1);
+	*PhysDiskNum = ActionData & 0xff;
+	return (0);
+}
+
+static int
+mpt_delete_physdisk(int fd, U8 PhysDiskNum)
+{
+
+	return (mpt_raid_action(fd, MPI_RAID_ACTION_DELETE_PHYSDISK, 0, 0,
+	    PhysDiskNum, 0, NULL, 0, NULL, NULL, 0, NULL, NULL, 0));
+}
+
+/*
+ * MPT's firmware does not have a clear command.  Instead, we
+ * implement it by deleting each array and disk by hand.
+ */
+static int
+clear_config(int ac, char **av)
+{
+	CONFIG_PAGE_IOC_2 *ioc2;
+	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
+	CONFIG_PAGE_IOC_3 *ioc3;
+	IOC_3_PHYS_DISK *disk;
+	CONFIG_PAGE_IOC_5 *ioc5;
+	IOC_5_HOT_SPARE *spare;
+	int ch, fd, i;
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
+	if (ioc2 == NULL) {
+		warn("Failed to fetch volume list");
+		return (errno);
+	}
+
+	/* Lock all the volumes first. */
+	vol = ioc2->RaidVolume;
+	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
+		if (mpt_lock_volume(vol->VolumeBus, vol->VolumeID) < 0) {
+			warnx("Volume %s is busy and cannot be deleted",
+			    mpt_volume_name(vol->VolumeBus, vol->VolumeID));
+			return (EBUSY);
+		}
+	}
+
+	printf(
+	    "Are you sure you wish to clear the configuration on mpt%u? [y/N] ",
+	    mpt_unit);
+	ch = getchar();
+	if (ch != 'y' && ch != 'Y') {
+		printf("\nAborting\n");
+		return (0);
+	}
+
+	/* Delete all the volumes. */
+	vol = ioc2->RaidVolume;
+	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++)
+		if (mpt_raid_action(fd, MPI_RAID_ACTION_DELETE_VOLUME,
+		    vol->VolumeBus, vol->VolumeID, 0,
+		    MPI_RAID_ACTION_ADATA_DEL_PHYS_DISKS |
+		    MPI_RAID_ACTION_ADATA_ZERO_LBA0, NULL, 0, NULL, NULL, 0,
+		    NULL, NULL, 0) < 0)
+			warn("Failed to delete volume %s",
+			    mpt_volume_name(vol->VolumeBus, vol->VolumeID));
+	free(ioc2);
+
+	/* Delete all the spares. */
+	ioc5 = mpt_read_ioc_page(fd, 5, NULL);
+	if (ioc5 == NULL)
+		warn("Failed to fetch spare list");
+	else {
+		spare = ioc5->HotSpare;
+		for (i = 0; i < ioc5->NumHotSpares; spare++, i++)
+			if (mpt_delete_physdisk(fd, spare->PhysDiskNum) < 0)
+				warn("Failed to delete physical disk %d",
+				    spare->PhysDiskNum);
+		free(ioc5);
+	}
+
+	/* Delete any RAID physdisks that may be left. */
+	ioc3 = mpt_read_ioc_page(fd, 3, NULL);
+	if (ioc3 == NULL)
+		warn("Failed to fetch drive list");
+	else {
+		disk = ioc3->PhysDisk;
+		for (i = 0; i < ioc3->NumPhysDisks; disk++, i++)
+			if (mpt_delete_physdisk(fd, disk->PhysDiskNum) < 0)
+				warn("Failed to delete physical disk %d",
+				    disk->PhysDiskNum);
+		free(ioc3);
+	}
+
+	printf("mpt%d: Configuration cleared\n", mpt_unit);
+	mpt_rescan_bus(-1, -1);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(top, clear, clear_config);
+
+#define	RT_RAID0	0
+#define	RT_RAID1	1
+#define	RT_RAID1E	2
+
+static struct raid_type_entry {
+	const char *name;
+	int	raid_type;
+} raid_type_table[] = {
+	{ "raid0",	RT_RAID0 },
+	{ "raid-0",	RT_RAID0 },
+	{ "raid1",	RT_RAID1 },
+	{ "raid-1",	RT_RAID1 },
+	{ "mirror",	RT_RAID1 },
+	{ "raid1e",	RT_RAID1E },
+	{ "raid-1e",	RT_RAID1E },
+	{ NULL,		0 },
+};
+
+struct config_id_state {
+	struct mpt_standalone_disk *sdisks;
+	struct mpt_drive_list *list;
+	CONFIG_PAGE_IOC_2 *ioc2;
+	U8	target_id;
+	int	nsdisks;
+};
+
+struct drive_info {
+	CONFIG_PAGE_RAID_PHYS_DISK_0 *info;
+	struct mpt_standalone_disk *sdisk;
+};
+
+struct volume_info {
+	int	drive_count;
+	struct drive_info *drives;
+};
+
+/* Parse a comma-separated list of drives for a volume. */
+static int
+parse_volume(int fd, int raid_type, struct config_id_state *state,
+    char *volume_str, struct volume_info *info)
+{
+	struct drive_info *dinfo;
+	U8 PhysDiskNum;
+	char *cp;
+	int count, error, i;
+
+	cp = volume_str;
+	for (count = 0; cp != NULL; count++) {
+		cp = strchr(cp, ',');
+		if (cp != NULL) {
+			cp++;
+			if (*cp == ',') {
+				warnx("Invalid drive list '%s'", volume_str);
+				return (EINVAL);
+			}
+		}
+	}
+
+	/* Validate the number of drives for this volume. */
+	switch (raid_type) {
+	case RT_RAID0:
+		if (count < 2) {
+			warnx("RAID0 requires at least 2 drives in each "
+			    "array");
+			return (EINVAL);
+		}
+		break;
+	case RT_RAID1:
+		if (count != 2) {
+			warnx("RAID1 requires exactly 2 drives in each "
+			    "array");
+			return (EINVAL);
+		}
+		break;
+	case RT_RAID1E:
+		if (count < 3) {
+			warnx("RAID1E requires at least 3 drives in each "
+			    "array");
+			return (EINVAL);
+		}
+		break;
+	}
+
+	/* Validate each drive. */
+	info->drives = calloc(count, sizeof(struct drive_info));
+	info->drive_count = count;
+	for (dinfo = info->drives; (cp = strsep(&volume_str, ",")) != NULL;
+	     dinfo++) {
+		/* If this drive is already a RAID phys just fetch the info. */
+		error = mpt_lookup_drive(state->list, cp, &PhysDiskNum);
+		if (error == 0) {
+			dinfo->info = mpt_pd_info(fd, PhysDiskNum, NULL);
+			if (dinfo->info == NULL)
+				return (errno);
+			continue;
+		}
+
+		/* See if it is a standalone disk. */
+		if (mpt_lookup_standalone_disk(cp, state->sdisks,
+		    state->nsdisks, &i) < 0) {
+			warn("Unable to lookup drive %s", cp);
+			return (errno);
+		}
+		dinfo->sdisk = &state->sdisks[i];
+
+		/* Lock the disk, we will create phys disk pages later. */
+		if (mpt_lock_physdisk(dinfo->sdisk) < 0)
+			return (errno);
+	}
+
+	return (0);
+}
+
+/*
+ * Add RAID physdisk pages for any standalone disks that a volume is
+ * going to use.
+ */
+static int
+add_drives(int fd, struct volume_info *info, int verbose)
+{
+	struct drive_info *dinfo;
+	U8 PhysDiskNum;
+	int i;
+
+	for (i = 0, dinfo = info->drives; i < info->drive_count;
+	     i++, dinfo++) {
+		if (dinfo->info == NULL) {
+			if (mpt_create_physdisk(fd, dinfo->sdisk,
+			    &PhysDiskNum) < 0) {
+				warn(
+			    "Failed to create physical disk page for %s",
+				    dinfo->sdisk->devname);
+				return (errno);
+			}
+			if (verbose)
+				printf("Added drive %s with PhysDiskNum %u\n",
+				    dinfo->sdisk->devname, PhysDiskNum);
+
+			dinfo->info = mpt_pd_info(fd, PhysDiskNum, NULL);
+			if (dinfo->info == NULL)
+				return (errno);
+		}
+	}
+	return (0);
+}
+
+/*
+ * Find the next free target ID assuming that 'target_id' is the last
+ * one used.  'target_id' should be 0xff for the initial test.
+ */
+static U8
+find_next_volume(struct config_id_state *state)
+{
+	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
+	int i;
+
+restart:
+	/* Assume the current one is used. */
+	state->target_id++;
+
+	/* Search drives first. */
+	for (i = 0; i < state->nsdisks; i++)
+		if (state->sdisks[i].target == state->target_id)
+			goto restart;
+	for (i = 0; i < state->list->ndrives; i++)
+		if (state->list->drives[i]->PhysDiskID == state->target_id)
+			goto restart;
+
+	/* Seach volumes second. */
+	vol = state->ioc2->RaidVolume;
+	for (i = 0; i < state->ioc2->NumActiveVolumes; vol++, i++)
+		if (vol->VolumeID == state->target_id)
+			goto restart;
+
+	return (state->target_id);
+}
+
+/* Create a volume and populate it with drives. */
+static CONFIG_PAGE_RAID_VOL_0 *
+build_volume(int fd, struct volume_info *info, int raid_type, long stripe_size,
+    struct config_id_state *state, int verbose)
+{
+	CONFIG_PAGE_HEADER header;
+	CONFIG_PAGE_RAID_VOL_0 *vol;
+	RAID_VOL0_PHYS_DISK *rdisk;
+	struct drive_info *dinfo;
+        U32 MinLBA;
+	uint64_t MaxLBA;
+	size_t page_size;
+	int i;
+
+	if (mpt_read_config_page_header(fd, MPI_CONFIG_PAGETYPE_RAID_VOLUME,
+	    0, 0, &header, NULL) < 0)
+		return (NULL);
+	if (header.PageVersion > MPI_RAIDVOLPAGE0_PAGEVERSION) {
+		warnx("Unsupported RAID volume page 0 version %d",
+		    header.PageVersion);
+		errno = EOPNOTSUPP;
+		return (NULL);
+	}
+	page_size = sizeof(CONFIG_PAGE_RAID_VOL_0) +
+	    sizeof(RAID_VOL0_PHYS_DISK) * (info->drive_count - 1);
+	vol = calloc(1, page_size);
+
+	/* Header */
+	vol->Header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
+	vol->Header.PageNumber = 0;
+	vol->Header.PageLength = page_size / 4;
+
+	/* Properties */
+	vol->VolumeID = find_next_volume(state);
+	vol->VolumeBus = 0;
+	vol->VolumeIOC = 0;	/* XXX */
+	vol->VolumeStatus.Flags = MPI_RAIDVOL0_STATUS_FLAG_ENABLED;
+	vol->VolumeStatus.State = MPI_RAIDVOL0_STATUS_STATE_OPTIMAL;
+	vol->VolumeSettings.Settings = MPI_RAIDVOL0_SETTING_USE_DEFAULTS;
+	vol->VolumeSettings.HotSparePool = MPI_RAID_HOT_SPARE_POOL_0;
+	vol->NumPhysDisks = info->drive_count;
+
+	/* Find the smallest drive. */
+	MinLBA = info->drives[0].info->MaxLBA;
+	for (i = 1; i < info->drive_count; i++)
+		if (info->drives[i].info->MaxLBA < MinLBA)
+			MinLBA = info->drives[i].info->MaxLBA;
+
+	/*
+	 * Now chop off 512MB at the end to leave room for the
+	 * metadata.  The controller might only use 64MB, but we just
+	 * chop off the max to be simple.
+	 */
+	MinLBA -= (512 * 1024 * 1024) / 512;
+
+	switch (raid_type) {
+	case RT_RAID0:
+		vol->VolumeType = MPI_RAID_VOL_TYPE_IS;
+		vol->StripeSize = stripe_size / 512;
+		MaxLBA = MinLBA * info->drive_count;
+		break;
+	case RT_RAID1:
+		vol->VolumeType = MPI_RAID_VOL_TYPE_IM;
+		MaxLBA = MinLBA * (info->drive_count / 2);
+		break;
+	case RT_RAID1E:
+		vol->VolumeType = MPI_RAID_VOL_TYPE_IME;
+		vol->StripeSize = stripe_size / 512;
+		MaxLBA = MinLBA * info->drive_count / 2;
+		break;
+	default:
+		/* Pacify gcc. */
+		abort();		
+	}
+
+	/*
+	 * If the controller doesn't support 64-bit addressing and the
+	 * new volume is larger than 2^32 blocks, warn the user and
+	 * truncate the volume.
+	 */
+	if (MaxLBA >> 32 != 0 &&
+	    !(state->ioc2->CapabilitiesFlags &
+	    MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING)) {
+		warnx(
+	    "Controller does not support volumes > 2TB, truncating volume.");
+		MaxLBA = 0xffffffff;
+	}
+	vol->MaxLBA = MaxLBA;
+	vol->MaxLBAHigh = MaxLBA >> 32;
+
+	/* Populate drives. */
+	for (i = 0, dinfo = info->drives, rdisk = vol->PhysDisk;
+	     i < info->drive_count; i++, dinfo++, rdisk++) {
+		if (verbose)
+			printf("Adding drive %u (%u:%u) to volume %u:%u\n",
+			    dinfo->info->PhysDiskNum, dinfo->info->PhysDiskBus,
+			    dinfo->info->PhysDiskID, vol->VolumeBus,
+			    vol->VolumeID);
+		if (raid_type == RT_RAID1) {
+			if (i == 0)
+				rdisk->PhysDiskMap =
+				    MPI_RAIDVOL0_PHYSDISK_PRIMARY;
+			else
+				rdisk->PhysDiskMap =
+				    MPI_RAIDVOL0_PHYSDISK_SECONDARY;
+		} else
+			rdisk->PhysDiskMap = i;
+		rdisk->PhysDiskNum = dinfo->info->PhysDiskNum;
+	}
+
+	return (vol);
+}
+
+static int
+create_volume(int ac, char **av)
+{
+	CONFIG_PAGE_RAID_VOL_0 *vol;
+	struct config_id_state state;
+	struct volume_info *info;
+	int ch, error, fd, i, raid_type, verbose, quick;
+	long stripe_size;
+#ifdef DEBUG
+	int dump;
+#endif
+
+	if (ac < 2) {
+		warnx("create: volume type required");
+		return (EINVAL);
+	}
+	
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	/* Lookup the RAID type first. */
+	raid_type = -1;
+	for (i = 0; raid_type_table[i].name != NULL; i++)
+		if (strcasecmp(raid_type_table[i].name, av[1]) == 0) {
+			raid_type = raid_type_table[i].raid_type;
+			break;
+		}
+
+	if (raid_type == -1) {
+		warnx("Unknown or unsupported volume type %s", av[1]);
+		return (EINVAL);
+	}
+
+	/* Parse any options. */
+	optind = 2;
+#ifdef DEBUG
+	dump = 0;
+#endif
+	quick = 0;
+	verbose = 0;
+	stripe_size = 64 * 1024;
+
+	while ((ch = getopt(ac, av, "dqs:v")) != -1) {
+		switch (ch) {
+#ifdef DEBUG
+		case 'd':
+			dump = 1;
+			break;
+#endif
+		case 'q':
+			quick = 1;
+			break;
+		case 's':
+			stripe_size = dehumanize(optarg);
+			if ((stripe_size < 512) || (!powerof2(stripe_size))) {
+				warnx("Invalid stripe size %s", optarg);
+				return (EINVAL);
+			}
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case '?':
+		default:
+			return (EINVAL);
+		}
+	}
+	ac -= optind;
+	av += optind;
+
+	/* Fetch existing config data. */
+	state.ioc2 = mpt_read_ioc_page(fd, 2, NULL);
+	if (state.ioc2 == NULL) {
+		warn("Failed to read volume list");
+		return (errno);
+	}
+	state.list = mpt_pd_list(fd);
+	if (state.list == NULL)
+		return (errno);
+	error = mpt_fetch_disks(fd, &state.nsdisks, &state.sdisks);
+	if (error) {
+		warn("Failed to fetch standalone disk list");
+		return (error);
+	}	
+	state.target_id = 0xff;
+	
+	/* Parse the drive list. */
+	if (ac != 1) {
+		warnx("Exactly one drive list is required");
+		return (EINVAL);
+	}
+	info = calloc(1, sizeof(*info));
+	error = parse_volume(fd, raid_type, &state, av[0], info);
+	if (error)
+		return (error);
+
+	/* Create RAID physdisk pages for standalone disks. */
+	error = add_drives(fd, info, verbose);
+	if (error)
+		return (error);
+
+	/* Build the volume. */
+	vol = build_volume(fd, info, raid_type, stripe_size, &state, verbose);
+
+#ifdef DEBUG
+	if (dump) {
+		dump_config(vol);
+		goto skip;
+	}
+#endif
+
+	/* Send the new volume to the controller. */
+	if (mpt_raid_action(fd, MPI_RAID_ACTION_CREATE_VOLUME, vol->VolumeBus,
+	    vol->VolumeID, 0, quick ? MPI_RAID_ACTION_ADATA_DO_NOT_SYNC : 0,
+	    vol, vol->Header.PageLength * 4, NULL, NULL, 0, NULL, NULL, 1) <
+	    0) {
+		warn("Failed to add volume");
+		return (errno);
+	}
+
+#ifdef DEBUG
+skip:
+#endif
+	mpt_rescan_bus(vol->VolumeBus, vol->VolumeID);
+
+	/* Clean up. */
+	free(vol);
+	free(info);
+	free(state.sdisks);
+	mpt_free_pd_list(state.list);
+	free(state.ioc2);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(top, create, create_volume);
+
+static int
+delete_volume(int ac, char **av)
+{
+	U8 VolumeBus, VolumeID;
+	int fd;
+
+	if (ac != 2) {
+		warnx("delete: volume required");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	if (mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID) < 0) {
+		warn("Invalid volume %s", av[1]);
+		return (errno);
+	}
+
+	if (mpt_lock_volume(VolumeBus, VolumeID) < 0)
+		return (errno);
+
+	if (mpt_raid_action(fd, MPI_RAID_ACTION_DELETE_VOLUME, VolumeBus,
+	    VolumeID, 0, MPI_RAID_ACTION_ADATA_DEL_PHYS_DISKS |
+	    MPI_RAID_ACTION_ADATA_ZERO_LBA0, NULL, 0, NULL, NULL, 0, NULL,
+	    NULL, 0) < 0) {
+		warn("Failed to delete volume");
+		return (errno);
+	}
+
+	mpt_rescan_bus(-1, -1);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(top, delete, delete_volume);
+
+static int
+find_volume_spare_pool(int fd, const char *name, int *pool)
+{
+	CONFIG_PAGE_RAID_VOL_0 *info;
+	CONFIG_PAGE_IOC_2 *ioc2;
+	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
+	U8 VolumeBus, VolumeID;
+	int i, j, new_pool, pool_count[7];
+
+	if (mpt_lookup_volume(fd, name, &VolumeBus, &VolumeID) < 0) {
+		warn("Invalid volume %s", name);
+		return (-1);
+	}
+
+	info = mpt_vol_info(fd, VolumeBus, VolumeID, NULL);
+	if (info == NULL)
+		return (-1);
+
+	/*
+	 * Check for an existing pool other than pool 0 (used for
+	 * global spares).
+	 */
+	if ((info->VolumeSettings.HotSparePool & ~MPI_RAID_HOT_SPARE_POOL_0) !=
+	    0) {
+		*pool = 1 << (ffs(info->VolumeSettings.HotSparePool &
+		    ~MPI_RAID_HOT_SPARE_POOL_0) - 1);
+		return (0);
+	}
+	free(info);
+
+	/*
+	 * Try to find a free pool.  First, figure out which pools are
+	 * in use.
+	 */
+	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
+	if (ioc2 == NULL) {
+		warn("Failed to fetch volume list");
+		return (-1);
+	}
+	bzero(pool_count, sizeof(pool_count));	
+	vol = ioc2->RaidVolume;
+	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
+		info = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, NULL);
+		if (info == NULL)
+			return (-1);
+		for (j = 0; j < 7; j++)
+			if (info->VolumeSettings.HotSparePool & (1 << (j + 1)))
+				pool_count[j]++;
+		free(info);
+	}
+	free(ioc2);
+
+	/* Find the pool with the lowest use count. */
+	new_pool = 0;
+	for (i = 1; i < 7; i++)
+		if (pool_count[i] < pool_count[new_pool])
+			new_pool = i;
+	new_pool++;
+
+	/* Add this pool to the volume. */
+	info = mpt_vol_info(fd, VolumeBus, VolumeID, NULL);
+	if (info == NULL)
+		return (-1);
+	info->VolumeSettings.HotSparePool |= (1 << new_pool);
+	if (mpt_raid_action(fd, MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS,
+	    VolumeBus, VolumeID, 0, *(U32 *)&info->VolumeSettings, NULL, 0,
+	    NULL, NULL, 0, NULL, NULL, 0) < 0) {
+		warnx("Failed to add spare pool %d to %s", new_pool,
+		    mpt_volume_name(VolumeBus, VolumeID));
+		return (-1);
+	}
+	free(info);
+
+	*pool = (1 << new_pool);
+	return (0);
+}
+
+static int
+add_spare(int ac, char **av)
+{
+	CONFIG_PAGE_RAID_PHYS_DISK_0 *info;
+	struct mpt_standalone_disk *sdisks;
+	struct mpt_drive_list *list;
+	U8 PhysDiskNum;
+	int error, fd, i, nsdisks, pool;
+
+	if (ac < 2) {
+		warnx("add spare: drive required");
+		return (EINVAL);
+	}
+	if (ac > 3) {
+		warnx("add spare: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	if (ac == 3) {
+		if (find_volume_spare_pool(fd, av[2], &pool) < 0)
+			return (errno);
+	} else
+		pool = MPI_RAID_HOT_SPARE_POOL_0;
+
+	list = mpt_pd_list(fd);
+	if (list == NULL)
+		return (errno);
+
+	error = mpt_lookup_drive(list, av[1], &PhysDiskNum);
+	if (error) {
+		error = mpt_fetch_disks(fd, &nsdisks, &sdisks);
+		if (error != 0) {
+			warn("Failed to fetch standalone disk list");
+			return (error);
+		}
+
+		if (mpt_lookup_standalone_disk(av[1], sdisks, nsdisks, &i) <
+		    0) {
+			warn("Unable to lookup drive %s", av[1]);
+			return (errno);
+		}
+
+		if (mpt_lock_physdisk(&sdisks[i]) < 0)
+			return (errno);
+
+		if (mpt_create_physdisk(fd, &sdisks[i], &PhysDiskNum) < 0) {
+			warn("Failed to create physical disk page");
+			return (errno);
+		}
+		free(sdisks);
+	}
+	mpt_free_pd_list(list);
+
+	info = mpt_pd_info(fd, PhysDiskNum, NULL);
+	if (info == NULL) {
+		warn("Failed to fetch drive info");
+		return (errno);
+	}
+
+	info->PhysDiskSettings.HotSparePool = pool;
+	error = mpt_raid_action(fd, MPI_RAID_ACTION_CHANGE_PHYSDISK_SETTINGS, 0,
+	    0, PhysDiskNum, *(U32 *)&info->PhysDiskSettings, NULL, 0, NULL,
+	    NULL, 0, NULL, NULL, 0);
+	if (error) {
+		warn("Failed to assign spare");
+		return (errno);
+	}
+
+	free(info);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(top, add, add_spare);
+
+static int
+remove_spare(int ac, char **av)
+{
+	CONFIG_PAGE_RAID_PHYS_DISK_0 *info;
+	struct mpt_drive_list *list;
+	U8 PhysDiskNum;
+	int error, fd;
+
+	if (ac != 2) {
+		warnx("remove spare: drive required");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	list = mpt_pd_list(fd);
+	if (list == NULL)
+		return (errno);
+
+	error = mpt_lookup_drive(list, av[1], &PhysDiskNum);
+	if (error) {
+		warn("Failed to find drive %s", av[1]);
+		return (error);
+	}
+	mpt_free_pd_list(list);
+
+	
+	info = mpt_pd_info(fd, PhysDiskNum, NULL);
+	if (info == NULL) {
+		warn("Failed to fetch drive info");
+		return (errno);
+	}
+
+	if (info->PhysDiskSettings.HotSparePool == 0) {
+		warnx("Drive %u is not a hot spare", PhysDiskNum);
+		return (EINVAL);
+	}
+
+	if (mpt_delete_physdisk(fd, PhysDiskNum) < 0) {
+		warn("Failed to delete physical disk page");
+		return (errno);
+	}
+
+	mpt_rescan_bus(info->PhysDiskBus, info->PhysDiskID);
+	free(info);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(top, remove, remove_spare);
+
+#ifdef DEBUG
+MPT_TABLE(top, pd);
+
+static int
+pd_create(int ac, char **av)
+{
+	struct mpt_standalone_disk *disks;
+	int error, fd, i, ndisks;
+	U8 PhysDiskNum;
+
+	if (ac != 2) {
+		warnx("pd create: drive required");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	error = mpt_fetch_disks(fd, &ndisks, &disks);
+	if (error != 0) {
+		warn("Failed to fetch standalone disk list");
+		return (error);
+	}
+
+	if (mpt_lookup_standalone_disk(av[1], disks, ndisks, &i) < 0) {
+		warn("Unable to lookup drive");
+		return (errno);
+	}
+
+	if (mpt_lock_physdisk(&disks[i]) < 0)
+		return (errno);
+
+	if (mpt_create_physdisk(fd, &disks[i], &PhysDiskNum) < 0) {
+		warn("Failed to create physical disk page");
+		return (errno);
+	}
+	free(disks);
+
+	printf("Added drive %s with PhysDiskNum %u\n", av[1], PhysDiskNum);
+
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(pd, create, pd_create);
+
+static int
+pd_delete(int ac, char **av)
+{
+	CONFIG_PAGE_RAID_PHYS_DISK_0 *info;
+	struct mpt_drive_list *list;
+	int fd;
+	U8 PhysDiskNum;
+
+	if (ac != 2) {
+		warnx("pd delete: drive required");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	list = mpt_pd_list(fd);
+	if (list == NULL)
+		return (errno);
+
+	if (mpt_lookup_drive(list, av[1], &PhysDiskNum) < 0) {
+		warn("Failed to find drive %s", av[1]);
+		return (errno);
+	}
+	mpt_free_pd_list(list);
+
+	info = mpt_pd_info(fd, PhysDiskNum, NULL);
+	if (info == NULL) {
+		warn("Failed to fetch drive info");
+		return (errno);
+	}
+
+	if (mpt_delete_physdisk(fd, PhysDiskNum) < 0) {
+		warn("Failed to delete physical disk page");
+		return (errno);
+	}
+
+	mpt_rescan_bus(info->PhysDiskBus, info->PhysDiskID);
+	free(info);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(pd, delete, pd_delete);
+
+/* Display raw data about a volume config. */
+static void
+dump_config(CONFIG_PAGE_RAID_VOL_0 *vol)
+{
+	int i;
+
+	printf("Volume Configuration (Debug):\n");
+	printf(
+   " Page Header: Type 0x%02x Number 0x%02x Length 0x%02x(%u) Version 0x%02x\n",
+	    vol->Header.PageType, vol->Header.PageNumber,
+	    vol->Header.PageLength, vol->Header.PageLength * 4,
+	    vol->Header.PageVersion);
+	printf("     Address: %d:%d IOC %d\n", vol->VolumeBus, vol->VolumeID,
+	    vol->VolumeIOC);
+	printf("        Type: %d (%s)\n", vol->VolumeType,
+	    mpt_raid_level(vol->VolumeType));
+	printf("      Status: %s (Flags 0x%02x)\n",
+	    mpt_volstate(vol->VolumeStatus.State), vol->VolumeStatus.Flags);
+	printf("    Settings: 0x%04x (Spare Pools 0x%02x)\n",
+	    vol->VolumeSettings.Settings, vol->VolumeSettings.HotSparePool);
+	printf("      MaxLBA: %ju\n", (uintmax_t)vol->MaxLBAHigh << 32 |
+	    vol->MaxLBA);
+	printf(" Stripe Size: %ld\n", (long)vol->StripeSize * 512);
+	printf(" %d Disks:\n", vol->NumPhysDisks);
+
+	for (i = 0; i < vol->NumPhysDisks; i++)
+		printf("    Disk %d: Num 0x%02x Map 0x%02x\n", i,
+		    vol->PhysDisk[i].PhysDiskNum, vol->PhysDisk[i].PhysDiskMap);
+}
+
+static int
+debug_config(int ac, char **av)
+{
+	CONFIG_PAGE_RAID_VOL_0 *vol;
+	U8 VolumeBus, VolumeID;
+	int fd;
+
+	if (ac != 2) {
+		warnx("debug: volume required");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	if (mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID) < 0) {
+		warn("Invalid volume: %s", av[1]);
+		return (errno);
+	}
+
+	vol = mpt_vol_info(fd, VolumeBus, VolumeID, NULL);
+	if (vol == NULL) {
+		warn("Failed to get volume info");
+		return (errno);
+	}
+
+	dump_config(vol);
+	free(vol);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(top, debug, debug_config);
+#endif
diff --git a/usr.sbin/mptutil/mpt_drive.c b/usr.sbin/mptutil/mpt_drive.c
new file mode 100644
index 00000000000..e941b967e5b
--- /dev/null
+++ b/usr.sbin/mptutil/mpt_drive.c
@@ -0,0 +1,395 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin 
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include 
+__RCSID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "mptutil.h"
+
+const char *
+mpt_pdstate(CONFIG_PAGE_RAID_PHYS_DISK_0 *info)
+{
+	static char buf[16];
+
+	switch (info->PhysDiskStatus.State) {
+	case MPI_PHYSDISK0_STATUS_ONLINE:
+		if ((info->PhysDiskStatus.Flags &
+		    MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC) &&
+		    info->PhysDiskSettings.HotSparePool == 0)
+			return ("REBUILD");
+		else
+			return ("ONLINE");
+	case MPI_PHYSDISK0_STATUS_MISSING:
+		return ("MISSING");
+	case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE:
+		return ("NOT COMPATIBLE");
+	case MPI_PHYSDISK0_STATUS_FAILED:
+		return ("FAILED");
+	case MPI_PHYSDISK0_STATUS_INITIALIZING:
+		return ("INITIALIZING");
+	case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED:
+		return ("OFFLINE REQUESTED");
+	case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED:
+		return ("FAILED REQUESTED");
+	case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE:
+		return ("OTHER OFFLINE");
+	default:
+		sprintf(buf, "PSTATE 0x%02x", info->PhysDiskStatus.State);
+		return (buf);
+	}
+}
+
+/*
+ * There are several ways to enumerate physical disks.  Unfortunately,
+ * none of them are truly complete, so we have to build a union of all of
+ * them.  Specifically:
+ * 
+ * - IOC2 : This gives us a list of volumes, and by walking the volumes we
+ *          can enumerate all of the drives attached to volumes including
+ *          online drives and failed drives.
+ * - IOC3 : This gives us a list of all online physical drives including
+ *          drives that are not part of a volume nor a spare drive.  It
+ *          does not include any failed drives.
+ * - IOC5 : This gives us a list of all spare drives including failed
+ *          spares.
+ *
+ * The specific edge cases are that 1) a failed volume member can only be
+ * found via IOC2, 2) a drive that is neither a volume member nor a spare
+ * can only be found via IOC3, and 3) a failed spare can only be found via
+ * IOC5.
+ *
+ * To handle this, walk all of the three lists and use the following
+ * routine to add each drive encountered.  It quietly succeeds if the
+ * drive is already present in the list.  It also sorts the list as it
+ * inserts new drives.
+ */
+static int
+mpt_pd_insert(int fd, struct mpt_drive_list *list, U8 PhysDiskNum)
+{
+	int i, j;
+
+	/*
+	 * First, do a simple linear search to see if we have already
+	 * seen this drive.
+	 */
+	for (i = 0; i < list->ndrives; i++) {
+		if (list->drives[i]->PhysDiskNum == PhysDiskNum)
+			return (0);
+		if (list->drives[i]->PhysDiskNum > PhysDiskNum)
+			break;
+	}
+
+	/*
+	 * 'i' is our slot for the 'new' drive.  Make room and then
+	 * read the drive info.
+	 */
+	for (j = list->ndrives - 1; j >= i; j--)
+		list->drives[j + 1] = list->drives[j];
+	list->drives[i] = mpt_pd_info(fd, PhysDiskNum, NULL);
+	if (list->drives[i] == NULL)
+		return (-1);
+	list->ndrives++;
+	return (0);
+}
+
+struct mpt_drive_list *
+mpt_pd_list(int fd)
+{
+	CONFIG_PAGE_IOC_2 *ioc2;
+	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
+	CONFIG_PAGE_RAID_VOL_0 **volumes;
+	RAID_VOL0_PHYS_DISK *rdisk;
+	CONFIG_PAGE_IOC_3 *ioc3;
+	IOC_3_PHYS_DISK *disk;
+	CONFIG_PAGE_IOC_5 *ioc5;
+	IOC_5_HOT_SPARE *spare;
+	struct mpt_drive_list *list;
+	int count, i, j;
+
+	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
+	if (ioc2 == NULL) {
+		warn("Failed to fetch volume list");
+		return (NULL);
+	}
+
+	ioc3 = mpt_read_ioc_page(fd, 3, NULL);
+	if (ioc3 == NULL) {
+		warn("Failed to fetch drive list");
+		free(ioc2);
+		return (NULL);
+	}
+
+	ioc5 = mpt_read_ioc_page(fd, 5, NULL);
+	if (ioc5 == NULL) {
+		warn("Failed to fetch spare list");
+		free(ioc3);
+		free(ioc2);
+		return (NULL);
+	}
+
+	/*
+	 * Go ahead and read the info for all the volumes.  For this
+	 * pass we figure out how many physical drives there are.
+	 */
+	volumes = malloc(sizeof(*volumes) * ioc2->NumActiveVolumes);
+	count = 0;
+	vol = ioc2->RaidVolume;
+	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
+		volumes[i] = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID,
+		    NULL);
+		if (volumes[i] == NULL) {
+			warn("Failed to read volume info");
+			return (NULL);
+		}
+		count += volumes[i]->NumPhysDisks;
+	}
+	count += ioc3->NumPhysDisks;
+	count += ioc5->NumHotSpares;
+
+	/* Walk the various lists enumerating drives. */
+	list = malloc(sizeof(*list) + sizeof(CONFIG_PAGE_RAID_PHYS_DISK_0) *
+	    count);
+	list->ndrives = 0;
+
+	for (i = 0; i < ioc2->NumActiveVolumes; i++) {
+		rdisk = volumes[i]->PhysDisk;
+		for (j = 0; j < volumes[i]->NumPhysDisks; rdisk++, j++)
+			if (mpt_pd_insert(fd, list, rdisk->PhysDiskNum) < 0)
+				return (NULL);
+		free(volumes[i]);
+	}
+	free(ioc2);
+	free(volumes);
+
+	spare = ioc5->HotSpare;
+	for (i = 0; i < ioc5->NumHotSpares; spare++, i++)
+		if (mpt_pd_insert(fd, list, spare->PhysDiskNum) < 0)
+			return (NULL);
+	free(ioc5);
+
+	disk = ioc3->PhysDisk;
+	for (i = 0; i < ioc3->NumPhysDisks; disk++, i++)
+		if (mpt_pd_insert(fd, list, disk->PhysDiskNum) < 0)
+			return (NULL);
+	free(ioc3);
+
+	return (list);
+}
+
+void
+mpt_free_pd_list(struct mpt_drive_list *list)
+{
+	int i;
+
+	for (i = 0; i < list->ndrives; i++)
+		free(list->drives[i]);
+	free(list);
+}
+
+int
+mpt_lookup_drive(struct mpt_drive_list *list, const char *drive,
+    U8 *PhysDiskNum)
+{
+	long val;
+	uint8_t bus, id;
+	char *cp;
+
+	/* Look for a raw device id first. */
+	val = strtol(drive, &cp, 0);
+	if (*cp == '\0') {
+		if (val < 0 || val > 0xff)
+			goto bad;
+		*PhysDiskNum = val;
+		return (0);
+	}
+
+	/* Look for a : string. */
+	if (*cp == ':') {
+		if (val < 0 || val > 0xff)
+			goto bad;
+		bus = val;
+		val = strtol(cp + 1, &cp, 0);
+		if (*cp != '\0')
+			goto bad;
+		if (val < 0 || val > 0xff)
+			goto bad;
+		id = val;
+
+		for (val = 0; val < list->ndrives; val++) {
+			if (list->drives[val]->PhysDiskBus == bus &&
+			    list->drives[val]->PhysDiskID == id) {
+				*PhysDiskNum = list->drives[val]->PhysDiskNum;
+				return (0);
+			}
+		}
+		errno = ENOENT;
+		return (-1);
+	}
+
+bad:
+	errno = EINVAL;
+	return (-1);
+}
+
+/* Borrowed heavily from scsi_all.c:scsi_print_inquiry(). */
+const char *
+mpt_pd_inq_string(CONFIG_PAGE_RAID_PHYS_DISK_0 *pd_info)
+{
+	RAID_PHYS_DISK0_INQUIRY_DATA *inq_data;
+	u_char vendor[9], product[17], revision[5];
+	static char inq_string[64];
+
+	inq_data = &pd_info->InquiryData;
+	cam_strvis(vendor, inq_data->VendorID, sizeof(inq_data->VendorID),
+	    sizeof(vendor));
+	cam_strvis(product, inq_data->ProductID, sizeof(inq_data->ProductID),
+	    sizeof(product));
+	cam_strvis(revision, inq_data->ProductRevLevel,
+	    sizeof(inq_data->ProductRevLevel), sizeof(revision));
+
+	/* Total hack. */
+	if (strcmp(vendor, "ATA") == 0)
+		snprintf(inq_string, sizeof(inq_string), "<%s %s> SATA",
+		    product, revision);
+	else
+		snprintf(inq_string, sizeof(inq_string), "<%s %s %s> SAS",
+		    vendor, product, revision);
+	return (inq_string);
+}
+
+/* Helper function to set a drive to a given state. */
+static int
+drive_set_state(char *drive, U8 Action, U8 State, const char *name)
+{
+	CONFIG_PAGE_RAID_PHYS_DISK_0 *info;
+	struct mpt_drive_list *list;
+	U8 PhysDiskNum;
+	int fd;
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	list = mpt_pd_list(fd);
+	if (list == NULL)
+		return (errno);
+
+	if (mpt_lookup_drive(list, drive, &PhysDiskNum) < 0) {
+		warn("Failed to find drive %s", drive);
+		return (errno);
+	}
+	mpt_free_pd_list(list);
+
+	/* Get the info for this drive. */
+	info = mpt_pd_info(fd, PhysDiskNum, NULL);
+	if (info == NULL) {
+		warn("Failed to fetch info for drive %u", PhysDiskNum);
+		return (errno);
+	}
+
+	/* Try to change the state. */
+	if (info->PhysDiskStatus.State == State) {
+		warnx("Drive %u is already in the desired state", PhysDiskNum);
+		return (EINVAL);
+	}
+
+	if (mpt_raid_action(fd, Action, 0, 0, PhysDiskNum, 0, NULL, 0, NULL,
+	    NULL, 0, NULL, NULL, 0) < 0) {
+		warn("Failed to set drive %u to %s", PhysDiskNum, name);
+		return (errno);
+	}
+
+	free(info);
+	close(fd);
+
+	return (0);
+}
+
+static int
+fail_drive(int ac, char **av)
+{
+
+	if (ac != 2) {
+		warnx("fail: %s", ac > 2 ? "extra arguments" :
+		    "drive required");
+		return (EINVAL);
+	}
+
+	return (drive_set_state(av[1], MPI_RAID_ACTION_FAIL_PHYSDISK,
+	    MPI_PHYSDISK0_STATUS_FAILED_REQUESTED, "FAILED"));
+}
+MPT_COMMAND(top, fail, fail_drive);
+
+static int
+online_drive(int ac, char **av)
+{
+
+	if (ac != 2) {
+		warnx("online: %s", ac > 2 ? "extra arguments" :
+		    "drive required");
+		return (EINVAL);
+	}
+
+	return (drive_set_state(av[1], MPI_RAID_ACTION_PHYSDISK_ONLINE,
+	    MPI_PHYSDISK0_STATUS_ONLINE, "ONLINE"));
+}
+MPT_COMMAND(top, online, online_drive);
+
+static int
+offline_drive(int ac, char **av)
+{
+
+	if (ac != 2) {
+		warnx("offline: %s", ac > 2 ? "extra arguments" :
+		    "drive required");
+		return (EINVAL);
+	}
+
+	return (drive_set_state(av[1], MPI_RAID_ACTION_PHYSDISK_OFFLINE,
+	    MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED, "OFFLINE"));
+}
+MPT_COMMAND(top, offline, offline_drive);
diff --git a/usr.sbin/mptutil/mpt_evt.c b/usr.sbin/mptutil/mpt_evt.c
new file mode 100644
index 00000000000..4b64352e42d
--- /dev/null
+++ b/usr.sbin/mptutil/mpt_evt.c
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin 
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include 
+__RCSID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mptutil.h"
+
+static CONFIG_PAGE_LOG_0 *
+mpt_get_events(int fd, U16 *IOCStatus)
+{
+
+	return (mpt_read_extended_config_page(fd, MPI_CONFIG_EXTPAGETYPE_LOG,
+	    0, 0, 0, IOCStatus));
+}
+
+/*
+ *          1         2         3         4         5         6         7
+ * 1234567890123456789012345678901234567890123456789012345678901234567890
+ * < ID> < time >  LogSequence, entry->TimeStamp,
+	    entry->LogEntryQualifier);
+	for (i = 0; i < 14; i++)
+		printf("%02x ", entry->LogData[i]);
+	printf("|");
+	for (i = 0; i < 14; i++)
+		printf("%c", isprint(entry->LogData[i]) ? entry->LogData[i] :
+		    '.');
+	printf("|\n");
+	printf("                    ");
+	for (i = 0; i < 14; i++)
+		printf("%02x ", entry->LogData[i + 14]);
+	printf("|");
+	for (i = 0; i < 14; i++)
+		printf("%c", isprint(entry->LogData[i + 14]) ?
+		    entry->LogData[i + 14] : '.');
+	printf("|\n");
+}
+
+static int
+event_compare(const void *first, const void *second)
+{
+	MPI_LOG_0_ENTRY * const *one;
+	MPI_LOG_0_ENTRY * const *two;
+
+	one = first;
+	two = second;
+	return ((*one)->LogSequence - ((*two)->LogSequence));
+}
+
+static int
+show_events(int ac, char **av)
+{
+	CONFIG_PAGE_LOG_0 *log;
+	MPI_LOG_0_ENTRY **entries;
+	int ch, fd, i, num_events, verbose;
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	log = mpt_get_events(fd, NULL);
+	if (log == NULL) {
+		warn("Failed to get event log info");
+		return (errno);
+	}
+
+	/* Default settings. */
+	verbose = 0;
+
+	/* Parse any options. */
+	optind = 1;
+	while ((ch = getopt(ac, av, "v")) != -1) {
+		switch (ch) {
+		case 'v':
+			verbose = 1;
+			break;
+		case '?':
+		default:
+			return (EINVAL);
+		}
+	}
+	ac -= optind;
+	av += optind;
+
+	/* Build a list of valid entries and sort them by sequence. */
+	entries = malloc(sizeof(MPI_LOG_0_ENTRY *) * log->NumLogEntries);
+	num_events = 0;
+	for (i = 0; i < log->NumLogEntries; i++) {
+		if (log->LogEntry[i].LogEntryQualifier ==
+		    MPI_LOG_0_ENTRY_QUAL_ENTRY_UNUSED)
+			continue;
+		entries[num_events] = &log->LogEntry[i];
+		num_events++;
+	}
+
+	qsort(entries, num_events, sizeof(MPI_LOG_0_ENTRY *), event_compare);
+
+	if (num_events == 0)
+		printf("Event log is empty\n");
+	else {
+		printf(" ID     Time   Type Log Data\n");
+		for (i = 0; i < num_events; i++)
+			mpt_print_event(entries[i], verbose);
+	}
+	
+	free(entries);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(show, events, show_events);
diff --git a/usr.sbin/mptutil/mpt_show.c b/usr.sbin/mptutil/mpt_show.c
new file mode 100644
index 00000000000..e0b6b74d136
--- /dev/null
+++ b/usr.sbin/mptutil/mpt_show.c
@@ -0,0 +1,559 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin 
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include 
+__RCSID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mptutil.h"
+
+MPT_TABLE(top, show);
+
+#define	STANDALONE_STATE	"ONLINE"
+
+static void
+format_stripe(char *buf, size_t buflen, U32 stripe)
+{
+
+	humanize_number(buf, buflen, stripe * 512, "", HN_AUTOSCALE,
+	    HN_B | HN_NOSPACE);
+}
+
+static void
+display_stripe_map(const char *label, U32 StripeMap)
+{
+	char stripe[5];
+	int comma, i;
+
+	comma = 0;
+	printf("%s: ", label);
+	for (i = 0; StripeMap != 0; i++, StripeMap >>= 1)
+		if (StripeMap & 1) {
+			format_stripe(stripe, sizeof(stripe), 1 << i);
+			if (comma)
+				printf(", ");
+			printf("%s", stripe);
+			comma = 1;
+		}
+	printf("\n");
+}
+
+static int
+show_adapter(int ac, char **av)
+{
+	CONFIG_PAGE_MANUFACTURING_0 *man0;
+	CONFIG_PAGE_IOC_2 *ioc2;
+	CONFIG_PAGE_IOC_6 *ioc6;
+	int fd, comma;
+
+	if (ac != 1) {
+		warnx("show adapter: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	man0 = mpt_read_man_page(fd, 0, NULL);
+	if (man0 == NULL) {
+		warn("Failed to get controller info");
+		return (errno);
+	}
+	if (man0->Header.PageLength < sizeof(*man0) / 4) {
+		warn("Invalid controller info");
+		return (EINVAL);
+	}
+	printf("mpt%d Adapter:\n", mpt_unit);
+	printf("       Board Name: %.16s\n", man0->BoardName);
+	printf("   Board Assembly: %.16s\n", man0->BoardAssembly);
+	printf("        Chip Name: %.16s\n", man0->ChipName);
+	printf("    Chip Revision: %.16s\n", man0->ChipRevision);
+
+	free(man0);
+
+	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
+	if (ioc2 != NULL) {
+		printf("      RAID Levels:");
+		comma = 0;
+		if (ioc2->CapabilitiesFlags &
+		    MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT) {
+			printf(" RAID0");
+			comma = 1;
+		}
+		if (ioc2->CapabilitiesFlags &
+		    MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT) {
+			printf("%s RAID1", comma ? "," : "");
+			comma = 1;
+		}
+		if (ioc2->CapabilitiesFlags &
+		    MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT) {
+			printf("%s RAID1E", comma ? "," : "");
+			comma = 1;
+		}
+		if (ioc2->CapabilitiesFlags &
+		    MPI_IOCPAGE2_CAP_FLAGS_RAID_5_SUPPORT) {
+			printf("%s RAID5", comma ? "," : "");
+			comma = 1;
+		}
+		if (ioc2->CapabilitiesFlags &
+		    MPI_IOCPAGE2_CAP_FLAGS_RAID_6_SUPPORT) {
+			printf("%s RAID6", comma ? "," : "");
+			comma = 1;
+		}
+		if (ioc2->CapabilitiesFlags &
+		    MPI_IOCPAGE2_CAP_FLAGS_RAID_10_SUPPORT) {
+			printf("%s RAID10", comma ? "," : "");
+			comma = 1;
+		}
+		if (ioc2->CapabilitiesFlags &
+		    MPI_IOCPAGE2_CAP_FLAGS_RAID_50_SUPPORT) {
+			printf("%s RAID50", comma ? "," : "");
+			comma = 1;
+		}
+		if (!comma)
+			printf(" none");
+		printf("\n");
+		free(ioc2);
+	}
+
+	ioc6 = mpt_read_ioc_page(fd, 6, NULL);
+	if (ioc6 != NULL) {
+		display_stripe_map("    RAID0 Stripes",
+		    ioc6->SupportedStripeSizeMapIS);
+		display_stripe_map("   RAID1E Stripes",
+		    ioc6->SupportedStripeSizeMapIME);
+		printf(" RAID0 Drives/Vol: %u", ioc6->MinDrivesIS);
+		if (ioc6->MinDrivesIS != ioc6->MaxDrivesIS)
+			printf("-%u", ioc6->MaxDrivesIS);
+		printf("\n");
+		printf(" RAID1 Drives/Vol: %u", ioc6->MinDrivesIM);
+		if (ioc6->MinDrivesIM != ioc6->MaxDrivesIM)
+			printf("-%u", ioc6->MaxDrivesIM);
+		printf("\n");
+		printf("RAID1E Drives/Vol: %u", ioc6->MinDrivesIME);
+		if (ioc6->MinDrivesIME != ioc6->MaxDrivesIME)
+			printf("-%u", ioc6->MaxDrivesIME);
+		printf("\n");
+		free(ioc6);
+	}
+
+	/* TODO: Add an ioctl to fetch IOC_FACTS and print firmware version. */
+
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(show, adapter, show_adapter);
+
+static void
+print_vol(CONFIG_PAGE_RAID_VOL_0 *info, int state_len)
+{
+	uint64_t size;
+	const char *level, *state;
+	char buf[6], stripe[5];
+
+	size = ((uint64_t)info->MaxLBAHigh << 32) | info->MaxLBA;
+	humanize_number(buf, sizeof(buf), (size + 1) * 512, "", HN_AUTOSCALE,
+	    HN_B | HN_NOSPACE | HN_DECIMAL);
+	if (info->VolumeType == MPI_RAID_VOL_TYPE_IM)
+		stripe[0] = '\0';
+	else
+		format_stripe(stripe, sizeof(stripe), info->StripeSize);
+	level = mpt_raid_level(info->VolumeType);
+	state = mpt_volstate(info->VolumeStatus.State);
+	if (state_len > 0)
+		printf("(%6s) %-8s %6s %-*s", buf, level, stripe, state_len,
+		    state);
+	else if (stripe[0] != '\0')
+		printf("(%s) %s %s %s", buf, level, stripe, state);
+	else
+		printf("(%s) %s %s", buf, level, state);
+}
+
+static void
+print_pd(CONFIG_PAGE_RAID_PHYS_DISK_0 *info, int state_len, int location)
+{
+	const char *inq, *state;
+	char buf[6];
+
+	humanize_number(buf, sizeof(buf), ((uint64_t)info->MaxLBA + 1) * 512,
+	    "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL);
+	state = mpt_pdstate(info);
+	if (state_len > 0)
+		printf("(%6s) %-*s", buf, state_len, state);
+	else
+		printf("(%s) %s", buf, state);
+	inq = mpt_pd_inq_string(info);
+	if (inq != NULL)
+		printf(" %s", inq);
+	if (!location)
+		return;
+	printf(" bus %d id %d", info->PhysDiskBus, info->PhysDiskID);
+}
+
+static void
+print_standalone(struct mpt_standalone_disk *disk, int state_len, int location)
+{
+	char buf[6];
+
+	humanize_number(buf, sizeof(buf), (disk->maxlba + 1) * 512,
+	    "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL);
+	if (state_len > 0)
+		printf("(%6s) %-*s", buf, state_len, STANDALONE_STATE);
+	else
+		printf("(%s) %s", buf, STANDALONE_STATE);
+	if (disk->inqstring[0] != '\0')
+		printf(" %s", disk->inqstring);
+	if (!location)
+		return;
+	printf(" bus %d id %d", disk->bus, disk->target);
+}
+
+static void
+print_spare_pools(U8 HotSparePool)
+{
+	int i;
+
+	if (HotSparePool == 0) {
+		printf("none");
+		return;
+	}
+	for (i = 0; HotSparePool != 0; i++) {
+		if (HotSparePool & 1) {
+			printf("%d", i);
+			if (HotSparePool == 1)
+				break;
+			printf(", ");
+		}
+		HotSparePool >>= 1;
+	}
+}
+
+static int
+show_config(int ac, char **av)
+{
+	CONFIG_PAGE_IOC_2 *ioc2;
+	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
+	CONFIG_PAGE_IOC_5 *ioc5;
+	IOC_5_HOT_SPARE *spare;
+	CONFIG_PAGE_RAID_VOL_0 *vinfo;
+	RAID_VOL0_PHYS_DISK *disk;
+	CONFIG_PAGE_RAID_VOL_1 *vnames;
+	CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo;
+	struct mpt_standalone_disk *sdisks;
+	int fd, i, j, nsdisks;
+
+	if (ac != 1) {
+		warnx("show config: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	/* Get the config from the controller. */
+	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
+	ioc5 = mpt_read_ioc_page(fd, 5, NULL);
+	if (ioc2 == NULL || ioc5 == NULL) {
+		warn("Failed to get config");
+		return (errno);
+	}
+	if (mpt_fetch_disks(fd, &nsdisks, &sdisks) < 0) {
+		warn("Failed to get standalone drive list");
+		return (errno);
+	}
+
+	/* Dump out the configuration. */
+	printf("mpt%d Configuration: %d volumes, %d drives\n",
+	    mpt_unit, ioc2->NumActiveVolumes, ioc2->NumActivePhysDisks +
+	    nsdisks);
+	vol = ioc2->RaidVolume;
+	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
+		printf("    volume %s ", mpt_volume_name(vol->VolumeBus,
+		    vol->VolumeID));
+		vinfo = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, NULL);
+		if (vinfo == NULL) {
+			printf("%s UNKNOWN", mpt_raid_level(vol->VolumeType));
+		} else
+			print_vol(vinfo, -1);
+		vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL);
+		if (vnames != NULL) {
+			if (vnames->Name[0] != '\0')
+				printf(" <%s>", vnames->Name);
+			free(vnames);
+		}
+		if (vinfo == NULL) {
+			printf("\n");
+			continue;
+		}
+		printf(" spans:\n");
+		disk = vinfo->PhysDisk;
+		for (j = 0; j < vinfo->NumPhysDisks; disk++, j++) {
+			printf("        drive %u ", disk->PhysDiskNum);
+			pinfo = mpt_pd_info(fd, disk->PhysDiskNum, NULL);
+			if (pinfo != NULL) {
+				print_pd(pinfo, -1, 0);
+				free(pinfo);
+			}
+			printf("\n");
+		}
+		if (vinfo->VolumeSettings.HotSparePool != 0) {
+			printf("        spare pools: ");
+			print_spare_pools(vinfo->VolumeSettings.HotSparePool);
+			printf("\n");
+		}
+		free(vinfo);
+	}
+
+	spare = ioc5->HotSpare;
+	for (i = 0; i < ioc5->NumHotSpares; spare++, i++) {
+		printf("    spare %u ", spare->PhysDiskNum);
+		pinfo = mpt_pd_info(fd, spare->PhysDiskNum, NULL);
+		if (pinfo != NULL) {
+			print_pd(pinfo, -1, 0);
+			free(pinfo);
+		}
+		printf(" backs pool %d\n", ffs(spare->HotSparePool) - 1);
+	}
+	for (i = 0; i < nsdisks; i++) {
+		printf("    drive %s ", sdisks[i].devname);
+		print_standalone(&sdisks[i], -1, 0);
+		printf("\n");
+	}
+	free(ioc2);
+	free(ioc5);
+	free(sdisks);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(show, config, show_config);
+
+static int
+show_volumes(int ac, char **av)
+{
+	CONFIG_PAGE_IOC_2 *ioc2;
+	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
+	CONFIG_PAGE_RAID_VOL_0 **volumes;
+	CONFIG_PAGE_RAID_VOL_1 *vnames;
+	int fd, i, len, state_len;
+
+	if (ac != 1) {
+		warnx("show volumes: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	/* Get the volume list from the controller. */
+	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
+	if (ioc2 == NULL) {
+		warn("Failed to get volume list");
+		return (errno);
+	}
+
+	/*
+	 * Go ahead and read the info for all the volumes and figure
+	 * out the maximum width of the state field.
+	 */
+	volumes = malloc(sizeof(*volumes) * ioc2->NumActiveVolumes);
+	state_len = strlen("State");
+	vol = ioc2->RaidVolume;
+	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
+		volumes[i] = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID,
+		    NULL);
+		if (volumes[i] == NULL)
+			len = strlen("UNKNOWN");
+		else
+			len = strlen(mpt_volstate(
+			    volumes[i]->VolumeStatus.State));
+		if (len > state_len)
+			state_len = len;
+	}
+	printf("mpt%d Volumes:\n", mpt_unit);
+	printf("  Id     Size    Level   Stripe ");
+	len = state_len - strlen("State");
+	for (i = 0; i < (len + 1) / 2; i++)
+		printf(" ");
+	printf("State");
+	for (i = 0; i < len / 2; i++)
+		printf(" ");
+	printf(" Write-Cache  Name\n");
+	vol = ioc2->RaidVolume;
+	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
+		printf("%6s ", mpt_volume_name(vol->VolumeBus, vol->VolumeID));
+		if (volumes[i] != NULL)
+			print_vol(volumes[i], state_len);
+		else
+			printf("         %-8s %-*s",
+			    mpt_raid_level(vol->VolumeType), state_len,
+			    "UNKNOWN");
+		if (volumes[i] != NULL) {
+			if (volumes[i]->VolumeSettings.Settings &
+			    MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE)
+				printf("   Enabled   ");
+			else
+				printf("   Disabled  ");
+		} else
+			printf("             ");
+		free(volumes[i]);
+		vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL);
+		if (vnames != NULL) {
+			if (vnames->Name[0] != '\0')
+				printf(" <%s>", vnames->Name);
+			free(vnames);
+		}
+		printf("\n");
+	}
+	free(ioc2);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(show, volumes, show_volumes);
+
+static int
+show_drives(int ac, char **av)
+{
+	struct mpt_drive_list *list;
+	struct mpt_standalone_disk *sdisks;
+	int fd, i, len, nsdisks, state_len;
+
+	if (ac != 1) {
+		warnx("show drives: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	/* Get the drive list. */
+	list = mpt_pd_list(fd);
+	if (list == NULL) {
+		warn("Failed to get drive list");
+		return (errno);
+	}
+
+	/* Fetch the list of standalone disks for this controller. */
+	state_len = 0;
+	if (mpt_fetch_disks(fd, &nsdisks, &sdisks) != 0) {
+		nsdisks = 0;
+		sdisks = NULL;
+	}
+	if (nsdisks != 0)
+		state_len = strlen(STANDALONE_STATE);
+
+	/* Walk the drive list to determine width of state column. */
+	for (i = 0; i < list->ndrives; i++) {
+		len = strlen(mpt_pdstate(list->drives[i]));
+		if (len > state_len)
+			state_len = len;
+	}
+
+	/* List the drives. */
+	printf("mpt%d Physical Drives:\n", mpt_unit);
+	for (i = 0; i < list->ndrives; i++) {
+		printf("%4u ", list->drives[i]->PhysDiskNum);
+		print_pd(list->drives[i], state_len, 1);
+		printf("\n");
+	}
+	mpt_free_pd_list(list);
+	for (i = 0; i < nsdisks; i++) {
+		printf("%4s ", sdisks[i].devname);
+		print_standalone(&sdisks[i], state_len, 1);
+		printf("\n");
+	}
+	free(sdisks);
+
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(show, drives, show_drives);
+
+#ifdef DEBUG
+static int
+show_physdisks(int ac, char **av)
+{
+	CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo;
+	U16 IOCStatus;
+	int fd, i;
+
+	if (ac != 1) {
+		warnx("show drives: extra arguments");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	/* Try to find each possible phys disk page. */
+	for (i = 0; i <= 0xff; i++) {
+		pinfo = mpt_pd_info(fd, i, &IOCStatus);
+		if (pinfo == NULL) {
+			if (IOCStatus != MPI_IOCSTATUS_CONFIG_INVALID_PAGE)
+				warnx("mpt_pd_info(%d): %s", i,
+				    mpt_ioc_status(IOCStatus));
+			continue;
+		}
+		printf("%3u ", i);
+		print_pd(pinfo, -1, 1);
+		printf("\n");
+	}
+
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(show, pd, show_physdisks);
+#endif
diff --git a/usr.sbin/mptutil/mpt_volume.c b/usr.sbin/mptutil/mpt_volume.c
new file mode 100644
index 00000000000..04adcb7c987
--- /dev/null
+++ b/usr.sbin/mptutil/mpt_volume.c
@@ -0,0 +1,248 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin 
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include 
+__RCSID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mptutil.h"
+
+MPT_TABLE(top, volume);
+
+const char *
+mpt_volstate(U8 State)
+{
+	static char buf[16];
+
+	switch (State) {
+	case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
+		return ("OPTIMAL");
+	case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
+		return ("DEGRADED");
+	case MPI_RAIDVOL0_STATUS_STATE_FAILED:
+		return ("FAILED");
+	case MPI_RAIDVOL0_STATUS_STATE_MISSING:
+		return ("MISSING");
+	default:
+		sprintf(buf, "VSTATE 0x%02x", State);
+		return (buf);
+	}
+}
+
+static int
+volume_name(int ac, char **av)
+{
+	CONFIG_PAGE_RAID_VOL_1 *vnames;
+	U8 VolumeBus, VolumeID;
+	int fd;
+
+	if (ac != 3) {
+		warnx("name: volume and name required");
+		return (EINVAL);
+	}
+
+	if (strlen(av[2]) >= sizeof(vnames->Name)) {
+		warnx("name: new name is too long");
+		return (ENOSPC);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	if (mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID) < 0) {
+		warn("Invalid volume: %s", av[1]);
+		return (errno);
+	}
+
+	vnames = mpt_vol_names(fd, VolumeBus, VolumeID, NULL);
+	if (vnames == NULL) {
+		warn("Failed to fetch volume names");
+		return (errno);
+	}
+
+	if (vnames->Header.PageType != MPI_CONFIG_PAGEATTR_CHANGEABLE) {
+		warnx("Volume name is read only");
+		return (EOPNOTSUPP);
+	}
+	printf("mpt%u changing volume %s name from \"%s\" to \"%s\"\n",
+	    mpt_unit, mpt_volume_name(VolumeBus, VolumeID), vnames->Name,
+	    av[2]);
+	bzero(vnames->Name, sizeof(vnames->Name));
+	strcpy(vnames->Name, av[2]);
+
+	if (mpt_write_config_page(fd, vnames, NULL) < 0) {
+		warn("Failed to set volume name");
+		return (errno);
+	}
+
+	free(vnames);
+	close(fd);
+
+	return (0);
+}
+MPT_COMMAND(top, name, volume_name);
+
+static int
+volume_status(int ac, char **av)
+{
+	MPI_RAID_VOL_INDICATOR prog;
+	RAID_VOL0_STATUS VolumeStatus;
+	uint64_t total, remaining;
+	float pct;
+	U8 VolumeBus, VolumeID;
+	int fd;
+
+	if (ac != 2) {
+		warnx("volume status: %s", ac > 2 ? "extra arguments" :
+		    "volume required");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	if (mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID) < 0) {
+		warn("Invalid volume: %s", av[1]);
+		return (errno);
+	}
+
+	if (mpt_raid_action(fd, MPI_RAID_ACTION_INDICATOR_STRUCT, VolumeBus,
+	    VolumeID, 0, 0, NULL, 0, &VolumeStatus, (U32 *)&prog, sizeof(prog),
+	    NULL, NULL, 0) < 0) {
+		warn("Fetching volume status failed");
+		return (errno);
+	}
+
+	printf("Volume %s status:\n", mpt_volume_name(VolumeBus, VolumeID));
+	printf("    state: %s\n", mpt_volstate(VolumeStatus.State));
+	printf("    flags:");
+	if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)
+		printf(" ENABLED");
+	else
+		printf(" DISABLED");
+	if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED)
+		printf(", QUIESCED");
+	if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)
+		printf(", REBUILDING");
+	if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)
+		printf(", INACTIVE");
+	if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL)
+		printf(", BAD BLOCK TABLE FULL");
+	printf("\n");
+	if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
+		total = (uint64_t)prog.TotalBlocks.High << 32 |
+		    prog.TotalBlocks.Low;
+		remaining = (uint64_t)prog.BlocksRemaining.High << 32 |
+		    prog.BlocksRemaining.Low;
+		pct = (float)(total - remaining) * 100 / total;
+		printf("   resync: %.2f%% complete\n", pct);
+	}
+
+	close(fd);
+	return (0);
+}
+MPT_COMMAND(volume, status, volume_status);
+
+static int
+volume_cache(int ac, char **av)
+{
+	CONFIG_PAGE_RAID_VOL_0 *volume;
+	U32 Settings, NewSettings;
+	U8 VolumeBus, VolumeID;
+	char *s1;
+	int fd;
+
+	if (ac != 3) {
+		warnx("volume cache: %s", ac > 3 ? "extra arguments" :
+		    "volume required");
+		return (EINVAL);
+	}
+
+        for (s1 = av[2]; *s1 != '\0'; s1++)
+                *s1 = tolower(*s1);
+	if ((strcmp(av[2], "enable")) && (strcmp(av[2], "enabled")) &&
+	    (strcmp(av[2], "disable")) && (strcmp(av[2], "disabled"))) {
+		warnx("volume cache: invalid flag, must be 'enable' or 'disable'\n");
+		return (EINVAL);
+	}
+
+	fd = mpt_open(mpt_unit);
+	if (fd < 0) {
+		warn("mpt_open");
+		return (errno);
+	}
+
+	if (mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID) < 0) {
+		warn("Invalid volume: %s", av[1]);
+		return (errno);
+	}
+
+	volume = mpt_vol_info(fd, VolumeBus, VolumeID, NULL);
+	if (volume == NULL)
+		return (-1);
+
+	Settings = volume->VolumeSettings.Settings;
+
+	NewSettings = Settings;
+	if (strncmp(av[2], "enable", sizeof("enable")) == 0)
+		NewSettings |= 0x01;
+	if (strncmp(av[2], "disable", sizeof("disable")) == 0)
+		NewSettings &= ~0x01;
+
+	if (NewSettings == Settings) {
+		warnx("volume cache unchanged\n");
+		close(fd);
+		return (0);
+	}
+
+	volume->VolumeSettings.Settings = NewSettings;
+	if (mpt_raid_action(fd, MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS,
+	    VolumeBus, VolumeID, 0, *(U32 *)&volume->VolumeSettings, NULL, 0,
+	    NULL, NULL, 0, NULL, NULL, 0) < 0)
+		warnx("volume cache change failed, errno= %d\n", errno);
+
+	close(fd);
+	return (0);
+}
+MPT_COMMAND(volume, cache, volume_cache);
diff --git a/usr.sbin/mptutil/mptutil.8 b/usr.sbin/mptutil/mptutil.8
new file mode 100644
index 00000000000..7acaf3e90d3
--- /dev/null
+++ b/usr.sbin/mptutil/mptutil.8
@@ -0,0 +1,386 @@
+.\"
+.\" Copyright (c) 2008 Yahoo!, Inc.
+.\" All rights reserved.
+.\" Written by: John Baldwin 
+.\"
+.\" 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.
+.\" 3. Neither the name of the author nor the names of any co-contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" 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$
+.\"
+.Dd August 16, 2009
+.Dt MPTUTIL 8
+.Os
+.Sh NAME
+.Nm mptutil
+.Nd Utility for managing LSI Fusion-MPT controllers
+.Sh SYNOPSIS
+.Nm
+.Cm version
+.Nm
+.Op Fl u Ar unit
+.Cm show adapter
+.Nm
+.Op Fl u Ar unit
+.Cm show config
+.Nm
+.Op Fl u Ar unit
+.Cm show drives
+.Nm
+.Op Fl u Ar unit
+.Cm show events
+.Nm
+.Op Fl u Ar unit
+.Cm show volumes
+.Nm
+.Op Fl u Ar unit
+.Cm fail Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm online Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm offline Ar drive
+.Nm
+.Op Fl u Ar unit
+.Cm name Ar volume Ar name
+.Nm
+.Op Fl u Ar unit
+.Cm volume status Ar volume
+.Nm
+.Op Fl u Ar unit
+.Cm volume cache Ar volume 
+.Ar enable|disable
+.Nm
+.Op Fl u Ar unit
+.Cm clear
+.Nm
+.Op Fl u Ar unit
+.Cm create Ar type
+.Op Fl q
+.Op Fl v
+.Op Fl s Ar stripe_size
+.Ar drive Ns Op \&, Ns Ar drive Ns Op ",..."
+.Nm
+.Op Fl u Ar unit
+.Cm delete Ar volume
+.Nm
+.Op Fl u Ar unit
+.Cm add Ar drive Op Ar volume
+.Nm
+.Op Fl u Ar unit
+.Cm remove Ar drive
+.Sh DESCRIPTION
+The
+.Nm
+utility can be used to display or modify various parameters on LSI
+Fusion-MPT controllers.
+Each invocation of
+.Nm
+consists of zero or more global options followed by a command.
+Commands may support additional optional or required arguments after the
+command.
+.Pp
+Currently one global option is supported:
+.Bl -tag -width indent
+.It Fl u Ar unit
+.Ar unit
+specifies the unit of the controller to work with.
+If no unit is specified,
+then unit 0 is used.
+.El
+.Pp
+Volumes may be specified in two forms.
+First,
+a volume may be identified by its location as
+.Sm off
+.Op Ar xx Ns \&:
+.Ar yy
+.Sm on
+where
+.Ar xx
+is the bus ID and
+.Ar yy
+is the target ID.
+If the bus ID is ommitted,
+the volume is assumed to be on bus 0.
+Second,
+on the volume may be specified by the corresponding
+.Em daX
+device,
+such as
+.Em da0 .
+.Pp
+The
+.Xr mpt 4
+controller divides drives up into two categories.
+Configured drives belong to a RAID volume either as a member drive or as a hot
+spare.
+Each configured drive is assigned a unique device ID such as 0 or 1 that is
+show in
+.Cm show config ,
+and in the first column of
+.Cm show drives .
+Any drive not associated with a RAID volume as either a member or a hot spare
+is a standalone drive.
+Standalone drives are visible to the operating system as SCSI disk devices.
+As a result, drives may be specified in three forms.
+First,
+a configured drive may be identified by its device ID.
+Second,
+any drive may be identified by its location as
+.Sm off
+.Ar xx Ns \&:
+.Ar yy
+.Sm on
+where
+.Ar xx
+is the bus ID and
+.Ar yy
+is the target ID for each drive as displayed in
+.Cm show drives .
+Note that unlike volumes,
+a drive location always requires the bus ID to avoid confusion with device IDs.
+Third,
+a standalone drive that is not part of a volume may be identified by its
+corresponding
+.Em daX
+device as displayed in
+.Cm show drives .
+.Pp
+The
+.Nm
+utility supports several different groups of commands.
+The first group of commands provide information about the controller,
+the volumes it manages, and the drives it controls.
+The second group of commands are used to manage the physical drives
+attached to the controller.
+The third group of commands are used to manage the logical volumes
+managed by the controller.
+The fourth group of commands are used to manage the drive configuration for
+the controller.
+.Pp
+The informational commands include:
+.Bl -tag -width indent
+.It Cm version
+Displays the version of
+.Nm .
+.It Cm show adapter
+Displays information about the RAID controller such as the model number.
+.It Cm show config
+Displays the volume and drive configuration for the controller.
+Each volume is listed along with the physical drives that the volume spans.
+If any hot spare drives are configured, then they are listed as well.
+.It Cm show drives
+Lists all of the physical drives attached to the controller.
+.It Cm show events
+Display all the entries from the controller's event log.
+Due to lack of documentation this command isn't very useful currently and
+just dumps each log entry in hex.
+.It Cm show volumes
+Lists all of the logical volumes managed by the controller.
+.El
+.Pp
+The physical drive management commands include:
+.Bl -tag -width indent
+.It Cm fail Ar drive
+Mark
+.Ar drive
+as
+.Dq failed requested .
+Note that this state is different from the
+.Dq failed
+state that is used when the firmware fails a drive.
+.Ar Drive
+must be a configured drive.
+.It Cm online Ar drive
+Mark
+.Ar drive
+as an online drive.
+.Ar Drive
+must be part a configured drive in either the
+.Dq offline
+or
+.Dq failed requested
+states.
+.It Cm offline Ar drive
+Mark
+.Ar drive
+as offline.
+.Ar Drive
+must be a configured, online drive.
+.El
+.Pp
+The logical volume management commands include:
+.Bl -tag -width indent
+.It Cm name Ar volume Ar name
+Sets the name of
+.Ar volume
+to
+.Ar name .
+.It Cm volume cache Ar volume Ar enable|disable
+Enables or disables the drive write cache for the member drives of
+.Ar volume .
+.It Cm volume status Ar volume
+Display more detailed status about a single volume including the current
+progress of a rebuild operation if one is being performed.
+.El
+.Pp
+The configuration commands include:
+.Bl -tag -width indent
+.It Cm clear
+Delete the entire configuration including all volumes and spares.
+All drives will become standalone drives.
+.It Xo Cm create Ar type
+.Op Fl q
+.Op Fl v
+.Op Fl s Ar stripe_size
+.Ar drive Ns Op \&, Ns Ar drive Ns Op ",..."
+.Xc
+Create a new volume.
+The
+.Ar type
+specifies the type of volume to create.
+Currently supported types include:
+.Bl -tag -width indent
+.It Cm raid0
+Creates one RAID0 volume spanning the drives listed in the single drive list.
+.It Cm raid1
+Creates one RAID1 volume spanning the drives listed in the single drive list.
+.It Cm raid1e
+Creates one RAID1E volume spanning the drives listed in the single drive list.
+.El
+.Pp
+.Sy Note:
+Not all volume types are supported by all controllers.
+.Pp
+If the
+.Fl q
+flag is specified after
+.Ar type ,
+then a
+.Dq quick
+initialization of the volume will be done.
+This is useful when the drives do not contain any existing data that need
+to be preserved.
+.Pp
+If the
+.Fl v
+flag is specified after
+.Ar type ,
+then more verbose output will be enabled.
+Currently this just provides notification as drives are added to volumes
+when building the configuration.
+.Pp
+The
+.Fl s
+.Ar stripe_size
+parameter allows the stripe size of the array to be set.
+By default a stripe size of 64K is used.
+The list of valid values for a given
+.Ar type
+are listed in the output of
+.Cm show adapter .
+.It Cm delete Ar volume
+Delete the volume
+.Ar volume .
+Member drives will become standalone drives.
+.It Cm add Ar drive Op Ar volume
+Mark
+.Ar drive
+as a hot spare.
+.Ar Drive
+must not be a member of a volume.
+If
+.Ar volume
+is specified,
+then the hot spare will be dedicated to that volume.
+Otherwise,
+.Ar drive
+will be used as a global hot spare backing all volumes for this controller.
+Note that
+.Ar drive
+must be as large as the smallest drive in all of the volumes it is going to
+back.
+.It Cm remove Ar drive
+Remove the hot spare
+.Ar drive
+from service.
+It will become a standalone drive.
+.El
+.Sh EXAMPLES
+Mark the drive at bus 0 target 4 as offline:
+.Pp
+.Dl Nm Cm offline 0:4
+.Pp
+Create a RAID1 array from the two standalone drives
+.Va da1
+and
+.Va da2 :
+.Pp
+.Dl Nm Cm create raid1 da1,da2
+.Pp
+Mark standalone drive
+.Va da3
+as a global hot spare:
+.Pp
+.Dl Nm Cm add da3
+.Sh SEE ALSO
+.Xr mpt 4
+.Sh BUGS
+.Pp
+The handling of spare drives appears to be unreliable.
+The
+.Xr mpt 4
+firmware manages spares via spare drive
+.Dq pools .
+There are eight pools numbered 0 through 7.
+Each spare drive can only be assigned to a single pool.
+Each volume can be backed by any combination of zero or more spare pools.
+The
+.Nm
+utility attempts to use the following algorithm for managing spares.
+Global spares are always assigned to pool 0,
+and all volumes are always backed by pool 0.
+For dedicated spares,
+.Nm
+assigns one of the remaining 7 pools to each volume and
+assigns dedicated drives to that pool.
+In practice however, it seems that assigning a drive as a spare does not
+take effect until the box has been rebooted.
+Also, the firmware renumbers the spare pool assignments after a reboot
+which undoes the effects of the algorithm above.
+Simple cases such as assigning global spares seem to work ok
+.Pq albeit requiring a reboot to take effect
+but more
+.Dq exotic
+configurations may not work reliably.
+.Pp
+Drive configuration commands result in an excessive flood of messages on the
+console.
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 8.0 .
diff --git a/usr.sbin/mptutil/mptutil.c b/usr.sbin/mptutil/mptutil.c
new file mode 100644
index 00000000000..e7b58060ef1
--- /dev/null
+++ b/usr.sbin/mptutil/mptutil.c
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin 
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include 
+__RCSID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mptutil.h"
+
+SET_DECLARE(MPT_DATASET(top), struct mptutil_command);
+
+int mpt_unit;
+
+static void
+usage(void)
+{
+
+	fprintf(stderr, "usage: mptutil [-u unit]  ...\n\n");
+	fprintf(stderr, "Commands include:\n");
+	fprintf(stderr, "    version\n");
+	fprintf(stderr, "    show adapter              - display controller information\n");
+	fprintf(stderr, "    show config               - display RAID configuration\n");
+	fprintf(stderr, "    show drives               - list physical drives\n");
+	fprintf(stderr, "    show events               - display event log\n");
+	fprintf(stderr, "    show volumes              - list logical volumes\n");
+	fprintf(stderr, "    fail               - fail a physical drive\n");
+	fprintf(stderr, "    online             - bring an offline physical drive online\n");
+	fprintf(stderr, "    offline            - mark a physical drive offline\n");
+	fprintf(stderr, "    name  \n");
+	fprintf(stderr, "    volume status     - display volume status\n");
+	fprintf(stderr, "    volume cache  \n");
+	fprintf(stderr, "                              - Enable or disable the volume drive caches\n");
+	fprintf(stderr, "    clear                     - clear volume configuration\n");
+	fprintf(stderr, "    create  [-vq] [-s stripe] [,[,...]]\n");
+	fprintf(stderr, "    delete \n");
+	fprintf(stderr, "    add  [volume]      - add a hot spare\n");
+	fprintf(stderr, "    remove             - remove a hot spare\n");
+#ifdef DEBUG
+	fprintf(stderr, "    pd create          - create RAID physdisk\n");
+	fprintf(stderr, "    pd delete          - delete RAID physdisk\n");
+	fprintf(stderr, "    debug                     - debug 'show config'\n");
+#endif
+	exit(1);
+}
+
+static int
+version(int ac, char **av)
+{
+
+	printf("mptutil version 1.0.3");
+#ifdef DEBUG
+	printf(" (DEBUG)");
+#endif
+	printf("\n");
+	return (0);
+}
+MPT_COMMAND(top, version, version);
+
+int
+main(int ac, char **av)
+{
+	struct mptutil_command **cmd;
+	int ch;
+
+	while ((ch = getopt(ac, av, "u:")) != -1) {
+		switch (ch) {
+		case 'u':
+			mpt_unit = atoi(optarg);
+			break;
+		case '?':
+			usage();
+		}
+	}
+
+	av += optind;
+	ac -= optind;
+
+	/* getopt() eats av[0], so we can't use mpt_table_handler() directly. */
+	if (ac == 0)
+		usage();
+
+	SET_FOREACH(cmd, MPT_DATASET(top)) {
+		if (strcmp((*cmd)->name, av[0]) == 0) {
+			(*cmd)->handler(ac, av);
+			return (0);
+		}
+	}
+	warnx("Unknown command %s.", av[0]);
+	return (0);
+}
diff --git a/usr.sbin/mptutil/mptutil.h b/usr.sbin/mptutil/mptutil.h
new file mode 100644
index 00000000000..39512359334
--- /dev/null
+++ b/usr.sbin/mptutil/mptutil.h
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin 
+ *
+ * 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.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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$
+ */
+
+#ifndef __MPTUTIL_H__
+#define	__MPTUTIL_H__
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#define	IOC_STATUS_SUCCESS(status)					\
+	(((status) & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS)
+
+struct mpt_query_disk {
+	char	devname[SPECNAMELEN + 1];
+};
+
+struct mpt_standalone_disk {
+	uint64_t maxlba;
+	char	inqstring[64];
+	char	devname[SPECNAMELEN + 1];
+	u_int	bus;
+	u_int	target;
+};
+
+struct mpt_drive_list {
+	int	ndrives;
+	CONFIG_PAGE_RAID_PHYS_DISK_0 *drives[0];
+};
+
+struct mptutil_command {
+	const char *name;
+	int (*handler)(int ac, char **av);
+};
+
+#define	MPT_DATASET(name)	mptutil_ ## name ## _table
+
+#define	MPT_COMMAND(set, name, function)				\
+	static struct mptutil_command function ## _mptutil_command =	\
+	{ #name, function };						\
+	DATA_SET(MPT_DATASET(set), function ## _mptutil_command)
+
+#define	MPT_TABLE(set, name)						\
+	SET_DECLARE(MPT_DATASET(name), struct mptutil_command);		\
+									\
+	static int							\
+	mptutil_ ## name ## _table_handler(int ac, char **av)		\
+	{								\
+		return (mpt_table_handler(SET_BEGIN(MPT_DATASET(name)), \
+		    SET_LIMIT(MPT_DATASET(name)), ac, av));		\
+	}								\
+	MPT_COMMAND(set, name, mptutil_ ## name ## _table_handler)
+
+extern int mpt_unit;
+
+#ifdef DEBUG
+void	hexdump(const void *ptr, int length, const char *hdr, int flags);
+#define	HD_COLUMN_MASK	0xff
+#define	HD_DELIM_MASK	0xff00
+#define	HD_OMIT_COUNT	(1 << 16)
+#define	HD_OMIT_HEX	(1 << 17)
+#define	HD_OMIT_CHARS	(1 << 18)
+#endif
+
+int	mpt_table_handler(struct mptutil_command **start,
+    struct mptutil_command **end, int ac, char **av);
+int	mpt_read_config_page_header(int fd, U8 PageType, U8 PageNumber,
+    U32 PageAddress, CONFIG_PAGE_HEADER *header, U16 *IOCStatus);
+void	*mpt_read_config_page(int fd, U8 PageType, U8 PageNumber,
+    U32 PageAddress, U16 *IOCStatus);
+void	*mpt_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion,
+    U8 PageNumber, U32 PageAddress, U16 *IOCStatus);
+int	mpt_write_config_page(int fd, void *buf, U16 *IOCStatus);
+const char *mpt_ioc_status(U16 IOCStatus);
+int	mpt_raid_action(int fd, U8 Action, U8 VolumeBus, U8 VolumeID,
+    U8 PhysDiskNum, U32 ActionDataWord, void *buf, int len,
+    RAID_VOL0_STATUS *VolumeStatus, U32 *ActionData, int datalen,
+    U16 *IOCStatus, U16 *ActionStatus, int write);
+const char *mpt_raid_status(U16 ActionStatus);
+int	mpt_open(int unit);
+const char *mpt_raid_level(U8 VolumeType);
+const char *mpt_volstate(U8 State);
+const char *mpt_pdstate(CONFIG_PAGE_RAID_PHYS_DISK_0 *info);
+const char *mpt_pd_inq_string(CONFIG_PAGE_RAID_PHYS_DISK_0 *pd_info);
+struct mpt_drive_list *mpt_pd_list(int fd);
+void	mpt_free_pd_list(struct mpt_drive_list *list);
+int	mpt_query_disk(U8 VolumeBus, U8 VolumeID, struct mpt_query_disk *qd);
+const char *mpt_volume_name(U8 VolumeBus, U8 VolumeID);
+int	mpt_fetch_disks(int fd, int *ndisks,
+    struct mpt_standalone_disk **disksp);
+int	mpt_lock_volume(U8 VolumeBus, U8 VolumeID);
+int	mpt_lookup_drive(struct mpt_drive_list *list, const char *drive,
+    U8 *PhysDiskNum);
+int	mpt_lookup_volume(int fd, const char *name, U8 *VolumeBus,
+    U8 *VolumeID);
+int	mpt_rescan_bus(int bus, int id);
+
+static __inline void *
+mpt_read_man_page(int fd, U8 PageNumber, U16 *IOCStatus)
+{
+
+	return (mpt_read_config_page(fd, MPI_CONFIG_PAGETYPE_MANUFACTURING,
+	    PageNumber, 0, IOCStatus));
+}
+
+static __inline void *
+mpt_read_ioc_page(int fd, U8 PageNumber, U16 *IOCStatus)
+{
+
+	return (mpt_read_config_page(fd, MPI_CONFIG_PAGETYPE_IOC, PageNumber,
+	    0, IOCStatus));
+}
+
+static __inline U32
+mpt_vol_pageaddr(U8 VolumeBus, U8 VolumeID)
+{
+
+	return (VolumeBus << 8 | VolumeID);
+}
+
+static __inline CONFIG_PAGE_RAID_VOL_0 *
+mpt_vol_info(int fd, U8 VolumeBus, U8 VolumeID, U16 *IOCStatus)
+{
+
+	return (mpt_read_config_page(fd, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0,
+	    mpt_vol_pageaddr(VolumeBus, VolumeID), IOCStatus));
+}
+
+static __inline CONFIG_PAGE_RAID_VOL_1 *
+mpt_vol_names(int fd, U8 VolumeBus, U8 VolumeID, U16 *IOCStatus)
+{
+
+	return (mpt_read_config_page(fd, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 1,
+	    mpt_vol_pageaddr(VolumeBus, VolumeID), IOCStatus));
+}
+
+static __inline CONFIG_PAGE_RAID_PHYS_DISK_0 *
+mpt_pd_info(int fd, U8 PhysDiskNum, U16 *IOCStatus)
+{
+
+	return (mpt_read_config_page(fd, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0,
+	    PhysDiskNum, IOCStatus));
+}
+
+#endif /* !__MPTUTIL_H__ */
diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c
index 570961a3e9f..17e439ce584 100644
--- a/usr.sbin/ndp/ndp.c
+++ b/usr.sbin/ndp/ndp.c
@@ -116,7 +116,7 @@
 
 #define NEXTADDR(w, s) \
 	if (rtm->rtm_addrs & (w)) { \
-		bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
+		bcopy((char *)&s, cp, sizeof(s)); cp += SA_SIZE(&s);}
 
 
 static pid_t pid;
diff --git a/usr.sbin/ntp/scripts/mkver b/usr.sbin/ntp/scripts/mkver
index 02c692491f3..a8f51752b60 100755
--- a/usr.sbin/ntp/scripts/mkver
+++ b/usr.sbin/ntp/scripts/mkver
@@ -23,8 +23,6 @@ case "" in
  *)  ConfStr="${ConfStr}-r" ;;
 esac
 
-ConfStr="$ConfStr `LC_ALL=C date`"
-
 if [ ! -f .version ]; then
   echo 0 > .version
 fi
diff --git a/usr.sbin/pkg_install/add/main.c b/usr.sbin/pkg_install/add/main.c
index b2d511ebc7b..eaed0c0c2eb 100644
--- a/usr.sbin/pkg_install/add/main.c
+++ b/usr.sbin/pkg_install/add/main.c
@@ -82,13 +82,15 @@ struct {
 	{ 700000, 700099, "/packages-7.0-release" },
 	{ 701000, 701099, "/packages-7.1-release" },
 	{ 702000, 702099, "/packages-7.2-release" },
+	{ 800000, 800499, "/packages-8.0-release" },
 	{ 300000, 399000, "/packages-3-stable" },
 	{ 400000, 499000, "/packages-4-stable" },
 	{ 502100, 502128, "/packages-5-current" },
 	{ 503100, 599000, "/packages-5-stable" },
 	{ 600100, 699000, "/packages-6-stable" },
 	{ 700100, 799000, "/packages-7-stable" },
-	{ 800000, 899000, "/packages-8-current" },
+	{ 800500, 899000, "/packages-8-stable" },
+	{ 900000, 999000, "/packages-9-current" },
 	{ 0, 9999999, "/packages-current" },
 	{ 0, 0, NULL }
 };
diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
index acbd017c83c..a3d04138797 100644
--- a/usr.sbin/pkg_install/lib/lib.h
+++ b/usr.sbin/pkg_install/lib/lib.h
@@ -84,14 +84,14 @@
 #define DISPLAY_FNAME		"+DISPLAY"
 #define MTREE_FNAME		"+MTREE_DIRS"
 
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
+#define INDEX_FNAME		"INDEX-9"
+#elif defined(__FreeBSD_version) && __FreeBSD_version >= 800000
 #define INDEX_FNAME		"INDEX-8"
 #elif defined(__FreeBSD_version) && __FreeBSD_version >= 700000
 #define INDEX_FNAME		"INDEX-7"
 #elif defined(__FreeBSD_version) && __FreeBSD_version >= 600000
 #define INDEX_FNAME		"INDEX-6"
-#elif defined(__FreeBSD_version) && __FreeBSD_version >= 500036
-#define INDEX_FNAME		"INDEX-5"
 #else
 #define INDEX_FNAME		"INDEX"
 #endif
@@ -102,10 +102,10 @@
 #define PKG_PREFIX_VNAME	"PKG_PREFIX"
 
 /*
- * Version of the package tools - increase only when some
- * functionality used by bsd.port.mk is changed, added or removed
+ * Version of the package tools - increase whenever you make a change
+ * in the code that is not cosmetic only.
  */
-#define PKG_INSTALL_VERSION	20090519
+#define PKG_INSTALL_VERSION	20090902
 
 #define PKG_WRAPCONF_FNAME	"/var/db/pkg_install.conf"
 #define main(argc, argv)	real_main(argc, argv)
diff --git a/usr.sbin/ppp/ether.c b/usr.sbin/ppp/ether.c
index e4e154ad7f3..a86f3bd5b19 100644
--- a/usr.sbin/ppp/ether.c
+++ b/usr.sbin/ppp/ether.c
@@ -193,17 +193,18 @@ static void
 ether_device2iov(struct device *d, struct iovec *iov, int *niov,
                  int maxiov __unused, int *auxfd, int *nauxfd)
 {
-  struct etherdevice *dev = device2ether(d);
+  struct etherdevice *dev;
   int sz = physical_MaxDeviceSize();
 
-  iov[*niov].iov_base = realloc(d, sz);
-  if (iov[*niov].iov_base == NULL) {
+  iov[*niov].iov_base = d = realloc(d, sz);
+  if (d == NULL) {
     log_Printf(LogALERT, "Failed to allocate memory: %d\n", sz);
     AbortProgram(EX_OSERR);
   }
   iov[*niov].iov_len = sz;
   (*niov)++;
 
+  dev = device2ether(d);
   if (dev->cs >= 0) {
     *auxfd = dev->cs;
     (*nauxfd)++;
diff --git a/usr.sbin/ppp/exec.c b/usr.sbin/ppp/exec.c
index 7c80034a6ac..a53db37270f 100644
--- a/usr.sbin/ppp/exec.c
+++ b/usr.sbin/ppp/exec.c
@@ -35,7 +35,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -63,24 +65,106 @@
 #include "cbcp.h"
 #include "datalink.h"
 #include "id.h"
+#include "main.h"
 #include "exec.h"
 
-static struct device execdevice = {
+
+struct execdevice {
+  struct device dev;		/* What struct physical knows about */
+  int fd_out;			/* output descriptor */
+};
+
+#define device2exec(d) ((d)->type == EXEC_DEVICE ? (struct execdevice *)d : NULL)
+
+unsigned
+exec_DeviceSize(void)
+{
+  return sizeof(struct execdevice);
+}
+
+static void
+exec_Free(struct physical *p)
+{
+  struct execdevice *dev = device2exec(p->handler);
+
+  if (dev->fd_out != -1)
+    close(dev->fd_out);
+  free(dev);
+}
+
+static void
+exec_device2iov(struct device *d, struct iovec *iov, int *niov,
+               int maxiov __unused, int *auxfd, int *nauxfd)
+{
+  struct execdevice *dev;
+  int sz = physical_MaxDeviceSize();
+
+  iov[*niov].iov_base = d = realloc(d, sz);
+  if (d == NULL) {
+    log_Printf(LogALERT, "Failed to allocate memory: %d\n", sz);
+    AbortProgram(EX_OSERR);
+  }
+  iov[*niov].iov_len = sz;
+  (*niov)++;
+
+  dev = device2exec(d);
+  if (dev->fd_out >= 0) {
+    *auxfd = dev->fd_out;
+    (*nauxfd)++;
+  }
+}
+
+static int
+exec_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e)
+{
+  struct execdevice *dev = device2exec(p->handler);
+  int sets;
+
+  p->handler->removefromset = NULL;
+  sets = physical_RemoveFromSet(p, r, w, e);
+  p->handler->removefromset = exec_RemoveFromSet;
+
+  if (dev->fd_out >= 0) {
+    if (w && FD_ISSET(dev->fd_out, w)) {
+      FD_CLR(dev->fd_out, w);
+      log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, dev->fd_out);
+      sets++;
+    }
+    if (e && FD_ISSET(dev->fd_out, e)) {
+      FD_CLR(dev->fd_out, e);
+      log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, dev->fd_out);
+      sets++;
+    }
+  }
+
+  return sets;
+}
+
+static ssize_t
+exec_Write(struct physical *p, const void *v, size_t n)
+{
+  struct execdevice *dev = device2exec(p->handler);
+  int fd = dev->fd_out == -1 ? p->fd : dev->fd_out;
+
+  return write(fd, v, n);
+}
+
+static struct device baseexecdevice = {
   EXEC_DEVICE,
   "exec",
   0,
   { CD_NOTREQUIRED, 0 },
   NULL,
+  exec_RemoveFromSet,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
+  exec_Free,
   NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
+  exec_Write,
+  exec_device2iov,
   NULL,
   NULL,
   NULL
@@ -88,146 +172,238 @@ static struct device execdevice = {
 
 struct device *
 exec_iov2device(int type, struct physical *p, struct iovec *iov,
-                int *niov, int maxiov __unused, int *auxfd __unused,
-		int *nauxfd __unused)
+                int *niov, int maxiov __unused, int *auxfd, int *nauxfd)
 {
   if (type == EXEC_DEVICE) {
-    free(iov[(*niov)++].iov_base);
-    physical_SetupStack(p, execdevice.name, PHYSICAL_NOFORCE);
-    return &execdevice;
+    struct execdevice *dev = (struct execdevice *)iov[(*niov)++].iov_base;
+
+    dev = realloc(dev, sizeof *dev);	/* Reduce to the correct size */
+    if (dev == NULL) {
+      log_Printf(LogALERT, "Failed to allocate memory: %d\n",
+                 (int)(sizeof *dev));
+      AbortProgram(EX_OSERR);
+    }
+
+    if (*nauxfd) {
+      dev->fd_out = *auxfd;
+      (*nauxfd)--;
+    } else
+      dev->fd_out = -1;
+
+    /* Refresh function pointers etc */
+    memcpy(&dev->dev, &baseexecdevice, sizeof dev->dev);
+
+    physical_SetupStack(p, dev->dev.name, PHYSICAL_NOFORCE);
+    return &dev->dev;
   }
 
   return NULL;
 }
 
+static int
+exec_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
+{
+  struct physical *p = descriptor2physical(d);
+  struct execdevice *dev = device2exec(p->handler);
+  int result = 0;
+
+  if (w && dev->fd_out >= 0) {
+    FD_SET(dev->fd_out, w);
+    log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, dev->fd_out);
+    result++;
+    w = NULL;
+  }
+
+  if (e && dev->fd_out >= 0) {
+    FD_SET(dev->fd_out, e);
+    log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, dev->fd_out);
+    result++;
+  }
+
+  if (result && *n <= dev->fd_out)
+    *n = dev->fd_out + 1;
+
+  return result + physical_doUpdateSet(d, r, w, e, n, 0);
+}
+
+static int
+exec_IsSet(struct fdescriptor *d, const fd_set *fdset)
+{
+  struct physical *p = descriptor2physical(d);
+  struct execdevice *dev = device2exec(p->handler);
+  int result = dev->fd_out >= 0 && FD_ISSET(dev->fd_out, fdset);
+  result += physical_IsSet(d, fdset);
+
+  return result;
+}
+
 struct device *
 exec_Create(struct physical *p)
 {
-  if (p->fd < 0 && *p->name.full == '!') {
-    int fids[2], type;
+  struct execdevice *dev;
 
-    p->fd--;	/* We own the device but maybe can't use it - change fd */
-    type = physical_IsSync(p) ? SOCK_DGRAM : SOCK_STREAM;
-
-    if (socketpair(AF_UNIX, type, PF_UNSPEC, fids) < 0)
-      log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
-                 strerror(errno));
-    else {
-      static int child_status;		/* This variable is abused ! */
-      int stat, argc, i, ret, wret, pidpipe[2];
-      pid_t pid, realpid;
-      char *argv[MAXARGS];
-
-      stat = fcntl(fids[0], F_GETFL, 0);
-      if (stat > 0) {
-        stat |= O_NONBLOCK;
-        fcntl(fids[0], F_SETFL, stat);
+  dev = NULL;
+  if (p->fd < 0) {
+    if (*p->name.full == '!') {
+      int fids[2], type;
+  
+      if ((dev = malloc(sizeof *dev)) == NULL) {
+        log_Printf(LogWARN, "%s: Cannot allocate an exec device: %s\n",
+                   p->link.name, strerror(errno));
+        return NULL;
       }
-      realpid = getpid();
-      if (pipe(pidpipe) == -1) {
-        log_Printf(LogPHASE, "Unable to pipe for line exec: %s\n",
+      dev->fd_out = -1;
+  
+      p->fd--;	/* We own the device but maybe can't use it - change fd */
+      type = physical_IsSync(p) ? SOCK_DGRAM : SOCK_STREAM;
+  
+      if (socketpair(AF_UNIX, type, PF_UNSPEC, fids) < 0) {
+        log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n",
                    strerror(errno));
-        close(fids[1]);
-      } else switch ((pid = fork())) {
-        case -1:
-          log_Printf(LogPHASE, "Unable to fork for line exec: %s\n",
+        free(dev);
+        dev = NULL;
+      } else {
+        static int child_status;		/* This variable is abused ! */
+        int stat, argc, i, ret, wret, pidpipe[2];
+        pid_t pid, realpid;
+        char *argv[MAXARGS];
+  
+        stat = fcntl(fids[0], F_GETFL, 0);
+        if (stat > 0) {
+          stat |= O_NONBLOCK;
+          fcntl(fids[0], F_SETFL, stat);
+        }
+        realpid = getpid();
+        if (pipe(pidpipe) == -1) {
+          log_Printf(LogPHASE, "Unable to pipe for line exec: %s\n",
                      strerror(errno));
-          close(pidpipe[0]);
-          close(pidpipe[1]);
           close(fids[1]);
-          break;
-
-        case  0:
-          close(pidpipe[0]);
           close(fids[0]);
-          timer_TermService();
-#ifndef NOSUID
-          setuid(ID0realuid());
-#endif
-
-          child_status = 0;
-          switch ((pid = vfork())) {
-            case 0:
-              close(pidpipe[1]);
-              break;
-
-            case -1:
-              ret = errno;
-              log_Printf(LogPHASE, "Unable to vfork to drop parent: %s\n",
-                         strerror(errno));
-              close(pidpipe[1]);
-              _exit(ret);
-
-            default:
-              write(pidpipe[1], &pid, sizeof pid);
-              close(pidpipe[1]);
-              _exit(child_status);	/* The error from exec() ! */
-          }
-
-          log_Printf(LogDEBUG, "Exec'ing ``%s''\n", p->name.base);
-
-          if ((argc = MakeArgs(p->name.base, argv, VECSIZE(argv),
-                               PARSE_REDUCE|PARSE_NOHASH)) < 0) {
-            log_Printf(LogWARN, "Syntax error in exec command\n");
-            _exit(ESRCH);
-          }
-
-          command_Expand(argv, argc, (char const *const *)argv,
-                         p->dl->bundle, 0, realpid);
-
-          dup2(fids[1], STDIN_FILENO);
-          dup2(fids[1], STDOUT_FILENO);
-          dup2(fids[1], STDERR_FILENO);
-          for (i = getdtablesize(); i > STDERR_FILENO; i--)
-            fcntl(i, F_SETFD, 1);
-
-          execvp(*argv, argv);
-          child_status = errno;		/* Only works for vfork() */
-          printf("execvp failed: %s: %s\r\n", *argv, strerror(child_status));
-          _exit(child_status);
-          break;
-
-        default:
-          close(pidpipe[1]);
-          close(fids[1]);
-          if (read(pidpipe[0], &p->session_owner, sizeof p->session_owner) !=
-              sizeof p->session_owner)
-            p->session_owner = (pid_t)-1;
-          close(pidpipe[0]);
-          while ((wret = waitpid(pid, &stat, 0)) == -1 && errno == EINTR)
-            ;
-          if (wret == -1) {
-            log_Printf(LogWARN, "Waiting for child process: %s\n",
+          free(dev);
+          dev = NULL;
+        } else switch ((pid = fork())) {
+          case -1:
+            log_Printf(LogPHASE, "Unable to fork for line exec: %s\n",
                        strerror(errno));
+            close(pidpipe[0]);
+            close(pidpipe[1]);
+            close(fids[1]);
             close(fids[0]);
-            p->session_owner = (pid_t)-1;
             break;
-          } else if (WIFSIGNALED(stat)) {
-            log_Printf(LogWARN, "Child process received sig %d !\n",
-                       WTERMSIG(stat));
+  
+          case 0:
+            close(pidpipe[0]);
             close(fids[0]);
-            p->session_owner = (pid_t)-1;
+            timer_TermService();
+  #ifndef NOSUID
+            setuid(ID0realuid());
+  #endif
+  
+            child_status = 0;
+            switch ((pid = vfork())) {
+              case 0:
+                close(pidpipe[1]);
+                break;
+  
+              case -1:
+                ret = errno;
+                log_Printf(LogPHASE, "Unable to vfork to drop parent: %s\n",
+                           strerror(errno));
+                close(pidpipe[1]);
+                _exit(ret);
+  
+              default:
+                write(pidpipe[1], &pid, sizeof pid);
+                close(pidpipe[1]);
+                _exit(child_status);	/* The error from exec() ! */
+            }
+  
+            log_Printf(LogDEBUG, "Exec'ing ``%s''\n", p->name.base);
+  
+            if ((argc = MakeArgs(p->name.base, argv, VECSIZE(argv),
+                                 PARSE_REDUCE|PARSE_NOHASH)) < 0) {
+              log_Printf(LogWARN, "Syntax error in exec command\n");
+              _exit(ESRCH);
+            }
+  
+            command_Expand(argv, argc, (char const *const *)argv,
+                           p->dl->bundle, 0, realpid);
+  
+            dup2(fids[1], STDIN_FILENO);
+            dup2(fids[1], STDOUT_FILENO);
+            dup2(fids[1], STDERR_FILENO);
+            for (i = getdtablesize(); i > STDERR_FILENO; i--)
+              fcntl(i, F_SETFD, 1);
+  
+            execvp(*argv, argv);
+            child_status = errno;		/* Only works for vfork() */
+            printf("execvp failed: %s: %s\r\n", *argv, strerror(child_status));
+            _exit(child_status);
             break;
-          } else if (WIFSTOPPED(stat)) {
-            log_Printf(LogWARN, "Child process received stop sig %d !\n",
-                       WSTOPSIG(stat));
-            /* I guess that's ok.... */
-          } else if ((ret = WEXITSTATUS(stat))) {
-            log_Printf(LogWARN, "Cannot exec \"%s\": %s\n", p->name.base,
-                       strerror(ret));
-            close(fids[0]);
-            p->session_owner = (pid_t)-1;
-            break;
-          }
-          p->fd = fids[0];
-          log_Printf(LogDEBUG, "Using descriptor %d for child\n", p->fd);
-          physical_SetupStack(p, execdevice.name, PHYSICAL_NOFORCE);
-          if (p->cfg.cd.necessity != CD_DEFAULT)
-            log_Printf(LogWARN, "Carrier settings ignored\n");
-          return &execdevice;
+  
+          default:
+            close(pidpipe[1]);
+            close(fids[1]);
+            if (read(pidpipe[0], &p->session_owner, sizeof p->session_owner) !=
+                sizeof p->session_owner)
+              p->session_owner = (pid_t)-1;
+            close(pidpipe[0]);
+            while ((wret = waitpid(pid, &stat, 0)) == -1 && errno == EINTR)
+              ;
+            if (wret == -1) {
+              log_Printf(LogWARN, "Waiting for child process: %s\n",
+                         strerror(errno));
+              close(fids[0]);
+              p->session_owner = (pid_t)-1;
+              break;
+            } else if (WIFSIGNALED(stat)) {
+              log_Printf(LogWARN, "Child process received sig %d !\n",
+                         WTERMSIG(stat));
+              close(fids[0]);
+              p->session_owner = (pid_t)-1;
+              break;
+            } else if (WIFSTOPPED(stat)) {
+              log_Printf(LogWARN, "Child process received stop sig %d !\n",
+                         WSTOPSIG(stat));
+              /* I guess that's ok.... */
+            } else if ((ret = WEXITSTATUS(stat))) {
+              log_Printf(LogWARN, "Cannot exec \"%s\": %s\n", p->name.base,
+                         strerror(ret));
+              close(fids[0]);
+              p->session_owner = (pid_t)-1;
+              break;
+            }
+            p->fd = fids[0];
+            log_Printf(LogDEBUG, "Using descriptor %d for child\n", p->fd);
+        }
       }
-      close(fids[0]);
     }
+  } else {
+    struct stat st;
+
+    if (fstat(p->fd, &st) != -1 && (st.st_mode & S_IFIFO)) {
+      if ((dev = malloc(sizeof *dev)) == NULL)
+        log_Printf(LogWARN, "%s: Cannot allocate an exec device: %s\n",
+                   p->link.name, strerror(errno));
+      else if (p->fd == STDIN_FILENO) {
+        log_Printf(LogPHASE, "%s: Using stdin/stdout to communicate with "
+                   "parent (pipe mode)\n", p->link.name);
+        dev->fd_out = dup(STDOUT_FILENO);
+
+        /* Hook things up so that we monitor dev->fd_out */
+        p->desc.UpdateSet = exec_UpdateSet;
+        p->desc.IsSet = exec_IsSet;
+      } else
+        dev->fd_out = -1;
+    }
+  }
+
+  if (dev) {
+    memcpy(&dev->dev, &baseexecdevice, sizeof dev->dev);
+    physical_SetupStack(p, dev->dev.name, PHYSICAL_NOFORCE);
+    if (p->cfg.cd.necessity != CD_DEFAULT)
+      log_Printf(LogWARN, "Carrier settings ignored\n");
+    return &dev->dev;
   }
 
   return NULL;
diff --git a/usr.sbin/ppp/exec.h b/usr.sbin/ppp/exec.h
index d4b338767fb..32bd748609e 100644
--- a/usr.sbin/ppp/exec.h
+++ b/usr.sbin/ppp/exec.h
@@ -32,4 +32,4 @@ struct device;
 extern struct device *exec_Create(struct physical *);
 extern struct device *exec_iov2device(int, struct physical *,
                                       struct iovec *, int *, int, int *, int *);
-#define exec_DeviceSize physical_DeviceSize
+extern unsigned exec_DeviceSize(void);
diff --git a/usr.sbin/ppp/main.c b/usr.sbin/ppp/main.c
index b4d5e29517d..fd826d0253a 100644
--- a/usr.sbin/ppp/main.c
+++ b/usr.sbin/ppp/main.c
@@ -509,9 +509,11 @@ main(int argc, char **argv)
       if (!sw.fg)
         setsid();
     } else {
-      /* -direct - STDIN_FILENO gets used by physical_Open */
+      /*
+       * -direct - STDIN_FILENO gets used by physical_Open.  STDOUT_FILENO
+       * *may* get used in exec/pipe mode.
+       */
       prompt_TtyInit(NULL);
-      close(STDOUT_FILENO);
       close(STDERR_FILENO);
     }
   } else {
diff --git a/usr.sbin/ppp/netgraph.c b/usr.sbin/ppp/netgraph.c
index 471dc0d15f5..23a575b4df3 100644
--- a/usr.sbin/ppp/netgraph.c
+++ b/usr.sbin/ppp/netgraph.c
@@ -235,7 +235,6 @@ ng_Read(struct physical *p, void *v, size_t n)
 {
   char hook[NG_HOOKSIZ];
 
-log_Printf(LogDEBUG, "ng_Read\n");
   switch (p->dl->state) {
     case DATALINK_DIAL:
     case DATALINK_LOGIN:
@@ -282,17 +281,18 @@ static void
 ng_device2iov(struct device *d, struct iovec *iov, int *niov,
               int maxiov __unused, int *auxfd, int *nauxfd)
 {
-  struct ngdevice *dev = device2ng(d);
+  struct ngdevice *dev;
   int sz = physical_MaxDeviceSize();
 
-  iov[*niov].iov_base = realloc(d, sz);
-  if (iov[*niov].iov_base == NULL) {
+  iov[*niov].iov_base = d = realloc(d, sz);
+  if (d == NULL) {
     log_Printf(LogALERT, "Failed to allocate memory: %d\n", sz);
     AbortProgram(EX_OSERR);
   }
   iov[*niov].iov_len = sz;
   (*niov)++;
 
+  dev = device2ng(d);
   *auxfd = dev->cs;
   (*nauxfd)++;
 }
diff --git a/usr.sbin/ppp/physical.c b/usr.sbin/ppp/physical.c
index ed3ab9c083e..03778006bcb 100644
--- a/usr.sbin/ppp/physical.c
+++ b/usr.sbin/ppp/physical.c
@@ -1017,6 +1017,7 @@ physical_Open(struct physical *p)
     p->fd = STDIN_FILENO;
     for (h = 0; h < NDEVICES && p->handler == NULL && p->fd >= 0; h++)
       p->handler = (*devices[h].create)(p);
+    close(STDOUT_FILENO);
     if (p->fd >= 0) {
       if (p->handler == NULL) {
         physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE);
diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4
index 2fc84e4c15b..66637595029 100644
--- a/usr.sbin/ppp/ppp.8.m4
+++ b/usr.sbin/ppp/ppp.8.m4
@@ -27,7 +27,7 @@ changecom(,)dnl
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 24, 2007
+.Dd August 25, 2009
 .Dt PPP 8
 .Os
 .Sh NAME
@@ -171,6 +171,17 @@ If callback is configured,
 will use the
 .Dq set device
 information when dialing back.
+.Pp
+When run in
+.Fl direct
+mode,
+.Nm
+will behave slightly differently if descriptor 0 was created by
+.Xr pipe 2 .
+As pipes are not bi-directional, ppp will redirect all writes to descriptor
+1 (standard output), leaving only reads acting on descriptor 0.
+No special action is taken if descriptor 0 was created by
+.Xr socketpair 2 .
 .It Fl dedicated
 This option is designed for machines connected with a dedicated
 wire.
@@ -6055,6 +6066,8 @@ This socket is used to pass links between different instances of
 .Xr tcpdump 1 ,
 .Xr telnet 1 ,
 .Xr kldload 2 ,
+.Xr pipe 2 ,
+.Xr socketpair 2 ,
 ifdef({LOCALNAT},{},{.Xr libalias 3 ,
 })dnl
 ifdef({LOCALRAD},{},{.Xr libradius 3 ,
diff --git a/usr.sbin/ppp/tty.c b/usr.sbin/ppp/tty.c
index 8d5d58bac28..ab984cca718 100644
--- a/usr.sbin/ppp/tty.c
+++ b/usr.sbin/ppp/tty.c
@@ -384,7 +384,6 @@ UnloadLineDiscipline(struct physical *p)
   struct ttydevice *dev = device2tty(p->handler);
 
   if (isngtty(dev)) {
-log_Printf(LogPHASE, "back to speed %d\n", dev->real.speed);
     if (!physical_SetSpeed(p, dev->real.speed))
       log_Printf(LogWARN, "Couldn't reset tty speed to %d\n", dev->real.speed);
     dev->real.speed = 0;
@@ -582,17 +581,19 @@ tty_device2iov(struct device *d, struct iovec *iov, int *niov,
 #endif
                )
 {
-  struct ttydevice *dev = device2tty(d);
+  struct ttydevice *dev;
   int sz = physical_MaxDeviceSize();
 
-  iov[*niov].iov_base = realloc(d, sz);
-  if (iov[*niov].iov_base == NULL) {
+  iov[*niov].iov_base = d = realloc(d, sz);
+  if (d == NULL) {
     log_Printf(LogALERT, "Failed to allocate memory: %d\n", sz);
     AbortProgram(EX_OSERR);
   }
   iov[*niov].iov_len = sz;
   (*niov)++;
 
+  dev = device2tty(d);
+
 #ifndef NONETGRAPH
   if (dev->cs >= 0) {
     *auxfd = dev->cs;
diff --git a/usr.sbin/pstat/pstat.c b/usr.sbin/pstat/pstat.c
index bf297f5ffba..54351667b27 100644
--- a/usr.sbin/pstat/pstat.c
+++ b/usr.sbin/pstat/pstat.c
@@ -460,6 +460,7 @@ getfiles(struct xfile **abuf, size_t *alen)
  */
 
 #define CONVERT(v)	((int64_t)(v) * pagesize / blocksize)
+#define CONVERT_BLOCKS(v)	((int64_t)(v) * pagesize)
 static struct kvm_swap swtot;
 static int nswdev;
 
@@ -492,10 +493,10 @@ print_swap_line(const char *swdevname, intmax_t nblks, intmax_t bused,
 	printf("%-15s %*jd ", swdevname, hlen, CONVERT(nblks));
 	if (humanflag) {
 		humanize_number(usedbuf, sizeof(usedbuf),
-		    CONVERT(blocksize * bused), "",
+		    CONVERT_BLOCKS(bused), "",
 		    HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
 		humanize_number(availbuf, sizeof(availbuf),
-		    CONVERT(blocksize * bavail), "",
+		    CONVERT_BLOCKS(bavail), "",
 		    HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
 		printf("%8s %8s %5.0f%%\n", usedbuf, availbuf, bpercent);
 	} else {
diff --git a/usr.sbin/sysinstall/devices.c b/usr.sbin/sysinstall/devices.c
index 3ba87325006..b95fdc595a5 100644
--- a/usr.sbin/sysinstall/devices.c
+++ b/usr.sbin/sysinstall/devices.c
@@ -80,6 +80,7 @@ static struct _devname {
     CDROM("acd%d",	"ATAPI/IDE CDROM",			4),
     DISK("da%d",	"SCSI disk device",			16),
     DISK("ad%d",	"ATA/IDE disk device",			16),
+    DISK("ada%d",	"SATA disk device",			16),
     DISK("ar%d",	"ATA/IDE RAID device",			16),
     DISK("afd%d",	"ATAPI/IDE floppy device",		4),
     DISK("mlxd%d",	"Mylex RAID disk",			4),
diff --git a/usr.sbin/sysinstall/install.c b/usr.sbin/sysinstall/install.c
index d00da3c8d4f..a2979c900b0 100644
--- a/usr.sbin/sysinstall/install.c
+++ b/usr.sbin/sysinstall/install.c
@@ -939,7 +939,7 @@ installFixupKernel(dialogMenuItem *self, int dists)
     if (RunningAsInit) {
 	/*
 	 * Install something as /boot/kernel.  Prefer SMP
-	 * over generic--this should handle the case where
+	 * over GENERIC--this should handle the case where
 	 * both SMP and GENERIC are installed (otherwise we
 	 * select the one kernel that was installed).
 	 *
diff --git a/usr.sbin/sysinstall/media.c b/usr.sbin/sysinstall/media.c
index e50b47c8edd..b325323c613 100644
--- a/usr.sbin/sysinstall/media.c
+++ b/usr.sbin/sysinstall/media.c
@@ -262,7 +262,8 @@ mediaSetUSB(dialogMenuItem *self)
 		mediaDevice = devs[0];
 	if (mediaDevice)
 		mediaDevice->private = NULL;
-	msgConfirm("Using USB device: %s", mediaDevice->name);
+	if (!variable_get(VAR_NONINTERACTIVE))
+		msgConfirm("Using USB device: %s", mediaDevice->name);
 	return (mediaDevice ? DITEM_LEAVE_MENU : DITEM_FAILURE);
 }
 
diff --git a/usr.sbin/sysinstall/sysinstall.8 b/usr.sbin/sysinstall/sysinstall.8
index 7cb55aa3808..46a14fc8d9c 100644
--- a/usr.sbin/sysinstall/sysinstall.8
+++ b/usr.sbin/sysinstall/sysinstall.8
@@ -411,9 +411,9 @@ Possible distribution values are:
 .Bl -tag -width indentxx
 .It Li base
 The base binary distribution.
-.It Li generic
+.It Li GENERIC
 The GENERIC kernel.
-.It Li smp
+.It Li SMP
 A kernel suitable for multiple processor systems.
 .It Li doc
 Miscellaneous documentation
diff --git a/usr.sbin/traceroute6/Makefile b/usr.sbin/traceroute6/Makefile
index 6ff72d2bf0c..60618a2ad40 100644
--- a/usr.sbin/traceroute6/Makefile
+++ b/usr.sbin/traceroute6/Makefile
@@ -13,12 +13,17 @@
 # A PARTICULAR PURPOSE.
 # $FreeBSD$
 
+TRACEROUTE_DISTDIR?= ${.CURDIR}/../../contrib/traceroute
+.PATH: ${TRACEROUTE_DISTDIR}
+
 PROG=	traceroute6
 MAN=	traceroute6.8
+SRCS=	as.c traceroute6.c
 BINOWN=	root
 BINMODE= 4555
 
 CFLAGS+= -DIPSEC -DUSE_RFC2292BIS -DHAVE_POLL
+CFLAGS+= -I${.CURDIR} -I${TRACEROUTE_DISTDIR} -I.
 
 DPADD=	${LIBIPSEC}
 LDADD=	-lipsec
diff --git a/usr.sbin/traceroute6/traceroute6.8 b/usr.sbin/traceroute6/traceroute6.8
index b6116f0aa1a..884ad6dc339 100644
--- a/usr.sbin/traceroute6/traceroute6.8
+++ b/usr.sbin/traceroute6/traceroute6.8
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 17, 1998
+.Dd August 24, 2009
 .Dt TRACEROUTE6 8
 .Os
 .\"
@@ -40,7 +40,7 @@
 .Sh SYNOPSIS
 .Nm
 .Bk -words
-.Op Fl dIlnNrvU
+.Op Fl adIlnNrvU
 .Ek
 .Bk -words
 .Op Fl f Ar firsthop
@@ -64,6 +64,9 @@
 .Op Fl w Ar waittime
 .Ek
 .Bk -words
+.Op Fl A Ar as_server
+.Ek
+.Bk -words
 .Ar target
 .Op Ar datalen
 .Ek
@@ -84,6 +87,10 @@ after the destination host name.
 .Pp
 Other options are:
 .Bl -tag -width Ds
+.It Fl a
+Turn on AS# lookups for each hop encountered.
+.It Fl A Ar as_server
+Turn on AS# lookups and use the given server instead of the default.
 .It Fl d
 Debug mode.
 .It Fl f Ar firsthop
diff --git a/usr.sbin/traceroute6/traceroute6.c b/usr.sbin/traceroute6/traceroute6.c
index d06502f076f..699af68c1dd 100644
--- a/usr.sbin/traceroute6/traceroute6.c
+++ b/usr.sbin/traceroute6/traceroute6.c
@@ -282,6 +282,8 @@ static const char rcsid[] =
 #include 
 #endif
 
+#include "as.h"
+
 #define DUMMY_PORT 10010
 
 #define	MAXPACKET	65535	/* max ip packet size */
@@ -359,6 +361,9 @@ int waittime = 5;		/* time to wait for response (in seconds) */
 int nflag;			/* print addresses numerically */
 int useproto = IPPROTO_UDP;	/* protocol to use to send packet */
 int lflag;			/* print both numerical address & hostname */
+int as_path;			/* print as numbers for each hop */
+char *as_server = NULL;
+void *asn;
 
 int
 main(argc, argv)
@@ -411,8 +416,15 @@ main(argc, argv)
 
 	seq = 0;
 
-	while ((ch = getopt(argc, argv, "df:g:Ilm:nNp:q:rs:Uvw:")) != -1)
+	while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:Uvw:")) != -1)
 		switch (ch) {
+		case 'a':
+			as_path = 1;
+			break;
+		case 'A':
+			as_path = 1;
+			as_server = optarg;
+			break;
 		case 'd':
 			options |= SO_DEBUG;
 			break;
@@ -867,6 +879,17 @@ main(argc, argv)
 		srcport = ntohs(Src.sin6_port);
 	}
 
+	if (as_path) {
+		asn = as_setup(as_server);
+		if (asn == NULL) {
+			fprintf(stderr,
+			    "traceroute6: as_setup failed, AS# lookups"
+			    " disabled\n");
+			(void)fflush(stderr);
+			as_path = 0;
+		}
+	}
+
 	/*
 	 * Message to users
 	 */
@@ -948,6 +971,8 @@ main(argc, argv)
 			exit(0);
 		}
 	}
+	if (as_path)
+		as_shutdown(asn);
 
 	exit(0);
 }
@@ -1361,6 +1386,8 @@ print(mhdr, cc)
 	if (getnameinfo((struct sockaddr *)from, from->sin6_len,
 	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
 		strlcpy(hbuf, "invalid", sizeof(hbuf));
+	if (as_path)
+		printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6));
 	if (nflag)
 		printf(" %s", hbuf);
 	else if (lflag)
diff --git a/usr.sbin/wpa/wpa_cli/Makefile b/usr.sbin/wpa/wpa_cli/Makefile
index ae16a72a0b9..123485a91fc 100644
--- a/usr.sbin/wpa/wpa_cli/Makefile
+++ b/usr.sbin/wpa/wpa_cli/Makefile
@@ -11,6 +11,8 @@ MAN=	wpa_cli.8
 
 CFLAGS+= -DCONFIG_CTRL_IFACE
 CFLAGS+= -DCONFIG_CTRL_IFACE_UNIX
+# enable use of d_type to identify unix domain sockets
+CFLAGS+= -D_DIRENT_HAVE_D_TYPE
 
 #CFLAGS+= -DCONFIG_READLINE
 #LDADD+= -ledit -ltermcap
diff --git a/usr.sbin/zic/zic.c b/usr.sbin/zic/zic.c
index cb959586a44..7670056fda5 100644
--- a/usr.sbin/zic/zic.c
+++ b/usr.sbin/zic/zic.c
@@ -3,7 +3,7 @@
 ** 2006-07-17 by Arthur David Olson.
 */
 
-static const char	elsieid[] = "@(#)zic.c	8.19";
+static const char	elsieid[] = "@(#)zic.c	8.20";
 
 #ifndef lint
 static const char rcsid[] =
@@ -1892,7 +1892,7 @@ const int			zonecount;
 		if (stdrp != NULL && stdrp->r_hiyear == 2037)
 			return;
 	}
-	if (stdrp == NULL && zp->z_nrules != 0)
+	if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0))
 		return;
 	abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
 	doabbr(result, zp->z_format, abbrvar, FALSE, TRUE);