From 4832a677bdc5f8b057d74087ff1eecc969fd52b9 Mon Sep 17 00:00:00 2001 From: Stefan Farfeleder Date: Sun, 20 Jun 2004 12:04:00 +0000 Subject: [PATCH 001/453] Remove files no longer on the vendor branch. --- usr.sbin/zic/Arts.htm | 177 ------------------------------------------ usr.sbin/zic/WWW.htm | 97 ----------------------- 2 files changed, 274 deletions(-) delete mode 100644 usr.sbin/zic/Arts.htm delete mode 100644 usr.sbin/zic/WWW.htm diff --git a/usr.sbin/zic/Arts.htm b/usr.sbin/zic/Arts.htm deleted file mode 100644 index 39dcab7cd19..00000000000 --- a/usr.sbin/zic/Arts.htm +++ /dev/null @@ -1,177 +0,0 @@ - - - -Time and the Arts - - -

Time and the Arts

-

-

-@(#)Arts.htm 7.18 -
-

-
-Data on recordings of "Save That Time," Russ Long, Serrob Publishing, BMI:
---------------------------------------------------------------------------
-Artist:		Karrin Allyson
-CD:		I Didn't Know About You
-Copyright Date:	1993
-Label:		Concord Jazz, Inc.
-ID:		CCD-4543
-Track Time:	3:44
-Personnel:	Karrin Allyson, vocal
-		Russ Long, piano
-		Gerald Spaits, bass
-		Todd Strait, drums
-Notes:		CD notes "additional lyric by Karrin Allyson;
-		arranged by Russ Long and Karrin Allyson"
-ADO Rating:	1 star
-AMG Rating:	3.5 stars
-Penguin Rating:	3.5 stars
---------------------------------------------------------------------------
-Artist:		Kevin Mahogany
-CD:		Double Rainbow
-Copyright Date:	1993
-Label:		Enja Records
-ID:		ENJ-7097 2
-Track Time:	6:27
-Personnel:	Kevin Mahogany, vocal
-		Kenny Barron, piano
-		Ray Drummond, bss
-		Ralph Moore, tenor saxophone
-		Lewis Nash, drums
-ADO Rating:	1.5 stars
-AMG Rating:	unrated
-Penguin Rating:	3 stars
---------------------------------------------------------------------------
-Artist:		Joe Williams
-CD:		Here's to Life
-Copyright Date:	1994
-Label:		Telarc International Corporation
-ID:		CD-83357
-Track Time:	3:58
-Personnel:	Joe Williams, vocal
-		The Robert Farnon [39 piece] Orchestra
-Notes:		On-line information and samples available at
-		http://telarc.dmn.com/telarc/releases/release.req?ID=83357
-ADO Rating:	black dot
-AMG Rating:	2 stars
-Penguin Rating:	3 stars
---------------------------------------------------------------------------
-Artist:		Charles Fambrough
-CD:		Keeper of the Spirit
-Copyright Date:	1995
-Label:		AudioQuest Music
-ID:		AQ-CD1033
-Track Time:	7:07
-Personnel:	Charles Fambrough, bass
-		Joel Levine, tenor recorder
-		Edward Simon, piano
-		Lenny White, drums
-		Marion Simon, percussion
-Notes:		On-line information and samples available at
-		http://wwmusic.com/~music/audioq/rel/1033.html
-ADO Rating:	2 stars
-AMG Rating:	unrated
-Penguin Rating:	3 stars
-==========================================================================
-Also of note:
---------------------------------------------------------------------------
-Artist:		Holly Cole Trio
-CD:		Blame It On My Youth
-Copyright Date:	1992
-Label:		Manhattan
-ID:		CDP 7 97349 2
-Total Time:	37:45
-Personnel:	Holly Cole, voice
-		Aaron Davis, piano
-		David Piltch, string bass
-Notes:		Lyrical reference to "Eastern Standard Time" in
-			Tom Waits' "Purple Avenue"
-ADO Rating:	2.5 stars
-AMG Rating:	2 stars
-Penguin Rating:	unrated
---------------------------------------------------------------------------
-Artist:		Milt Hinton
-CD:		Old Man Time
-Copyright Date:	1990
-Label:		Chiaroscuro
-ID:		CR(D) 310
-Total Time:	149:38 (two CDs)
-Personnel:	Milt Hinton, bass
-		Doc Cheatham, Dizzy Gillespie, Clark Terry, trumpet
-		Al Grey, trombone
-		Eddie Barefield, Joe Camel (Flip Phillips), Buddy Tate,
-			clarinet and saxophone
-		John Bunch, Red Richards, Norman Simmons, Derek Smith,
-			Ralph Sutton, piano
-		Danny Barker, Al Casey, guitar
-		Gus Johnson, Gerryck King, Bob Rosengarden, Jackie Williams,
-			drums
-		Lionel Hampton, vibraphone
-		Cab Calloway, Joe Williams, vocal
-		Buck Clayton, arrangements
-Notes:		tunes include Old Man Time, Time After Time,
-			Sometimes I'm Happy,
-			A Hot Time in the Old Town Tonight,
-			Four or Five Times, Now's the Time,
-			Time on My Hands, This Time It's Us,
-			and Good Time Charlie
-		On-line samples available at
-		http://www.globalmusic.com/labels/chiaroscuro/chiaro_cd_gallery.html
-ADO Rating:	3 stars
-AMG Rating:	4.5 stars
-Penguin Rating:	3 stars
---------------------------------------------------------------------------
-Artist:		Paul Broadbent
-CD:		Pacific Standard Time
-Copyright Date:	1995
-Label:		Concord Jazz, Inc.
-ID:		CCD-4664
-Total Time:	62:42
-Personnel:	Paul Broadbent, piano
-		Putter Smith, Bass
-		Frank Gibson, Jr., drums
-Notes:		The CD cover features an analemma for equation of time fans
-ADO Rating:	1 star
-AMG Rating:	3 stars
-Penguin Rating:	3.5 stars
---------------------------------------------------------------------------
-Artist:		Anthony Braxton/Richard Teitelbaum
-CD:		Silence/Time Zones
-Copyright Date:	1996
-Label:		Black Lion
-ID:		BLCD 760221
-Total Time:	72:58
-Personnel:	Anthony Braxton, sporanino and alto saxophones,
-			contrebasse clarinet, miscellaneous instruments
-		Leo Smith, trumpet and miscellaneous instruments
-		Leroy Jenkins, violin and miscellaneous instruments
-		Richard Teitelbaum, modular moog and micromoog synthesizer
-ADO Rating:	black dot
-AMG Rating:	unrated
---------------------------------------------------------------------------
-Artist:		Jules Verne
-Book:		Le Tour du Monde en Quatre-Vingts Jours
-		(Around the World in Eighty Days)
-Notes:		Wall-clock time plays a central role in the plot.
-		European readers of the 1870s clearly held the U.S. press in
-		deep contempt; the protagonists cross the U.S. without once
-		reading a paper.
-		An on-line French-language version of the book
-		"with illustrations from the original 1873 French-language edition"
-		is available at
-		http://fourmilab.ch/etexts/www/tdm80j
-		An on-line English-language translation of the book is available at
-		http://www.literature.org/Works/Jules-Verne/eighty
---------------------------------------------------------------------------
-Film:		Bell Science - About Time
-Notes:		The Frank Baxter/Richard Deacon extravaganza
-		Information on ordering is available at
-		http://www.videoflicks.com/VF/38/038332.htm
---------------------------------------------------------------------------
-The syndicated comic strip "Dilbert" featured an all-too-rare example of
-time zone humor on 1998-03-14.
-
- - diff --git a/usr.sbin/zic/WWW.htm b/usr.sbin/zic/WWW.htm deleted file mode 100644 index 2151c898e37..00000000000 --- a/usr.sbin/zic/WWW.htm +++ /dev/null @@ -1,97 +0,0 @@ - - - -Sources for Time Zone and Daylight Saving Time Data - - -

Sources for Time Zone and Daylight Saving Time Data

-

-

-@(#)WWW.htm 7.16 -
-

Paul Eggert writes:

-The public-domain tz database contains code and data -that represent the history of local time -for many representative locations around the globe. -It is updated periodically to reflect changes made by political bodies -to UTC offsets and daylight-saving rules. -This database (often called zoneinfo) -is used by several implementations, -including BSD, DJGPP, GNU/Linux, HP-UX, IRIX, Solaris, and UnixWare. -In the tz database's -FTP distribution, -the code is in the file tzcodeC.tar.gz, -where C is the code's version; -similarly, the data are in tzdataD.tar.gz, -where D is the data's version. -

-The GNU C Library -has an independent, thread-safe implementation of -a time zone file reader. -This library is freely available under the GNU Library General Public License, -and is widely used in GNU/Linux systems. -

-The Web has several other sources for time zone and daylight saving time data. -Here are some recent links that may be of interest. -

-

--- eggert@twinsun.com -(1998-09-22) -

-

Arthur David Olson writes:

-A good source of information about ISO 8601 seems to be -International -Standard Date and Time Notation -maintained by Markus Kuhn. -

--- arthur_david_olson@nih.gov -(1996-01-04) -

- - From 5197bde3b8832b8061853c0e72f300f16c10b9ed Mon Sep 17 00:00:00 2001 From: Edwin Groothuis Date: Sat, 27 Sep 2008 11:30:00 +0000 Subject: [PATCH 002/453] Flatten the dist tree of vendor/tzcode --- {lib/libc => libc}/stdtime/asctime.c | 0 {lib/libc => libc}/stdtime/difftime.c | 0 {lib/libc => libc}/stdtime/localtime.c | 0 {lib/libc => libc}/stdtime/private.h | 0 {lib/libc => libc}/stdtime/strftime.c | 0 {lib/libc => libc}/stdtime/time2posix.3 | 0 {lib/libc => libc}/stdtime/tzfile.5 | 0 {lib/libc => libc}/stdtime/tzfile.h | 0 {usr.sbin/zic => zic}/Makefile | 0 {usr.sbin/zic => zic}/Music | 0 {usr.sbin/zic => zic}/README | 0 {usr.sbin/zic => zic}/Theory | 0 {usr.sbin/zic => zic}/WWW | 0 {usr.sbin/zic => zic}/ialloc.c | 0 {usr.sbin/zic => zic}/private.h | 0 {usr.sbin/zic => zic}/scheck.c | 0 {usr.sbin/zic => zic}/tz-art.htm | 0 {usr.sbin/zic => zic}/tz-link.htm | 0 {usr.sbin/zic => zic}/zdump.8 | 0 {usr.sbin/zic => zic}/zdump.c | 0 {usr.sbin/zic => zic}/zic.8 | 0 {usr.sbin/zic => zic}/zic.c | 0 22 files changed, 0 insertions(+), 0 deletions(-) rename {lib/libc => libc}/stdtime/asctime.c (100%) rename {lib/libc => libc}/stdtime/difftime.c (100%) rename {lib/libc => libc}/stdtime/localtime.c (100%) rename {lib/libc => libc}/stdtime/private.h (100%) rename {lib/libc => libc}/stdtime/strftime.c (100%) rename {lib/libc => libc}/stdtime/time2posix.3 (100%) rename {lib/libc => libc}/stdtime/tzfile.5 (100%) rename {lib/libc => libc}/stdtime/tzfile.h (100%) rename {usr.sbin/zic => zic}/Makefile (100%) rename {usr.sbin/zic => zic}/Music (100%) rename {usr.sbin/zic => zic}/README (100%) rename {usr.sbin/zic => zic}/Theory (100%) rename {usr.sbin/zic => zic}/WWW (100%) rename {usr.sbin/zic => zic}/ialloc.c (100%) rename {usr.sbin/zic => zic}/private.h (100%) rename {usr.sbin/zic => zic}/scheck.c (100%) rename {usr.sbin/zic => zic}/tz-art.htm (100%) rename {usr.sbin/zic => zic}/tz-link.htm (100%) rename {usr.sbin/zic => zic}/zdump.8 (100%) rename {usr.sbin/zic => zic}/zdump.c (100%) rename {usr.sbin/zic => zic}/zic.8 (100%) rename {usr.sbin/zic => zic}/zic.c (100%) diff --git a/lib/libc/stdtime/asctime.c b/libc/stdtime/asctime.c similarity index 100% rename from lib/libc/stdtime/asctime.c rename to libc/stdtime/asctime.c diff --git a/lib/libc/stdtime/difftime.c b/libc/stdtime/difftime.c similarity index 100% rename from lib/libc/stdtime/difftime.c rename to libc/stdtime/difftime.c diff --git a/lib/libc/stdtime/localtime.c b/libc/stdtime/localtime.c similarity index 100% rename from lib/libc/stdtime/localtime.c rename to libc/stdtime/localtime.c diff --git a/lib/libc/stdtime/private.h b/libc/stdtime/private.h similarity index 100% rename from lib/libc/stdtime/private.h rename to libc/stdtime/private.h diff --git a/lib/libc/stdtime/strftime.c b/libc/stdtime/strftime.c similarity index 100% rename from lib/libc/stdtime/strftime.c rename to libc/stdtime/strftime.c diff --git a/lib/libc/stdtime/time2posix.3 b/libc/stdtime/time2posix.3 similarity index 100% rename from lib/libc/stdtime/time2posix.3 rename to libc/stdtime/time2posix.3 diff --git a/lib/libc/stdtime/tzfile.5 b/libc/stdtime/tzfile.5 similarity index 100% rename from lib/libc/stdtime/tzfile.5 rename to libc/stdtime/tzfile.5 diff --git a/lib/libc/stdtime/tzfile.h b/libc/stdtime/tzfile.h similarity index 100% rename from lib/libc/stdtime/tzfile.h rename to libc/stdtime/tzfile.h diff --git a/usr.sbin/zic/Makefile b/zic/Makefile similarity index 100% rename from usr.sbin/zic/Makefile rename to zic/Makefile diff --git a/usr.sbin/zic/Music b/zic/Music similarity index 100% rename from usr.sbin/zic/Music rename to zic/Music diff --git a/usr.sbin/zic/README b/zic/README similarity index 100% rename from usr.sbin/zic/README rename to zic/README diff --git a/usr.sbin/zic/Theory b/zic/Theory similarity index 100% rename from usr.sbin/zic/Theory rename to zic/Theory diff --git a/usr.sbin/zic/WWW b/zic/WWW similarity index 100% rename from usr.sbin/zic/WWW rename to zic/WWW diff --git a/usr.sbin/zic/ialloc.c b/zic/ialloc.c similarity index 100% rename from usr.sbin/zic/ialloc.c rename to zic/ialloc.c diff --git a/usr.sbin/zic/private.h b/zic/private.h similarity index 100% rename from usr.sbin/zic/private.h rename to zic/private.h diff --git a/usr.sbin/zic/scheck.c b/zic/scheck.c similarity index 100% rename from usr.sbin/zic/scheck.c rename to zic/scheck.c diff --git a/usr.sbin/zic/tz-art.htm b/zic/tz-art.htm similarity index 100% rename from usr.sbin/zic/tz-art.htm rename to zic/tz-art.htm diff --git a/usr.sbin/zic/tz-link.htm b/zic/tz-link.htm similarity index 100% rename from usr.sbin/zic/tz-link.htm rename to zic/tz-link.htm diff --git a/usr.sbin/zic/zdump.8 b/zic/zdump.8 similarity index 100% rename from usr.sbin/zic/zdump.8 rename to zic/zdump.8 diff --git a/usr.sbin/zic/zdump.c b/zic/zdump.c similarity index 100% rename from usr.sbin/zic/zdump.c rename to zic/zdump.c diff --git a/usr.sbin/zic/zic.8 b/zic/zic.8 similarity index 100% rename from usr.sbin/zic/zic.8 rename to zic/zic.8 diff --git a/usr.sbin/zic/zic.c b/zic/zic.c similarity index 100% rename from usr.sbin/zic/zic.c rename to zic/zic.c From 9556ff65cd40f2afcdbab50cd76fc44ed2d3dcc3 Mon Sep 17 00:00:00 2001 From: Edwin Groothuis Date: Sat, 27 Sep 2008 12:24:26 +0000 Subject: [PATCH 003/453] Cleanup of vendor/tzcode/dist, these files don't exist in the latest imported sources. --- libc/stdtime/time2posix.3 | 119 ------------- libc/stdtime/tzfile.5 | 138 -------------- zic/Makefile | 365 -------------------------------------- zic/WWW | 71 -------- 4 files changed, 693 deletions(-) delete mode 100644 libc/stdtime/time2posix.3 delete mode 100644 libc/stdtime/tzfile.5 delete mode 100644 zic/Makefile delete mode 100644 zic/WWW diff --git a/libc/stdtime/time2posix.3 b/libc/stdtime/time2posix.3 deleted file mode 100644 index 846a52ed193..00000000000 --- a/libc/stdtime/time2posix.3 +++ /dev/null @@ -1,119 +0,0 @@ -.TH TIME2POSIX 3 -.SH NAME -time2posix, posix2time \- convert seconds since the Epoch -.SH SYNOPSIS -.nf -.B #include -.B #include -.PP -.B time_t time2posix(t) -.B time_t t -.PP -.B time_t posix2time(t) -.B time_t t -.PP -.B cc ... -lz -.fi -.SH DESCRIPTION -IEEE Standard 1003.1 -(POSIX) -legislates that a time_t value of -536457599 shall correspond to "Wed Dec 31 23:59:59 GMT 1986." -This effectively implies that POSIX time_t's cannot include leap -seconds and, -therefore, -that the system time must be adjusted as each leap occurs. -.PP -If the time package is configured with leap-second support -enabled, -however, -no such adjustment is needed and -time_t values continue to increase over leap events -(as a true `seconds since...' value). -This means that these values will differ from those required by POSIX -by the net number of leap seconds inserted since the Epoch. -.PP -Typically this is not a problem as the type time_t is intended -to be -(mostly) -opaque\(emtime_t values should only be obtained-from and -passed-to functions such as -.IR time(2) , -.IR localtime(3) , -.IR mktime(3) , -and -.IR difftime(3) . -However, -POSIX gives an arithmetic -expression for directly computing a time_t value from a given date/time, -and the same relationship is assumed by some -(usually older) -applications. -Any programs creating/dissecting time_t's -using such a relationship will typically not handle intervals -over leap seconds correctly. -.PP -The -.I time2posix -and -.I posix2time -functions are provided to address this time_t mismatch by converting -between local time_t values and their POSIX equivalents. -This is done by accounting for the number of time-base changes that -would have taken place on a POSIX system as leap seconds were inserted -or deleted. -These converted values can then be used in lieu of correcting the older -applications, -or when communicating with POSIX-compliant systems. -.PP -.I Time2posix -is single-valued. -That is, -every local time_t -corresponds to a single POSIX time_t. -.I Posix2time -is less well-behaved: -for a positive leap second hit the result is not unique, -and for a negative leap second hit the corresponding -POSIX time_t doesn't exist so an adjacent value is returned. -Both of these are good indicators of the inferiority of the -POSIX representation. -.PP -The following table summarizes the relationship between a time -T and it's conversion to, -and back from, -the POSIX representation over the leap second inserted at the end of June, -1993. -.nf -.ta \w'93/06/30 'u +\w'23:59:59 'u +\w'A+0 'u +\w'X=time2posix(T) 'u -DATE TIME T X=time2posix(T) posix2time(X) -93/06/30 23:59:59 A+0 B+0 A+0 -93/06/30 23:59:60 A+1 B+1 A+1 or A+2 -93/07/01 00:00:00 A+2 B+1 A+1 or A+2 -93/07/01 00:00:01 A+3 B+2 A+3 - -A leap second deletion would look like... - -DATE TIME T X=time2posix(T) posix2time(X) -??/06/30 23:59:58 A+0 B+0 A+0 -??/07/01 00:00:00 A+1 B+2 A+1 -??/07/01 00:00:01 A+2 B+3 A+2 -.sp -.ce - [Note: posix2time(B+1) => A+0 or A+1] -.fi -.PP -If leap-second support is not enabled, -local time_t's and -POSIX time_t's are equivalent, -and both -.I time2posix -and -.I posix2time -degenerate to the identity function. -.SH SEE ALSO -difftime(3), -localtime(3), -mktime(3), -time(2) -.\" @(#)time2posix.3 7.3 diff --git a/libc/stdtime/tzfile.5 b/libc/stdtime/tzfile.5 deleted file mode 100644 index c7ef0b4ff47..00000000000 --- a/libc/stdtime/tzfile.5 +++ /dev/null @@ -1,138 +0,0 @@ -.TH TZFILE 5 -.SH NAME -tzfile \- time zone information -.SH SYNOPSIS -.B -#include -.SH DESCRIPTION -The time zone information files used by -.IR tzset (3) -begin with the magic characters "TZif" to identify then as -time zone information files, -followed by sixteen bytes reserved for future use, -followed by six four-byte values of type -.BR long , -written in a ``standard'' byte order -(the high-order byte of the value is written first). -These values are, -in order: -.TP -.I tzh_ttisgmtcnt -The number of UTC/local indicators stored in the file. -.TP -.I tzh_ttisstdcnt -The number of standard/wall indicators stored in the file. -.TP -.I tzh_leapcnt -The number of leap seconds for which data is stored in the file. -.TP -.I tzh_timecnt -The number of "transition times" for which data is stored -in the file. -.TP -.I tzh_typecnt -The number of "local time types" for which data is stored -in the file (must not be zero). -.TP -.I tzh_charcnt -The number of characters of "time zone abbreviation strings" -stored in the file. -.PP -The above header is followed by -.I tzh_timecnt -four-byte values of type -.BR long , -sorted in ascending order. -These values are written in ``standard'' byte order. -Each is used as a transition time (as returned by -.IR time (2)) -at which the rules for computing local time change. -Next come -.I tzh_timecnt -one-byte values of type -.BR "unsigned char" ; -each one tells which of the different types of ``local time'' types -described in the file is associated with the same-indexed transition time. -These values serve as indices into an array of -.I ttinfo -structures that appears next in the file; -these structures are defined as follows: -.in +.5i -.sp -.nf -.ta .5i +\w'unsigned int\0\0'u -struct ttinfo { - long tt_gmtoff; - int tt_isdst; - unsigned int tt_abbrind; -}; -.in -.5i -.fi -.sp -Each structure is written as a four-byte value for -.I tt_gmtoff -of type -.BR long , -in a standard byte order, followed by a one-byte value for -.I tt_isdst -and a one-byte value for -.IR tt_abbrind . -In each structure, -.I tt_gmtoff -gives the number of seconds to be added to UTC, -.I tt_isdst -tells whether -.I tm_isdst -should be set by -.I localtime (3) -and -.I tt_abbrind -serves as an index into the array of time zone abbreviation characters -that follow the -.I ttinfo -structure(s) in the file. -.PP -Then there are -.I tzh_leapcnt -pairs of four-byte values, written in standard byte order; -the first value of each pair gives the time -(as returned by -.IR time(2)) -at which a leap second occurs; -the second gives the -.I total -number of leap seconds to be applied after the given time. -The pairs of values are sorted in ascending order by time. -.PP -Then there are -.I tzh_ttisstdcnt -standard/wall indicators, each stored as a one-byte value; -they tell whether the transition times associated with local time types -were specified as standard time or wall clock time, -and are used when a time zone file is used in handling POSIX-style -time zone environment variables. -.PP -Finally there are -.I tzh_ttisgmtcnt -UTC/local indicators, each stored as a one-byte value; -they tell whether the transition times associated with local time types -were specified as UTC or local time, -and are used when a time zone file is used in handling POSIX-style -time zone environment variables. -.PP -.I Localtime -uses the first standard-time -.I ttinfo -structure in the file -(or simply the first -.I ttinfo -structure in the absence of a standard-time structure) -if either -.I tzh_timecnt -is zero or the time argument is less than the first transition time recorded -in the file. -.SH SEE ALSO -newctime(3) -.\" @(#)tzfile.5 7.11 -.\" This file is in the public domain, so clarified as of -.\" 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). diff --git a/zic/Makefile b/zic/Makefile deleted file mode 100644 index 0aefc95e3d5..00000000000 --- a/zic/Makefile +++ /dev/null @@ -1,365 +0,0 @@ -# @(#)Makefile 7.67 - -# Change the line below for your time zone (after finding the zone you want in -# the time zone files, or adding it to a time zone file). -# Alternately, if you discover you've got the wrong time zone, you can just -# zic -l rightzone -# to correct things. -# Use the command -# make zonenames -# to get a list of the values you can use for LOCALTIME. - -LOCALTIME= Factory - -# If you want something other than Eastern United States time as a template -# for handling POSIX-style time zone environment variables, -# change the line below (after finding the zone you want in the -# time zone files, or adding it to a time zone file). -# (When a POSIX-style environment variable is handled, the rules in the -# template file are used to determine "spring forward" and "fall back" days and -# times; the environment variable itself specifies UTC offsets of standard and -# summer time.) -# Alternately, if you discover you've got the wrong time zone, you can just -# zic -p rightzone -# to correct things. -# Use the command -# make zonenames -# to get a list of the values you can use for POSIXRULES. -# If you want POSIX compatibility, use "America/New_York". - -POSIXRULES= America/New_York - -# Everything gets put in subdirectories of. . . - -TOPDIR= /usr/local - -# "Compiled" time zone information is placed in the "TZDIR" directory -# (and subdirectories). -# Use an absolute path name for TZDIR unless you're just testing the software. - -TZDIR= $(TOPDIR)/etc/zoneinfo - -# The "zic" and "zdump" commands get installed in. . . - -ETCDIR= $(TOPDIR)/etc - -# If you "make INSTALL", the "date" command gets installed in. . . - -BINDIR= $(TOPDIR)/bin - -# Manual pages go in subdirectories of. . . - -MANDIR= $(TOPDIR)/man - -# Library functions are put in an archive in LIBDIR. - -LIBDIR= $(TOPDIR)/lib -TZLIB= $(LIBDIR)/libtz.a - -# If you always want time values interpreted as "seconds since the epoch -# (not counting leap seconds)", use -# REDO= posix_only -# below. If you always want right time values interpreted as "seconds since -# the epoch" (counting leap seconds)", use -# REDO= right_only -# below. If you want both sets of data available, with leap seconds not -# counted normally, use -# REDO= posix_right -# below. If you want both sets of data available, with leap seconds counted -# normally, use -# REDO= right_posix -# below. -# POSIX mandates that leap seconds not be counted; for compatibility with it, -# use either "posix_only" or "posix_right". - -REDO= posix_right - -# Since "." may not be in PATH... - -YEARISTYPE= ./yearistype - -# Non-default libraries needed to link. -# Add -lintl if you want to use `gettext' on Solaris. -LDLIBS= - -# Add the following to the end of the "CFLAGS=" line as needed. -# -DHAVE_ADJTIME=0 if `adjtime' does not exist (SVR0?) -# -DHAVE_GETTEXT=1 if `gettext' works (GNU, Linux, Solaris); also see LDLIBS -# -DHAVE_LONG_DOUBLE=1 if your compiler supports the `long double' type -# -DHAVE_SETTIMEOFDAY=0 if settimeofday does not exist (SVR0?) -# -DHAVE_SETTIMEOFDAY=1 if settimeofday has just 1 arg (SVR4) -# -DHAVE_SETTIMEOFDAY=2 if settimeofday uses 2nd arg (4.3BSD) -# -DHAVE_SETTIMEOFDAY=3 if settimeofday ignores 2nd arg (4.4BSD) -# -DHAVE_STRERROR=1 if `strerror' works -# -DHAVE_SYMLINK=0 if your system lacks the symlink function -# -DLOCALE_HOME=\"path\" if locales are in "path", not "/usr/lib/locale" -# -DHAVE_UNISTD_H=0 if your compiler lacks a "unistd.h" (Microsoft C++ 7?) -# -DHAVE_UTMPX_H=1 if your compiler has a "utmpx.h" -# -DTZ_DOMAIN=\"foo\" to use "foo" for gettext domain name; default is "tz" -# -TTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory; -# the default is system-supplied, typically "/usr/lib/locale" -# $(GCC_DEBUG_FLAGS) if you are using GCC and want lots of checking -# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1 -# if you do not want run time warnings about formats that may cause -# year 2000 grief -# -GCC_DEBUG_FLAGS = -Dlint -g -O -fno-common \ - -Wall -Wcast-qual -Wconversion -Wmissing-prototypes \ - -Wnested-externs -Wpointer-arith -Wshadow \ - -Wtraditional # -Wstrict-prototypes -Wwrite-strings -# -# If you want to use System V compatibility code, add -# -DUSG_COMPAT -# to the end of the "CFLAGS=" line. This arrange for "timezone" and "daylight" -# variables to be kept up-to-date by the time conversion functions. Neither -# "timezone" nor "daylight" is described in X3J11's work. -# -# If your system has a "GMT offset" field in its "struct tm"s -# (or if you decide to add such a field in your system's "time.h" file), -# add the name to a define such as -# -DTM_GMTOFF=tm_gmtoff -# or -# -DTM_GMTOFF=_tm_gmtoff -# to the end of the "CFLAGS=" line. -# Neither tm_gmtoff nor _tm_gmtoff is described in X3J11's work; -# in its work, use of "tm_gmtoff" is described as non-conforming. -# Both Linux and BSD have done the equivalent of defining TM_GMTOFF in -# their recent releases. -# -# If your system has a "zone abbreviation" field in its "struct tm"s -# (or if you decide to add such a field in your system's "time.h" file), -# add the name to a define such as -# -DTM_ZONE=tm_zone -# or -# -DTM_ZONE=_tm_zone -# to the end of the "CFLAGS=" line. -# Neither tm_zone nor _tm_zone is described in X3J11's work; -# in its work, use of "tm_zone" is described as non-conforming. -# Both UCB and Sun have done the equivalent of defining TM_ZONE in -# their recent releases. -# -# If you want functions that were inspired by early versions of X3J11's work, -# add -# -DSTD_INSPIRED -# to the end of the "CFLAGS=" line. This arranges for the functions -# "tzsetwall", "offtime", "timelocal", "timegm", "timeoff", -# "posix2time", and "time2posix" to be added to the time conversion library. -# "tzsetwall" is like "tzset" except that it arranges for local wall clock -# time (rather than the time specified in the TZ environment variable) -# to be used. -# "offtime" is like "gmtime" except that it accepts a second (long) argument -# that gives an offset to add to the time_t when converting it. -# "timelocal" is equivalent to "mktime". -# "timegm" is like "timelocal" except that it turns a struct tm into -# a time_t using UTC (rather than local time as "timelocal" does). -# "timeoff" is like "timegm" except that it accepts a second (long) argument -# that gives an offset to use when converting to a time_t. -# "posix2time" and "time2posix" are described in an included manual page. -# None of these functions are described in X3J11's current work. -# Sun has provided "tzsetwall", "timelocal", and "timegm" in SunOS 4.0. -# These functions may well disappear in future releases of the time -# conversion package. -# -# If you want Source Code Control System ID's left out of object modules, add -# -DNOID -# to the end of the "CFLAGS=" line. -# -# If you'll never want to handle solar-time-based time zones, add -# -DNOSOLAR -# to the end of the "CFLAGS=" line -# (and comment out the "SDATA=" line below). -# This reduces (slightly) the run-time data-space requirements of -# the time conversion functions; it may reduce the acceptability of your system -# to folks in oil- and cash-rich places. -# -# If you want to allocate state structures in localtime, add -# -DALL_STATE -# to the end of the "CFLAGS=" line. Storage is obtained by calling malloc. -# -# If you want an "altzone" variable (a la System V Release 3.1), add -# -DALTZONE -# to the end of the "CFLAGS=" line. -# This variable is not described in X3J11's work. -# -# If you want a "gtime" function (a la MACH), add -# -DCMUCS -# to the end of the "CFLAGS=" line -# This function is not described in X3J11's work. -# -# NIST-PCTS:151-2, Version 1.4, (1993-12-03) is a test suite put -# out by the National Institute of Standards and Technology -# which claims to test C and Posix conformance. If you want to pass PCTS, add -# -DPCTS -# to the end of the "CFLAGS=" line. -# -# If you want strict compliance with XPG4 as of 1994-04-09, add -# -DXPG4_1994_04_09 -# to the end of the "CFLAGS=" line. This causes "strftime" to always return -# 53 as a week number (rather than 52 or 53) for those days in January that -# before the first Monday in January when a "%V" format is used and January 1 -# falls on a Friday, Saturday, or Sunday. - -CFLAGS= - -# If you want zic's -s option used when installing, uncomment the next line -# ZFLAGS= -s - -zic= ./zic -ZIC= $(zic) $(ZFLAGS) - -# The name of a Posix-compliant `awk' on your system. -AWK= awk - -############################################################################### - -cc= cc -CC= $(cc) -DTZDIR=\"$(TZDIR)\" - -TZCSRCS= zic.c localtime.c asctime.c scheck.c ialloc.c -TZCOBJS= zic.o localtime.o asctime.o scheck.o ialloc.o -TZDSRCS= zdump.c localtime.c asctime.c ialloc.c -TZDOBJS= zdump.o localtime.o asctime.o ialloc.o -DATESRCS= date.c localtime.c logwtmp.c strftime.c asctime.c -DATEOBJS= date.o localtime.o logwtmp.o strftime.o asctime.o -LIBSRCS= localtime.c asctime.c difftime.c -LIBOBJS= localtime.o asctime.o difftime.o -HEADERS= tzfile.h private.h -NONLIBSRCS= zic.c zdump.c scheck.c ialloc.c -NEWUCBSRCS= date.c logwtmp.c strftime.c -SOURCES= $(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS) tzselect.ksh -MANS= newctime.3 newstrftime.3 newtzset.3 time2posix.3 \ - tzfile.5 tzselect.8 zic.8 zdump.8 -DOCS= README Theory $(MANS) date.1 Makefile -PRIMARY_YDATA= africa antarctica asia australasia \ - europe northamerica southamerica -YDATA= $(PRIMARY_YDATA) pacificnew etcetera factory backward -NDATA= systemv -SDATA= solar87 solar88 solar89 -TDATA= $(YDATA) $(NDATA) $(SDATA) -TABDATA= iso3166.tab zone.tab -DATA= $(YDATA) $(NDATA) $(SDATA) $(TABDATA) leapseconds yearistype.sh -MISC= usno1988 usno1989 usno1989a usno1995 usno1997 usno1998 \ - Arts.htm WWW.htm gccdiffs checktab.awk -ENCHILADA= $(DOCS) $(SOURCES) $(DATA) $(MISC) - -# And for the benefit of csh users on systems that assume the user -# shell should be used to handle commands in Makefiles. . . - -SHELL= /bin/sh - -all: zic zdump $(LIBOBJS) - -ALL: all date tzselect - -install: all $(DATA) $(REDO) $(TZLIB) $(MANS) $(TABDATA) - $(ZIC) -y $(YEARISTYPE) \ - -d $(TZDIR) -l $(LOCALTIME) -p $(POSIXRULES) - -rm -f $(TZDIR)/iso3166.tab $(TZDIR)/zone.tab - cp iso3166.tab zone.tab $(TZDIR)/. - -mkdir $(TOPDIR) $(ETCDIR) - cp zic zdump $(ETCDIR)/. - -mkdir $(TOPDIR) $(MANDIR) \ - $(MANDIR)/man3 $(MANDIR)/man5 $(MANDIR)/man8 - -rm -f $(MANDIR)/man3/newctime.3 \ - $(MANDIR)/man3/newtzset.3 \ - $(MANDIR)/man5/tzfile.5 \ - $(MANDIR)/man8/tzselect.8 \ - $(MANDIR)/man8/zdump.8 \ - $(MANDIR)/man8/zic.8 - cp newctime.3 newtzset.3 $(MANDIR)/man3/. - cp tzfile.5 $(MANDIR)/man5/. - cp tzselect.8 zdump.8 zic.8 $(MANDIR)/man8/. - -INSTALL: ALL install date.1 - -mkdir $(TOPDIR) $(BINDIR) - cp date $(BINDIR)/. - -mkdir $(TOPDIR) $(MANDIR) $(MANDIR)/man1 - -rm -f $(MANDIR)/man1/date.1 - cp date.1 $(MANDIR)/man1/. - -zdump: $(TZDOBJS) - $(CC) $(CFLAGS) $(LFLAGS) $(TZDOBJS) $(LDLIBS) -o $@ - -zic: $(TZCOBJS) yearistype - $(CC) $(CFLAGS) $(LFLAGS) $(TZCOBJS) $(LDLIBS) -o $@ - -yearistype: yearistype.sh - cp yearistype.sh yearistype - chmod +x yearistype - -posix_only: zic $(TDATA) - $(ZIC) -y $(YEARISTYPE) -d $(TZDIR) -L /dev/null $(TDATA) - -right_only: zic leapseconds $(TDATA) - $(ZIC) -y $(YEARISTYPE) -d $(TZDIR) -L leapseconds $(TDATA) - -# In earlier versions of this makefile, the other two directories were -# subdirectories of $(TZDIR). However, this led to configuration errors. -# For example, with posix_right under the earlier scheme, -# TZ='right/Australia/Adelaide' got you localtime with leap seconds, -# but gmtime without leap seconds, which led to problems with applications -# like sendmail that subtract gmtime from localtime. -# Therefore, the other two directories are now siblings of $(TZDIR). -# You must replace all of $(TZDIR) to switch from not using leap seconds -# to using them, or vice versa. -other_two: zic leapseconds $(TDATA) - $(ZIC) -y $(YEARISTYPE) -d $(TZDIR)-posix -L /dev/null $(TDATA) - $(ZIC) -y $(YEARISTYPE) \ - -d $(TZDIR)-leaps -L leapseconds $(TDATA) - -posix_right: posix_only other_two - -right_posix: right_only other_two - -zones: $(REDO) - -$(TZLIB): $(LIBOBJS) - -mkdir $(TOPDIR) $(LIBDIR) - ar ru $@ $(LIBOBJS) - if [ -x /usr/ucb/ranlib -o -x /usr/bin/ranlib ] ; \ - then ranlib $@ ; fi - -# We use the system's logwtmp in preference to ours if available. - -date: $(DATEOBJS) - ar r ,lib.a logwtmp.o - if [ -x /usr/ucb/ranlib -o -x /usr/bin/ranlib ] ; \ - then ranlib ,lib.a ; fi - $(CC) $(CFLAGS) date.o localtime.o asctime.o strftime.o \ - $(LDLIBS) -lc ,lib.a -o $@ - rm -f ,lib.a - -tzselect: tzselect.ksh - sed \ - -e 's|AWK=[^}]*|AWK=$(AWK)|g' \ - -e 's|TZDIR=[^}]*|TZDIR=$(TZDIR)|' \ - <$? >$@ - chmod +x $@ - -check_tables: checktab.awk $(PRIMARY_YDATA) - $(AWK) -f checktab.awk $(PRIMARY_YDATA) - -clean: - rm -f core *.o *.out tzselect zdump zic yearistype date \ - ,* *.tar.gz - -names: - @echo $(ENCHILADA) - -public: $(ENCHILADA) - tar cf - $(DOCS) $(SOURCES) $(MISC) | gzip -9 > tzcode.tar.gz - tar cf - $(DATA) | gzip -9 > tzdata.tar.gz - -zonenames: $(TDATA) - @awk '/^Zone/ { print $$2 } /^Link/ { print $$3 }' $(TDATA) - -asctime.o: private.h tzfile.h -date.o: private.h -difftime.o: private.h -ialloc.o: private.h -localtime.o: private.h tzfile.h -scheck.o: private.h -strftime.o: tzfile.h -zic.o: private.h tzfile.h - -.KEEP_STATE: diff --git a/zic/WWW b/zic/WWW deleted file mode 100644 index d2fd6844819..00000000000 --- a/zic/WWW +++ /dev/null @@ -1,71 +0,0 @@ -# '@(#)WWW 7.3' - -# From Paul Eggert (1995-11-03) -# -# The Web has several other sources for time zone and daylight savings data. -# Here are some recent links that may be of interest. -# -# Date and Time Gateway -# http://www.bsdi.com/date -# A text-based source for tables of current time throughout the world. -# Its point-and-click interface accesses a recent version of the tz data. -# -# Local Times Around the World -# http://www.hilink.com.au/times/ -# This text-based system contains links to local time servers -# throughout the world, and though the coverage is limited, -# the live data provide a nice way to check one's tables. -# -# World Time Zones -# http://tycho.usno.navy.mil/tzones.html -# US Naval Observatory data, used as the source for `usno1995'. -# -# Standard Time Zones of the World -# http://www.odci.gov/cia/publications/95fact/802389.gif [54 kB] -# http://www.odci.gov/cia/publications/95fact/802389h.gif [1317 kB] -# A static time zone map, available in both low-resolution and -# high-resolution versions. The quality is good, but the map does not -# indicate summer time, and parts of the data are a few years out of date. -# -# VIBE's World Map -# http://pathfinder.com/vibe/vibeworld -# An active time zone map. You can point to the map and find out what -# time it is at that location. The map and data are not as good as -# other sources. - -############################################################################### - -# From Manavendra Thakur (1995-11-06) -# -# To Paul's list of time zone information on the web, I would add the -# following URL: -# http://www.dhl.com/dhl/dhlinfo/1bb.html -# or more simply: -# http://www.dhl.com/ -# -# This is run by DHL (the courier company), and it presents a list of the -# countries served by that company. If you then click on a particular -# country, here's an example of what you'll see (graphics stripped out): -# -# United Kingdom -# -# HOLIDAYS: Jan 1, 2, Apr 14, 17, May 1, 29, Aug 28, Dec 25, 26 -# -# INTERNATIONAL DIALING CODE: +44 -# -# CURRENT LOCAL TIME: 09:41 Monday 6 November 1995 -# -# I find this rather handy, and given that DHL covers 217 countries and -# territories, it's pretty comprehensive coverage. -# -# (I have no idea what system DHL is using to calculate the local time, but -# it's been accurate so far.) - -############################################################################### - - -# From Arthur David Olson (1996-01-04) -# -# A good source of information about ISO 8601 seems to be -# http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html -# maintained by Markus Kuhn. From 80ca36b52f4732dba27b6bb58743c0f1ab5bd8e3 Mon Sep 17 00:00:00 2001 From: Edwin Groothuis Date: Wed, 20 May 2009 12:24:39 +0000 Subject: [PATCH 004/453] Vendor import of tzcode2009e. Obtained from: ftp://elsie.nci.nih.gov/pub/ --- libc/stdtime/asctime.c | 106 +++- libc/stdtime/difftime.c | 98 ++-- libc/stdtime/localtime.c | 809 ++++++++++++++++++------- libc/stdtime/private.h | 194 +++--- libc/stdtime/strftime.c | 125 ++-- libc/stdtime/time2posix.3 | 121 ++++ libc/stdtime/tzfile.5 | 152 +++++ libc/stdtime/tzfile.h | 62 +- unused/Makefile | 418 +++++++++++++ unused/checktab.awk | 159 +++++ unused/date.1 | 175 ++++++ unused/date.1.txt | 127 ++++ unused/date.c | 945 +++++++++++++++++++++++++++++ unused/itca.jpg | Bin 0 -> 55948 bytes unused/newctime.3 | 239 ++++++++ unused/newctime.3.txt | 149 +++++ unused/newstrftime.3 | 230 ++++++++ unused/newstrftime.3.txt | 149 +++++ unused/newtzset.3 | 237 ++++++++ unused/newtzset.3.txt | 153 +++++ unused/time2posix.3.txt | 83 +++ {zic => unused}/tz-art.htm | 154 ++++- unused/tz-link.htm | 648 ++++++++++++++++++++ unused/tzfile.5.txt | 106 ++++ unused/tzselect.8 | 41 ++ unused/tzselect.8.txt | 41 ++ unused/tzselect.ksh | 323 ++++++++++ unused/usno1988 | 111 ++++ unused/usno1989 | 452 ++++++++++++++ unused/usno1989a | 452 ++++++++++++++ unused/usno1995 | 326 +++++++++++ unused/usno1997 | 327 +++++++++++ unused/usno1998 | 327 +++++++++++ unused/workman.sh | 29 + unused/zdump.8.txt | 43 ++ unused/zic.8.txt | 308 ++++++++++ unused/zoneinfo2tdf.pl | 54 ++ zic/Music | 81 --- zic/README | 12 +- zic/Theory | 109 ++-- zic/ialloc.c | 7 +- zic/private.h | 194 +++--- zic/scheck.c | 14 +- zic/tz-link.htm | 443 -------------- zic/zdump.8 | 20 +- zic/zdump.c | 535 +++++++++++++---- zic/zic.8 | 91 ++- zic/zic.c | 1141 +++++++++++++++++++++++++----------- 48 files changed, 9497 insertions(+), 1623 deletions(-) create mode 100644 libc/stdtime/time2posix.3 create mode 100644 libc/stdtime/tzfile.5 create mode 100644 unused/Makefile create mode 100644 unused/checktab.awk create mode 100644 unused/date.1 create mode 100644 unused/date.1.txt create mode 100644 unused/date.c create mode 100644 unused/itca.jpg create mode 100644 unused/newctime.3 create mode 100644 unused/newctime.3.txt create mode 100644 unused/newstrftime.3 create mode 100644 unused/newstrftime.3.txt create mode 100644 unused/newtzset.3 create mode 100644 unused/newtzset.3.txt create mode 100644 unused/time2posix.3.txt rename {zic => unused}/tz-art.htm (65%) create mode 100644 unused/tz-link.htm create mode 100644 unused/tzfile.5.txt create mode 100644 unused/tzselect.8 create mode 100644 unused/tzselect.8.txt create mode 100644 unused/tzselect.ksh create mode 100644 unused/usno1988 create mode 100644 unused/usno1989 create mode 100644 unused/usno1989a create mode 100644 unused/usno1995 create mode 100644 unused/usno1997 create mode 100644 unused/usno1998 create mode 100644 unused/workman.sh create mode 100644 unused/zdump.8.txt create mode 100644 unused/zic.8.txt create mode 100755 unused/zoneinfo2tdf.pl delete mode 100644 zic/Music delete mode 100644 zic/tz-link.htm diff --git a/libc/stdtime/asctime.c b/libc/stdtime/asctime.c index 6578663c0d3..e0804f16f4d 100644 --- a/libc/stdtime/asctime.c +++ b/libc/stdtime/asctime.c @@ -1,11 +1,17 @@ /* ** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +** 1996-06-05 by Arthur David Olson. +*/ + +/* +** Avoid the temptation to punt entirely to strftime; +** the output of strftime is supposed to be locale specific +** whereas the output of asctime is supposed to be constant. */ #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)asctime.c 7.9"; +static char elsieid[] = "@(#)asctime.c 8.2"; #endif /* !defined NOID */ #endif /* !defined lint */ @@ -15,7 +21,57 @@ static char elsieid[] = "@(#)asctime.c 7.9"; #include "tzfile.h" /* -** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, Second Edition, 1996-07-12. +** Some systems only handle "%.2d"; others only handle "%02d"; +** "%02.2d" makes (most) everybody happy. +** At least some versions of gcc warn about the %02.2d; +** we conditionalize below to avoid the warning. +*/ +/* +** All years associated with 32-bit time_t values are exactly four digits long; +** some years associated with 64-bit time_t values are not. +** Vintage programs are coded for years that are always four digits long +** and may assume that the newline always lands in the same place. +** For years that are less than four digits, we pad the output with +** leading zeroes to get the newline in the traditional place. +** The -4 ensures that we get four characters of output even if +** we call a strftime variant that produces fewer characters for some years. +** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year, +** but many implementations pad anyway; most likely the standards are buggy. +*/ +#ifdef __GNUC__ +#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n" +#else /* !defined __GNUC__ */ +#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n" +#endif /* !defined __GNUC__ */ +/* +** For years that are more than four digits we put extra spaces before the year +** so that code trying to overwrite the newline won't end up overwriting +** a digit within a year and truncating the year (operating on the assumption +** that no output is better than wrong output). +*/ +#ifdef __GNUC__ +#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n" +#else /* !defined __GNUC__ */ +#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n" +#endif /* !defined __GNUC__ */ + +#define STD_ASCTIME_BUF_SIZE 26 +/* +** Big enough for something such as +** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n +** (two three-character abbreviations, five strings denoting integers, +** seven explicit spaces, two explicit colons, a newline, +** and a trailing ASCII nul). +** The values above are for systems where an int is 32 bits and are provided +** as an example; the define below calculates the maximum for the system at +** hand. +*/ +#define MAX_ASCTIME_BUF_SIZE (2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1) + +static char buf_asctime[MAX_ASCTIME_BUF_SIZE]; + +/* +** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition. */ char * @@ -32,6 +88,8 @@ char * buf; }; register const char * wn; register const char * mn; + char year[INT_STRLEN_MAXIMUM(int) + 2]; + char result[MAX_ASCTIME_BUF_SIZE]; if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK) wn = "???"; @@ -40,35 +98,41 @@ char * buf; mn = "???"; else mn = mon_name[timeptr->tm_mon]; /* - ** The X3J11-suggested format is - ** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n" - ** Since the .2 in 02.2d is ignored, we drop it. + ** Use strftime's %Y to generate the year, to avoid overflow problems + ** when computing timeptr->tm_year + TM_YEAR_BASE. + ** Assume that strftime is unaffected by other out-of-range members + ** (e.g., timeptr->tm_mday) when processing "%Y". */ - (void) sprintf(buf, "%.3s %.3s%3d %02d:%02d:%02d %d\n", + (void) strftime(year, sizeof year, "%Y", timeptr); + /* + ** We avoid using snprintf since it's not available on all systems. + */ + (void) sprintf(result, + ((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B), wn, mn, timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, - TM_YEAR_BASE + timeptr->tm_year); - return buf; + year); + if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime) { + (void) strcpy(buf, result); + return buf; + } else { +#ifdef EOVERFLOW + errno = EOVERFLOW; +#else /* !defined EOVERFLOW */ + errno = EINVAL; +#endif /* !defined EOVERFLOW */ + return NULL; + } } /* -** A la X3J11, with core dump avoidance. +** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition. */ char * asctime(timeptr) register const struct tm * timeptr; { - /* - ** Big enough for something such as - ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n - ** (two three-character abbreviations, five strings denoting integers, - ** three explicit spaces, two explicit colons, a newline, - ** and a trailing ASCII nul). - */ - static char result[3 * 2 + 5 * INT_STRLEN_MAXIMUM(int) + - 3 + 2 + 1 + 1]; - - return asctime_r(timeptr, result); + return asctime_r(timeptr, buf_asctime); } diff --git a/libc/stdtime/difftime.c b/libc/stdtime/difftime.c index 1d1519e1593..da779773bfd 100644 --- a/libc/stdtime/difftime.c +++ b/libc/stdtime/difftime.c @@ -1,83 +1,65 @@ /* ** This file is in the public domain, so clarified as of -** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov). +** 1996-06-05 by Arthur David Olson. */ #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)difftime.c 7.9"; +static char elsieid[] = "@(#)difftime.c 8.1"; #endif /* !defined NOID */ #endif /* !defined lint */ /*LINTLIBRARY*/ -#include "private.h" - -/* -** Algorithm courtesy Paul Eggert (eggert@twinsun.com). -*/ - -#ifdef HAVE_LONG_DOUBLE -#define long_double long double -#endif /* defined HAVE_LONG_DOUBLE */ -#ifndef HAVE_LONG_DOUBLE -#define long_double double -#endif /* !defined HAVE_LONG_DOUBLE */ +#include "private.h" /* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */ double difftime(time1, time0) const time_t time1; const time_t time0; { - time_t delta; - time_t hibit; - - { - time_t tt; - double d; - long_double ld; - - if (sizeof tt < sizeof d) - return (double) time1 - (double) time0; - if (sizeof tt < sizeof ld) - return (long_double) time1 - (long_double) time0; + /* + ** If (sizeof (double) > sizeof (time_t)) simply convert and subtract + ** (assuming that the larger type has more precision). + ** This is the common real-world case circa 2004. + */ + if (sizeof (double) > sizeof (time_t)) + return (double) time1 - (double) time0; + if (!TYPE_INTEGRAL(time_t)) { + /* + ** time_t is floating. + */ + return time1 - time0; + } + if (!TYPE_SIGNED(time_t)) { + /* + ** time_t is integral and unsigned. + ** The difference of two unsigned values can't overflow + ** if the minuend is greater than or equal to the subtrahend. + */ + if (time1 >= time0) + return time1 - time0; + else return -((double) (time0 - time1)); } - if (time1 < time0) - return -difftime(time0, time1); /* - ** As much as possible, avoid loss of precision - ** by computing the difference before converting to double. + ** time_t is integral and signed. + ** Handle cases where both time1 and time0 have the same sign + ** (meaning that their difference cannot overflow). */ - delta = time1 - time0; - if (delta >= 0) - return delta; + if ((time1 < 0) == (time0 < 0)) + return time1 - time0; /* - ** Repair delta overflow. + ** time1 and time0 have opposite signs. + ** Punt if unsigned long is too narrow. */ - hibit = (~ (time_t) 0) << (TYPE_BIT(time_t) - 1); + if (sizeof (unsigned long) < sizeof (time_t)) + return (double) time1 - (double) time0; /* - ** The following expression rounds twice, which means - ** the result may not be the closest to the true answer. - ** For example, suppose time_t is 64-bit signed int, - ** long_double is IEEE 754 double with default rounding, - ** time1 = 9223372036854775807 and time0 = -1536. - ** Then the true difference is 9223372036854777343, - ** which rounds to 9223372036854777856 - ** with a total error of 513. - ** But delta overflows to -9223372036854774273, - ** which rounds to -9223372036854774784, and correcting - ** this by subtracting 2 * (long_double) hibit - ** (i.e. by adding 2**64 = 18446744073709551616) - ** yields 9223372036854776832, which - ** rounds to 9223372036854775808 - ** with a total error of 1535 instead. - ** This problem occurs only with very large differences. - ** It's too painful to fix this portably. - ** We are not alone in this problem; - ** some C compilers round twice when converting - ** large unsigned types to small floating types, - ** so if time_t is unsigned the "return delta" above - ** has the same double-rounding problem with those compilers. + ** Stay calm...decent optimizers will eliminate the complexity below. */ - return delta - 2 * (long_double) hibit; + if (time1 >= 0 /* && time0 < 0 */) + return (unsigned long) time1 + + (unsigned long) (-(time0 + 1)) + 1; + return -(double) ((unsigned long) time0 + + (unsigned long) (-(time1 + 1)) + 1); } diff --git a/libc/stdtime/localtime.c b/libc/stdtime/localtime.c index 33dcd5d052c..d186080bf35 100644 --- a/libc/stdtime/localtime.c +++ b/libc/stdtime/localtime.c @@ -1,18 +1,17 @@ /* ** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +** 1996-06-05 by Arthur David Olson. */ #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)localtime.c 7.78"; +static char elsieid[] = "@(#)localtime.c 8.9"; #endif /* !defined NOID */ #endif /* !defined lint */ /* -** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu). -** POSIX-style TZ environment variable handling from Guy Harris -** (guy@auspex.com). +** Leap second handling from Bradley White. +** POSIX-style TZ environment variable handling from Guy Harris. */ /*LINTLIBRARY*/ @@ -20,6 +19,20 @@ static char elsieid[] = "@(#)localtime.c 7.78"; #include "private.h" #include "tzfile.h" #include "fcntl.h" +#include "float.h" /* for FLT_MAX and DBL_MAX */ + +#ifndef TZ_ABBR_MAX_LEN +#define TZ_ABBR_MAX_LEN 16 +#endif /* !defined TZ_ABBR_MAX_LEN */ + +#ifndef TZ_ABBR_CHAR_SET +#define TZ_ABBR_CHAR_SET \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" +#endif /* !defined TZ_ABBR_CHAR_SET */ + +#ifndef TZ_ABBR_ERR_CHAR +#define TZ_ABBR_ERR_CHAR '_' +#endif /* !defined TZ_ABBR_ERR_CHAR */ /* ** SunOS 4.1.1 headers lack O_BINARY. @@ -46,16 +59,16 @@ static char elsieid[] = "@(#)localtime.c 7.78"; ** 5. They might reference tm.TM_ZONE after calling offtime. ** What's best to do in the above cases is open to debate; ** for now, we just set things up so that in any of the five cases -** WILDABBR is used. Another possibility: initialize tzname[0] to the +** WILDABBR is used. Another possibility: initialize tzname[0] to the ** string "tzname[0] used before set", and similarly for the other cases. -** And another: initialize tzname[0] to "ERA", with an explanation in the +** And another: initialize tzname[0] to "ERA", with an explanation in the ** manual page of what this "time zone abbreviation" means (doing this so ** that tzname[0] has the "normal" length of three characters). */ #define WILDABBR " " #endif /* !defined WILDABBR */ -static char wildabbr[] = "WILDABBR"; +static char wildabbr[] = WILDABBR; static const char gmt[] = "GMT"; @@ -97,6 +110,8 @@ struct state { int timecnt; int typecnt; int charcnt; + int goback; + int goahead; time_t ats[TZ_MAX_TIMES]; unsigned char types[TZ_MAX_TIMES]; struct ttinfo ttis[TZ_MAX_TYPES]; @@ -121,43 +136,52 @@ struct rule { ** Prototypes for static functions. */ -static long detzcode P((const char * codep)); -static const char * getzname P((const char * strp)); -static const char * getnum P((const char * strp, int * nump, int min, - int max)); -static const char * getsecs P((const char * strp, long * secsp)); -static const char * getoffset P((const char * strp, long * offsetp)); -static const char * getrule P((const char * strp, struct rule * rulep)); -static void gmtload P((struct state * sp)); -static void gmtsub P((const time_t * timep, long offset, - struct tm * tmp)); -static void localsub P((const time_t * timep, long offset, - struct tm * tmp)); -static int increment_overflow P((int * number, int delta)); -static int normalize_overflow P((int * tensptr, int * unitsptr, - int base)); -static void settzname P((void)); -static time_t time1 P((struct tm * tmp, - void(*funcp) P((const time_t *, - long, struct tm *)), - long offset)); -static time_t time2 P((struct tm *tmp, - void(*funcp) P((const time_t *, - long, struct tm*)), - long offset, int * okayp)); -static time_t time2sub P((struct tm *tmp, - void(*funcp) P((const time_t *, - long, struct tm*)), - long offset, int * okayp, int do_norm_secs)); -static void timesub P((const time_t * timep, long offset, - const struct state * sp, struct tm * tmp)); -static int tmcomp P((const struct tm * atmp, - const struct tm * btmp)); -static time_t transtime P((time_t janfirst, int year, - const struct rule * rulep, long offset)); -static int tzload P((const char * name, struct state * sp)); -static int tzparse P((const char * name, struct state * sp, - int lastditch)); +static long detzcode(const char * codep); +static time_t detzcode64(const char * codep); +static int differ_by_repeat(time_t t1, time_t t0); +static const char * getzname(const char * strp); +static const char * getqzname(const char * strp, const int delim); +static const char * getnum(const char * strp, int * nump, int min, + int max); +static const char * getsecs(const char * strp, long * secsp); +static const char * getoffset(const char * strp, long * offsetp); +static const char * getrule(const char * strp, struct rule * rulep); +static void gmtload(struct state * sp); +static struct tm * gmtsub(const time_t * timep, long offset, + struct tm * tmp); +static struct tm * localsub(const time_t * timep, long offset, + struct tm * tmp); +static int increment_overflow(int * number, int delta); +static int leaps_thru_end_of(int y); +static int long_increment_overflow(long * number, int delta); +static int long_normalize_overflow(long * tensptr, + int * unitsptr, int base); +static int normalize_overflow(int * tensptr, int * unitsptr, + int base); +static void settzname(void); +static time_t time1(struct tm * tmp, + struct tm * (*funcp)(const time_t *, + long, struct tm *), + long offset); +static time_t time2(struct tm *tmp, + struct tm * (*funcp)(const time_t *, + long, struct tm*), + long offset, int * okayp); +static time_t time2sub(struct tm *tmp, + struct tm * (*funcp)(const time_t *, + long, struct tm*), + long offset, int * okayp, int do_norm_secs); +static struct tm * timesub(const time_t * timep, long offset, + const struct state * sp, struct tm * tmp); +static int tmcomp(const struct tm * atmp, + const struct tm * btmp); +static time_t transtime(time_t janfirst, int year, + const struct rule * rulep, long offset); +static int typesequiv(const struct state * sp, int a, int b); +static int tzload(const char * name, struct state * sp, + int doextend); +static int tzparse(const char * name, struct state * sp, + int lastditch); #ifdef ALL_STATE static struct state * lclptr; @@ -189,7 +213,7 @@ char * tzname[2] = { ** Except for the strftime function, these functions [asctime, ** ctime, gmtime, localtime] return values in one of two static ** objects: a broken-down time structure and an array of char. -** Thanks to Paul Eggert (eggert@twinsun.com) for noting this. +** Thanks to Paul Eggert for noting this. */ static struct tm tm; @@ -210,14 +234,27 @@ const char * const codep; register long result; register int i; - result = (codep[0] & 0x80) ? ~0L : 0L; + result = (codep[0] & 0x80) ? ~0L : 0; for (i = 0; i < 4; ++i) result = (result << 8) | (codep[i] & 0xff); return result; } +static time_t +detzcode64(codep) +const char * const codep; +{ + register time_t result; + register int i; + + result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; + for (i = 0; i < 8; ++i) + result = result * 256 + (codep[i] & 0xff); + return result; +} + static void -settzname P((void)) +settzname(void) { register struct state * const sp = lclptr; register int i; @@ -264,16 +301,54 @@ settzname P((void)) tzname[ttisp->tt_isdst] = &sp->chars[ttisp->tt_abbrind]; } + /* + ** Finally, scrub the abbreviations. + ** First, replace bogus characters. + */ + for (i = 0; i < sp->charcnt; ++i) + if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL) + sp->chars[i] = TZ_ABBR_ERR_CHAR; + /* + ** Second, truncate long abbreviations. + */ + for (i = 0; i < sp->typecnt; ++i) { + register const struct ttinfo * const ttisp = &sp->ttis[i]; + register char * cp = &sp->chars[ttisp->tt_abbrind]; + + if (strlen(cp) > TZ_ABBR_MAX_LEN && + strcmp(cp, GRANDPARENTED) != 0) + *(cp + TZ_ABBR_MAX_LEN) = '\0'; + } } static int -tzload(name, sp) +differ_by_repeat(t1, t0) +const time_t t1; +const time_t t0; +{ + if (TYPE_INTEGRAL(time_t) && + TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) + return 0; + return t1 - t0 == SECSPERREPEAT; +} + +static int +tzload(name, sp, doextend) register const char * name; register struct state * const sp; +register const int doextend; { - register const char * p; - register int i; - register int fid; + register const char * p; + register int i; + register int fid; + register int stored; + register int nread; + union { + struct tzhead tzhead; + char buf[2 * sizeof(struct tzhead) + + 2 * sizeof *sp + + 4 * TZ_MAX_TIMES]; + } u; if (name == NULL && (name = TZDEFAULT) == NULL) return -1; @@ -311,18 +386,13 @@ register struct state * const sp; if ((fid = open(name, OPEN_MODE)) == -1) return -1; } - { - struct tzhead * tzhp; - union { - struct tzhead tzhead; - char buf[sizeof *sp + sizeof *tzhp]; - } u; + nread = read(fid, u.buf, sizeof u.buf); + if (close(fid) < 0 || nread <= 0) + return -1; + for (stored = 4; stored <= 8; stored *= 2) { int ttisstdcnt; int ttisgmtcnt; - i = read(fid, u.buf, sizeof u.buf); - if (close(fid) != 0) - return -1; ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); @@ -337,17 +407,19 @@ register struct state * const sp; (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) return -1; - if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */ + if (nread - (p - u.buf) < + sp->timecnt * stored + /* ats */ sp->timecnt + /* types */ - sp->typecnt * (4 + 2) + /* ttinfos */ + sp->typecnt * 6 + /* ttinfos */ sp->charcnt + /* chars */ - sp->leapcnt * (4 + 4) + /* lsinfos */ + sp->leapcnt * (stored + 4) + /* lsinfos */ ttisstdcnt + /* ttisstds */ ttisgmtcnt) /* ttisgmts */ return -1; for (i = 0; i < sp->timecnt; ++i) { - sp->ats[i] = detzcode(p); - p += 4; + sp->ats[i] = (stored == 4) ? + detzcode(p) : detzcode64(p); + p += stored; } for (i = 0; i < sp->timecnt; ++i) { sp->types[i] = (unsigned char) *p++; @@ -375,8 +447,9 @@ register struct state * const sp; register struct lsinfo * lsisp; lsisp = &sp->lsis[i]; - lsisp->ls_trans = detzcode(p); - p += 4; + lsisp->ls_trans = (stored == 4) ? + detzcode(p) : detzcode64(p); + p += stored; lsisp->ls_corr = detzcode(p); p += 4; } @@ -406,10 +479,127 @@ register struct state * const sp; return -1; } } + /* + ** Out-of-sort ats should mean we're running on a + ** signed time_t system but using a data file with + ** unsigned values (or vice versa). + */ + for (i = 0; i < sp->timecnt - 2; ++i) + if (sp->ats[i] > sp->ats[i + 1]) { + ++i; + if (TYPE_SIGNED(time_t)) { + /* + ** Ignore the end (easy). + */ + sp->timecnt = i; + } else { + /* + ** Ignore the beginning (harder). + */ + register int j; + + for (j = 0; j + i < sp->timecnt; ++j) { + sp->ats[j] = sp->ats[j + i]; + sp->types[j] = sp->types[j + i]; + } + sp->timecnt = j; + } + break; + } + /* + ** If this is an old file, we're done. + */ + if (u.tzhead.tzh_version[0] == '\0') + break; + nread -= p - u.buf; + for (i = 0; i < nread; ++i) + u.buf[i] = p[i]; + /* + ** If this is a narrow integer time_t system, we're done. + */ + if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) + break; + } + if (doextend && nread > 2 && + u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && + sp->typecnt + 2 <= TZ_MAX_TYPES) { + struct state ts; + register int result; + + u.buf[nread - 1] = '\0'; + result = tzparse(&u.buf[1], &ts, FALSE); + if (result == 0 && ts.typecnt == 2 && + sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { + for (i = 0; i < 2; ++i) + ts.ttis[i].tt_abbrind += + sp->charcnt; + for (i = 0; i < ts.charcnt; ++i) + sp->chars[sp->charcnt++] = + ts.chars[i]; + i = 0; + while (i < ts.timecnt && + ts.ats[i] <= + sp->ats[sp->timecnt - 1]) + ++i; + while (i < ts.timecnt && + sp->timecnt < TZ_MAX_TIMES) { + sp->ats[sp->timecnt] = + ts.ats[i]; + sp->types[sp->timecnt] = + sp->typecnt + + ts.types[i]; + ++sp->timecnt; + ++i; + } + sp->ttis[sp->typecnt++] = ts.ttis[0]; + sp->ttis[sp->typecnt++] = ts.ttis[1]; + } + } + sp->goback = sp->goahead = FALSE; + if (sp->timecnt > 1) { + for (i = 1; i < sp->timecnt; ++i) + if (typesequiv(sp, sp->types[i], sp->types[0]) && + differ_by_repeat(sp->ats[i], sp->ats[0])) { + sp->goback = TRUE; + break; + } + for (i = sp->timecnt - 2; i >= 0; --i) + if (typesequiv(sp, sp->types[sp->timecnt - 1], + sp->types[i]) && + differ_by_repeat(sp->ats[sp->timecnt - 1], + sp->ats[i])) { + sp->goahead = TRUE; + break; + } } return 0; } +static int +typesequiv(sp, a, b) +const struct state * const sp; +const int a; +const int b; +{ + register int result; + + if (sp == NULL || + a < 0 || a >= sp->typecnt || + b < 0 || b >= sp->typecnt) + result = FALSE; + else { + register const struct ttinfo * ap = &sp->ttis[a]; + register const struct ttinfo * bp = &sp->ttis[b]; + result = ap->tt_gmtoff == bp->tt_gmtoff && + ap->tt_isdst == bp->tt_isdst && + ap->tt_ttisstd == bp->tt_ttisstd && + ap->tt_ttisgmt == bp->tt_ttisgmt && + strcmp(&sp->chars[ap->tt_abbrind], + &sp->chars[bp->tt_abbrind]) == 0; + } + return result; +} + static const int mon_lengths[2][MONSPERYEAR] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } @@ -421,7 +611,7 @@ static const int year_lengths[2] = { /* ** Given a pointer into a time zone string, scan until a character that is not -** a valid character in a zone name is found. Return a pointer to that +** a valid character in a zone name is found. Return a pointer to that ** character. */ @@ -437,6 +627,25 @@ register const char * strp; return strp; } +/* +** Given a pointer into an extended time zone string, scan until the ending +** delimiter of the zone name is located. Return a pointer to the delimiter. +** +** As with getzname above, the legal character set is actually quite +** restricted, with other characters producing undefined results. +** We don't do any checking here; checking is done later in common-case code. +*/ + +static const char * +getqzname(register const char *strp, const int delim) +{ + register int c; + + while ((c = *strp) != '\0' && c != delim) + ++strp; + return strp; +} + /* ** Given a pointer into a time zone string, extract a number from that string. ** Check that the number is within a specified range; if it is not, return @@ -502,7 +711,7 @@ long * const secsp; *secsp += num * SECSPERMIN; if (*strp == ':') { ++strp; - /* `SECSPERMIN' allows for leap seconds. */ + /* `SECSPERMIN' allows for leap seconds. */ strp = getnum(strp, &num, 0, SECSPERMIN); if (strp == NULL) return NULL; @@ -541,7 +750,7 @@ long * const offsetp; /* ** Given a pointer into a time zone string, extract a rule in the form -** date[/time]. See POSIX section 8 for the format of "date" and "time". +** date[/time]. See POSIX section 8 for the format of "date" and "time". ** If a valid rule is not found, return NULL. ** Otherwise, return a pointer to the first character not part of the rule. */ @@ -660,7 +869,7 @@ const long offset; dow += DAYSPERWEEK; /* - ** "dow" is the day-of-week of the first day of the month. Get + ** "dow" is the day-of-week of the first day of the month. Get ** the day-of-month (zero-origin) of the first "dow" day of the ** month. */ @@ -683,7 +892,7 @@ const long offset; /* ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in - ** question. To get the Epoch-relative time of the specified local + ** question. To get the Epoch-relative time of the specified local ** time on that day, add the transition time and the current offset ** from UTC. */ @@ -721,25 +930,40 @@ const int lastditch; stdlen = (sizeof sp->chars) - 1; stdoffset = 0; } else { - name = getzname(name); - stdlen = name - stdname; - if (stdlen < 3) - return -1; + if (*name == '<') { + name++; + stdname = name; + name = getqzname(name, '>'); + if (*name != '>') + return (-1); + stdlen = name - stdname; + name++; + } else { + name = getzname(name); + stdlen = name - stdname; + } if (*name == '\0') return -1; name = getoffset(name, &stdoffset); if (name == NULL) return -1; } - load_result = tzload(TZDEFRULES, sp); + load_result = tzload(TZDEFRULES, sp, FALSE); if (load_result != 0) sp->leapcnt = 0; /* so, we're off a little */ if (*name != '\0') { - dstname = name; - name = getzname(name); - dstlen = name - dstname; /* length of DST zone name */ - if (dstlen < 3) - return -1; + if (*name == '<') { + dstname = ++name; + name = getqzname(name, '>'); + if (*name != '>') + return -1; + dstlen = name - dstname; + name++; + } else { + dstname = name; + name = getzname(name); + dstlen = name - dstname; /* length of DST zone name */ + } if (*name != '\0' && *name != ',' && *name != ';') { name = getoffset(name, &dstoffset); if (name == NULL) @@ -766,11 +990,8 @@ const int lastditch; return -1; sp->typecnt = 2; /* standard time and DST */ /* - ** Two transitions per year, from EPOCH_YEAR to 2037. + ** Two transitions per year, from EPOCH_YEAR forward. */ - sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); - if (sp->timecnt > TZ_MAX_TIMES) - return -1; sp->ttis[0].tt_gmtoff = -dstoffset; sp->ttis[0].tt_isdst = 1; sp->ttis[0].tt_abbrind = stdlen + 1; @@ -780,7 +1001,12 @@ const int lastditch; atp = sp->ats; typep = sp->types; janfirst = 0; - for (year = EPOCH_YEAR; year <= 2037; ++year) { + sp->timecnt = 0; + for (year = EPOCH_YEAR; + sp->timecnt + 2 <= TZ_MAX_TIMES; + ++year) { + time_t newfirst; + starttime = transtime(janfirst, year, &start, stdoffset); endtime = transtime(janfirst, year, &end, @@ -796,8 +1022,13 @@ const int lastditch; *atp++ = endtime; *typep++ = 1; /* DST ends */ } - janfirst += year_lengths[isleap(year)] * + sp->timecnt += 2; + newfirst = janfirst; + newfirst += year_lengths[isleap(year)] * SECSPERDAY; + if (newfirst <= janfirst) + break; + janfirst = newfirst; } } else { register long theirstdoffset; @@ -912,7 +1143,7 @@ static void gmtload(sp) struct state * const sp; { - if (tzload(gmt, sp) != 0) + if (tzload(gmt, sp, TRUE) != 0) (void) tzparse(gmt, sp, TRUE); } @@ -924,7 +1155,7 @@ struct state * const sp; static #endif /* !defined STD_INSPIRED */ void -tzsetwall P((void)) +tzsetwall(void) { if (lcl_is_set < 0) return; @@ -939,13 +1170,13 @@ tzsetwall P((void)) } } #endif /* defined ALL_STATE */ - if (tzload((char *) NULL, lclptr) != 0) + if (tzload((char *) NULL, lclptr, TRUE) != 0) gmtload(lclptr); settzname(); } void -tzset P((void)) +tzset(void) { register const char * name; @@ -981,7 +1212,7 @@ tzset P((void)) lclptr->ttis[0].tt_gmtoff = 0; lclptr->ttis[0].tt_abbrind = 0; (void) strcpy(lclptr->chars, gmt); - } else if (tzload(name, lclptr) != 0) + } else if (tzload(name, lclptr, TRUE) != 0) if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) (void) gmtload(lclptr); settzname(); @@ -990,14 +1221,14 @@ tzset P((void)) /* ** The easy way to behave "as if no library function calls" localtime ** is to not call it--so we drop its guts into "localsub", which can be -** freely called. (And no, the PANS doesn't require the above behavior-- +** freely called. (And no, the PANS doesn't require the above behavior-- ** but it *is* desirable.) ** ** The unused offset argument is for the benefit of mktime variants. */ /*ARGSUSED*/ -static void +static struct tm * localsub(timep, offset, tmp) const time_t * const timep; const long offset; @@ -1006,15 +1237,53 @@ struct tm * const tmp; register struct state * sp; register const struct ttinfo * ttisp; register int i; + register struct tm * result; const time_t t = *timep; sp = lclptr; #ifdef ALL_STATE - if (sp == NULL) { - gmtsub(timep, offset, tmp); - return; - } + if (sp == NULL) + return gmtsub(timep, offset, tmp); #endif /* defined ALL_STATE */ + if ((sp->goback && t < sp->ats[0]) || + (sp->goahead && t > sp->ats[sp->timecnt - 1])) { + time_t newt = t; + register time_t seconds; + register time_t tcycles; + register int_fast64_t icycles; + + if (t < sp->ats[0]) + seconds = sp->ats[0] - t; + else seconds = t - sp->ats[sp->timecnt - 1]; + --seconds; + tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; + ++tcycles; + icycles = tcycles; + if (tcycles - icycles >= 1 || icycles - tcycles >= 1) + return NULL; + seconds = icycles; + seconds *= YEARSPERREPEAT; + seconds *= AVGSECSPERYEAR; + if (t < sp->ats[0]) + newt += seconds; + else newt -= seconds; + if (newt < sp->ats[0] || + newt > sp->ats[sp->timecnt - 1]) + return NULL; /* "cannot happen" */ + result = localsub(&newt, offset, tmp); + if (result == tmp) { + register time_t newy; + + newy = tmp->tm_year; + if (t < sp->ats[0]) + newy -= icycles * YEARSPERREPEAT; + else newy += icycles * YEARSPERREPEAT; + tmp->tm_year = newy; + if (tmp->tm_year != newy) + return NULL; + } + return result; + } if (sp->timecnt == 0 || t < sp->ats[0]) { i = 0; while (sp->ttis[i].tt_isdst) @@ -1023,10 +1292,17 @@ struct tm * const tmp; break; } } else { - for (i = 1; i < sp->timecnt; ++i) - if (t < sp->ats[i]) - break; - i = sp->types[i - 1]; + register int lo = 1; + register int hi = sp->timecnt; + + while (lo < hi) { + register int mid = (lo + hi) >> 1; + + if (t < sp->ats[mid]) + hi = mid; + else lo = mid + 1; + } + i = (int) sp->types[lo - 1]; } ttisp = &sp->ttis[i]; /* @@ -1035,12 +1311,13 @@ struct tm * const tmp; ** t += ttisp->tt_gmtoff; ** timesub(&t, 0L, sp, tmp); */ - timesub(&t, ttisp->tt_gmtoff, sp, tmp); + result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); tmp->tm_isdst = ttisp->tt_isdst; tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; #ifdef TM_ZONE tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; #endif /* defined TM_ZONE */ + return result; } struct tm * @@ -1048,8 +1325,7 @@ localtime(timep) const time_t * const timep; { tzset(); - localsub(timep, 0L, &tm); - return &tm; + return localsub(timep, 0L, &tm); } /* @@ -1057,24 +1333,25 @@ const time_t * const timep; */ struct tm * -localtime_r(timep, tm) +localtime_r(timep, tmp) const time_t * const timep; -struct tm * tm; +struct tm * tmp; { - localsub(timep, 0L, tm); - return tm; + return localsub(timep, 0L, tmp); } /* ** gmtsub is to gmtime as localsub is to localtime. */ -static void +static struct tm * gmtsub(timep, offset, tmp) const time_t * const timep; const long offset; struct tm * const tmp; { + register struct tm * result; + if (!gmt_is_set) { gmt_is_set = TRUE; #ifdef ALL_STATE @@ -1083,7 +1360,7 @@ struct tm * const tmp; #endif /* defined ALL_STATE */ gmtload(gmtptr); } - timesub(timep, offset, gmtptr, tmp); + result = timesub(timep, offset, gmtptr, tmp); #ifdef TM_ZONE /* ** Could get fancy here and deliver something such as @@ -1103,14 +1380,14 @@ struct tm * const tmp; #endif /* State Farm */ } #endif /* defined TM_ZONE */ + return result; } struct tm * gmtime(timep) const time_t * const timep; { - gmtsub(timep, 0L, &tm); - return &tm; + return gmtsub(timep, 0L, &tm); } /* @@ -1118,12 +1395,11 @@ const time_t * const timep; */ struct tm * -gmtime_r(timep, tm) +gmtime_r(timep, tmp) const time_t * const timep; -struct tm * tm; +struct tm * tmp; { - gmtsub(timep, 0L, tm); - return tm; + return gmtsub(timep, 0L, tmp); } #ifdef STD_INSPIRED @@ -1133,13 +1409,25 @@ offtime(timep, offset) const time_t * const timep; const long offset; { - gmtsub(timep, offset, &tm); - return &tm; + return gmtsub(timep, offset, &tm); } #endif /* defined STD_INSPIRED */ -static void +/* +** Return the number of leap years through the end of the given year +** where, to make the math easy, the answer for year zero is defined as zero. +*/ + +static int +leaps_thru_end_of(y) +register const int y; +{ + return (y >= 0) ? (y / 4 - y / 100 + y / 400) : + -(leaps_thru_end_of(-(y + 1)) + 1); +} + +static struct tm * timesub(timep, offset, sp, tmp) const time_t * const timep; const long offset; @@ -1147,10 +1435,10 @@ register const struct state * const sp; register struct tm * const tmp; { register const struct lsinfo * lp; - register long days; + register time_t tdays; + register int idays; /* unsigned would be so 2003 */ register long rem; - register int y; - register int yleap; + int y; register const int * ip; register long corr; register int hit; @@ -1184,60 +1472,93 @@ register struct tm * const tmp; break; } } - days = *timep / SECSPERDAY; - rem = *timep % SECSPERDAY; -#ifdef mc68k - if (*timep == 0x80000000) { - /* - ** A 3B1 muffs the division on the most negative number. - */ - days = -24855; - rem = -11648; + y = EPOCH_YEAR; + tdays = *timep / SECSPERDAY; + rem = *timep - tdays * SECSPERDAY; + while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { + int newy; + register time_t tdelta; + register int idelta; + register int leapdays; + + tdelta = tdays / DAYSPERLYEAR; + idelta = tdelta; + if (tdelta - idelta >= 1 || idelta - tdelta >= 1) + return NULL; + if (idelta == 0) + idelta = (tdays < 0) ? -1 : 1; + newy = y; + if (increment_overflow(&newy, idelta)) + return NULL; + leapdays = leaps_thru_end_of(newy - 1) - + leaps_thru_end_of(y - 1); + tdays -= ((time_t) newy - y) * DAYSPERNYEAR; + tdays -= leapdays; + y = newy; } -#endif /* defined mc68k */ - rem += (offset - corr); + { + register long seconds; + + seconds = tdays * SECSPERDAY + 0.5; + tdays = seconds / SECSPERDAY; + rem += seconds - tdays * SECSPERDAY; + } + /* + ** Given the range, we can now fearlessly cast... + */ + idays = tdays; + rem += offset - corr; while (rem < 0) { rem += SECSPERDAY; - --days; + --idays; } while (rem >= SECSPERDAY) { rem -= SECSPERDAY; - ++days; + ++idays; } + while (idays < 0) { + if (increment_overflow(&y, -1)) + return NULL; + idays += year_lengths[isleap(y)]; + } + while (idays >= year_lengths[isleap(y)]) { + idays -= year_lengths[isleap(y)]; + if (increment_overflow(&y, 1)) + return NULL; + } + tmp->tm_year = y; + if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) + return NULL; + tmp->tm_yday = idays; + /* + ** The "extra" mods below avoid overflow problems. + */ + tmp->tm_wday = EPOCH_WDAY + + ((y - EPOCH_YEAR) % DAYSPERWEEK) * + (DAYSPERNYEAR % DAYSPERWEEK) + + leaps_thru_end_of(y - 1) - + leaps_thru_end_of(EPOCH_YEAR - 1) + + idays; + tmp->tm_wday %= DAYSPERWEEK; + if (tmp->tm_wday < 0) + tmp->tm_wday += DAYSPERWEEK; tmp->tm_hour = (int) (rem / SECSPERHOUR); - rem = rem % SECSPERHOUR; + rem %= SECSPERHOUR; tmp->tm_min = (int) (rem / SECSPERMIN); /* ** A positive leap second requires a special - ** representation. This uses "... ??:59:60" et seq. + ** representation. This uses "... ??:59:60" et seq. */ tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; - tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); - if (tmp->tm_wday < 0) - tmp->tm_wday += DAYSPERWEEK; - y = EPOCH_YEAR; -#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) - while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { - register int newy; - - newy = y + days / DAYSPERNYEAR; - if (days < 0) - --newy; - days -= (newy - y) * DAYSPERNYEAR + - LEAPS_THRU_END_OF(newy - 1) - - LEAPS_THRU_END_OF(y - 1); - y = newy; - } - tmp->tm_year = y - TM_YEAR_BASE; - tmp->tm_yday = (int) days; - ip = mon_lengths[yleap]; - for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) - days = days - (long) ip[tmp->tm_mon]; - tmp->tm_mday = (int) (days + 1); + ip = mon_lengths[isleap(y)]; + for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) + idays -= ip[tmp->tm_mon]; + tmp->tm_mday = (int) (idays + 1); tmp->tm_isdst = 0; #ifdef TM_GMTOFF tmp->TM_GMTOFF = offset; #endif /* defined TM_GMTOFF */ + return tmp; } char * @@ -1247,7 +1568,7 @@ const time_t * const timep; /* ** Section 4.12.3.2 of X3.159-1989 requires that ** The ctime function converts the calendar time pointed to by timer -** to local time in the form of a string. It is equivalent to +** to local time in the form of a string. It is equivalent to ** asctime(localtime(timer)) */ return asctime(localtime(timep)); @@ -1258,17 +1579,16 @@ ctime_r(timep, buf) const time_t * const timep; char * buf; { - struct tm tm; + struct tm mytm; - return asctime_r(localtime_r(timep, &tm), buf); + return asctime_r(localtime_r(timep, &mytm), buf); } /* ** Adapted from code provided by Robert Elz, who writes: ** The "best" way to do mktime I think is based on an idea of Bob ** Kridle's (so its said...) from a long time ago. -** [kridle@xinet.com as of 1996-01-16.] -** It does a binary search of the time_t space. Since time_t's are +** It does a binary search of the time_t space. Since time_t's are ** just 32 bits, its a max of 32 iterations (even at 64 bits it ** would still be very reasonable). */ @@ -1278,7 +1598,7 @@ char * buf; #endif /* !defined WRONG */ /* -** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com). +** Simplified normalize logic courtesy Paul Eggert. */ static int @@ -1293,6 +1613,18 @@ int delta; return (*number < number0) != (delta < 0); } +static int +long_increment_overflow(number, delta) +long * number; +int delta; +{ + long number0; + + number0 = *number; + *number += delta; + return (*number < number0) != (delta < 0); +} + static int normalize_overflow(tensptr, unitsptr, base) int * const tensptr; @@ -1308,6 +1640,21 @@ const int base; return increment_overflow(tensptr, tensdelta); } +static int +long_normalize_overflow(tensptr, unitsptr, base) +long * const tensptr; +int * const unitsptr; +const int base; +{ + register int tensdelta; + + tensdelta = (*unitsptr >= 0) ? + (*unitsptr / base) : + (-1 - (-1 - *unitsptr) / base); + *unitsptr -= tensdelta * base; + return long_increment_overflow(tensptr, tensdelta); +} + static int tmcomp(atmp, btmp) register const struct tm * const atmp; @@ -1327,16 +1674,19 @@ register const struct tm * const btmp; static time_t time2sub(tmp, funcp, offset, okayp, do_norm_secs) struct tm * const tmp; -void (* const funcp) P((const time_t*, long, struct tm*)); +struct tm * (* const funcp)(const time_t*, long, struct tm*); const long offset; int * const okayp; const int do_norm_secs; { register const struct state * sp; register int dir; - register int bits; - register int i, j ; + register int i, j; register int saved_seconds; + register long li; + register time_t lo; + register time_t hi; + long y; time_t newt; time_t t; struct tm yourtm, mytm; @@ -1352,42 +1702,46 @@ const int do_norm_secs; return WRONG; if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) return WRONG; - if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR)) + y = yourtm.tm_year; + if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) return WRONG; /* - ** Turn yourtm.tm_year into an actual year number for now. + ** Turn y into an actual year number for now. ** It is converted back to an offset from TM_YEAR_BASE later. */ - if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE)) + if (long_increment_overflow(&y, TM_YEAR_BASE)) return WRONG; while (yourtm.tm_mday <= 0) { - if (increment_overflow(&yourtm.tm_year, -1)) + if (long_increment_overflow(&y, -1)) return WRONG; - i = yourtm.tm_year + (1 < yourtm.tm_mon); - yourtm.tm_mday += year_lengths[isleap(i)]; + li = y + (1 < yourtm.tm_mon); + yourtm.tm_mday += year_lengths[isleap(li)]; } while (yourtm.tm_mday > DAYSPERLYEAR) { - i = yourtm.tm_year + (1 < yourtm.tm_mon); - yourtm.tm_mday -= year_lengths[isleap(i)]; - if (increment_overflow(&yourtm.tm_year, 1)) + li = y + (1 < yourtm.tm_mon); + yourtm.tm_mday -= year_lengths[isleap(li)]; + if (long_increment_overflow(&y, 1)) return WRONG; } for ( ; ; ) { - i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon]; + i = mon_lengths[isleap(y)][yourtm.tm_mon]; if (yourtm.tm_mday <= i) break; yourtm.tm_mday -= i; if (++yourtm.tm_mon >= MONSPERYEAR) { yourtm.tm_mon = 0; - if (increment_overflow(&yourtm.tm_year, 1)) + if (long_increment_overflow(&y, 1)) return WRONG; } } - if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE)) + if (long_increment_overflow(&y, -TM_YEAR_BASE)) + return WRONG; + yourtm.tm_year = y; + if (yourtm.tm_year != y) return WRONG; if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) saved_seconds = 0; - else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) { + else if (y + TM_YEAR_BASE < EPOCH_YEAR) { /* ** We can't set tm_sec to 0, because that might push the ** time below the minimum representable time. @@ -1405,27 +1759,53 @@ const int do_norm_secs; yourtm.tm_sec = 0; } /* - ** Divide the search space in half - ** (this works whether time_t is signed or unsigned). + ** Do a binary search (this works whatever time_t's type is). */ - bits = TYPE_BIT(time_t) - 1; - /* - ** If time_t is signed, then 0 is just above the median, - ** assuming two's complement arithmetic. - ** If time_t is unsigned, then (1 << bits) is just above the median. - */ - t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits); + if (!TYPE_SIGNED(time_t)) { + lo = 0; + hi = lo - 1; + } else if (!TYPE_INTEGRAL(time_t)) { + if (sizeof(time_t) > sizeof(float)) + hi = (time_t) DBL_MAX; + else hi = (time_t) FLT_MAX; + lo = -hi; + } else { + lo = 1; + for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) + lo *= 2; + hi = -(lo + 1); + } for ( ; ; ) { - (*funcp)(&t, offset, &mytm); - dir = tmcomp(&mytm, &yourtm); + t = lo / 2 + hi / 2; + if (t < lo) + t = lo; + else if (t > hi) + t = hi; + if ((*funcp)(&t, offset, &mytm) == NULL) { + /* + ** Assume that t is too extreme to be represented in + ** a struct tm; arrange things so that it is less + ** extreme on the next pass. + */ + dir = (t > 0) ? 1 : -1; + } else dir = tmcomp(&mytm, &yourtm); if (dir != 0) { - if (bits-- < 0) + if (t == lo) { + ++t; + if (t <= lo) + return WRONG; + ++lo; + } else if (t == hi) { + --t; + if (t >= hi) + return WRONG; + --hi; + } + if (lo > hi) return WRONG; - if (bits < 0) - --t; /* may be needed if new t is minimal */ - else if (dir > 0) - t -= ((time_t) 1) << bits; - else t += ((time_t) 1) << bits; + if (dir > 0) + hi = t; + else lo = t; continue; } if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) @@ -1436,12 +1816,8 @@ const int do_norm_secs; ** It's okay to guess wrong since the guess ** gets checked. */ - /* - ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. - */ sp = (const struct state *) - (((void *) funcp == (void *) localsub) ? - lclptr : gmtptr); + ((funcp == localsub) ? lclptr : gmtptr); #ifdef ALL_STATE if (sp == NULL) return WRONG; @@ -1454,7 +1830,8 @@ const int do_norm_secs; continue; newt = t + sp->ttis[j].tt_gmtoff - sp->ttis[i].tt_gmtoff; - (*funcp)(&newt, offset, &mytm); + if ((*funcp)(&newt, offset, &mytm) == NULL) + continue; if (tmcomp(&mytm, &yourtm) != 0) continue; if (mytm.tm_isdst != yourtm.tm_isdst) @@ -1473,15 +1850,15 @@ label: if ((newt < t) != (saved_seconds < 0)) return WRONG; t = newt; - (*funcp)(&t, offset, tmp); - *okayp = TRUE; + if ((*funcp)(&t, offset, tmp)) + *okayp = TRUE; return t; } static time_t time2(tmp, funcp, offset, okayp) struct tm * const tmp; -void (* const funcp) P((const time_t*, long, struct tm*)); +struct tm * (* const funcp)(const time_t*, long, struct tm*); const long offset; int * const okayp; { @@ -1499,7 +1876,7 @@ int * const okayp; static time_t time1(tmp, funcp, offset) struct tm * const tmp; -void (* const funcp) P((const time_t *, long, struct tm *)); +struct tm * (* const funcp)(const time_t *, long, struct tm *); const long offset; { register time_t t; @@ -1517,7 +1894,7 @@ const long offset; t = time2(tmp, funcp, offset, &okay); #ifdef PCTS /* - ** PCTS code courtesy Grant Sullivan (grant@osf.org). + ** PCTS code courtesy Grant Sullivan. */ if (okay) return t; @@ -1534,11 +1911,7 @@ const long offset; ** We try to divine the type they started from and adjust to the ** type they need. */ - /* - ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. - */ - sp = (const struct state *) (((void *) funcp == (void *) localsub) ? - lclptr : gmtptr); + sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr); #ifdef ALL_STATE if (sp == NULL) return WRONG; @@ -1680,7 +2053,7 @@ time_t t; tzset(); /* ** For a positive leap second hit, the result - ** is not unique. For a negative leap second + ** is not unique. For a negative leap second ** hit, the corresponding time doesn't exist, ** so we return an adjacent second. */ diff --git a/libc/stdtime/private.h b/libc/stdtime/private.h index c8f45486837..008d468ac78 100644 --- a/libc/stdtime/private.h +++ b/libc/stdtime/private.h @@ -4,7 +4,7 @@ /* ** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +** 1996-06-05 by Arthur David Olson. */ /* @@ -21,10 +21,12 @@ #ifndef lint #ifndef NOID -static char privatehid[] = "@(#)private.h 7.53"; +static char privatehid[] = "@(#)private.h 8.6"; #endif /* !defined NOID */ #endif /* !defined lint */ +#define GRANDPARENTED "Local time zone must be set--see zic manual page" + /* ** Defaults for preprocessor symbols. ** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'. @@ -46,10 +48,6 @@ static char privatehid[] = "@(#)private.h 7.53"; #define HAVE_SETTIMEOFDAY 3 #endif /* !defined HAVE_SETTIMEOFDAY */ -#ifndef HAVE_STRERROR -#define HAVE_STRERROR 1 -#endif /* !defined HAVE_STRERROR */ - #ifndef HAVE_SYMLINK #define HAVE_SYMLINK 1 #endif /* !defined HAVE_SYMLINK */ @@ -87,17 +85,17 @@ static char privatehid[] = "@(#)private.h 7.53"; #include "stdio.h" #include "errno.h" #include "string.h" -#include "limits.h" /* for CHAR_BIT */ +#include "limits.h" /* for CHAR_BIT et al. */ #include "time.h" #include "stdlib.h" -#if HAVE_GETTEXT - 0 +#if HAVE_GETTEXT #include "libintl.h" -#endif /* HAVE_GETTEXT - 0 */ +#endif /* HAVE_GETTEXT */ -#if HAVE_SYS_WAIT_H - 0 +#if HAVE_SYS_WAIT_H #include /* for WIFEXITED and WEXITSTATUS */ -#endif /* HAVE_SYS_WAIT_H - 0 */ +#endif /* HAVE_SYS_WAIT_H */ #ifndef WIFEXITED #define WIFEXITED(status) (((status) & 0xff) == 0) @@ -106,106 +104,82 @@ static char privatehid[] = "@(#)private.h 7.53"; #define WEXITSTATUS(status) (((status) >> 8) & 0xff) #endif /* !defined WEXITSTATUS */ -#if HAVE_UNISTD_H - 0 -#include "unistd.h" /* for F_OK and R_OK */ -#endif /* HAVE_UNISTD_H - 0 */ +#if HAVE_UNISTD_H +#include "unistd.h" /* for F_OK, R_OK, and other POSIX goodness */ +#endif /* HAVE_UNISTD_H */ -#if !(HAVE_UNISTD_H - 0) #ifndef F_OK #define F_OK 0 #endif /* !defined F_OK */ #ifndef R_OK #define R_OK 4 #endif /* !defined R_OK */ -#endif /* !(HAVE_UNISTD_H - 0) */ -/* Unlike 's isdigit, this also works if c < 0 | c > UCHAR_MAX. */ +/* Unlike 's isdigit, this also works if c < 0 | c > UCHAR_MAX. */ #define is_digit(c) ((unsigned)(c) - '0' <= 9) +/* +** Define HAVE_STDINT_H's default value here, rather than at the +** start, since __GLIBC__'s value depends on previously-included +** files. +** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.) +*/ +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H \ + (199901 <= __STDC_VERSION__ || \ + 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__))) +#endif /* !defined HAVE_STDINT_H */ + +#if HAVE_STDINT_H +#include "stdint.h" +#endif /* !HAVE_STDINT_H */ + +#ifndef INT_FAST64_MAX +/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */ +#if defined LLONG_MAX || defined __LONG_LONG_MAX__ +typedef long long int_fast64_t; +#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ +#if (LONG_MAX >> 31) < 0xffffffff +Please use a compiler that supports a 64-bit integer type (or wider); +you may need to compile with "-DHAVE_STDINT_H". +#endif /* (LONG_MAX >> 31) < 0xffffffff */ +typedef long int_fast64_t; +#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ +#endif /* !defined INT_FAST64_MAX */ + +#ifndef INT32_MAX +#define INT32_MAX 0x7fffffff +#endif /* !defined INT32_MAX */ +#ifndef INT32_MIN +#define INT32_MIN (-1 - INT32_MAX) +#endif /* !defined INT32_MIN */ + /* ** Workarounds for compilers/systems. */ /* -** SunOS 4.1.1 cc lacks prototypes. -*/ - -#ifndef P -#ifdef __STDC__ -#define P(x) x -#endif /* defined __STDC__ */ -#ifndef __STDC__ -#define P(x) () -#endif /* !defined __STDC__ */ -#endif /* !defined P */ - -/* -** SunOS 4.1.1 headers lack EXIT_SUCCESS. -*/ - -#ifndef EXIT_SUCCESS -#define EXIT_SUCCESS 0 -#endif /* !defined EXIT_SUCCESS */ - -/* -** SunOS 4.1.1 headers lack EXIT_FAILURE. -*/ - -#ifndef EXIT_FAILURE -#define EXIT_FAILURE 1 -#endif /* !defined EXIT_FAILURE */ - -/* -** SunOS 4.1.1 headers lack FILENAME_MAX. -*/ - -#ifndef FILENAME_MAX - -#ifndef MAXPATHLEN -#ifdef unix -#include "sys/param.h" -#endif /* defined unix */ -#endif /* !defined MAXPATHLEN */ - -#ifdef MAXPATHLEN -#define FILENAME_MAX MAXPATHLEN -#endif /* defined MAXPATHLEN */ -#ifndef MAXPATHLEN -#define FILENAME_MAX 1024 /* Pure guesswork */ -#endif /* !defined MAXPATHLEN */ - -#endif /* !defined FILENAME_MAX */ - -/* -** SunOS 4.1.1 libraries lack remove. -*/ - -#ifndef remove -extern int unlink P((const char * filename)); -#define remove unlink -#endif /* !defined remove */ - -/* -** Some ancient errno.h implementations don't declare errno. -** But some newer errno.h implementations define it as a macro. +** Some time.h implementations don't declare asctime_r. +** Others might define it as a macro. ** Fix the former without affecting the latter. */ -#ifndef errno -extern int errno; -#endif /* !defined errno */ + +#ifndef asctime_r +extern char * asctime_r(struct tm const *, char *); +#endif /* ** Private function declarations. */ -char * icalloc P((int nelem, int elsize)); -char * icatalloc P((char * old, const char * new)); -char * icpyalloc P((const char * string)); -char * imalloc P((int n)); -void * irealloc P((void * pointer, int size)); -void icfree P((char * pointer)); -void ifree P((char * pointer)); -char * scheck P((const char *string, const char *format)); +char * icalloc(int nelem, int elsize); +char * icatalloc(char * old, const char * new); +char * icpyalloc(const char * string); +char * imalloc(int n); +void * irealloc(void * pointer, int size); +void icfree(char * pointer); +void ifree(char * pointer); +const char * scheck(const char * string, const char * format); /* ** Finally, some convenience items. @@ -227,6 +201,15 @@ char * scheck P((const char *string, const char *format)); #define TYPE_SIGNED(type) (((type) -1) < 0) #endif /* !defined TYPE_SIGNED */ +/* +** Since the definition of TYPE_INTEGRAL contains floating point numbers, +** it cannot be used in preprocessor directives. +*/ + +#ifndef TYPE_INTEGRAL +#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5) +#endif /* !defined TYPE_INTEGRAL */ + #ifndef INT_STRLEN_MAXIMUM /* ** 302 / 1000 is log10(2.0) rounded up. @@ -235,7 +218,8 @@ char * scheck P((const char *string, const char *format)); ** add one more for a minus sign if the type is signed. */ #define INT_STRLEN_MAXIMUM(type) \ - ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type)) + ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ + 1 + TYPE_SIGNED(type)) #endif /* !defined INT_STRLEN_MAXIMUM */ /* @@ -269,11 +253,11 @@ char * scheck P((const char *string, const char *format)); */ #ifndef _ -#if HAVE_GETTEXT - 0 +#if HAVE_GETTEXT #define _(msgid) gettext(msgid) -#else /* !(HAVE_GETTEXT - 0) */ +#else /* !HAVE_GETTEXT */ #define _(msgid) msgid -#endif /* !(HAVE_GETTEXT - 0) */ +#endif /* !HAVE_GETTEXT */ #endif /* !defined _ */ #ifndef TZ_DOMAIN @@ -283,10 +267,30 @@ char * scheck P((const char *string, const char *format)); #if HAVE_INCOMPATIBLE_CTIME_R #undef asctime_r #undef ctime_r -char *asctime_r P((struct tm const *, char *)); -char *ctime_r P((time_t const *, char *)); +char *asctime_r(struct tm const *, char *); +char *ctime_r(time_t const *, char *); #endif /* HAVE_INCOMPATIBLE_CTIME_R */ +#ifndef YEARSPERREPEAT +#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ +#endif /* !defined YEARSPERREPEAT */ + +/* +** The Gregorian year averages 365.2425 days, which is 31556952 seconds. +*/ + +#ifndef AVGSECSPERYEAR +#define AVGSECSPERYEAR 31556952L +#endif /* !defined AVGSECSPERYEAR */ + +#ifndef SECSPERREPEAT +#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR) +#endif /* !defined SECSPERREPEAT */ + +#ifndef SECSPERREPEAT_BITS +#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ +#endif /* !defined SECSPERREPEAT_BITS */ + /* ** UNIX was a registered trademark of The Open Group in 2003. */ diff --git a/libc/stdtime/strftime.c b/libc/stdtime/strftime.c index 365a42e12b8..d036d07690f 100644 --- a/libc/stdtime/strftime.c +++ b/libc/stdtime/strftime.c @@ -1,6 +1,6 @@ #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)strftime.c 7.64"; +static char elsieid[] = "@(#)strftime.c 8.3"; /* ** Based on the UCB version with the ID appearing below. ** This is ANSIish only when "multibyte character == plain character". @@ -19,7 +19,7 @@ static char elsieid[] = "@(#)strftime.c 7.64"; ** duplicated in all such forms and that any documentation, ** advertising materials, and other materials related to such ** distribution and use acknowledge that the software was developed -** by the University of California, Berkeley. The name of the +** by the University of California, Berkeley. The name of the ** University may not be used to endorse or promote products derived ** from this software without specific prior written permission. ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR @@ -53,7 +53,7 @@ struct lc_time_T { #ifdef LOCALE_HOME #include "sys/stat.h" static struct lc_time_T localebuf; -static struct lc_time_T * _loc P((void)); +static struct lc_time_T * _loc(void); #define Locale _loc() #endif /* defined LOCALE_HOME */ #ifndef LOCALE_HOME @@ -91,7 +91,7 @@ static const struct lc_time_T C_time_locale = { ** C99 requires this format. ** Previously this code used "%D %X", but we now conform to C99. ** Note that - ** "%a %b %d %H:%M:%S %Y" + ** "%a %b %d %H:%M:%S %Y" ** is used by Solaris 2.3. */ "%a %b %e %T %Y", @@ -106,11 +106,11 @@ static const struct lc_time_T C_time_locale = { "%a %b %e %H:%M:%S %Z %Y" }; -static char * _add P((const char *, char *, const char *)); -static char * _conv P((int, const char *, char *, const char *)); -static char * _fmt P((const char *, const struct tm *, char *, const char *, int *)); - -size_t strftime P((char *, size_t, const char *, const struct tm *)); +static char * _add(const char *, char *, const char *); +static char * _conv(int, const char *, char *, const char *); +static char * _fmt(const char *, const struct tm *, char *, const char *, + int *); +static char * _yconv(int, int, int, int, char *, const char *); extern char * tzname[]; @@ -118,7 +118,6 @@ extern char * tzname[]; #define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS" #endif /* !defined YEAR_2000_NAME */ - #define IN_NONE 0 #define IN_SOME 1 #define IN_THIS 2 @@ -210,14 +209,14 @@ label: ** something completely different. ** (ado, 1993-05-24) */ - pt = _conv((t->tm_year + TM_YEAR_BASE) / 100, - "%02d", pt, ptlim); + pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0, + pt, ptlim); continue; case 'c': { int warn2 = IN_SOME; - pt = _fmt(Locale->c_fmt, t, pt, ptlim, warnp); + pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2); if (warn2 == IN_ALL) warn2 = IN_THIS; if (warn2 > *warnp) @@ -266,7 +265,7 @@ label: ** t->tm_hour % 12 : 12, 2, ' '); ** ...and has been changed to the below to ** match SunOS 4.1.1 and Arnold Robbins' - ** strftime version 3.0. That is, "%k" and + ** strftime version 3.0. That is, "%k" and ** "%l" have been swapped. ** (ado, 1993-05-24) */ @@ -286,7 +285,7 @@ label: ** _conv(t->tm_hour, 2, ' '); ** ...and has been changed to the below to ** match SunOS 4.1.1 and Arnold Robbin's - ** strftime version 3.0. That is, "%k" and + ** strftime version 3.0. That is, "%k" and ** "%l" have been swapped. ** (ado, 1993-05-24) */ @@ -361,7 +360,7 @@ label: case 'G': /* ISO 8601 year (four digits) */ case 'g': /* ISO 8601 year (two digits) */ /* -** From Arnold Robbins' strftime version 3.0: "the week number of the +** From Arnold Robbins' strftime version 3.0: "the week number of the ** year (the first Monday as the first day of week 1) as a decimal number ** (01-53)." ** (ado, 1993-05-24) @@ -374,17 +373,19 @@ label: ** might also contain days from the previous year and the week before week ** 01 of a year is the last week (52 or 53) of the previous year even if ** it contains days from the new year. A week starts with Monday (day 1) -** and ends with Sunday (day 7). For example, the first week of the year +** and ends with Sunday (day 7). For example, the first week of the year ** 1997 lasts from 1996-12-30 to 1997-01-05..." ** (ado, 1996-01-02) */ { int year; + int base; int yday; int wday; int w; - year = t->tm_year + TM_YEAR_BASE; + year = t->tm_year; + base = TM_YEAR_BASE; yday = t->tm_yday; wday = t->tm_wday; for ( ; ; ) { @@ -392,7 +393,7 @@ label: int bot; int top; - len = isleap(year) ? + len = isleap_sum(year, base) ? DAYSPERLYEAR : DAYSPERNYEAR; /* @@ -411,7 +412,7 @@ label: top += DAYSPERWEEK; top += len; if (yday >= top) { - ++year; + ++base; w = 1; break; } @@ -420,26 +421,26 @@ label: DAYSPERWEEK); break; } - --year; - yday += isleap(year) ? + --base; + yday += isleap_sum(year, base) ? DAYSPERLYEAR : DAYSPERNYEAR; } #ifdef XPG4_1994_04_09 - if ((w == 52 - && t->tm_mon == TM_JANUARY) - || (w == 1 - && t->tm_mon == TM_DECEMBER)) - w = 53; + if ((w == 52 && + t->tm_mon == TM_JANUARY) || + (w == 1 && + t->tm_mon == TM_DECEMBER)) + w = 53; #endif /* defined XPG4_1994_04_09 */ if (*format == 'V') pt = _conv(w, "%02d", pt, ptlim); else if (*format == 'g') { *warnp = IN_ALL; - pt = _conv(year % 100, "%02d", + pt = _yconv(year, base, 0, 1, pt, ptlim); - } else pt = _conv(year, "%04d", + } else pt = _yconv(year, base, 1, 1, pt, ptlim); } continue; @@ -477,11 +478,11 @@ label: continue; case 'y': *warnp = IN_ALL; - pt = _conv((t->tm_year + TM_YEAR_BASE) % 100, - "%02d", pt, ptlim); + pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1, + pt, ptlim); continue; case 'Y': - pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d", + pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1, pt, ptlim); continue; case 'Z': @@ -512,12 +513,12 @@ label: /* ** C99 says that the UTC offset must ** be computed by looking only at - ** tm_isdst. This requirement is + ** tm_isdst. This requirement is ** incorrect, since it means the code ** must rely on magic (in this case ** altzone and timezone), and the ** magic might not have the correct - ** offset. Doing things correctly is + ** offset. Doing things correctly is ** tricky and requires disobeying C99; ** see GNU C strftime for details. ** For now, punt and conform to the @@ -546,9 +547,10 @@ label: diff = -diff; } else sign = "+"; pt = _add(sign, pt, ptlim); - diff /= 60; - pt = _conv((diff/60)*100 + diff%60, - "%04d", pt, ptlim); + diff /= SECSPERMIN; + diff = (diff / MINSPERHOUR) * 100 + + (diff % MINSPERHOUR); + pt = _conv(diff, "%04d", pt, ptlim); } continue; case '+': @@ -558,7 +560,7 @@ label: case '%': /* ** X311J/88-090 (4.12.3.5): if conversion char is - ** undefined, behavior is undefined. Print out the + ** undefined, behavior is undefined. Print out the ** character itself as printf(3) also does. */ default: @@ -596,9 +598,50 @@ const char * const ptlim; return pt; } +/* +** POSIX and the C Standard are unclear or inconsistent about +** what %C and %y do if the year is negative or exceeds 9999. +** Use the convention that %C concatenated with %y yields the +** same output as %Y, and that %Y contains at least 4 bytes, +** with more only if necessary. +*/ + +static char * +_yconv(a, b, convert_top, convert_yy, pt, ptlim) +const int a; +const int b; +const int convert_top; +const int convert_yy; +char * pt; +const char * const ptlim; +{ + register int lead; + register int trail; + +#define DIVISOR 100 + trail = a % DIVISOR + b % DIVISOR; + lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR; + trail %= DIVISOR; + if (trail < 0 && lead > 0) { + trail += DIVISOR; + --lead; + } else if (lead < 0 && trail > 0) { + trail -= DIVISOR; + ++lead; + } + if (convert_top) { + if (lead == 0 && trail < 0) + pt = _add("-0", pt, ptlim); + else pt = _conv(lead, "%02d", pt, ptlim); + } + if (convert_yy) + pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim); + return pt; +} + #ifdef LOCALE_HOME static struct lc_time_T * -_loc P((void)) +_loc(void) { static const char locale_home[] = LOCALE_HOME; static const char lc_time[] = "LC_TIME"; @@ -640,7 +683,7 @@ _loc P((void)) ** Slurp the locale file into the cache. */ namesize = strlen(name) + 1; - if (sizeof filename < + if (sizeof filename < ((sizeof locale_home) + namesize + (sizeof lc_time))) goto no_locale; oldsun = 0; @@ -663,7 +706,7 @@ _loc P((void)) goto bad_locale; bufsize = namesize + st.st_size; locale_buf = NULL; - lbuf = (lbuf == NULL) ? malloc(bufsize) : realloc(lbuf, bufsize); + lbuf = (lbuf == NULL) ? malloc(bufsize) : realloc(lbuf, bufsize); if (lbuf == NULL) goto bad_locale; (void) strcpy(lbuf, name); diff --git a/libc/stdtime/time2posix.3 b/libc/stdtime/time2posix.3 new file mode 100644 index 00000000000..96959c642ed --- /dev/null +++ b/libc/stdtime/time2posix.3 @@ -0,0 +1,121 @@ +.TH TIME2POSIX 3 +.SH NAME +time2posix, posix2time \- convert seconds since the Epoch +.SH SYNOPSIS +.nf +.B #include +.B #include +.PP +.B time_t time2posix(t) +.B time_t t +.PP +.B time_t posix2time(t) +.B time_t t +.PP +.B cc ... -ltz +.fi +.SH DESCRIPTION +IEEE Standard 1003.1 +(POSIX) +legislates that a time_t value of +536457599 shall correspond to "Wed Dec 31 23:59:59 UTC 1986." +This effectively implies that POSIX time_t's cannot include leap +seconds and, +therefore, +that the system time must be adjusted as each leap occurs. +.PP +If the time package is configured with leap-second support +enabled, +however, +no such adjustment is needed and +time_t values continue to increase over leap events +(as a true `seconds since...' value). +This means that these values will differ from those required by POSIX +by the net number of leap seconds inserted since the Epoch. +.PP +Typically this is not a problem as the type time_t is intended +to be +(mostly) +opaque\(emtime_t values should only be obtained-from and +passed-to functions such as +.IR time(2) , +.IR localtime(3) , +.IR mktime(3) , +and +.IR difftime(3) . +However, +POSIX gives an arithmetic +expression for directly computing a time_t value from a given date/time, +and the same relationship is assumed by some +(usually older) +applications. +Any programs creating/dissecting time_t's +using such a relationship will typically not handle intervals +over leap seconds correctly. +.PP +The +.I time2posix +and +.I posix2time +functions are provided to address this time_t mismatch by converting +between local time_t values and their POSIX equivalents. +This is done by accounting for the number of time-base changes that +would have taken place on a POSIX system as leap seconds were inserted +or deleted. +These converted values can then be used in lieu of correcting the older +applications, +or when communicating with POSIX-compliant systems. +.PP +.I Time2posix +is single-valued. +That is, +every local time_t +corresponds to a single POSIX time_t. +.I Posix2time +is less well-behaved: +for a positive leap second hit the result is not unique, +and for a negative leap second hit the corresponding +POSIX time_t doesn't exist so an adjacent value is returned. +Both of these are good indicators of the inferiority of the +POSIX representation. +.PP +The following table summarizes the relationship between a time +T and it's conversion to, +and back from, +the POSIX representation over the leap second inserted at the end of June, +1993. +.nf +.ta \w'93/06/30 'u +\w'23:59:59 'u +\w'A+0 'u +\w'X=time2posix(T) 'u +DATE TIME T X=time2posix(T) posix2time(X) +93/06/30 23:59:59 A+0 B+0 A+0 +93/06/30 23:59:60 A+1 B+1 A+1 or A+2 +93/07/01 00:00:00 A+2 B+1 A+1 or A+2 +93/07/01 00:00:01 A+3 B+2 A+3 + +A leap second deletion would look like... + +DATE TIME T X=time2posix(T) posix2time(X) +??/06/30 23:59:58 A+0 B+0 A+0 +??/07/01 00:00:00 A+1 B+2 A+1 +??/07/01 00:00:01 A+2 B+3 A+2 +.sp +.ce + [Note: posix2time(B+1) => A+0 or A+1] +.fi +.PP +If leap-second support is not enabled, +local time_t's and +POSIX time_t's are equivalent, +and both +.I time2posix +and +.I posix2time +degenerate to the identity function. +.SH SEE ALSO +difftime(3), +localtime(3), +mktime(3), +time(2) +.\" @(#)time2posix.3 8.1 +.\" This file is in the public domain, so clarified as of +.\" 1996-06-05 by Arthur David Olson. diff --git a/libc/stdtime/tzfile.5 b/libc/stdtime/tzfile.5 new file mode 100644 index 00000000000..6b8768cc9fc --- /dev/null +++ b/libc/stdtime/tzfile.5 @@ -0,0 +1,152 @@ +.TH TZFILE 5 +.SH NAME +tzfile \- time zone information +.SH SYNOPSIS +.B +#include +.SH DESCRIPTION +The time zone information files used by +.IR tzset (3) +begin with the magic characters "TZif" to identify then as +time zone information files, +followed by a character identifying the version of the file's format +(as of 2005, either an ASCII NUL or a '2') +followed by fifteen bytes containing zeroes reserved for future use, +followed by six four-byte values of type +.BR long , +written in a ``standard'' byte order +(the high-order byte of the value is written first). +These values are, +in order: +.TP +.I tzh_ttisgmtcnt +The number of UTC/local indicators stored in the file. +.TP +.I tzh_ttisstdcnt +The number of standard/wall indicators stored in the file. +.TP +.I tzh_leapcnt +The number of leap seconds for which data is stored in the file. +.TP +.I tzh_timecnt +The number of "transition times" for which data is stored +in the file. +.TP +.I tzh_typecnt +The number of "local time types" for which data is stored +in the file (must not be zero). +.TP +.I tzh_charcnt +The number of characters of "time zone abbreviation strings" +stored in the file. +.PP +The above header is followed by +.I tzh_timecnt +four-byte values of type +.BR long , +sorted in ascending order. +These values are written in ``standard'' byte order. +Each is used as a transition time (as returned by +.IR time (2)) +at which the rules for computing local time change. +Next come +.I tzh_timecnt +one-byte values of type +.BR "unsigned char" ; +each one tells which of the different types of ``local time'' types +described in the file is associated with the same-indexed transition time. +These values serve as indices into an array of +.I ttinfo +structures (with +.I tzh_typecnt +entries) that appears next in the file; +these structures are defined as follows: +.in +.5i +.sp +.nf +.ta .5i +\w'unsigned int\0\0'u +struct ttinfo { + long tt_gmtoff; + int tt_isdst; + unsigned int tt_abbrind; +}; +.in -.5i +.fi +.sp +Each structure is written as a four-byte value for +.I tt_gmtoff +of type +.BR long , +in a standard byte order, followed by a one-byte value for +.I tt_isdst +and a one-byte value for +.IR tt_abbrind . +In each structure, +.I tt_gmtoff +gives the number of seconds to be added to UTC, +.I tt_isdst +tells whether +.I tm_isdst +should be set by +.I localtime (3) +and +.I tt_abbrind +serves as an index into the array of time zone abbreviation characters +that follow the +.I ttinfo +structure(s) in the file. +.PP +Then there are +.I tzh_leapcnt +pairs of four-byte values, written in standard byte order; +the first value of each pair gives the time +(as returned by +.IR time(2)) +at which a leap second occurs; +the second gives the +.I total +number of leap seconds to be applied after the given time. +The pairs of values are sorted in ascending order by time. +.PP +Then there are +.I tzh_ttisstdcnt +standard/wall indicators, each stored as a one-byte value; +they tell whether the transition times associated with local time types +were specified as standard time or wall clock time, +and are used when a time zone file is used in handling POSIX-style +time zone environment variables. +.PP +Finally there are +.I tzh_ttisgmtcnt +UTC/local indicators, each stored as a one-byte value; +they tell whether the transition times associated with local time types +were specified as UTC or local time, +and are used when a time zone file is used in handling POSIX-style +time zone environment variables. +.PP +.I Localtime +uses the first standard-time +.I ttinfo +structure in the file +(or simply the first +.I ttinfo +structure in the absence of a standard-time structure) +if either +.I tzh_timecnt +is zero or the time argument is less than the first transition time recorded +in the file. +.PP +For version-2-format time zone files, +the above header and data is followed by a second header and data, +identical in format except that +eight bytes are used for each transition time or leap second time. +After the second header and data comes a newline-enclosed, +POSIX-TZ-environment-variable-style string for use in handling instants +after the last transition time stored in the file +(with nothing between the newlines if there is no POSIX representation for +such instants). +.SH SEE ALSO +newctime(3) +.\" @(#)tzfile.5 8.2 +.\" This file is in the public domain, so clarified as of +.\" 1996-06-05 by Arthur David Olson. diff --git a/libc/stdtime/tzfile.h b/libc/stdtime/tzfile.h index 0921c3c3396..3a9eee305a5 100644 --- a/libc/stdtime/tzfile.h +++ b/libc/stdtime/tzfile.h @@ -4,7 +4,7 @@ /* ** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +** 1996-06-05 by Arthur David Olson. */ /* @@ -21,7 +21,7 @@ #ifndef lint #ifndef NOID -static char tzfilehid[] = "@(#)tzfile.h 7.14"; +static char tzfilehid[] = "@(#)tzfile.h 8.1"; #endif /* !defined NOID */ #endif /* !defined lint */ @@ -48,8 +48,9 @@ static char tzfilehid[] = "@(#)tzfile.h 7.14"; #define TZ_MAGIC "TZif" struct tzhead { - char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_reserved[16]; /* reserved for future use */ + char tzh_magic[4]; /* TZ_MAGIC */ + char tzh_version[1]; /* '\0' or '2' as of 2005 */ + char tzh_reserved[15]; /* reserved--must be zero */ char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ char tzh_leapcnt[4]; /* coded number of leap seconds */ @@ -83,19 +84,23 @@ struct tzhead { ** assumed to be local time */ +/* +** If tzh_version is '2' or greater, the above is followed by a second instance +** of tzhead and a second instance of the data in which each coded transition +** time uses 8 rather than 4 chars, +** then a POSIX-TZ-environment-variable-style string for use in handling +** instants after the last transition time stored in the file +** (with nothing between the newlines if there is no POSIX representation for +** such instants). +*/ + /* ** In the current implementation, "tzset()" refuses to deal with files that ** exceed any of the limits below. */ #ifndef TZ_MAX_TIMES -/* -** The TZ_MAX_TIMES value below is enough to handle a bit more than a -** year's worth of solar time (corrected daily to the nearest second) or -** 138 years of Pacific Presidential Election time -** (where there are three time zone transitions every fourth year). -*/ -#define TZ_MAX_TIMES 370 +#define TZ_MAX_TIMES 1200 #endif /* !defined TZ_MAX_TIMES */ #ifndef TZ_MAX_TYPES @@ -105,7 +110,7 @@ struct tzhead { #ifdef NOSOLAR /* ** Must be at least 14 for Europe/Riga as of Jan 12 1995, -** as noted by Earl Chew . +** as noted by Earl Chew. */ #define TZ_MAX_TYPES 20 /* Maximum number of local time types */ #endif /* !defined NOSOLAR */ @@ -156,33 +161,20 @@ struct tzhead { #define EPOCH_YEAR 1970 #define EPOCH_WDAY TM_THURSDAY -/* -** Accurate only for the past couple of centuries; -** that will probably do. -*/ - #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) -#ifndef USG - /* -** Use of the underscored variants may cause problems if you move your code to -** certain System-V-based systems; for maximum portability, use the -** underscore-free variants. The underscored variants are provided for -** backward compatibility only; they may disappear from future versions of -** this file. +** Since everything in isleap is modulo 400 (or a factor of 400), we know that +** isleap(y) == isleap(y % 400) +** and so +** isleap(a + b) == isleap((a + b) % 400) +** or +** isleap(a + b) == isleap(a % 400 + b % 400) +** This is true even if % means modulo rather than Fortran remainder +** (which is allowed by C89 but not C99). +** We use this to avoid addition overflow problems. */ -#define SECS_PER_MIN SECSPERMIN -#define MINS_PER_HOUR MINSPERHOUR -#define HOURS_PER_DAY HOURSPERDAY -#define DAYS_PER_WEEK DAYSPERWEEK -#define DAYS_PER_NYEAR DAYSPERNYEAR -#define DAYS_PER_LYEAR DAYSPERLYEAR -#define SECS_PER_HOUR SECSPERHOUR -#define SECS_PER_DAY SECSPERDAY -#define MONS_PER_YEAR MONSPERYEAR - -#endif /* !defined USG */ +#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) #endif /* !defined TZFILE_H */ diff --git a/unused/Makefile b/unused/Makefile new file mode 100644 index 00000000000..3865f23766e --- /dev/null +++ b/unused/Makefile @@ -0,0 +1,418 @@ +# @(#)Makefile 8.7 + +# Change the line below for your time zone (after finding the zone you want in +# the time zone files, or adding it to a time zone file). +# Alternately, if you discover you've got the wrong time zone, you can just +# zic -l rightzone +# to correct things. +# Use the command +# make zonenames +# to get a list of the values you can use for LOCALTIME. + +LOCALTIME= Factory + +# If you want something other than Eastern United States time as a template +# for handling POSIX-style time zone environment variables, +# change the line below (after finding the zone you want in the +# time zone files, or adding it to a time zone file). +# (When a POSIX-style environment variable is handled, the rules in the +# template file are used to determine "spring forward" and "fall back" days and +# times; the environment variable itself specifies UTC offsets of standard and +# summer time.) +# Alternately, if you discover you've got the wrong time zone, you can just +# zic -p rightzone +# to correct things. +# Use the command +# make zonenames +# to get a list of the values you can use for POSIXRULES. +# If you want POSIX compatibility, use "America/New_York". + +POSIXRULES= America/New_York + +# Also see TZDEFRULESTRING below, which takes effect only +# if the time zone files cannot be accessed. + +# Everything gets put in subdirectories of. . . + +TOPDIR= /usr/local + +# "Compiled" time zone information is placed in the "TZDIR" directory +# (and subdirectories). +# Use an absolute path name for TZDIR unless you're just testing the software. + +TZDIR= $(TOPDIR)/etc/zoneinfo + +# The "tzselect", "zic", and "zdump" commands get installed in. . . + +ETCDIR= $(TOPDIR)/etc + +# If you "make INSTALL", the "date" command gets installed in. . . + +BINDIR= $(TOPDIR)/bin + +# Manual pages go in subdirectories of. . . + +MANDIR= $(TOPDIR)/man + +# Library functions are put in an archive in LIBDIR. + +LIBDIR= $(TOPDIR)/lib +TZLIB= $(LIBDIR)/libtz.a + +# If you always want time values interpreted as "seconds since the epoch +# (not counting leap seconds)", use +# REDO= posix_only +# below. If you always want right time values interpreted as "seconds since +# the epoch" (counting leap seconds)", use +# REDO= right_only +# below. If you want both sets of data available, with leap seconds not +# counted normally, use +# REDO= posix_right +# below. If you want both sets of data available, with leap seconds counted +# normally, use +# REDO= right_posix +# below. +# POSIX mandates that leap seconds not be counted; for compatibility with it, +# use either "posix_only" or "posix_right". + +REDO= posix_right + +# Since "." may not be in PATH... + +YEARISTYPE= ./yearistype + +# Non-default libraries needed to link. +# Add -lintl if you want to use `gettext' on Solaris. +LDLIBS= + +# Add the following to the end of the "CFLAGS=" line as needed. +# -DHAVE_ADJTIME=0 if `adjtime' does not exist (SVR0?) +# -DHAVE_GETTEXT=1 if `gettext' works (GNU, Linux, Solaris); also see LDLIBS +# -DHAVE_INCOMPATIBLE_CTIME_R=1 if your system's time.h declares +# ctime_r and asctime_r incompatibly with the POSIX standard (Solaris 8). +# -DHAVE_SETTIMEOFDAY=0 if settimeofday does not exist (SVR0?) +# -DHAVE_SETTIMEOFDAY=1 if settimeofday has just 1 arg (SVR4) +# -DHAVE_SETTIMEOFDAY=2 if settimeofday uses 2nd arg (4.3BSD) +# -DHAVE_SETTIMEOFDAY=3 if settimeofday ignores 2nd arg (4.4BSD) +# -DHAVE_STDINT_H=1 if you have a pre-C99 compiler with "stdint.h" +# -DHAVE_SYMLINK=0 if your system lacks the symlink function +# -DHAVE_SYS_STAT_H=0 if your compiler lacks a "sys/stat.h" +# -DHAVE_SYS_WAIT_H=0 if your compiler lacks a "sys/wait.h" +# -DLOCALE_HOME=\"path\" if locales are in "path", not "/usr/lib/locale" +# -DHAVE_UNISTD_H=0 if your compiler lacks a "unistd.h" (Microsoft C++ 7?) +# -DHAVE_UTMPX_H=1 if your compiler has a "utmpx.h" +# -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified +# DST transitions if the time zone files cannot be accessed +# -DTZ_DOMAIN=\"foo\" to use "foo" for gettext domain name; default is "tz" +# -TTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory; +# the default is system-supplied, typically "/usr/lib/locale" +# $(GCC_DEBUG_FLAGS) if you are using GCC and want lots of checking +# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1 +# if you do not want run time warnings about formats that may cause +# year 2000 grief +# -DZIC_MAX_ABBR_LEN_WO_WARN=3 +# (or some other number) to set the maximum time zone abbreviation length +# that zic will accept without a warning (the default is 6) +GCC_DEBUG_FLAGS = -Dlint -g -O -fno-common \ + -Wall -Wcast-qual -Wconversion -Wmissing-prototypes \ + -Wnested-externs -Wpointer-arith -Wshadow \ + -Wtraditional # -Wstrict-prototypes -Wwrite-strings +# +# If you want to use System V compatibility code, add +# -DUSG_COMPAT +# to the end of the "CFLAGS=" line. This arrange for "timezone" and "daylight" +# variables to be kept up-to-date by the time conversion functions. Neither +# "timezone" nor "daylight" is described in X3J11's work. +# +# If your system has a "GMT offset" field in its "struct tm"s +# (or if you decide to add such a field in your system's "time.h" file), +# add the name to a define such as +# -DTM_GMTOFF=tm_gmtoff +# or +# -DTM_GMTOFF=_tm_gmtoff +# to the end of the "CFLAGS=" line. +# Neither tm_gmtoff nor _tm_gmtoff is described in X3J11's work; +# in its work, use of "tm_gmtoff" is described as non-conforming. +# Both Linux and BSD have done the equivalent of defining TM_GMTOFF in +# their recent releases. +# +# If your system has a "zone abbreviation" field in its "struct tm"s +# (or if you decide to add such a field in your system's "time.h" file), +# add the name to a define such as +# -DTM_ZONE=tm_zone +# or +# -DTM_ZONE=_tm_zone +# to the end of the "CFLAGS=" line. +# Neither tm_zone nor _tm_zone is described in X3J11's work; +# in its work, use of "tm_zone" is described as non-conforming. +# Both UCB and Sun have done the equivalent of defining TM_ZONE in +# their recent releases. +# +# If you want functions that were inspired by early versions of X3J11's work, +# add +# -DSTD_INSPIRED +# to the end of the "CFLAGS=" line. This arranges for the functions +# "tzsetwall", "offtime", "timelocal", "timegm", "timeoff", +# "posix2time", and "time2posix" to be added to the time conversion library. +# "tzsetwall" is like "tzset" except that it arranges for local wall clock +# time (rather than the time specified in the TZ environment variable) +# to be used. +# "offtime" is like "gmtime" except that it accepts a second (long) argument +# that gives an offset to add to the time_t when converting it. +# "timelocal" is equivalent to "mktime". +# "timegm" is like "timelocal" except that it turns a struct tm into +# a time_t using UTC (rather than local time as "timelocal" does). +# "timeoff" is like "timegm" except that it accepts a second (long) argument +# that gives an offset to use when converting to a time_t. +# "posix2time" and "time2posix" are described in an included manual page. +# X3J11's work does not describe any of these functions. +# Sun has provided "tzsetwall", "timelocal", and "timegm" in SunOS 4.0. +# These functions may well disappear in future releases of the time +# conversion package. +# +# If you want Source Code Control System ID's left out of object modules, add +# -DNOID +# to the end of the "CFLAGS=" line. +# +# If you'll never want to handle solar-time-based time zones, add +# -DNOSOLAR +# to the end of the "CFLAGS=" line +# (and comment out the "SDATA=" line below). +# This reduces (slightly) the run-time data-space requirements of +# the time conversion functions; it may reduce the acceptability of your system +# to folks in oil- and cash-rich places. +# +# If you want to allocate state structures in localtime, add +# -DALL_STATE +# to the end of the "CFLAGS=" line. Storage is obtained by calling malloc. +# +# If you want an "altzone" variable (a la System V Release 3.1), add +# -DALTZONE +# to the end of the "CFLAGS=" line. +# This variable is not described in X3J11's work. +# +# If you want a "gtime" function (a la MACH), add +# -DCMUCS +# to the end of the "CFLAGS=" line +# This function is not described in X3J11's work. +# +# NIST-PCTS:151-2, Version 1.4, (1993-12-03) is a test suite put +# out by the National Institute of Standards and Technology +# which claims to test C and Posix conformance. If you want to pass PCTS, add +# -DPCTS +# to the end of the "CFLAGS=" line. +# +# If you want strict compliance with XPG4 as of 1994-04-09, add +# -DXPG4_1994_04_09 +# to the end of the "CFLAGS=" line. This causes "strftime" to always return +# 53 as a week number (rather than 52 or 53) for those days in January that +# before the first Monday in January when a "%V" format is used and January 1 +# falls on a Friday, Saturday, or Sunday. + +CFLAGS= + +# If you want zic's -s option used when installing, uncomment the next line +# ZFLAGS= -s + +zic= ./zic +ZIC= $(zic) $(ZFLAGS) + +# The name of a Posix-compliant `awk' on your system. +AWK= nawk + +# The path where SGML DTDs are kept. +SGML_SEARCH_PATH= $(TOPDIR)/share/doc/sgml-lib/REC-html401-19991224/ + +# The catalog file(s) to use when validating. +SGML_CATALOG_FILES= HTML4.cat + +# The name, arguments and environment of a program to validate your web pages. +# See for a validator, and +# for a validation library. +VALIDATE = nsgmls +VALIDATE_FLAGS = -s -B -wall -wno-unused-param +VALIDATE_ENV = \ + SGML_CATALOG_FILES=$(SGML_CATALOG_FILES) \ + SGML_SEARCH_PATH=$(SGML_SEARCH_PATH) \ + SP_CHARSET_FIXED=YES \ + SP_ENCODING=UTF-8 + +############################################################################### + +cc= cc +CC= $(cc) -DTZDIR=\"$(TZDIR)\" + +TZCSRCS= zic.c localtime.c asctime.c scheck.c ialloc.c +TZCOBJS= zic.o localtime.o asctime.o scheck.o ialloc.o +TZDSRCS= zdump.c localtime.c ialloc.c +TZDOBJS= zdump.o localtime.o ialloc.o +DATESRCS= date.c localtime.c strftime.c asctime.c +DATEOBJS= date.o localtime.o strftime.o asctime.o +LIBSRCS= localtime.c asctime.c difftime.c +LIBOBJS= localtime.o asctime.o difftime.o +HEADERS= tzfile.h private.h +NONLIBSRCS= zic.c zdump.c scheck.c ialloc.c +NEWUCBSRCS= date.c strftime.c +SOURCES= $(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS) tzselect.ksh +MANS= newctime.3 newstrftime.3 newtzset.3 time2posix.3 \ + tzfile.5 tzselect.8 zic.8 zdump.8 +DOCS= README Theory $(MANS) date.1 Makefile +PRIMARY_YDATA= africa antarctica asia australasia \ + europe northamerica southamerica +YDATA= $(PRIMARY_YDATA) pacificnew etcetera factory backward +NDATA= systemv +SDATA= solar87 solar88 solar89 +TDATA= $(YDATA) $(NDATA) $(SDATA) +TABDATA= iso3166.tab zone.tab +DATA= $(YDATA) $(NDATA) $(SDATA) $(TABDATA) leapseconds yearistype.sh +WEB_PAGES= tz-art.htm tz-link.htm +MISC= usno1988 usno1989 usno1989a usno1995 usno1997 usno1998 \ + itca.jpg $(WEB_PAGES) checktab.awk workman.sh \ + zoneinfo2tdf.pl +ENCHILADA= $(DOCS) $(SOURCES) $(DATA) $(MISC) + +# And for the benefit of csh users on systems that assume the user +# shell should be used to handle commands in Makefiles. . . + +SHELL= /bin/sh + +all: tzselect zic zdump $(LIBOBJS) + +ALL: all date + +install: all $(DATA) $(REDO) $(TZLIB) $(MANS) $(TABDATA) + $(ZIC) -y $(YEARISTYPE) \ + -d $(TZDIR) -l $(LOCALTIME) -p $(POSIXRULES) + -rm -f $(TZDIR)/iso3166.tab $(TZDIR)/zone.tab + cp iso3166.tab zone.tab $(TZDIR)/. + -mkdir $(TOPDIR) $(ETCDIR) + cp tzselect zic zdump $(ETCDIR)/. + -mkdir $(TOPDIR) $(MANDIR) \ + $(MANDIR)/man3 $(MANDIR)/man5 $(MANDIR)/man8 + -rm -f $(MANDIR)/man3/newctime.3 \ + $(MANDIR)/man3/newtzset.3 \ + $(MANDIR)/man5/tzfile.5 \ + $(MANDIR)/man8/tzselect.8 \ + $(MANDIR)/man8/zdump.8 \ + $(MANDIR)/man8/zic.8 + cp newctime.3 newtzset.3 $(MANDIR)/man3/. + cp tzfile.5 $(MANDIR)/man5/. + cp tzselect.8 zdump.8 zic.8 $(MANDIR)/man8/. + +INSTALL: ALL install date.1 + -mkdir $(TOPDIR) $(BINDIR) + cp date $(BINDIR)/. + -mkdir $(TOPDIR) $(MANDIR) $(MANDIR)/man1 + -rm -f $(MANDIR)/man1/date.1 + cp date.1 $(MANDIR)/man1/. + +zdump: $(TZDOBJS) + $(CC) $(CFLAGS) $(LFLAGS) $(TZDOBJS) $(LDLIBS) -o $@ + +zic: $(TZCOBJS) yearistype + $(CC) $(CFLAGS) $(LFLAGS) $(TZCOBJS) $(LDLIBS) -o $@ + +yearistype: yearistype.sh + cp yearistype.sh yearistype + chmod +x yearistype + +posix_only: zic $(TDATA) + $(ZIC) -y $(YEARISTYPE) -d $(TZDIR) -L /dev/null $(TDATA) + +right_only: zic leapseconds $(TDATA) + $(ZIC) -y $(YEARISTYPE) -d $(TZDIR) -L leapseconds $(TDATA) + +# In earlier versions of this makefile, the other two directories were +# subdirectories of $(TZDIR). However, this led to configuration errors. +# For example, with posix_right under the earlier scheme, +# TZ='right/Australia/Adelaide' got you localtime with leap seconds, +# but gmtime without leap seconds, which led to problems with applications +# like sendmail that subtract gmtime from localtime. +# Therefore, the other two directories are now siblings of $(TZDIR). +# You must replace all of $(TZDIR) to switch from not using leap seconds +# to using them, or vice versa. +other_two: zic leapseconds $(TDATA) + $(ZIC) -y $(YEARISTYPE) -d $(TZDIR)-posix -L /dev/null $(TDATA) + $(ZIC) -y $(YEARISTYPE) \ + -d $(TZDIR)-leaps -L leapseconds $(TDATA) + +posix_right: posix_only other_two + +right_posix: right_only other_two + +zones: $(REDO) + +$(TZLIB): $(LIBOBJS) + -mkdir $(TOPDIR) $(LIBDIR) + ar ru $@ $(LIBOBJS) + if [ -x /usr/ucb/ranlib -o -x /usr/bin/ranlib ] ; \ + then ranlib $@ ; fi + +date: $(DATEOBJS) + $(CC) $(CFLAGS) date.o localtime.o asctime.o strftime.o \ + $(LDLIBS) -lc -o $@ + +tzselect: tzselect.ksh + sed \ + -e 's|AWK=[^}]*|AWK=$(AWK)|g' \ + -e 's|TZDIR=[^}]*|TZDIR=$(TZDIR)|' \ + <$? >$@ + chmod +x $@ + +check: check_tables check_web + +check_tables: checktab.awk $(PRIMARY_YDATA) + $(AWK) -f checktab.awk $(PRIMARY_YDATA) + +check_web: $(WEB_PAGES) + $(VALIDATE_ENV) $(VALIDATE) $(VALIDATE_FLAGS) $(WEB_PAGES) + +clean: + rm -f core *.o *.out tzselect zdump zic yearistype date + +maintainer-clean: clean + @echo 'This command is intended for maintainers to use; it' + @echo 'deletes files that may need special tools to rebuild.' + rm -f *.[1-8].txt tzcode.tar.gz tzdata.tar.gz + +names: + @echo $(ENCHILADA) + +# The zics below ensure that each data file can stand on its own. +# We also do an all-files run to catch links to links. + +public: $(ENCHILADA) + make maintainer-clean + make "CFLAGS=$(GCC_DEBUG_FLAGS)" + -mkdir /tmp/,tzpublic + -for i in $(TDATA) ; do zic -v -d /tmp/,tzpublic $$i 2>&1 | grep -v "starting year" ; done + for i in $(TDATA) ; do zic -d /tmp/,tzpublic $$i || exit; done + zic -v -d /tmp/,tzpublic $(TDATA) || exit + rm -f -r /tmp/,tzpublic + for i in *.[1-8] ; do sh workman.sh $$i > $$i.txt || exit; done + $(AWK) -f checktab.awk $(PRIMARY_YDATA) + tar cf - $(DOCS) $(SOURCES) $(MISC) *.[1-8].txt | gzip -9 > tzcode.tar.gz + tar cf - $(DATA) | gzip -9 > tzdata.tar.gz + +typecheck: + make clean + for i in "long long" unsigned double; \ + do \ + make CFLAGS="-DTYPECHECK -D_TIME_T \"-Dtime_t=$$i\"" ; \ + ./zdump -v Europe/Rome ; \ + make clean ; \ + done + +zonenames: $(TDATA) + @$(AWK) '/^Zone/ { print $$2 } /^Link/ { print $$3 }' $(TDATA) + +asctime.o: private.h tzfile.h +date.o: private.h +difftime.o: private.h +ialloc.o: private.h +localtime.o: private.h tzfile.h +scheck.o: private.h +strftime.o: tzfile.h +zic.o: private.h tzfile.h + +.KEEP_STATE: diff --git a/unused/checktab.awk b/unused/checktab.awk new file mode 100644 index 00000000000..80ad7d57015 --- /dev/null +++ b/unused/checktab.awk @@ -0,0 +1,159 @@ +# Check tz tables for consistency. + +# @(#)checktab.awk 8.1 + +# Contributed by Paul Eggert. + +BEGIN { + FS = "\t" + + if (!iso_table) iso_table = "iso3166.tab" + if (!zone_table) zone_table = "zone.tab" + if (!want_warnings) want_warnings = -1 + + while (getline >"/dev/stderr" + status = 1 + } + cc = $1 + name = $2 + if (cc !~ /^[A-Z][A-Z]$/) { + printf "%s:%d: invalid country code `%s'\n", \ + iso_table, iso_NR, cc >>"/dev/stderr" + status = 1 + } + if (cc <= cc0) { + if (cc == cc0) { + s = "duplicate"; + } else { + s = "out of order"; + } + + printf "%s:%d: country code `%s' is %s\n", \ + iso_table, iso_NR, cc, s \ + >>"/dev/stderr" + status = 1 + } + cc0 = cc + if (name2cc[name]) { + printf "%s:%d: `%s' and `%s' have the sname name\n", \ + iso_table, iso_NR, name2cc[name], cc \ + >>"/dev/stderr" + status = 1 + } + name2cc[name] = cc + cc2name[cc] = name + cc2NR[cc] = iso_NR + } + + zone_table = "zone.tab" + cc0 = "" + + while (getline >"/dev/stderr" + status = 1 + } + cc = $1 + coordinates = $2 + tz = $3 + comments = $4 + if (cc < cc0) { + printf "%s:%d: country code `%s' is out of order\n", \ + zone_table, zone_NR, cc >>"/dev/stderr" + status = 1 + } + cc0 = cc + if (tz2cc[tz]) { + printf "%s:%d: %s: duplicate TZ column\n", \ + zone_table, zone_NR, tz >>"/dev/stderr" + status = 1 + } + tz2cc[tz] = cc + tz2comments[tz] = comments + tz2NR[tz] = zone_NR + if (cc2name[cc]) { + cc_used[cc]++ + } else { + printf "%s:%d: %s: unknown country code\n", \ + zone_table, zone_NR, cc >>"/dev/stderr" + status = 1 + } + if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \ + && coordinates !~ /^[-+][0-9][0-9][0-5][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9][0-5][0-9]$/) { + printf "%s:%d: %s: invalid coordinates\n", \ + zone_table, zone_NR, coordinates >>"/dev/stderr" + status = 1 + } + } + + for (tz in tz2cc) { + if (cc_used[tz2cc[tz]] == 1) { + if (tz2comments[tz]) { + printf "%s:%d: unnecessary comment `%s'\n", \ + zone_table, tz2NR[tz], tz2comments[tz] \ + >>"/dev/stderr" + status = 1 + } + } else { + if (!tz2comments[tz]) { + printf "%s:%d: missing comment\n", \ + zone_table, tz2NR[tz] >>"/dev/stderr" + status = 1 + } + } + } + + FS = " " +} + +{ + tz = "" + if ($1 == "Zone") tz = $2 + if ($1 == "Link") { + # Ignore Link commands if source and destination basenames + # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. + src = $2 + dst = $3 + while ((i = index(src, "/"))) src = substr(src, i+1) + while ((i = index(dst, "/"))) dst = substr(dst, i+1) + if (src != dst) tz = $3 + } + if (tz && tz ~ /\//) { + if (!tz2cc[tz]) { + printf "%s: no data for `%s'\n", zone_table, tz \ + >>"/dev/stderr" + status = 1 + } + zoneSeen[tz] = 1 + } +} + +END { + for (tz in tz2cc) { + if (!zoneSeen[tz]) { + printf "%s:%d: no Zone table for `%s'\n", \ + zone_table, tz2NR[tz], tz >>"/dev/stderr" + status = 1 + } + } + + if (0 < want_warnings) { + for (cc in cc2name) { + if (!cc_used[cc]) { + printf "%s:%d: warning: " \ + "no Zone entries for %s (%s)\n", \ + iso_table, cc2NR[cc], cc, cc2name[cc] + } + } + } + + exit status +} diff --git a/unused/date.1 b/unused/date.1 new file mode 100644 index 00000000000..3c75ba4337c --- /dev/null +++ b/unused/date.1 @@ -0,0 +1,175 @@ +.TH DATE 1 +.SH NAME +date \- show and set date and time +.SH SYNOPSIS +.if n .nh +.if n .na +.B date +[ +.B \-u +] [ +.B \-c +] [ +.B \-n +] [ +.B \-d +dsttype +] [ +.B \-t +minutes-west +] [ +\fB\-a \fR[\fB+\fR|\fB-]\fIsss\fB.\fIfff\fR +] [ +.BI + format +] [ +\fR[\fIyyyy\fR]\fImmddhhmm\fR[\fIyy\fR][\fB.\fIss\fR] +] +.SH DESCRIPTION +.I Date +without arguments writes the date and time to the standard output in +the form +.ce 1 +Wed Mar 8 14:54:40 EST 1989 +.br +with +.B EST +replaced by the local time zone's abbreviation +(or by the abbreviation for the time zone specified in the +.B TZ +environment variable if set). +The exact output format depends on the locale. +.PP +If a command-line argument starts with a plus sign +.RB (` + '), +the rest of the argument is used as a +.I format +that controls what appears in the output. +In the format, when a percent sign +.RB (` % ') +appears, +it and the character after it are not output, +but rather identify part of the date or time +to be output in a particular way +(or identify a special character to output): +.nf +.sp +.if t .in +.5i +.if n .in +2 +.ta \w'%M\0\0'u +\w'Wed Mar 8 14:54:40 EST 1989\0\0'u + Sample output Explanation +%a Wed Abbreviated weekday name* +%A Wednesday Full weekday name* +%b Mar Abbreviated month name* +%B March Full month name* +%c Wed Mar 08 14:54:40 1989 Date and time* +%C 19 Century +%d 08 Day of month (always two digits) +%D 03/08/89 Month/day/year (eight characters) +%e 8 Day of month (leading zero blanked) +%h Mar Abbreviated month name* +%H 14 24-hour-clock hour (two digits) +%I 02 12-hour-clock hour (two digits) +%j 067 Julian day number (three digits) +%k 2 12-hour-clock hour (leading zero blanked) +%l 14 24-hour-clock hour (leading zero blanked) +%m 03 Month number (two digits) +%M 54 Minute (two digits) +%n \\n newline character +%p PM AM/PM designation +%r 02:54:40 PM Hour:minute:second AM/PM designation +%R 14:54 Hour:minute +%S 40 Second (two digits) +%t \\t tab character +%T 14:54:40 Hour:minute:second +%U 10 Sunday-based week number (two digits) +%w 3 Day number (one digit, Sunday is 0) +%W 10 Monday-based week number (two digits) +%x 03/08/89 Date* +%X 14:54:40 Time* +%y 89 Last two digits of year +%Y 1989 Year in full +%Z EST Time zone abbreviation +%+ Wed Mar 8 14:54:40 EST 1989 Default output format* +.if t .in -.5i +.if n .in -2 +* The exact output depends on the locale. +.sp +.fi +If a character other than one of those shown above appears after +a percent sign in the format, +that following character is output. +All other characters in the format are copied unchanged to the output; +a newline character is always added at the end of the output. +.PP +In Sunday-based week numbering, +the first Sunday of the year begins week 1; +days preceding it are part of ``week 0.'' +In Monday-based week numbering, +the first Monday of the year begins week 1. +.PP +To set the date, use a command line argument with one of the following forms: +.nf +.if t .in +.5i +.if n .in +2 +.ta \w'198903081454\0'u +1454 24-hour-clock hours (first two digits) and minutes +081454 Month day (first two digits), hours, and minutes +03081454 Month (two digits, January is 01), month day, hours, minutes +8903081454 Year, month, month day, hours, minutes +0308145489 Month, month day, hours, minutes, year + (on System V-compatible systems) +030814541989 Month, month day, hours, minutes, four-digit year +198903081454 Four-digit year, month, month day, hours, minutes +.if t .in -.5i +.if n .in -2 +.fi +If the century, year, month, or month day is not given, +the current value is used. +Any of the above forms may be followed by a period and two digits that give +the seconds part of the new time; if no seconds are given, zero is assumed. +.PP +These options are available: +.TP +.BR \-u " or " \-c +Use UTC when setting and showing the date and time. +.TP +.B \-n +Do not notify other networked systems of the time change. +.TP +.BI "\-d " dsttype +Set the kernel-stored Daylight Saving Time type to the given value. +(The kernel-stored DST type is used mostly by ``old'' binaries.) +.TP +.BI "\-t " minutes-west +Set the kernel-stored ``minutes west of UTC'' value to the one given on the +command line. +(The kernel-stored DST type is used mostly by ``old'' binaries.) +.TP +.BI "\-a " adjustment +Change the time forward (or backward) by the number of seconds +(and fractions thereof) specified in the +.I adjustment\^ +argument. +Either the seconds part or the fractions part of the argument (but not both) +may be omitted. +On BSD-based systems, +the adjustment is made by changing the rate at which time advances; +on System-V-based systems, the adjustment is made by changing the time. +.SH FILES +.ta \w'/usr/local/etc/zoneinfo/posixrules\0\0'u +/usr/lib/locale/\f2L\fP/LC_TIME description of time locale \f2L\fP +.br +/usr/local/etc/zoneinfo time zone information directory +.br +/usr/local/etc/zoneinfo/localtime local time zone file +.br +/usr/local/etc/zoneinfo/posixrules used with POSIX-style TZ's +.br +/usr/local/etc/zoneinfo/GMT for UTC leap seconds +.sp +If +.B /usr/local/etc/zoneinfo/GMT +is absent, +UTC leap seconds are loaded from +.BR /usr/local/etc/zoneinfo/posixrules . +.\" @(#)date.1 8.1 diff --git a/unused/date.1.txt b/unused/date.1.txt new file mode 100644 index 00000000000..2910aaac370 --- /dev/null +++ b/unused/date.1.txt @@ -0,0 +1,127 @@ +NAME + + date - show and set date and time + +SYNOPSIS + date [ -u ] [ -c ] [ -n ] [ -d dsttype ] [ -t minutes-west ] + [ -a [+|-]sss.fff ] [ +format ] [ [yyyy]mmddhhmm[yy][.ss] ] + +DESCRIPTION + Date without arguments writes the date and time to the + standard output in the form + Wed Mar 8 14:54:40 EST 1989 + with EST replaced by the local time zone's abbreviation (or + by the abbreviation for the time zone specified in the TZ + environment variable if set). The exact output format + depends on the locale. + + If a command-line argument starts with a plus sign (`+'), + the rest of the argument is used as a format that controls + what appears in the output. In the format, when a percent + sign (`%') appears, it and the character after it are not + output, but rather identify part of the date or time to be + output in a particular way (or identify a special character + to output): + + Sample output Explanation + %a Wed Abbreviated weekday name* + %A Wednesday Full weekday name* + %b Mar Abbreviated month name* + %B March Full month name* + %c Wed Mar 08 14:54:40 1989 Date and time* + %C 19 Century + %d 08 Day of month (always two digits) + %D 03/08/89 Month/day/year (eight characters) + %e 8 Day of month (leading zero blanked) + %h Mar Abbreviated month name* + %H 14 24-hour-clock hour (two digits) + %I 02 12-hour-clock hour (two digits) + %j 067 Julian day number (three digits) + %k 2 12-hour-clock hour (leading zero blanked) + %l 14 24-hour-clock hour (leading zero blanked) + %m 03 Month number (two digits) + %M 54 Minute (two digits) + %n \n newline character + %p PM AM/PM designation + %r 02:54:40 PM Hour:minute:second AM/PM designation + %R 14:54 Hour:minute + %S 40 Second (two digits) + %t \t tab character + %T 14:54:40 Hour:minute:second + %U 10 Sunday-based week number (two digits) + %w 3 Day number (one digit, Sunday is 0) + %W 10 Monday-based week number (two digits) + %x 03/08/89 Date* + %X 14:54:40 Time* + %y 89 Last two digits of year + %Y 1989 Year in full + %Z EST Time zone abbreviation + %+ Wed Mar 8 14:54:40 EST 1989 Default output format* + * The exact output depends on the locale. + + If a character other than one of those shown above appears + after a percent sign in the format, that following character + is output. All other characters in the format are copied + unchanged to the output; a newline character is always added + at the end of the output. + In Sunday-based week numbering, the first Sunday of the year + begins week 1; days preceding it are part of ``week 0.'' In + Monday-based week numbering, the first Monday of the year + begins week 1. + + To set the date, use a command line argument with one of the + following forms: + 1454 24-hour-clock hours (first two digits) and minutes + 081454 Month day (first two digits), hours, and minutes + 03081454 Month (two digits, January is 01), month day, hours, minutes + 8903081454 Year, month, month day, hours, minutes + 0308145489 Month, month day, hours, minutes, year + (on System V-compatible systems) + 030814541989 Month, month day, hours, minutes, four-digit year + 198903081454 Four-digit year, month, month day, hours, minutes + If the century, year, month, or month day is not given, the + current value is used. Any of the above forms may be + followed by a period and two digits that give the seconds + part of the new time; if no seconds are given, zero is + assumed. + + These options are available: + + -u or -c + Use UTC when setting and showing the date and time. + + -n Do not notify other networked systems of the time + change. + + -d dsttype + Set the kernel-stored Daylight Saving Time type to the + given value. (The kernel-stored DST type is used + mostly by ``old'' binaries.) + + -t minutes-west + Set the kernel-stored ``minutes west of UTC'' value to + the one given on the command line. (The kernel-stored + DST type is used mostly by ``old'' binaries.) + + -a adjustment + Change the time forward (or backward) by the number of + seconds (and fractions thereof) specified in the + adjustment argument. Either the seconds part or the + fractions part of the argument (but not both) may be + omitted. On BSD-based systems, the adjustment is made + by changing the rate at which time advances; on System- + V-based systems, the adjustment is made by changing the + time. + +FILES + /usr/lib/locale/L/LC_TIME description of time + locale L + /usr/local/etc/zoneinfo time zone information + directory + /usr/local/etc/zoneinfo/localtime local time zone file + /usr/local/etc/zoneinfo/posixrules used with POSIX-style + TZ's + /usr/local/etc/zoneinfo/GMT for UTC leap seconds + + If /usr/local/etc/zoneinfo/GMT is absent, UTC leap seconds + are loaded from /usr/local/etc/zoneinfo/posixrules. diff --git a/unused/date.c b/unused/date.c new file mode 100644 index 00000000000..6a6d2cdaffc --- /dev/null +++ b/unused/date.c @@ -0,0 +1,945 @@ +#ifndef lint +#ifndef NOID +static char elsieid[] = "@(#)date.c 8.4"; +/* +** Modified from the UCB version with the SCCS ID appearing below. +*/ +#endif /* !defined NOID */ +#endif /* !defined lint */ + +/* + * Copyright (c) 1985, 1987, 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANT[A]BILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1985, 1987, 1988 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)date.c 4.23 (Berkeley) 9/20/88"; +#endif /* not lint */ + +#include "private.h" +#if HAVE_ADJTIME || HAVE_SETTIMEOFDAY +#include "sys/time.h" /* for struct timeval, struct timezone */ +#endif /* HAVE_ADJTIME || HAVE_SETTIMEOFDAY */ +#include "locale.h" +#include "utmp.h" /* for OLD_TIME (or its absence) */ +#if HAVE_UTMPX_H +#include "utmpx.h" +#endif + +#ifndef OTIME_MSG +#define OTIME_MSG "old time" +#endif +#ifndef NTIME_MSG +#define NTIME_MSG "new time" +#endif + +/* +** The two things date knows about time are. . . +*/ + +#ifndef TM_YEAR_BASE +#define TM_YEAR_BASE 1900 +#endif /* !defined TM_YEAR_BASE */ + +#ifndef SECSPERMIN +#define SECSPERMIN 60 +#endif /* !defined SECSPERMIN */ + +extern double atof(); +extern char ** environ; +extern char * getlogin(); +extern time_t mktime(); +extern char * optarg; +extern int optind; +extern char * strchr(); +extern time_t time(); +extern char * tzname[2]; + +static int retval = EXIT_SUCCESS; + +static void checkfinal(const char *, int, time_t, time_t); +static int comptm(const struct tm *, const struct tm *); +static time_t convert(const char *, int, time_t); +static void display(const char *); +static void dogmt(void); +static void errensure(void); +static void iffy(time_t, time_t, const char *, const char *); +int main(int, char**); +static const char * nondigit(const char *); +static void oops(const char *); +static void reset(time_t, int); +static void timeout(FILE *, const char *, const struct tm *); +static void usage(void); +static void wildinput(const char *, const char *, + const char *); + +int +main(argc, argv) +const int argc; +char * argv[]; +{ + register const char * format; + register const char * value; + register const char * cp; + register int ch; + register int dousg; + register int aflag = 0; + register int dflag = 0; + register int nflag = 0; + register int tflag = 0; + register int minuteswest; + register int dsttime; + register double adjust; + time_t now; + time_t t; + + INITIALIZE(dousg); + INITIALIZE(minuteswest); + INITIALIZE(dsttime); + INITIALIZE(adjust); + INITIALIZE(t); +#ifdef LC_ALL + (void) setlocale(LC_ALL, ""); +#endif /* defined(LC_ALL) */ +#if HAVE_GETTEXT +#ifdef TZ_DOMAINDIR + (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); +#endif /* defined(TEXTDOMAINDIR) */ + (void) textdomain(TZ_DOMAIN); +#endif /* HAVE_GETTEXT */ + (void) time(&now); + format = value = NULL; + while ((ch = getopt(argc, argv, "ucnd:t:a:")) != EOF && ch != -1) { + switch (ch) { + default: + usage(); + case 'u': /* do it in UTC */ + case 'c': + dogmt(); + break; + case 'n': /* don't set network */ + nflag = 1; + break; + case 'd': /* daylight saving time */ + if (dflag) { + (void) fprintf(stderr, + _("date: error: multiple -d's used")); + usage(); + } + dflag = 1; + cp = optarg; + dsttime = atoi(cp); + if (*cp == '\0' || *nondigit(cp) != '\0') + wildinput(_("-t value"), optarg, + _("must be a non-negative number")); + break; + case 't': /* minutes west of UTC */ + if (tflag) { + (void) fprintf(stderr, + _("date: error: multiple -t's used")); + usage(); + } + tflag = 1; + cp = optarg; + minuteswest = atoi(cp); + if (*cp == '+' || *cp == '-') + ++cp; + if (*cp == '\0' || *nondigit(cp) != '\0') + wildinput(_("-d value"), optarg, + _("must be a number")); + break; + case 'a': /* adjustment */ + if (aflag) { + (void) fprintf(stderr, + _("date: error: multiple -a's used")); + usage(); + } + aflag = 1; + cp = optarg; + adjust = atof(cp); + if (*cp == '+' || *cp == '-') + ++cp; + if (*cp == '\0' || strcmp(cp, ".") == 0) + wildinput(_("-a value"), optarg, + _("must be a number")); + cp = nondigit(cp); + if (*cp == '.') + ++cp; + if (*nondigit(cp) != '\0') + wildinput(_("-a value"), optarg, + _("must be a number")); + break; + } + } + while (optind < argc) { + cp = argv[optind++]; + if (*cp == '+') + if (format == NULL) + format = cp + 1; + else { + (void) fprintf(stderr, +_("date: error: multiple formats in command line\n")); + usage(); + } + else if (value == NULL) + value = cp; + else { + (void) fprintf(stderr, +_("date: error: multiple values in command line\n")); + usage(); + } + } + if (value != NULL) { + /* + ** This order ensures that "reasonable" twelve-digit inputs + ** (such as 120203042006) won't be misinterpreted + ** even if time_t's range all the way back to the thirteenth + ** century. Do not change the order. + */ + t = convert(value, (dousg = TRUE), now); + if (t == -1) + t = convert(value, (dousg = FALSE), now); + if (t == -1) { + /* + ** Out of range values, + ** or time that falls in a DST transition hole? + */ + if ((cp = strchr(value, '.')) != NULL) { + /* + ** Ensure that the failure of + ** TZ=America/New_York date 8712312359.60 + ** doesn't get misdiagnosed. (It was + ** TZ=America/New_York date 8712311859.60 + ** when the leap second was inserted.) + ** The normal check won't work since + ** the given time is valid in UTC. + */ + if (atoi(cp + 1) >= SECSPERMIN) + wildinput(_("time"), value, + _("out of range seconds given")); + } + dogmt(); + t = convert(value, FALSE, now); + if (t == -1) + t = convert(value, TRUE, now); + wildinput(_("time"), value, + (t == -1) ? + _("out of range value given") : + _("time skipped when clock springs forward")); + } + } + /* + ** Entire command line has now been checked. + */ + if (aflag) { +#if HAVE_ADJTIME + struct timeval tv; + + tv.tv_sec = (int) adjust; + tv.tv_usec = (int) ((adjust - tv.tv_sec) * 1000000L); + if (adjtime(&tv, (struct timeval *) NULL) != 0) + oops("adjtime"); +#endif /* HAVE_ADJTIME */ +#if !HAVE_ADJTIME + reset((time_t) (now + adjust), nflag); +#endif /* !HAVE_ADJTIME */ + /* + ** Sun silently ignores everything else; we follow suit. + */ + exit(retval); + } + if (dflag || tflag) { +#if HAVE_SETTIMEOFDAY == 2 + struct timezone tz; + + if (!dflag || !tflag) + if (gettimeofday((struct timeval *) NULL, &tz) != 0) + oops("gettimeofday"); + if (dflag) + tz.tz_dsttime = dsttime; + if (tflag) + tz.tz_minuteswest = minuteswest; + if (settimeofday((struct timeval *) NULL, &tz) != 0) + oops("settimeofday"); +#endif /* HAVE_SETTIMEOFDAY == 2 */ +#if HAVE_SETTIMEOFDAY != 2 + (void) fprintf(stderr, +_("date: warning: kernel doesn't keep -d/-t information, option ignored\n")); +#endif /* HAVE_SETTIMEOFDAY != 2 */ + } + + if (value == NULL) + display(format); + + reset(t, nflag); + + checkfinal(value, dousg, t, now); + +#ifdef EBUG + { + struct tm tm; + + tm = *localtime(&t); + timeout(stdout, "%c\n", &tm); + exit(retval); + } +#endif /* defined EBUG */ + + display(format); + + /* gcc -Wall pacifier */ + for ( ; ; ) + continue; +} + +static void +dogmt(void) +{ + static char ** fakeenv; + + if (fakeenv == NULL) { + register int from; + register int to; + register int n; + static char tzegmt0[] = "TZ=GMT0"; + + for (n = 0; environ[n] != NULL; ++n) + continue; + fakeenv = (char **) malloc((size_t) (n + 2) * sizeof *fakeenv); + if (fakeenv == NULL) { + (void) perror(_("Memory exhausted")); + errensure(); + exit(retval); + } + to = 0; + fakeenv[to++] = tzegmt0; + for (from = 1; environ[from] != NULL; ++from) + if (strncmp(environ[from], "TZ=", 3) != 0) + fakeenv[to++] = environ[from]; + fakeenv[to] = NULL; + environ = fakeenv; + } +} + +#ifdef OLD_TIME + +/* +** We assume we're on a System-V-based system, +** should use stime, +** should write System-V-format utmp entries, +** and don't have network notification to worry about. +*/ + +#include "fcntl.h" /* for O_WRONLY, O_APPEND */ + +/*ARGSUSED*/ +static void +reset(const time_t newt, const int nflag) +{ + register int fid; + time_t oldt; + static struct { + struct utmp before; + struct utmp after; + } s; +#if HAVE_UTMPX_H + static struct { + struct utmpx before; + struct utmpx after; + } sx; +#endif + + /* + ** Wouldn't it be great if stime returned the old time? + */ + (void) time(&oldt); + if (stime(&newt) != 0) + oops("stime"); + s.before.ut_type = OLD_TIME; + s.before.ut_time = oldt; + (void) strcpy(s.before.ut_line, OTIME_MSG); + s.after.ut_type = NEW_TIME; + s.after.ut_time = newt; + (void) strcpy(s.after.ut_line, NTIME_MSG); + fid = open(WTMP_FILE, O_WRONLY | O_APPEND); + if (fid < 0) + oops(_("log file open")); + if (write(fid, (char *) &s, sizeof s) != sizeof s) + oops(_("log file write")); + if (close(fid) != 0) + oops(_("log file close")); +#if !HAVE_UTMPX_H + pututline(&s.before); + pututline(&s.after); +#endif /* !HAVE_UTMPX_H */ +#if HAVE_UTMPX_H + sx.before.ut_type = OLD_TIME; + sx.before.ut_tv.tv_sec = oldt; + (void) strcpy(sx.before.ut_line, OTIME_MSG); + sx.after.ut_type = NEW_TIME; + sx.after.ut_tv.tv_sec = newt; + (void) strcpy(sx.after.ut_line, NTIME_MSG); +#if !SUPPRESS_WTMPX_FILE_UPDATE + /* In Solaris 2.5 (and presumably other systems), + `date' does not update /var/adm/wtmpx. + This must be a bug. If you'd like to reproduce the bug, + define SUPPRESS_WTMPX_FILE_UPDATE to be nonzero. */ + fid = open(WTMPX_FILE, O_WRONLY | O_APPEND); + if (fid < 0) + oops(_("log file open")); + if (write(fid, (char *) &sx, sizeof sx) != sizeof sx) + oops(_("log file write")); + if (close(fid) != 0) + oops(_("log file close")); +#endif /* !SUPPRESS_WTMPX_FILE_UPDATE */ + pututxline(&sx.before); + pututxline(&sx.after); +#endif /* HAVE_UTMPX_H */ +} + +#endif /* defined OLD_TIME */ +#ifndef OLD_TIME + +/* +** We assume we're on a BSD-based system, +** should use settimeofday, +** should write BSD-format utmp entries (using logwtmp), +** and may get to worry about network notification. +** The "time name" changes between 4.3-tahoe and 4.4; +** we include sys/param.h to determine which we should use. +*/ + +#ifndef TIME_NAME +#include "sys/param.h" +#ifdef BSD4_4 +#define TIME_NAME "date" +#endif /* defined BSD4_4 */ +#ifndef BSD4_4 +#define TIME_NAME "" +#endif /* !defined BSD4_4 */ +#endif /* !defined TIME_NAME */ + +#include "syslog.h" +#include "sys/socket.h" +#include "netinet/in.h" +#include "netdb.h" +#define TSPTYPES +#include "protocols/timed.h" + +extern int logwtmp(); + +#if HAVE_SETTIMEOFDAY == 1 +#define settimeofday(t, tz) (settimeofday)(t) +#endif /* HAVE_SETTIMEOFDAY == 1 */ + +#ifndef TSP_SETDATE +/*ARGSUSED*/ +#endif /* !defined TSP_SETDATE */ +static void +reset(newt, nflag) +const time_t newt; +const int nflag; +{ + register const char * username; + static struct timeval tv; /* static so tv_usec is 0 */ + +#ifdef EBUG + return; +#endif /* defined EBUG */ + username = getlogin(); + if (username == NULL || *username == '\0') /* single-user or no tty */ + username = "root"; + tv.tv_sec = newt; +#ifdef TSP_SETDATE + if (nflag || !netsettime(tv)) +#endif /* defined TSP_SETDATE */ + { + /* + ** "old" entry is always written, for compatibility. + */ + logwtmp("|", TIME_NAME, ""); + if (settimeofday(&tv, (struct timezone *) NULL) == 0) { + logwtmp("{", TIME_NAME, ""); /* } */ + syslog(LOG_AUTH | LOG_NOTICE, _("date set by %s"), + username); + } else oops("settimeofday"); + } +} + +#endif /* !defined OLD_TIME */ + +static void +wildinput(item, value, reason) +const char * const item; +const char * const value; +const char * const reason; +{ + (void) fprintf(stderr, + _("date: error: bad command line %s \"%s\", %s\n"), + item, value, reason); + usage(); +} + +static void +errensure(void) +{ + if (retval == EXIT_SUCCESS) + retval = EXIT_FAILURE; +} + +static const char * +nondigit(cp) +register const char * cp; +{ + while (is_digit(*cp)) + ++cp; + return cp; +} + +static void +usage(void) +{ + (void) fprintf(stderr, _("date: usage is date [-u] [-c] [-n] [-d dst] \ +[-t min-west] [-a sss.fff] [[yyyy]mmddhhmm[yyyy][.ss]] [+format]\n")); + errensure(); + exit(retval); +} + +static void +oops(string) +const char * const string; +{ + int e = errno; + + (void) fprintf(stderr, _("date: error: ")); + errno = e; + (void) perror(string); + errensure(); + display((char *) NULL); +} + +static void +display(format) +const char * const format; +{ + struct tm tm; + time_t now; + + (void) time(&now); + tm = *localtime(&now); + timeout(stdout, format ? format : "%+", &tm); + (void) putchar('\n'); + (void) fflush(stdout); + (void) fflush(stderr); + if (ferror(stdout) || ferror(stderr)) { + (void) fprintf(stderr, + _("date: error: couldn't write results\n")); + errensure(); + } + exit(retval); +} + +extern size_t strftime(); + +#define INCR 1024 + +static void +timeout(fp, format, tmp) +FILE * const fp; +const char * const format; +const struct tm * const tmp; +{ + char * cp; + size_t result; + size_t size; + + if (*format == '\0') + return; + size = INCR; + cp = malloc((size_t) size); + for ( ; ; ) { + if (cp == NULL) { + (void) fprintf(stderr, + _("date: error: can't get memory\n")); + errensure(); + exit(retval); + } + cp[0] = '\1'; + result = strftime(cp, size, format, tmp); + if (result != 0 || cp[0] == '\0') + break; + size += INCR; + cp = realloc(cp, (size_t) size); + } + (void) fwrite(cp, 1, result, fp); + free(cp); +} + +static int +comptm(atmp, btmp) +register const struct tm * const atmp; +register const struct tm * const btmp; +{ + register int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +/* +** convert -- +** convert user's input into a time_t. +*/ + +#define ATOI2(ar) (ar[0] - '0') * 10 + (ar[1] - '0'); ar += 2; + +static time_t +convert(register const char * const value, const int dousg, const time_t t) +{ + register const char * cp; + register const char * dotp; + register int cent, year_in_cent, month, hour, day, mins, secs; + struct tm tm, outtm; + time_t outt; + + tm = *localtime(&t); +#define DIVISOR 100 + year_in_cent = tm.tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR; + cent = tm.tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR + + year_in_cent / DIVISOR; + year_in_cent %= DIVISOR; + if (year_in_cent < 0) { + year_in_cent += DIVISOR; + --cent; + } + month = tm.tm_mon + 1; + day = tm.tm_mday; + hour = tm.tm_hour; + mins = tm.tm_min; + secs = 0; + + dotp = strchr(value, '.'); + for (cp = value; *cp != '\0'; ++cp) + if (!is_digit(*cp) && cp != dotp) + wildinput(_("time"), value, _("contains a nondigit")); + + if (dotp == NULL) + dotp = strchr(value, '\0'); + else { + cp = dotp + 1; + if (strlen(cp) != 2) + wildinput(_("time"), value, + _("seconds part is not two digits")); + secs = ATOI2(cp); + } + + cp = value; + switch (dotp - cp) { + default: + wildinput(_("time"), value, + _("main part is wrong length")); + case 12: + if (!dousg) { + cent = ATOI2(cp); + year_in_cent = ATOI2(cp); + } + month = ATOI2(cp); + day = ATOI2(cp); + hour = ATOI2(cp); + mins = ATOI2(cp); + if (dousg) { + cent = ATOI2(cp); + year_in_cent = ATOI2(cp); + } + break; + case 8: /* mmddhhmm */ + month = ATOI2(cp); + /* fall through to. . . */ + case 6: /* ddhhmm */ + day = ATOI2(cp); + /* fall through to. . . */ + case 4: /* hhmm */ + hour = ATOI2(cp); + mins = ATOI2(cp); + break; + case 10: + if (!dousg) { + year_in_cent = ATOI2(cp); + } + month = ATOI2(cp); + day = ATOI2(cp); + hour = ATOI2(cp); + mins = ATOI2(cp); + if (dousg) { + year_in_cent = ATOI2(cp); + } + break; + } + + tm.tm_year = cent * 100 + year_in_cent - TM_YEAR_BASE; + tm.tm_mon = month - 1; + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = mins; + tm.tm_sec = secs; + tm.tm_isdst = -1; + outtm = tm; + outt = mktime(&outtm); + return (comptm(&tm, &outtm) == 0) ? outt : -1; +} + +/* +** Code from here on out is either based on code provided by UCB +** or is only called just before the program exits. +*/ + +/* +** Check for iffy input. +*/ + +static void +checkfinal(const char * const value, + const int didusg, + const time_t t, + const time_t oldnow) +{ + time_t othert; + struct tm tm; + struct tm othertm; + register int pass; + register long offset; + + /* + ** See if there's both a USG and a BSD interpretation. + */ + othert = convert(value, !didusg, oldnow); + if (othert != -1 && othert != t) + iffy(t, othert, value, _("year could be at start or end")); + /* + ** See if there's both a DST and a STD version. + */ + tm = *localtime(&t); + othertm = tm; + othertm.tm_isdst = !tm.tm_isdst; + othert = mktime(&othertm); + if (othert != -1 && othertm.tm_isdst != tm.tm_isdst && + comptm(&tm, &othertm) == 0) + iffy(t, othert, value, + _("both standard and summer time versions exist")); +/* +** Final check. +** +** If a jurisdiction shifts time *without* shifting whether time is +** summer or standard (as Hawaii, the United Kingdom, and Saudi Arabia +** have done), routine checks for iffy times may not work. +** So we perform this final check, deferring it until after the time has +** been set--it may take a while, and we don't want to introduce an unnecessary +** lag between the time the user enters their command and the time that +** stime/settimeofday is called. +** +** We just check nearby times to see if any have the same representation +** as the time that convert returned. We work our way out from the center +** for quick response in solar time situations. We only handle common cases-- +** offsets of at most a minute, and offsets of exact numbers of minutes +** and at most an hour. +*/ + for (offset = 1; offset <= 60; ++offset) + for (pass = 1; pass <= 4; ++pass) { + if (pass == 1) + othert = t + offset; + else if (pass == 2) + othert = t - offset; + else if (pass == 3) + othert = t + 60 * offset; + else othert = t - 60 * offset; + othertm = *localtime(&othert); + if (comptm(&tm, &othertm) == 0) + iffy(t, othert, value, + _("multiple matching times exist")); + } +} + +static void +iffy(const time_t thist, const time_t thatt, + const char * const value, const char * const reason) +{ + struct tm tm; + + (void) fprintf(stderr, _("date: warning: ambiguous time \"%s\", %s.\n"), + value, reason); + tm = *gmtime(&thist); + /* + ** Avoid running afoul of SCCS! + */ + timeout(stderr, _("Time was set as if you used\n\tdate -u %m%d%H\ +%M\ +%Y.%S\n"), &tm); + tm = *localtime(&thist); + timeout(stderr, _("to get %c"), &tm); + (void) fprintf(stderr, _(" (%s). Use\n"), + tm.tm_isdst ? _("summer time") : _("standard time")); + tm = *gmtime(&thatt); + timeout(stderr, _("\tdate -u %m%d%H\ +%M\ +%Y.%S\n"), &tm); + tm = *localtime(&thatt); + timeout(stderr, _("to get %c"), &tm); + (void) fprintf(stderr, _(" (%s).\n"), + tm.tm_isdst ? _("summer time") : _("standard time")); + errensure(); + exit(retval); +} + +#ifdef TSP_SETDATE +#define WAITACK 2 /* seconds */ +#define WAITDATEACK 5 /* seconds */ + +/* + * Set the date in the machines controlled by timedaemons + * by communicating the new date to the local timedaemon. + * If the timedaemon is in the master state, it performs the + * correction on all slaves. If it is in the slave state, it + * notifies the master that a correction is needed. + * Returns 1 on success, 0 on failure. + */ +netsettime(ntv) + struct timeval ntv; +{ + int s, length, port, timed_ack, found, err; + long waittime; + fd_set ready; + char hostname[MAXHOSTNAMELEN]; + struct timeval tout; + struct servent *sp; + struct tsp msg; + struct sockaddr_in sin, dest, from; + + sp = getservbyname("timed", "udp"); + if (sp == 0) { + fputs(_("udp/timed: unknown service\n"), stderr); + retval = 2; + return (0); + } + dest.sin_port = sp->s_port; + dest.sin_family = AF_INET; + dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY); + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + if (errno != EPROTONOSUPPORT) + perror("date: socket"); + goto bad; + } + bzero((char *)&sin, sizeof (sin)); + sin.sin_family = AF_INET; + for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { + sin.sin_port = htons((u_short)port); + if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) + break; + if (errno != EADDRINUSE) { + if (errno != EADDRNOTAVAIL) + perror("date: bind"); + goto bad; + } + } + if (port == IPPORT_RESERVED / 2) { + fputs(_("date: All ports in use\n"), stderr); + goto bad; + } + msg.tsp_type = TSP_SETDATE; + msg.tsp_vers = TSPVERSION; + if (gethostname(hostname, sizeof (hostname))) { + perror("gethostname"); + goto bad; + } + (void) strncpy(msg.tsp_name, hostname, sizeof (hostname)); + msg.tsp_seq = htons((u_short)0); + msg.tsp_time.tv_sec = htonl((u_long)ntv.tv_sec); + msg.tsp_time.tv_usec = htonl((u_long)ntv.tv_usec); + length = sizeof (struct sockaddr_in); + if (connect(s, &dest, length) < 0) { + perror("date: connect"); + goto bad; + } + if (send(s, (char *)&msg, sizeof (struct tsp), 0) < 0) { + if (errno != ECONNREFUSED) + perror("date: send"); + goto bad; + } + timed_ack = -1; + waittime = WAITACK; +loop: + tout.tv_sec = waittime; + tout.tv_usec = 0; + FD_ZERO(&ready); + FD_SET(s, &ready); + found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout); + length = sizeof err; + if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&err, &length) == 0 + && err) { + errno = err; + if (errno != ECONNREFUSED) + perror(_("date: send (delayed error)")); + goto bad; + } + if (found > 0 && FD_ISSET(s, &ready)) { + length = sizeof (struct sockaddr_in); + if (recvfrom(s, (char *)&msg, sizeof (struct tsp), 0, &from, + &length) < 0) { + if (errno != ECONNREFUSED) + perror("date: recvfrom"); + goto bad; + } + msg.tsp_seq = ntohs(msg.tsp_seq); + msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec); + msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec); + switch (msg.tsp_type) { + + case TSP_ACK: + timed_ack = TSP_ACK; + waittime = WAITDATEACK; + goto loop; + + case TSP_DATEACK: + (void)close(s); + return (1); + + default: + fprintf(stderr, + _("date: Wrong ack received from timed: %s\n"), + tsptype[msg.tsp_type]); + timed_ack = -1; + break; + } + } + if (timed_ack == -1) + fputs(_("date: Can't reach time daemon, time set locally.\n"), + stderr); +bad: + (void)close(s); + retval = 2; + return (0); +} +#endif /* defined TSP_SETDATE */ diff --git a/unused/itca.jpg b/unused/itca.jpg new file mode 100644 index 0000000000000000000000000000000000000000..89a7119c0ccccf06d6686d0aaeea798137ade546 GIT binary patch literal 55948 zcmbTdWmH>T6fGLuJy0BqCTMZ@;+jw_NU;LJDOy|#v}u6il;Q-J0>!Nq2$U9zyA*dV zTA=jiyZ4Rz#(2Npy*cCjIwxoBwfEU;%{Avd|K|R!0w{Gfv^4-&SXcl@%mMhf2v7qM z;^PzG;}H@N5D*a&5|aYSNJ&UY8K`L}fGmt`tSpSo%%rV9)d+gL_|tLN>4^cFZ!7IvFQKt?_UpqiVz2i&4Gi(0l=oh!lA3sapS)7CL^)C1(FJnuwV05j_JVHxDle%qK1(DJ3lAF_*zQ6;5i zA=u>Uu%1pp}y7H08qr~pcU>q6Zq zeTK_2^7QTA5xPEXgxq+(Ym*(Jx)5j`=?k6c8lXoF&SW4$%ds<35G8gb8laM@rXC#_ zs8UM>A#$WHX!4#YsRq~x`HrJi+$97j+%AF~KH*(S6+gt$MtlH!Vtd0iXHw6K&&mz@ z=#UfsC6(K)(J|kO5FwFi`LS{c5u*)n>O_4Z5J#dZj#dFRcq(UN3%*S1Z3~CLW>nUy zp*8L1;-^4!WBpYJv0qm~UpL!Nfr^2|E;wEE-%5%q*clSxK_%j*R?YNrACq7KAoSD1 zfJaytMNzsi?gBCng#Tk&>Ui7MtRf@?^207x2n-s5x~Pti2y#CM5oJp;LctIg26^Tug!&zUa{h(%{Xyi0yhs_18l90G)RN4BcHX_F?~~zE@t*GDeiK% zW&Pq81}Y5Sy@lB11Ux0h&SZv;kNA{xRU7%L(-#8|d-TS25jv)}Kmu0!rjIw#RM0t0m02yOc+4|)bIl5RoTa=91O#ik>9W7o15^t1X z01Pui3`TIDRR&ByX~oP^>S^U?Wnd$8y8Mj}2o1C-pcp_x)JbuGStUg!Xb~iuN1;+j z&lFlRCnQcyCQYM_(9zAtVatZua^#3u_6Bkz;9z)}%z=UDLNpyhrs!P(4bT|~v1rcd zqs#b^Z8fdoA|Ut}_$3#(pr>k&5K(uUj$=93&Gz(Jh=fM5O33~GDN6ZK~Um(->pql$;23MEeyWOyUd;JI{GD&T zE`9euKxV7g;z^6Y2fV>zX|K73PA|n$+;yxykvRD)t%5&;Z<3C5QQO;4A3Lww{cMww znk9-d3yF)AZ^dr?75I&tAaI{)a&Jx@mCZHywZ&Q$0F8P zry{NL8-Dx)6fjy7QWd}p;|QDHaXw)4$@sIWJ+;qxZ=ca&f59#-ZW>-yvzN^bmaGUP zLm4cZYg z^qzyO)}KnG(}n8^WbQ{osA&(oxU;~;#@~eZ)0akbqh3F2o~bywLoB?5-f6aX)0r+L zbk0f(IK1tn#Hy!Sl&*1Gc~1iqAjEhl~H&SP~dn-~$OgZj0rOewM+@ zlsq28Phq49%cu~ai6$L4-&_Ae(eXV7R!2e8_>$j>FWuH#1@{(_EU#HK^wOhv+I=%i zW1@lUJKD(KA*SbAf^|Z{{BT4^XGjrzdNbfZB1Njqwx>OGzkj*>w_as}9$zJHrkZ^p9R=UbW||bTcWafIi%$0ctNAVC--)(IkvPlo#X8*=j7<9OP;2{y7+O- z45q5J=i0VRAC`Q`;u}b<65%cAk*PTGPmnT5=IHEhiPmJ$+I)}iRj}{If5{MlsCg0L zTw(d=O3G+SJ*8vayNAs{ZaPTfFUJlfOpy%w({hSSpsKe8SZ5 zo@+sRR^#o})WhUJ_()R=*1=?1m*PJ_zpQDlO!W5I)3v~?Vq?zA+jJu>){8%57TGzN zHw}MsAdhuQ;P^z~5_IfwIHu75zDgR&eA#pG_1lrb#JzQqo2I+!&r~#KsSZRHkOGduy)XC$f7;mHBlA?yn3i{7Q_wkl|H2Bja-mK6n58ml#;Y33h zOxdzvuJ;sfQsddNYCfl_(KdKZ4|7<<{^BdPWgfg9gTO;rZu0zypR4Ur= zjMMC4__Xo8rr*rt@E_D9tX3=4N0U4Ev=Kkse|$n%AZIfn#UM|6&xT<^P;bVezf_jQMaY7|~mbKtYp7FvU8WH-=wymeOX2ZKRgh-UbX&p@@{|_)5>dBgWXZ+mk?E5i}p@1^- zg}WJZo_Y8`Kw0@d{}`Ys<&D*9;q<*7%cOQh*|!Xl#w6Zb@d$sT+&1bIl|fu`qOT(^ zp%T&NifnuO{4dHhT8YV3iRfD)7o>Q8!8sF)@Ic?M6#3%b9jK=pApkA51mEZ69IY)k zA*I^V%UtzcJ%}d&qeCmuMUOOUI(o<2>M7=hs#WA&-p`~H(Jr=vN7%ma>=XRC9&pQ= zUi2VUpQP0~wes`QW3`%(epDD|`*5%Vtw_NL|NJ+JYN@b2F9;|~k-mo8?d_A4 zwu;=&6eSV+cWK#`&ZUXQ7xs#uz zBb%kz^j7}?__mGL>D~!tc@;k*jj9pB2$a^d~ z1yU{a=;*$d{~fS{{Z?nq>E*A}d{-$^T@T6V1csIB4o@O~oc9E&Lo9<(8C3k>LeXP{ zAo-Je)eaNrW>jh{=e3gG#i;9X)2q$q@lR#3%|B>66XO}a5^I(21{#JG!e^n)dpymF zn(hu<Y*cDp^bOHZs{V3cRPIx z7Y}a9TH-7^%TG$pr_)tLDzP^sBbEm@j9gjCr~E12+kG8|l|g`4cw?FQTAI@mId$3t7`tdJZeD3gR1l zb{3wzt{U3WfvtALc92QnqI6vUt!f1{DcqD#VZGNLHf7qdtT8S=0ro)j;YJc}e~huj z`$@27`p&DyrTw@o1Y7Cq=whVlJ=-$&GpxZ1*G%;Ipj1Bv{;p&O)T*zvYNeCvh~9+B zID_3=`NTRurje*qWX+O=&cZHjf#)li&a)>!U#jrtq*@r=n3=bn%@nWucQzy+d!QSQ zhM3m5a9In^Q$&OPQR^q(5{JSgTbN@zK`>^%b~BO_9B$wIgnblj{d1xAM>*gx1cBg~!oD;_$_Os%2#-y8~gHIkL++X7OpZuDMWiS^?_!4i!)Op(Sntk#l zS8>eoRkrjZKix)dttsj6&fw zC)+nvEVZ}UwCEq;`Iknww>9#exaVz}0k!}v3%Q*{ezO51!_||h7>$$&#mj=kujXvs z$KJ}Lwo(pzmJ9hYC-yTJ)*-5H=Kdt~>NUecXot2K`UNfAXxT)ibnOi#B3B!5_xOU` zqPhFU9je2HE8*i$e|c;bdX|vDvhR=hT+h^34P%TKOQ~waPq^4D%soceN3u7a?<7B- zrs|%e2a8(o1mN~hfw>qoMa290e^(bGcIukM%UGvVJ1 zWN{9lH>rKW@rWbAi-UPV55KJsj=A=NoZlbas5}n%`>GIqL6TiZ-zl?JWnO!%S2RPo zCffEjIg(iRnwKrtCmg%I>mMLCVMAA6^^efjNaOdRYZIOPv=AZXd;Z$?3C|OGH8+Jm zSa+%ilY8?E?#{^`-?>#stVOQv&(-q0zIJDHcm3W!+*op#ixwr?ACslC$B*h=6%7m7 z-5b4egN?qv7k%_{#g#R5FX_Ju$38(L*zX+S_N-#a})ga^=-9`1?`1`D9!H#?8`A(iw)oNt1Ahqqp2NP7 zHa0b!nj{=nJAIidev}zV@#EXEsAyOe&S@1)DcbKyxW}RQC5=L{>Y2{m!t+;L`3|Fd zCVs*cL79CEj*Jq`H4X}|aU5wzJqH|<8s5|MQ%%Z;@p;&a-urvGt&Ya$f!iCNX*bDe zKQ{9k6`Ja~7j@O9DGiUINPodb)kmjiY>jw zWG|M_u@XD6R?5!4#PXcQy=BeF&YUYcH`UgPkH{iW-+v-z;#RYiLkr>_R87fw2W5{(aEAe{b+q&i}!RdETcC|TcE3^(ImT{{iL~@|Su&{ zXlN*T6OISoMrF|3EgLX(iJ># z;2X2z+p;HN9Z^kcIew!oRaEb8=vLpSXs=a#JRU$E+3t*yrcx>9``!7)GQEoZ*@wfz z{|KF3vy!m(@y8;t#SNwRREWpCm^5g}iQQ+GWk2~QcC9nAC6FR7R-nx8mfLtr-g+(9 zwKq(5e-hf(oU0=n@xqF-Z*lXli&q`p18YfR9!0}cp_$k||JBD2FJxZ5Pzp*>%wnlW z?DM}lrE3e3TiOkjbt-1*N}>y#mGmIYql(1BC4I7Yf}Hiz#~}t4rT2h}vq84fen2CF z?}}+=u5(dEnN8x*NH+vt;&!47YILS~?7eteOFEFCpo)2!U+3j;GjFsokP|*jkB}Q`lIGOR==O4h7Ze#{*Xs z-!l+8^>{pB7qqTEa-%b%d>`y)SFk(rrb)rx0b6%==nd(&e}Kpb{|PwE4`z_+T&6s1 z-xO=7I>;4EKXkp`5UN)2d}V(j{4;8K@oR*AibjPmRnVr{fXY`q!|yV*#t+mr#=2p7 z?59V=RL&1d0!&9wl3wDoMDV>;uZ>~zU3KICLT=@f`G|VROW~~RLtn1={jjYMU|I)R+=00DP3+i)h|XgR(6F+IlV2yi_7ob zG}1eJ);tvH&0%|n_QG6zBktPfY2YW4&(e3z{{g5J+&u4k$6ZC|<@}-hARO zETuJ=%Q*pwtEPViO;YW}LRA;#B`PJA(Wo-szkS+kTl{NXf?Aw($)s%8cw%T7MXDLi zzcTv&(I53ilzxKpNZUot$-mD1j}U)S5_PMSIgkW0Zd7rdnf zu*$31nU)k?md-u?r^;bv(h}c;GW)OdPviF~N?{GIdBJ-JG~dLS8$1A;j?_3Y{{Z{7 zp9~`x_L^t5C6H+9QnbfcZ;?oEu|Lmvhc6f$fY1qFle*Z_bYP=X>Q+VqAd*UV1lXtn zcE`3)gu7I3DocsC6$7)X|89!FK_#V4lxg8WRLG={MdKK{WJC%-QJwh+u&)Y+E8&<< zUtl=Q3Fc?NFR>_ez;F?x$yR)qZ^giP#kAb9KKY3W=u}N076A+*PI|@SrmWoB*q!C%m6SP9&2h$2xkCW&x!~5!nl=`f9 zca>_qF-ypc;IvICVmTW>Ee}}ba-~%w8`C#Sre=)GYs^BDI^3$tvXzL; z$d#C9pN}v|koWiuZ3vnfq@mZ@NL=YwnZqi3!fI(wekb&u!5YKaZ$f_lM$Sg7+$-7U zE8XJxT|o8CoypeOSX?q$S*B`|{l&OuCZ0yZKO^g*1kccZD~w_hy~3zJXPqzqCbI0Y z_krg`DY{&7bdzD~yp{H(x6lW1sOb!bg;u9EZKs4FK&72Ms$|TQ6;Jq><;d5=#Uafp z#U`yJn&Lj1tWC;-*eS?qUqTqnLr{X9c<_uTRj9tSkCdCF&!4PEo4#_WzR!aT2e~me zgBDa^#EG%SHuuk^9(eV7QsM9xeg0`#2!9%9?vatwa_w=&;$FtpZ36m6wDUX?HT2lF zQf8sxv{-)C2%ix)*6*L>axKz0zZ9zK3@_bs=X>s! z-SEyD+9~egprS^5VkJgUMF0R*ax{VPV5de{jo(bo`(ZWu>T2*yQN7h6d%UMCe^p`d zvqu&Is!e!}VdtB)m#`B-1tvV~7|}qZfT6es2-(MW*fTN=^m0GrIv-@xd$3ZO!#?AGF4rBsD9bCNrPGNok4cTp8c27 zpTK7)h_$hBu=(<``I7bG9?bH`n_^t9RK*_iJfJsz*g?^x_`oS|pNIXnMR7>HWrC_9 z?_Zc)v}%D;uQcnW6r6kzy23U7NZ(p(f9AQJ^Y58ey$*(UTjte#SC3C`FXWb0#P2*z zXDo++4LuEHo8&0so{4{e&+@#dgWByg)PmVzDBsY1A{xMk*EXZl>AJ zSC#$vT?)t~528(rUSJwBWG6$h@%Wg)gZHhUOB0U$Es|qZIw4brc&8|1m;RO}yGgO+ zgv~keZ-crMO{C}jf4}BkAveT2(A23C5yqJytQj-f=27GKgI$f3>$i$h z{~UWbZBPEBzi1Xpq*=9f{|hAhvz1iuI~R}p$KYrh(wD!MT9M5< zp<6yVIUAm0)*}*?t+Wy>IzP1PQ?8BL5*HTay)x8dt#U~7YcwQk#6K!s>=G<$cr?tN zw~qceK)?J4pmlUUb-r@6IB&B2Ch(r(YRUNmzw&0MZvzcW%rE%*@~UBe;YS#0af0^7x@E`N}tbSsh`nfe4yT13tolY^* zpLfm-r|SG=Pk*D2~Z?QE&aSGFizlWa#Hb>gG9w7`0M zpsiz0>P?EiV&iOi>}U-=swnp^@-@Vu7?`VAjuD~TO3>WSaNhF17>tZK0&OuOg@$9K zL&qKu`V#SH(igVez{a%pNJfLDi7{8$z6c>kE?X$pjfCX8Lexzf$MD$vAUYzAKI#F2 zZyCWVr3mj@S3{M0I2=@SQV@$Om~cu>!FhLswD7w#HNVc$E2j349|&T7joj)GI)NQ- zU}mO``H0yWQ(y9FauO8BD7Z3cq8q41arLxDUu^L15(FQux-UM}=u0Emyz7z+F(uZ` zZD^-~`~-t)YPF19iVBg2y&0(o>RKe~K>NG`ULd9bmH^YLaav2$2nxTV%E%l46f1B= z8ib5z2fzsndlxZ!7%@!eqd5UYJKJjJyO!z%G+ex`Y#0lZ@?rz25(}O&=EuL73WXFOaNKBQdwppB^?fwUI-p)KPkKPQW?w`T zWVOX}su!5O-4zxRz}qq-NH?P!!H+L)q`WYH&0A&_Y!dPb&t{*EBD1$8dtTb)%?cNr z9A-xm@_qu)9GzH~f<>UKaydzFLK!5#yec-htxpsbc^y61!wN>RFl2I;*)22{j~(-- zobKPI{!;P9YPl0m<9z$Ll098ZfKeyUuD8bqeXUmK=pnCCsFjws+FynNA$$ z@Mh1;_1*%+eo553p?(m&6>c)?6y+YKQmuPsOV~@tNtXB0y2=a)ZHgRv*Ox)}z|}r` zH2I^uy@gVz$Ge9)j&ru)9_$xJXU#KlEH%a5-rDwI+wCnx4Ol2koP)1vo4VxL- z=S+FmJDV*P!#yruW3Xv(PKVg#i%$xT%DQ#PxId`I!C@FGDT)O)k3lDyV>b^(Q3?U?wbUE8DeIscU%NlFWgEl$Fc6~{RkYQPNIUxfI87t z?-5f6ez+=Hl@rgw><^4mOoEVwV)TUCEF#@(u!u&LEnO-C#Ji9>Wv877T92`i#8O6$ zU>ARcM14Eb9+6EcDaBgJ`1lj<`_!C*1rPXjdo^ry264f0!G$L%?pJ0;rhu>?zcB*U z#@5A(r!j(E2&m4u&G!NhnJde)n(dcbe}Bxl_la8CnCQ^@GFAHOkEZnCp4F$M6w`?{ zk?OhU;u&w_%&zsM395Vt?S_u5pDDjFVwqo1JR7=qlU!W$KbXqyE*b{XLod}Paj0oluS6ul`Kh>ThhuyW6!tH=nD zYo-9B?*mPi31JxFnLiSuxu>h&`@OkGjMHm7syr^^rg*Bpc?AJptWD1n8+UVz4Z9 zeSio4(gjUl-uRwKS9wH;FU1`fgBN~^sq<1&BSc1MB>~0EkQHS1$3XfeUk&hF>3hwI z!hs$c&F`{)McFAr=$$%@z%rf8f$&BF*Q}Wou?_S5~2H1)ALXPWaaO3C~bydtcEhv_KTG1DN9rHzq_%&`%m0^DNx>mo#a2vT-@ z;k}|Z(7(d?-87&P>Z|^!dlmS46*{hCqs-${QdGL)0MHlYroR@Sv=tVI8ojFOj%Lw- zgDSVNTrg?7$7)=A1o#Jog+7!V8D?P~jh}uAz@%eCZ*nlpcWT}_r))zN%M?t>U=0ObVM%_#-+EcK^RgO?A@&w$x`RS5)!IsF-(fW= z&D+3m$0|RmKVse}^S8=yWyepZtmo{kOXP-j*6JVmEtH=X8Z*8(K2An|r;4{-!RGoew-#w*P%~LLelAm3EeMOh4kZuP7^a^X{o-kpH`|NlqsHK{nNiOII=iM=Cx;~W z0wvE|`#Nw67#!w^hvLoh4W~l6`3|Jaq;C5ve_81L!GcNJe^uJbn*sPFish^qwmqI_ z&7qK=m`#Rvb51?)mkgM23*?1)K(&MpxA>a7RWsJbkTflxPXe85{A8Q*YMj@}7$<)8 z!#@6a74#wnOsYq>|#UId1R^==wp3#5s--(<8K+wSR&d;==ddSJ&p$q z4nnbS`k@`Co3UJqQr^`O%b*lMw@#m5w)W%IfeL6ELw}Xf?hZO?-9FbzFwfbc<%Mm= zK_A)56MW3U#oF~>Sxe|L>N)a6BFyrP3$lG`6m&d4-)k~=DP1loVkZw(zYhu zSP39=cc#1vI<@g_DbUK{#SNwXGp75w2Y~>VpZv~-1b33NkH7vl=FnK`i<-hv$C9DL zVI(r*j!sCZ{l}NecCHnl5?uLfgeLVe=#N&Ocse=09Da7C7Abi#Dsxo}3YD6!x%|_q zyrVZQd@}X7ePs)U;CA2Ad!ZtYgF{N8H(P-*_qbCiz3YV?r-wLH!KrrNFZVIm={r_& zD35m#dVAZNa&RkI!F;P1Z_pCW zlK5NbA3%`n`Eic($Y?WOaDqe>m+g9Ku-ftTW~!iSE&FVeD^BinWRhe+`KW^2hV*q+YYFQG=mIDC zqsnX(8RLOYYpPyTvrBxM$Lqua<*yA}_32#9*D@6~jULc*bU^k>1#SALIgia~(2*mY zwBu^?Gp!Y9v1jKKY#+{VVACt}i_kTApo*?SvI={U`uPu*RKf)%QLG+&ro1+W6U6RE zIfEtVX1Gh0CDu2WTSJ8Vy-HZQ^-%Gvz~4`uv|g8_Ljvwm*SAwwx8x<|LD4K`7M9YS zjVm4=9@-JPQO2BYI9yHp;9Nec}AhFCVH{h_q-{F<}sJliGC z&qrzAGE;&9zJ94HFS+D>4W#9vhgLhl0<1CnwhayKm*1+8TD>@lJL3BRa5A^UHCh+M z(J>F)S6fp@dk)hFOhI5^LKvv1f|GtooT z2_%G-iNRpkSMLG0=q^o^dVGG2N#r1FXN5wbv zC6E`4yoQx^_Tr;5#s@&O&`&LDkYFWoTwo)vVx z$tdh8ra3g;!U7c~PW>;Isu;nitRqu|h>PRKk5N~%29WW&-f+$upu*v za**tINHu+qv@@+&5~Gm9f^DSZgfl{H5caMx!NjAOPb|?#UF(bAOIeIn6xzU^TEenh z6om(bPIF<0i^pZ86lsx1pognUYS*O99v5$dsoI9v(1%?=`8}tooB?vbIj#QWhm=JG z_n!HksyP61O+FwC@ed_KGkLwb#YSCMn)y5)^S8j&2UfBMy#SMh0}ZxhMOvN9HJDZR?}?Y^<+vrymHA6;xkp^JOJ{qF zdshDd39A19FNzyRW6v%94Dctnl(-|_+)}`H1y$(YM>EMil3NsrUhVzB;ZfCE<0(2y>5vEiyeqqf$z<#F*Sb0Pi2@GJnT zvJmmc(Z6Cxt-c;jUxX+rkIB}lsB$%Oxz(R3_U#yIMt=K>Z@y8-GPKKQDc9G%);+1H26NVGP-_zd^(bkePQbJV9? z@MeCFFJp+FfwR=ri&6sPaOP22Ps`rLPSqa~rqwi?S{rX1Y9e{FlR~etLpfj_eJ#xr zZw!$V92*Z&yl`qe;vbN;sS3~FYcXws4sQ3cY;~wQ8619~cXw`)=w@nisn8TD9w|@<^yS~o<)*0y{M$Fjb0a|Ve5UmC z8K-qnku|wB-|_SWelAZ|>HITkz1kVx?pJ8$9|h(sqg}wX4_^mdjGI@L#4&_)6SOrN z!=YnSsS9$eA?PtFro@(5L>*|3oiu>Z!T7BqhyVZ@7!HK|uqFNPsv}m6c8spN91j*k zj}d0%0x|Ta0e)ahP)xA*Ld98d6Z%2Ak3C>0~>h#1=v>tW2zw4!hN z6~K{{2A1p>^m~S!3)$+vBO-;~6s850JE_^2X7}SCQtt$BP=fOF51p-C5D+yP%7JIy7R?YGQ2cx!srqw<7`H$f#Z+KN53dvo|&OI1De0ZlM3y# z>JCYVckZ~5Eg@{lEoSog)@lkSy?VG7GUH_XPep^t!CfXV!Hp(!zTV7b48deg7SPrn zN-Q)jPaacuRqb#l+D-?aS}^jllJ@GRBQxawe*3Y?Koklo+Q`K~REI|Kh z7`q6W;~-BiqV2yyL9w?W(OtrQOTv(r<(Mext$Mkp!pZU%yv%DWc5hd4Jav&kJblD^ z{3>?xtFKZTqx9%^Q7rjy#yHHYvqT{gv}KW(HLM3_mV(cfTX~kQ}J1zzfozF-Ql*?6gOx0^A-Wx)gIZ9Toas z&3u@pPWbXFap`>Y#`NKRs9XhHv=7CTE19=hUB6gFKg9X|yYyaS`6nQs%kAHzuIA4nq{PiqalBvNuVrr*=V{9Yywo(fEUC8M zy;cs%M=qSYvwPMR5If2`C`(8)t4>J(dAjao`a`Pjsw#8 z@mS-V$CP~~bA$AFs)FrNF;fn-mDTv!@TW+Ja#zbIzWL&i_2MVK4ke%4TX8S4`Jq6*1^CrwlBjYNmcr*KlcT02 zilAKQy14BhM#MO}o;^|wtLX|2veV)j(dY8lgR)&YFoHOn6|;{<_541d`u7ZluT@Po zM&&ezi+K@4lY)Npq0VJ+vF9)q+U;CEy_xLJRE7SJsm@vd0KzAt+Vs~)HluDOdsjLK za0d^7PaKtMC4I=MufaS0`j{V2<`)OIHcP)nF6OoNte4I2%H`>oz<<=}qk>=;OWcF; zD^63G2Df9(hk=(<(a!eat5yvK{(&t1hjk^OIeej{igT1=uF!4d!QqwKV-jk^k>tVP z6VFS1F~b=TcPBhyf0_o-x_W94Q)y=$X224SY1{|f2CnFVIa%f^!c6u%AEUir%5575 zm3uTdA$_oshvuW|?g|_mfos$&cdkEE{RYz{V?I6GT`9INnvxwjgu zgA!x9HSmC6K=#BigP&4Knn9>vvPh-uGB4hkS;S%YpvP6A|CLMlIPz5o{(Z1>&C>qwDbfAx9S(VMJv*(0f6HjQ2T!cM71W*WpPEDfN^A=m! zbeeqrriY+zQg$pmfUuGSX9SD zFwHC{(yTlv;9}o~dD4r~Bz?O%VRVH<+!yUmbOCpz>&9Eip@(bc2MK{E zXfJ9sDV*8$N%^}-#YkhMd+%l%L`%c9nX(b04&Vkt*Hd6f9k5Fw2C-N{G03P93Ncs} z#1w4LUUCd$DS!r@0zNiE>_k`JA~Fp+j$pKvjM7Dr844Q_gT;NhQQW-xvRlr+U0&1oHQ8f#_7^>I2A16l@iyt>=Ba=4y;{Fnez*Dn zAT=O>99WGeo&Qb3!fGMnS}@h4T+z$wy>Q5jyxwjXd_q;Sfb$O^Z+vr&@lQQqT1uPC z=*;fHv6gHDm!gU{J+sF}liP`wa$3g{i>)I~MXV*hDdtz|`-Wrw9Bmnv6cko23xXR< z3Z?Jdg<@(NQ;2rtBJV1d7tfi48*a@EYjzb`ySv^&rq|*}pZ+e+)?Sbo@{Nk4^_&+E zqtGM)W?U@^NHn69At$TJQRP?_6>w2R;ah!@at!a60vj@+nqF4cRgdND6UKw=NCJ2&nv^NzK`j2%W_-)@9$54BFe| zeTe2K806TT+k5V4o*i*yXLR}AgX^xs$MUg^WvFCY+*;1U z9KX<=mr{FMJ;Sc4OM`H`@;V_aNvdw@c(y-N^7B$@ZnbMW#$itYIjJ$Y$BAO~ zCEsB4%~VvoEwCKd6fL-Z3jW@lVyWxxK*RgtvDq6DEZuadnfJ*^04zS{Ua88uWcnc; z_nL@4!7+3b^iyUOk{UB*?0i}lAMu%|F<-x#E{Q$Q`p=&nzX12mLzi z;)Loed0}WaQgvxjrHV`I^aK4T@-Lj8G9-EN3^hrFHp`MNTqS^3O8@XfK_Vu7YvOdKYV*(f71vB{O;~7wXHOf zTJ_!Gc7HButBV8pvx1u|eAZYzu_W7ke9A`cd<1^En!N8BKU!p8!1^kf&?TzDPs~Pn z^GTE4iqpED39 z*e}gYuf1AbEzrP5lk!3$1i$1)KTM&vG~4|)p))X1_05MrL%RxZ59KCnFOPV7ujKf< zbY@6C_%wjIu@VgkSa+gymyZ?niTS0B&gha$mNh*>B1mbpl!*sRgBTt#|3q{DdgJ$z z#eht9{g$h<)n99Ev!1tLqtrWiV%#6c05Lors)pM2VB9www``0|Hyx5@vBW808Cq}T zOy+s};_dW?H-m+N3PB-$dQTWzEVrQeF?)fJI?(?=@t{U75~2=_G;k?CEBcJ#FmOu6 zv?C$fn!%Yo7%Y7c=le59KJvH->0@vd8J&R;%g)-x$`;cEb{d<7DeD-(ebjZ|0Z`%r z1ZV{-(#1~BOI689AIdyBM zRz?cXh}l{P-jy5qv0&{gRACat>h2j+KpzqFdkvMplN(9vG6Mv@7@A0Mec;zHDcg7J zuOEGW$_yR52{#Xp=PMm=2IS|(+8O`sP+^-Iw8eg z&YRgQT8d1;!dc3$30qa5Fq%9%;b_GkF6%`DA@^rdq-Y zCWRZ5ORcP38!QQg)Lf}E?0x#EUn&m*E~@HoJO>o0ceFm#)*cC|5#cTO>Ge}ZONnqj z`&}o^pU-p?{j0yhykwYq-fBhP%S}8u~oy zKvrtd;n+F3!q%dJ4(4YrWMI$p9n{%7?j$O-c4=lbo8OA#$7!E2=W*G3+fnE9(@^HJ zeDfxv$O@jacTHA43LO379m zx;*f^zwS25aih z;9N@SNQ9Sln!K&h{3h|gtGvJf@LvmcBVf#@y<}4veIS$O22n5$K{Ul| zjebp#`PU-r1djQWCZ-r_`OHl2`C>D&7T;9NM^;PQ&0p%OYXx>JJn|Sk*PpferFSk- ztes>1#5WAznJG(dmdkmFlYd^jmmOXs)b_%ecDi!t%Ei5N*waYO(}_WGZcyPsa@2UL zF)8j*c6yBYpg*QuTK#>`r$ZND*#6o!hx}D-i{5GJ2h`rg-c>?y^Uul-#w*jgM+K^u ze2Q6>)SZryMC= zFPn?xN3AAGJ$MZo+duyUyj9GPaC8^rx%}Xm{e(7Zhp;3yuP|10M|aZwf!S>#jc(>@ zwmrP?l|o6sPi)Yp_M$DW?+}*HSPbH%^fWI?G0Ck&n{@l$ldG5wyphx9$L$%)jKAiSn6MJ)Kcc zl=IC_pA^X_RqtjAT+Y?DQ+ZQ9Ll#?ajyCT4=+IZi{ScrXkM83~e^Dx{b}i>%JNZv^ z4L~2OUGDSTZ4SpDKmUl{j&w2&*yl=o5fpekFvxJ%%^q=!>rq!{McXfUqMYsCzF6rf z6G)um(jKs@#c;i+R^I0JjqJl`ZZ1vA7^0%x2Jr*mz0zz;z%CojMaIrwtBbuc+KyH& zNr|$~!q8aCC&^OoI$RHBHun48B{jey-J{J+Yy z8!g%XaaiJ3M*KBINk5K2p59zC)SrKp%Fu^ZWoOZ!ahAQ*f6n2b^18c5`MiPlfk{ysfX?Ypeaz8q-a|qp2Q1j?_kP z_k;oOQKL(Q-h#nAZURS1$#fAWt7Lj?1SiM7a4QpPz{}Br1(H8Z&(wz$4EV7Epxl-; zFHt?tJZb{0gSzQAV4<2HIkJF~1o{D#NLYjcoB1EC!-=8u9hEd3b+KeKK4?a~UBo_-+CToexhQ4emKmiya$9Y^RCx3_zp^BIn zC7Ev-TZRZ_z2pD87}*kh012kqZnNe>kTH9Vpi|HC z%Y>|OKAnZ)R&kV)m%g<7zmXz}+>cNfhm~FCUmffJun>`G)VFA%y)l&CM6nGI^bjVgtdcu`HKt^!I*O(=VTl3cjx+)y94 zuFWely(=ZH)R7rFJwzB;?EuFpIuzxWlw&0$QQ}@h)!n*KP}vIvIaY#@VtOz?0iI}z zI!XrSvl^f(LxJ4F!V&NAgw&83BGUKxs0z!CWR#UH=v0>r;!mHy7)U)H9N+?)v(*O0CZ>?Y8sZRsVMORrR*qC zQ0eI{s1=by^biJX=w$vV3498`QKYK|K(+SS^>U~y5rL=9F#|w7Ruy$^lm<|AP=(k3 z-OW*win>PuP?DWc1IWxp{k-{hs8P^!N0r5#uK>y|!N$>yhDxL0aK<>yLDi92c^*u> zY|f`j?5Im!R^?{5fFhg#C{QSvqZ`dfLruxdO<^HH6Kb*8g(jdX2b-aqabPJNrr|iC z@nZ|D1UFG*UH$wIkXn)h`gcdZ(#F!jsU%FN7p;%WM6X0$(#413<4c7diyI_*6|B#` zQXl_zh}t;O&65a3IkggVApgwAe`xF+2(4S4Ty%u0U#kt?LFm)|1MF85@9RIbD|nJT zcprU80Adc??&OKDop=+4&zUVQp6xHToVs$zk(iG(a@^}COtQ~_vz<$YvjRw>Yb;#8 zZnR}ni2X88jAu;^%I@>PbEgkTxlG=wd8d8VHRd6FZbsqmxUvi1-X3GioO)4%ORlV{ zSKAx>3bF*fcAegXqo`9&#G9Tdks_$$IW+jnt`+<{DIk?WEP6_=Z7UQ zPae1*F7L-wfoA)}q&586;KD4*fR5So9!nT4tyCq!Z?-F>`0H2-L7}<;PK%FaHb>%P zT%{l7=Jy)f`wCE&w`~7*r}Xuq!8dI~EN-^49ugvv*s&iKUBSd@Ku?M6JXOcm(W05DWi&BSUb-G|QmPeky?HO8qXzYQ7nBZ~!COLKeSEM>;IvZ;S+U7i;fQSi~P zQG>i6By(1QkCsxSG|^jS<8tk7#Izgc)EY0p)twDrRC3A9Ss1I8239Xx_Gcq!7j;Nj z!t5+(TqX&I#s5(Ky*#y8{VXj8pB3RIe5J977(3Filx0i*S&@wfEGQ=a-3Ym_>(|II z`1kG2zu6W1Oj3fvrvlPCe*-7o# z@Aq*cF=yd^rNg4_4&;SJqdgOEGJ@;b>HZ3+?GZ|z>LKn;zNKy}^7srPUg$LO+tAYO z>|>uAY^_8|{LV9LxFVn-A8Wf|t8nMZUj6EnS+cj(9fqEIxU37%PBPb%~)uS1fX0eXRRNvS>5)yvBZ8n`w1SblAcmhA8_28!^sy zy;trv^(aE|n)^J&&p6;!WJ%umqv6-*aO8=9ND0XHruMrK*R?-dMydqU&VIgK=j1;| z7bwKjt+q?4xIy%g>e9Y5>0q<=6ElF^pz3%Mn;c%_-1Q$I-knJ@rT{{^t|X+Kx=DFc z?hF-})NKs&4k;|m{JS&1hEc|W<%;u9DS=?;<0>~%PTk*>A@#@5roLRJC%wNl;xE|Z$)$px*2mkpOIwrw z`1Q&kwlycuWWRf3(tM;UC)Iv6?_Z-8S*k>4h=W?LonIuFsnh&VtWw+hUrED6i4wZ? z^tu7CvRR3e^mHne+>O^V!pll#h#GV1%}1c3oJs~zI&mfxP&O)=o}m`;1=TDYTo->% zQ2f8Crw%8GTgne0gZi@w<#0u*>}0yz<@|cpC!{6Z_A(QgjG{DWS_J;L zwDct38XeaF)(RQ~U2H&+a^q%!#};H4U76#_nJoi8h=M}yzE?(Xh7h_?Ap;};g>`Pj ze!jR;Vx?Q!#6)>544F{)l90g{eAFLe^&SCg4K)SCX6mYlmt_~xSC*CJh{U2y8t5AT z;}S<{B2eeC*nvrXu0*GQ`_e~6Sl0lxoa+6rsTEXR?&EeNHa23GkfQVMsL&7iQ24M+55HMOrU z7KkJ5%Ku>j5$YdqJ4#?9wh00nN_r`}m{c=lhL(P4FlXTtZZXXH09s{n*qiibS9AV1 zM@#<<488~(t0zZ@UBRB6kwS8Gt1mQxF_Nizd)-VZQTb9;{>-`59Ca4|w=M}OyO=9V z@H&kdLmi8QJUxrFg9vL=M{a6=M)Y*x0Z_pgFDGG$k3ew99)2&%iJ|syR>OI#5X5H~ zYdpOl86m(VG3OG!CtJ?rOJ$o(+v&mD6{Tbz5|DYWru(I!Xg~5hTr{X<1~~d?@SEmi zJH?`j+K=3`GOjv%3lD-0J%x4)-`|zp=swn~`v_mtx4c^LnPEQn;`HO!ujrB? z8f)%u*@urNaARja`&3N55D#hN3=0j%e`qT$l`R^7E{rbD-Ac4Xjjop_OhpU&Ihd*7 zsCRv$0Us{Y!YprfcE6zSxha<})WDgb-E)}c+>~Q3rg!Nq!wzu`at{R*BKA0UrE%YQ zO@)&f-i7MXGiyRGKsE~Tns!0itO0|s1H{n9Yu^IKgD4Vx?z=_WzXvgo?QOxooq(T) zNmz>6r9+(1MN0RAiW3#{wSXc=Uur+oi5>zwss;zJ8O`b(-;Cu{_0Gke`|&CpHB(Pa-7z0SXw9?yWc)Gj^$Uc!(PSeS^KUL@M~2Yk*Bg+($S(JemI(l zr2zAuDkEXS^fvB*&!H14Xz81DcC~#I{3HL?YP5FS8~p`=J<2A-D2js1wLZuful-NO zN7n`mdyVu59e7pCmaRBO!zZhpKUZ4A;Kf0fWGcQ*#b^mtMB*&_FpH(S*R6{`pdmpX zZ!A1eU*X!#dmSRzZ??URzv@{K7ta#aEorm%*A9zxbz_~I3RkN@-EWsg3^4af)9sc- zS3it%k`1N=xee{&arN|||3&%~8YHk%|Nlszjwjj>?zi-7lPDF~|pv~c+@q{)i9jp|+haRTiYz#mP^0d6W ziy$9hFotTOiARI%uDXH{>3K72b8Vh?r+S=*xw1tJ+*86@gia5BAr2J}!H26ORqjIL zU>`f6`$%dr3wUr%4!|H&1$8s}?QLeMO#!zPJ~ajADyO%(;t4C6NS8&(osIetWFk83|4cFI$Oi1E~Pu&@Njp-wqr=EKce#oO`cmr0{PU~TD!uX&QG z14uP~Sl&@kk&f4-$EPIg-Hy-QG&F7xsJ;`HyQ#KARJN}{y-BY8yj#M+#1 zlQIMDg{bJ5O{b2a+7YtzE%w^ao4`0zjefk%(k<(jwkAuETVt6#B^6JH_7}zvVAJ+V z-kdlQciE%ifYq?ql8Ksp%nhJVr$<<(6q-OZet~?5UClNjvE7UvD$u~PC`tWdNXrPp zov2X5lt>KSp#?$&4}6(dIt;s-7kZrP;TNC%IJ?uS-J#z< zfZmr*qxCsppm$45k{jDeQMVQdu3Ss0-O;Mn*$=2%IT*X$4zP>(_e`mJ7%Q&c;%~jU zKGN&&=m>N)5mVw%&7jQucW6#n`U7&gTB^I1by`L_*M7(!Nq=F$N+gZV*4;eY!l>_J7`z%U3c3x70 zjN|lUT5?nmS2CVN&$Thws6S1gOo;vUmf?~zSN^pPgCnPRpYl#MV4vNPNRl@#8l)BJ z>+kq*fOCujvMre~e;WD{7bC%G7Ts<0?y)Ep!%Wi3U;*l#kYzN~t5Rpbt^ju`gnkRmqM>2CJK{miQHrJrX^I-UzYdvTphB#?dQG50JuZJ~=#JsBb>biF7vH_aSJWDZE~v$%G_J>hpYWFpQqmjz3kz*;?gKQ z>Dgyfk+rKVgKdTSy=RYMLK_afc(r~wf+9}mAICiD!1umpo3_a3e(_Ddt-t<9GND!O zJxZlkF4xDRU0E%wzsmnGCChy)P5vNT(qTT0>$LE!?c)hMUCog!NLe4~YK!HaYt8bC z22E^Dlgtx+;I99b@5Pt(f-jCQm$yfQpuX* z<5{If;U3x-&vQ^{Kq2nfDNxG4Npxm^zV#a%z1^LAn7ob44pmC#SnBSk!vxr8ShPo1 zbhWiS5pE}ixSWH1__NW~(alqdh~(+>K?{&oxeS*2v#8lTqPY}U0TZ$#i*?P#bMp|^mw zfH;4leL%9@TrOUP6`C1j!0E}jwxhG%>S_@&{`cqIc(fcDd~4B z*a;bLw)gSatoD6NAWht%Dk(iTXDiXxY!z8nC>bNu;Lg-l2kchbsjxYWo3NVJOaKCGr~UpL-MN5L3_ z=u3DS@#3lF7=Q|32aOr=Ddf2l>5GKT>gzAU{fIdx2?A1vfqzrw?-}k0P@N83n4a&( zY>D^0&f{#qGjQw!ItOcmpu$n-{&w?Q_ekI31?eJn}HiK2YdEYJQ5A# zsA9&Xs>F4*OEY_w#;Djy9I@a0$t=;~=EZmvYic(0A#V(Q?~Dphn_`y~{(k_*Ku^tO z-rFbm2b}Fd!hwuHuA1w8c4?2Tv=g+N99f=up7ZlMK9LaBy-saG3J~^e|2D(+-Q=2? z)v;J1;}ZL?e?`YcsVjm?q-E(UOwLywSYtT)v*BFHM_S9Pqd8sEYo{-f-`7XUK+X+n zJW?9yw6U82iLF%dsrurX4AG+A6;@8g@xqoywW(Y?{=X!iCc<<&dy?oIVwnCft5%=- zKo6dF&71;bM8T)d#5Ldkp!_=f_i3gW`>!Rp}5(?!QzF()C2pwveyp- zjGv3JFR*uAiiaZs-l3q8VS_B#Kb&|h|HWVZ74e%jb3@|#B!r%KY`pb>Ve{JF(kyvVtj z#zRaQ?Z#*faPdOp;8oHL!{+{~EAZHYdwZgfuV=~6+_(MLN`-X#dhcCrx*P)Y{q|2B zqzNZ?_Yxv86mWk%g=RN^wuzvW%bTv-?wljvzp^kj5lv&L31Gea^!!vX>&~hX_(Mul zRnfl1hH_AX`q99w3)EIqPS1MaiPw8}V;zQ zE_7a2onVcisx8pA7Nx1nb)c^-c zf3TT)2j zHu~5*U_&P=UgNWV{0jL1RdIe>nm*^;+Js;=VeZhGs_WduFIf8n9+*5<8#C7AOEIO) zp7Fc4^}+4f=$;}HJHH#Z(656P(n{F3w?Dm~>Qs%6*$x#9Bp(mNSNnCe#_M_Jd)-wl zdQ3jEbbrxI$%X%77R^J+-0&`U1p)t=IPO@ZKRQwEo=F3tU=+$Mt9z%jVQ>oOn~g zk9xbj+1k=bcAa+8jj5O(f5U!#zxVBX2eroMpm}3**5fS5yB#|0I6E43G09LW{O3!G zLNzj`%oyo6Q}*lgE|e{44;ZlnAt_w1HhULeD>7Z6zCAz1x>%>xa?0Z1HQ)rfW4Nm} z;mVc)%t#f9GZLD~`&3$QxMZ(7`%1hK7zbC$Oc9jdxxGYV0#eU%e^?#!R^!VNna#X^ z^r&Iaaq>BgbxZ3ME0?t#pz{uKBG1`9576qoN{QEjttaZD1aF!AsdPIg_@o7qvc#yv zVCi7xX%|IK*-1MxIj>|Zw0Qdb+I;}HaM>*kVR~&;K|br=&jVX$X7a( zIp@n~to#1}ea_wJmDHCSrh*R%V~k|x4?)ihp)$=Dyci`dnt)G>Ea%G z_aUK@3Z`FFntixFZV|)n+H!Zh{|b%2D*sZ?B{T!-+8SoF(G<2x$?Exbd&FFrSvMB^ zk%kpQGxAtnn-sv0G*dH;A`&D~8#+Q4M;CGTbT_qk=!nUd&UrmXN$+!P@chpAt+Y&q zcJF3umj{Tfh5{X%DI)l=L&lreM}E20S(uljHKXYSLA8VFr1N6h;~mnyyYT{aBl0W$ zv{u^ODZKtfGFYany*Y}rZz+fCWMi6uE)*g9_`9k{eh;n8T=Cvyr@N=n1R>?$rJ9K4 z=7E_aet&9#9o3>iOH49D1cQZ_Ssa6BI9vsRrk024?`O9<@lN_baHVy{JY$w26-!() zPK?^q1kV>ya~O~pqqBDppa2VWqhT|DFHsS@&CGLMrkh-MMn*ic^8O#w^+$OpJK!f& zD8#hn*5@%`y--6mI^3f#{HTF$Y7CiHx#AXN281C@$E26KiuDmS*F5c1tUl@c*8mv20vBa=; zjJ_uN+Ap;%^?ZI!6I;O4-I^`OPc6Zv?O>Z4)_Ja-yGE#60~*m(`djt#KLA|T`#FFA z@F-=hJoXy7M-HWpFZ(=8zA%XKL}Fzx9OQ1TentN;^;$6`g!K^SN?-+4>J=R@m7B&H zIGS%1FV$Vx`#0aS3iti|N-IvMspCDxxB5=T--|4Pn`n9wzl0hJLtva(ah1405Dou{ zJvyt;1VcyprlmRZy+dcAIFQ~-1@E1Zg>qbot=|>f<8ST8PKw`M9~IB-rd0RSm4fg| zf5^?^L4F@2yND@=oy215M}MSs%fE7qH_uJJ#?d2t;ghl2YPc1#prx;!e(bLIxL!vs zJsPhLoB9tBLOm;U{L6*HScBVqYfx}ReFB)uuOLO|ThH3Qz+3(RWV~071XHxTV|H|d zYAxBb)T|{8zi@u6ZWxde-+z;?#d6B&C!0e5Exorg*43oNzahbS<-HxmVyDs2f$@@I zSsFn|te;|z;G?RQgk^r>v?KKsN2itv9X~SaTL5Ie5gI>K75v=e5LZcmI^%aPJ7>96 zC;TKsHiiiF-hCYvV$Dt5D+<6FlfOMS{m0cGYW>7^IgFGoL*`R7BU?@@CX(=_S#>qY z>8b7xh+1kdy}D%VxHr^}(s4YB)1Ci4gP3^wbtDaRPrBSz-CZe)U4C<^^4CsTkgP(E zT7%}|ilYvXlsYstof?g zaNmx4sb95F*$fm?XW^XAR^C-Gm@>6U_enV`fj^aRzFYN3+PGwyb(4Ub@nyJkVBzJ5 zHi`^W^NpI;Z^q6SEIjfG5eHt9&?U*3_;ik$A00tzB=yivZ^<1e=q_;CuJ!5=<|{2z z{WsQ}3a(N9uCk>c0yGoo+he~&Mo=%U0?oH_I5lf@^4qBl^T@$YvlH>gK(pxvX zzFe|D8sftOjDz{4GU9a#mxisfqESyz*m}@4lOA`$V{cK*0_yNM8MMPD`*!(~hiKKM zXQ_aIS}ThWE7$N+$yvG#d|dD+JiKJpjW(ECY+RXI?Qxp$F%rRREIbFt`ZtnjftuC8u{P-v^zEt(4m)y`w%YG3Cvn&{^IUCg?z<2vMrDAYlxp87Yl#yEjTFN9OS_Aymm{kTk;%lqAu{~Xb?Z-*K*xAFbHz?y6xj+*a!Ra*TD;Nk=q1 zq+UC?(bETW6IZ5XVFn*ko7Ui9d!}M`y@fw4iVRPR-jPsc)K&42(+>oScn|f>Far- zpXpt1jdfkunZe0@&y+O$j_)iuIjEM7=a%~PnGtNz8v22dQnho5T_tcwYlE5EN#;f5 zW=4c;>)c0~j+ooTQ*pk33-sBgU<{k-LqTO0DOCCj#COic^RwRU`=y(?Bf)E2bHkUSd;R0wXzcL%+SV$7Jt$Yf!E=D0@-c^ zJH+}{%y3sTw=nW$VJ$`d_C(`_`X!UzmTw)(X|xBE2bG&WN3^buIcmQ!!sz>!f!Qm8 ze8#{n4POKaaZ>^s3^b}BIki%kThd9I%Gxv)?n~vK!NM+U2e8Zm!mH7j>#-&FO~z$GfYOB|Xp|f4TQ` zku6*Nbr8%eZ46eBB8SbgxP^1j!(6>S7gUKf2@KI`T=zY^4~d1ONJos2vN!@`E&Kpr zWY-yFU*tg0^&eyB{Id_b3x3z(VMv~Z5PNQ-?=Uw(IO*4^vixI7hT`3jzodV|HY&~M zNYXBl^1j=;NLnAdf4`j{uS~lkx4hO?k{?Q88?@AH$^UlD|D2pqurZ~jE&W}b*FO`< z2!XpudM#cQYw&(O7UUrLpG8mNi2iia{f-e|1-R>4#qP9%czk!REk3bW;|6B`(kr(a zxPNR(9DSF9du+vZg<MP9oK4B3`-LCY zdUFq}0tI*@T^45?JZ?^od8a0&o2<=;?1#D2Qh32*-@|a>D0Eom*CS!@_S0X~4Q&gDs#3?yjaOO8^}-7(Q@!Q?{1m&>9VJy=0#xZDgr-64#x#zZ;$?o^&#w|z1x712J*1VJ_5Nsi z=hWB{^?nD#DNvnFV36t6gATTJ#Yy&Kc9whPh`%BjPZK>AuZ95f=vTe^*wY3r&vU~1 zDzX%iJfybgu;KCIfMW7;gZ!`=6owc6xvMVk;~Ne3*2u7_CdpCO!GPHvaUL{_V8^j#Zt2H9V~T4T9EycmsJYGj(DuO>IB`~gP|^v>YWfs2+IZ}Y!S28)M{uAU7oww7f^ zH;Pg61IGi51#Xmvj6wjJnIO^9@SUeQ(uZs<+Z9D&iW#Tj%a7yZS;+xMo*#mZn9?7) zW81GF;Q12~z(n_b$jHG3*%bxP3=Jy4<`<%|5FF08n!z-jB=Uw4IhB1tX!tt+LN zrJr%p3}LTYU3$11!`y}@BO$#C$qs%jHjla%Ev-JC+EMK z3;yx!%L}`5NSFhAzJg_(S*lNLn)V%`(~-1k=hPQhcQ8Qe>WZ_XIe*H}f|_RNNQ9eJ z)5c19X4e2A87OCM#9rV>^74^;Yaj=tgsu&+>7{%j$DB&cL^E-uxkJI^lI8$*Y|Mu#AlajEv@-WxbK$J|9UOxiv2jYc6L!#+e zzVdOd12gHocIf!`i|c8AZ51Yg;m-HL1sN>xpfHvM4K?@qVz;qkVp_E$j}JmK&hYb? z*qVT{>i%cu733*?jk95b(kq1*7wBbS{%6U#l>zH1ii^VTes`7{Morlh8?s*o$1^y> z`2{Zs$3NigwbWmp`%Y8Wd$N(34|NyJ*;>4fsB5v^n|p=)+34015bNC2VG6Wi#@kS% z8oSgEUU|rHB0P!|K@+Lo#JN{%DL?P9%|>4jFdU6vT4^0a#AGOf?#nv561J61<*wTs zbVmH73$q$(Yl*1n=;#=-4$WGRqBay&Z&guaDvc*auX`_HmnjzP937zus=K|;OFC&Y z+2(ME-3Lvh-$rfCmgXDE4_O$s_U<)NA7;86E(ieS&-tDO$%cNH6X zv_duT;^f~H?g_v6P4nc<1$6ZJAOO+IT(LCK4Uqv|``8T7P@j%64BDC0s*JzzPic+%6w>1+%f!^E(WKH3 z_1M{HNjTVq{b1%OZ$dlkQCHiNK*?1rL`8RBdoIJrb(vu$ES8~eOt*b5oH<=+b{%%f zPh-ift;igM*eTBT)RI{rF7mU0mlCIA+#f2BNlm6}%yo7J`~xXKllJz7(fuvK^)__2uim4{Lc^nD!H=tir4OGb>rQF- zl7DNt{w6>wnw+ zItf5-2)j{!E|!9#9kk6=?2=Qns$abopZWY~JBu573c1&$N9|TlnJXQU681akk})EF zG@vlLhYX{h-fk$p0&>sXq|SaW2WxCSrSeZd$+2Q3g;da6p3+5H{me+WhCgRNByf|~ z$E`B|N?tGOFS=j4O}M&#B2`vDpO8j@{+%-pq^ARYzGek8x$R9iie{QG)89;B+>Ez6 zok*Uo^r6jrARcv^{${;pZRc9d^gFUS;xVVk0_W?}#Pj$C*Hu-Zw%8gBuGKm?C18@X zpk#-n^7kiMs`Bn^PLhESK8_j?qy*ncP#ShLCkNey95jVGZcC8_(F8S?E1UfADcFeE z+MqLpgX`VSdK_Srs4h~TBE20f9HW_*O&V(v`TN7*m=qKyYin|=&BX@c8{u3c0P9$3 zI{{sJe{3j`@mD#e4WJo>tb|3DmFHkExdgN;6)BNyYEl~jBy<3yLSt_R9<0t>jP=aS zDIh^tkT2iAStdP*ZujWizc7FM@;Crmac@t^wT&ZvMVEca0Gy!4%zPoJqP{xoI(s)q zqE+PbhS10yRL8b>Kmkq41Za`)#iJ>+hB?|Z9q_4$38?kctrdcG*ryKW9b z?nqZ-khGyO{hsqQt7)N7DZ<$&FyV>{&iAWuM=xT`3Mz*_!m_?b-+lfl9~vZExiIQO zaMq`R9r-l|U=vkZ*z051^UkN%HRERz7QAZoZ7$QY!_CV}RoLR_r?u<;{@=2fy?(?r)3nMvg8W54`&Xbm7eJa-&P2-xTTPQDlFR;vQ=EW6ZHeANDBH)#3wzX zkInLoB?e}^z$&1Mk1C;(GIl@ZMKidC^{mogdy2@d;SQw=rNDeBUgn}35qj zFR||n2vJnD64~|ula3@F08og@OI7s)P>KrA5%I#~m*E5n8J;kejmvOq(N_mUP{5%L zYG*^OB3e}3$b!xyn#8Qn11do)S^*We{ERYG<9%r9J?7*`k=C%{G<#i*lwfY926EFp zFNV@O5QR6+pQqn7t{_qXf8bBG8G%|RuK>2Q{C$z3hAj0XMWqRB0)b0?&)=0Z5GDVl zDJgduE{9J9AHR7COrDwz#W)n@#Sb0Pg8~c+b?$_NfGag8cQL;F{9``KC%QQ3mjaK7 zKXPD$DkJ>jPT|}t=|-qFNAOY?xrrs+eGO`pB%;%R{{Zeww~4Mb1;x_qXzb|iW_-`D zcQ=0W+IB3QZFB3kVUon)^bVlnbbd;wYRfpktiG+fCy(<5=Y+kyw#(6)XIgC8;(B`L zDKIuIWPkmN&RbC8xRBdP_t(FST9aX5<(eYcornM|dBBGy{wxmf=g{;vg-Tl;ZYGck*=(plR||IRThVT<a6OS2TYZ4T@iy|`4GV^#?wQq*0>+D_w# zNq&CQzNzk252tDgA%ph_6q{{mdt#;8r_Ode$iLVfw+TE5(TDd46`Rfx+#_Wm`U+|Z z@7r}IwDpJt2|>6j<(vTtCoyJ5o7uUhzHk}G?k}ctEIm5yybX>vSO8BeB8l4X4+_%U z`6)!lE?&w;%V8wAV=G+0lGc%E0s=RBIFO{e>N(I{_WZTu=xf5A&L5scNtk-@pNuukB0+ZcUhNhuz$(&7>0(zg$?c>!dd zz^41>hmyz`@D_O~5Qx#8o~53a2EO&^8DJ~oQWE`(>GKw91S`kDXZAUmO@1x-TsaEodKh{twWgRN3?Sf=2uY zq)C=FJkzEQ_YO`-YuL9ULUj;zzhWuj4$PKoJFD*<{NvNJk6{l1r^=k-^*y`WmKJX) z6TTzQ+S39)Vasx=+Rf>3jm19R0HrPH}6469uqr8QC4T*snQ878o9&i7nNX59*UO3fYxss>j$7#Pr zH)cCVCX#E2Q$}G))rRXowoVEfo6f~WbFu4Oh50mIDShyy?>p+#92Lk1 zym3EFHkhO>wHaoP66CTl&N&N(c7s{J3BV_b4>^IbLy4QJxpbPD1U<2HxnDi z;B3+FG@W{75njP5E;pw?Ti|@ZExSXcj2Fv$HQYZiGfs7vLdrh*?taZkPAXjb@lqv} ztPzzQM)sM-sg&8Cajc*ndiCV_%KGO&@|M5*imq3Zx zpcy}-u-B{lri-OZ7jADFmu^=(BeU0=>87ejsd5eg0lw6L+fn1@t|g+i*OeZ1@LJyO z!|Oc`CJPT#ut80sB=n{x{8b?IaAnED#Y;tGwA(VspT;1=;tj=!c@9rCUX+?0vF)OW z$Nj0!)!QMe){xkiSD`U=hY79%T&fdd#91kHbs=}fdJ3IC(erJtG%SWskTL&ST}w>o z$V&@EJRLg(u-Sdw@e)1=q^iABZ{2m*`>hkL)3)?pE2v^yrZz*NTh9&CX22(z%HF9` zIE25m1u@dZqs7IOG*xAr@t~*V=P8^-XG|jfd74X{HLSE<{fD$|IsRWCC0Fk>7x3qU zmM_WaOnPK#%c`3=w?K=(g{`jcK{b}n;kL~^JzY@}`e*el2}bX>tH-G}XUiCfuvxzP zXGPr6DBC1h#^YhB$pGrPx~{O}>wBo-XkoS;Ez7pe8o4}3YAZ1TKe=Jhx3BT%GyaI< zZ6d3wNhvXBKKTW}B(uwS+HluN9hu zwmz(1O(wiOlr&Yb+wA<2bV{k6?g=Um;?yTf`YSyudnv@O_~o=SvbXQj1hsfOl{s!| zc_8Es5?+cnS82(2Aa2uQhImY>x&ZaQmEtSIv6SjLkPmgUc?T>CE52gZpcpexwrIJY z(&GDCps`->BAcoQyeKHM$I3>^ARowF$8qm6=;K6H_RJmEwQ~2BC@=~kqi@*K)!5$( z)v^DicyIg}om7>b!zVcin>@Glp?*Z{@#1TR%--b^FI#H&v9}T#DU%+7!&EM1KHZaV z<(gBuE+pA?u0=u`T({9vYOx5nvb--2=%RyyvH@`6~K@iF{zZV)jHfM=AXnZ30Egv>?^>JuZ!pMj1 zvOmI{YTN_lT_iczZWitw8hx(ww|V;JW72-uw|)QZjydWY@jAgF{EjfzZ56)&cOPa@ zp}pSUB$7RSPBbwhQ)MaWM90drp~EiR+QQut;g9fSOM)kTd0!~}@#P0K0u{{=zw)ez z+gd#!^oEf%aMh??5`LH)Y#%kc08H4>2I)(Cn!==C;43!oexG%`h1Qm*>fR4H7eQ{eb5I%XF&OiNWG_K$rB|gH8UUmq2vs&1 z&tqUE*%QmENI0jU}v$*|4F4lE_M`1yMOmY9Ds!D`)5{D{aUe(-VwQ zJI3UeB+#P2(*HHnS5dp+l5Xwta?TBAXTr7?!Pq+{b@dg-9{(&{$ZW2Zqu19=(Tuxz zRvXPHdn}cCTU#IhHsEg-fwd!X#iXA{h6eqqJXdy>0pLY`vT_i4i2fDf-@|Q$2+p;kruyu?>!_qg~gJ?JQYXB#7dSWZ(5GQGbzGc*i-UGH~_MjbQ4k|El zp@$|x6LUOY8L>VlVI=?ow(|7hsO`tiuHIGgy(#dZ2q>VA=3uf_cSk=&K~|2Zlr%%9 z3=BP8h=sR(8!WmT=GGLZF9%;wladjT6n?sT(60}B6Yj)1+Imqy-&RGAG%FLdtc*!4 z|8=N`MaIE$RVa|`(wSpGAyO|*?GzqVV_{+SoqU-$8yOf~DM$7Z7G@D8sBLvv(faG) z{(fD0lqG?YSRnbhv6n(H3lYx17|p#bx@PnmqGjiURld*!SW& z7cjKLWb;>YQfSGskW%Hg%*f4_1~@i#@&`BFCxRfRaD6jqb^)jsv`RtQ`2T1+>!_%@ z_w5fQNP|PCbPY&15)$K(1Jd0C(p^djDAFlNcY}0GhX^u5$wmh&9*%>=Td5J>6t$>nxudk()T_3Z5{Y8`;~ zlGL9S(ML)Ld14ga&o!=8X;v-RnPwXOTj4c1uBN+F(;iOxFS#5(FUZ7Bk@ua%BsVe{KGl6J#* zxLG-ndfFCq!jI6ed3vq0KA%5lQp4Ch&G;7<3_#D&xbirLNRigh#vNxAf3sT*Zb(Zy z293;6qGP`^{n=6$8)~fmZOmsy{;>96XJoxp1@fWvr%dT;&Z$V#ac1~I(poBVSAP9> zKRz_8b|fE+YuyVuJ&`vwYuQ86xnlnIe@z;|W*_N%gliSEv-QgxSGS`pLVwo9rt_1Q zY;)JTjbAU#?bVwj@uLTY9jjSm8cn!Iu@`iR!mw%?q{ z(+~#c6x)|O{gvsM7IkPn_x?g_KIBv{`%7Fn+Rp4ChWMFD!EOYqL{4ayx#8?_*EC;Y zH}V_PQ`hVdX&LU8z7Dw&@%iyQZj8OY9>Ym5lK6cqBWc*ONxa6Yxq=zWM!c%V*=}0N z4hkZ_KbbUUZNrf;U*!S?Vi-y{JJ&J#dt6P(%{>mT$_O=HRaMOzg1lqNwMWuN&*1m7?3TIHuoI^gGi^$%TbF#3McHbOzr03Ph7PUq$4CzR zFbsFRF*Hc7ZKrnSmREHqSk}4FjO`q4+|i_d(WoZ4=&_4UUK~iTuTr*I^}cY1-}~M~ zHA1r~{=~K;dxWiWzY810xMX{?(Qz!cv2&`?+Sb`(g4mM(f#35h^EjLEuimuAUih%j ze56QcjS6h@`jcHcMYxWe=NaGob~H6N&9K(4p+OepZ%V%Tt@8_%(ta!DF`>Ay6ZUWA zdBjrPs7_L7`yGDGMjerYn@m>ryf}R9Z55iIazky`6dUq8U@GLa(CK8yoP8eQ!1V6`<%r{8OxWtjUbid}cl#G*`Vuhs z)~$bJaE8~<@Y{7kkD$+fQ$eU{hCRU-**5#HTxAFfmYkj(JO*FSH)`xQT~9Y@(&sCM zlYl~nq_4_uRR;$K?_36VB+{Loqgqq@?>Brw45L43;CO%a{G$zKy_c0D8u5mo^+^fylO{KI>Kb!WmKFohAx|saFz)l z@*n7d=MRy{X`^W0mydttXu>V)Wa=a9%O&j_TTZ+yY>$`)0ec4vvs~w668#` z8r#<{DK|WP6zL>7dX*rywakXOnyHD3;7mL5^wKzk)J)t&HPcC}buFAgR@lteC9UGi z%8ZBdjL$+ER*D?O;4q>(w6(u0Ls4S57v;-{ud(qX=;G;MXt`6zpS0#eLs%KKtYqt= zsAX$8u@YBP&9ysqZlbitlB4xkX+}U9^iM&V)DNH6E~Q4b#`Z5{Um1Qu6Jz}LSVR?C zU?3DX&^xdkxbtUseaYgU#EuH;#YBGw2?lrJtOMy;7nQ$60_q)K+u0Oco@hM9V&jR; z+cs*ea(blyaot5=pfLsE5!7LCe|{ohn`HF!#2!6Dm%u49Zh`aDXt`<1+zIhGrxvGj zrK7)gqHSFP0Dgpf9GkY(c~zU`QrS@HKpPcd%mCbz{Z${VC5dDI9S)*SvMs zy(Gu*Yp3DP8*^1RnXO$eV4~-*=cConUrXQ~2chi%MU8x3TO0|k_?T{sV3SJS8f!g? z8h_{wq;-0bLvD7at2xXRG^Z=^{u~J0cQwsUsV9rg^~m-@HN1YqR^Mledkzz&Ns)AXVJzV2oX-nWj}1K(X~6{g4^u4$@@ zzY0TIU*+jfzYLf^^`QOSk}Rq4x=JKqvCYy4JVB>@W_QwFQy^v3)G|X!TKgkaf&R7P zx{B6BZcqyP!-G*(?FWwyH3;7pGT*`GvHg=St|4RjH+wSVR1DG)IzAy$7J0pa3?t}S z)Uj1ZQfc~%^cb9#l|CJh4z!zBC(1tZPGrn=^ONZTjcr|`)L+(d23?BxRLDL ztUa=K?`zARMk&+^!=nP^*d0~=0tA#<{;Wwo1a=arDm(U=?c}oHrk<)+2Dfm+e_rSF zJ;GKQ8dr1qC7@3p)I+x;0kXY-=ixYx3y+a6_oH4Ujy~;5!+u``5~Ir{F>n6t6S9Gj zdFy9o#h(j#I=z|3niqiGSij^hoR=8uKwW9han@5%a6n>d0&C2Y)=M+L?HKWSipx#s z4#sR72hv`n1)eT`KZP8xH?_p9tO(KzGOHm2dBQ?**WtFWf@sh?{b)aYTEn!TtdF$S zeqj4BUdbAW>kufj^Lr?U0BBhe`^r5muuhhF6JqLLL{Ai!C(yo+`w+wXqKULHn>#$4 z7vGDH0V-eA?Gp4J*csq4>`zZlPyW}9QanX}8q*~mv;lKGwwj~uUp8a&f%$kI#WQF^ z*D#A>qL_#exi<(H;30v$35`Q+{BgG6(fDtJm~^1H2wdE5$H6;Vd$N`*U1e** zvAt<3vPb+%4L4j>w4%;gcW>Vn0u*)uOSPNK@m%%7ne=~Hue=NH@^$v;whe_4=QbC-kRD|^OE$})bW-;k&Hdwo#`tgNv<6yM+W zkJ=$!t_-GJb7yNOat8W@)L0Us+YkAkYq{_6J8}hQDfc0+!2&)mUS9m;)Z6U|H@)2U z_RKk-u*zhWUm{m}<=lw;!%ud#Iy%qjNknt{auoO1byID59z9&z%;c`d5t*zn4_DQg z9ca{iDh~Q|avYA1*c$y%?*NI0caeqZ7oFY7xY0SzCz*#-RBuE zdCb^|R;{0s57mwbIb9ECQCX^#;*fQ=aSES1^ zSen#WE!-bzz9~j-Oi=C)n$vdx=DNtFb__-vs?75n>e0hPeV;$}OeA~LPP)S=Hak6@ zM4|6}D$q5;q~t*S@AYSoD#{fCs|u|*uvI>ecN)ZmEZjHP(A#9kZ$x`PlB@Z3;6^si zFx*}{<{?{e@ugb-TasdLxM2aL3*eVXj8OPOSat{I&z)NXYmRTv(;q`>s&&(re2?{L zK(3r$=bN>E)t31bJxI}hTs+81UGXj{NcPEcSwWZ;v~99Z$Fx%=q*Kn&-atE|=$Nb6 zD%d3WrL^tn^KvD;DotRRhzI5ads zw+|;u;c8Q~9Z(CkIObd`O`Kv=;(G(<^#W+y`F9CdsLzNa9IDNYoX=OGo_6idT3-rJ z(^A~9J*BY1_D{7L#0`Krl^-fIu55lEAhqU)Fg;9ilJDOYv%`>{0SA&*x(~|9lRmII zlI4o@N!Vx+bW`X^os#%n+`C7ULV=7A`f+8k@8(;`mK|^A^jr5PT)ZUJ1@TP73qDw+ zJ{diRExB&a#NNLA4|FfA*ktCSwEu+f!_y|FF8oN$q|Su21i5DR=%{8hvAeeohkYXZ zb&N-gf0EQQ{Z__zo=hdbjh4BpHq$a|o4q0-Ts1a2NWXsKg!g4B;9JrU8r)MAI$vT8 z?D*WwI)&2eL5RoHEyv9f`MzJ^L#vctN~ZCnR_%M(>B5e~$?l@uMqaT=Pu}LT@#67( zW3Tru$D)@z3de>mKMl7GUn&qjwrN9=9oUG_eQPVoKJsr`_Z`t8+bm356YsACb%a4D3lmkH0T+7 zgULyZtsGf5jKLS}^7@;o`>^UgPlbx(oX`MnUYaUn)0m7_HPBpdSB?<7Bg_zMX+f$n z*vA<*HeQT-OMAq3F*$wI>+VSz>0xZnUAaRo#11jiHJ_JRQK}_@#ztJ_D_jT%-jc}B zE;SyctaMLQ>lmXo04D&(rt+wdG&QTMHHlUSZ}$}2j4je-^%ZreGRkf(1tR_LNf zq7?mH$nFQ%$k|I{{S=P;7DDp2BXMo7ks`Lty!FmU=s{REa*&nx%(vmR!Z7<|4F{Z{Is{9lmmUt5DX0n_908 zoQW-CTheNAUOUM5$B@~Qn1~8vtlH3Ei(HU_vc(s$wpB3bBm8Ety8t9 z_UX%|Q7^JY_3`z@{KVwxqB+m20DR(bXKC|Tb2`eg)Ssg@HQXkNnA+A|wV*WHLV+AX z8#0&YIv!B*qg;K9GWo>|tc6$dpf?UHUmhIjQP4ta_`RS-KpZ4n&gO+otLZu3!9e*{ zl^ow(-K7bPv%Zmv+|+!)b-@xd%AEu*$;uo^J3cGWtW&k;=eggS_|kRjz0r_wHHXF1 zQ8rAf^3!Pwq2_9#!5*9@Un-B)6^>ed<*6CNDm4q&?_{B!VrQ+?4*?aMznZ_pLfkuM zN3Lu3UZh|4N54j7vv54ag&cTl*stE+?To1RbiO4q#horCTUDGcwI&2t@e6m6E_d?; z$XHY?boLajkJVUaqIgLzKcQinbQ19P-xAo_xgb&EQ9kLHzv9b^_Xc1ehs2|(H`Ho= znkdpzSZJm0vc@}AKPT3ak>!Zy|5~AC)f9k#Nb1N&%wT4uO&`T@yHo7;UhKN`d{O6% zzbJthX*`-H*`kRCibodp$P-U;Sa9DsP~byU2>@*{(En=tHHtlN{0U#>SxRh_`Pwgq zKTb~!e)`&SyHxCvja4|&wv^TIIe&pbYHVo6n8apjY;Nz)bp2HoKdOG|$Z?75LPriP zL&*+FZPGN$s2QSZI4R1i4s;yRvO8r`YG=m%(^A7igItq1R)`+HuQRlEwEVtkx=+Qe zT~N4EHr_ZPj_X6Ve)cz(rCFraSKR>7{Um*(Peb5XnluGg8FG+}C2?BdIg0L{`{+bl z=E*Q}wCpxDmh3m}&I9L$tb^ecU)>cEb>W1|Zf0R7o~saMsn?HgRjW~h@UD`x zUsp?VknKHOB##-p_~UTDAMx%=N&}M6mJu^q3^iv#?v&hDGS)LE#6oRW;@jvl9$XxI z_r?e3$3Uj5_q~~57xXRTX9t$H|DspGRZjxP44-^uL{6zjXUz4TfsLte#^wi~pmBi)gt=YZ%qdBB>(k=* z{HIxJz2CwO7=mIqI%&%nzR)lHYMwD}KAuhQ4sgIZ>JK>HjNuqRekEZKmw&1(7);@m zI1Y4_uc7QdeZTYP-9Gmd!iwvAEXkYa8ci`B!&4n97z*0s&775Cin0ch_V!Ci80OMwX2VcPhHm- z0k3CmL?YDzG&;Y3&Bjz@VSK86ox)>fAn-Ygoq0kkM#Dl|@(1N!R&BQ(MQL6+dSQ?q zYAduzW0>mWGt3}QWB#_pVbxz%Zhl^7OI8S*tO zEJ`JjVImRr_ohHWf|Xt;0j2I@YR+?9_lyawZI9v8>6nkhQ>#$M2t<|nqH;rkEBg!_ zr5uT0OYy9(9p-x2<$z!~Gfz@e<_JA64;J;=&;gUmhAS0+V$MWbKOaruMC z)G2O7?dias=w#Y%^8liEJYo5#5rH@L56)!6i>0|)e(v&mp{qY)hx#aE6zbAg-Hcid z84#mb&u-)?RE&xDL&?xs;GKXsEJyQh?oc!Q{ES>A9z8hXMh(~8qz-PR&-Iixuvv_8 ziib+l$WCy(+2T?m)-9gw|7FU1*?b16{GDsVx6vD|;>V{ZXT`8c@5h*y;qhxxw`aO! znqTyzqsVpa>u~gP%kP4;cd-odn`yh8*||I2yx^6c6yw^)>vJxuzQ+iF!g#x*fu}!4a#)w4$i0V^G0!YRfuN`Ic$OH-susAo-qfB2$lhVGXc?@jjE;%BBb z$9WhI+!=4pZ~k+VJ#nuzYfm0NUowQ+5mmnU z^(9H&sn4)wjTlDmU)vC)FK^>-pxQnqBkoXQW;*0~J+}S9CN`gUkvU~T0oZR`^^ZbJ z8;ZVY2(yic%T4SEdb=NZ8d}<^QrCvZ-oJ9h6>wQU_6dgCRhc{MXFOV=fh<#w4x2Hg z#S1>|qr;WC*{Hh>QtdwtCNPuM!ubMC`!rG zmZ&XEj!K-QGy0`cR|Ttkku_Tb&^g&WpHar1a}2%0V(J`&nnY9eM zhc$P!v{BlO<0xR53yrul*UQ8=&*^Bev4+jaF`7HmdMO3HEmacg@>05%g}?<_=)>1P zWl)a}%Wuu?gymZxS|J{O{HX*S1B`iPKqhl`Iv@1Towu+sUJr-JX?PQkJgGhwAW9po zXy(Us{Tbph{3h*(;|iYCn@+JhnK^_o`m=?ARuko3Zz8O1Y-x$mmww(VOIS(g0G9%> z&fp{SOh!_!)iEp3nC?aL3Nqcg)3<`p0u(PC_M@3SA>4;f!x=VX0H3zH2fGmrIG5th zy>MyY4Pbug4kUSb+^FK%q@){%df={J*mo&3J(%;{+nrE()np}-G-{Xz`3ibimOp+a z;)dxIs5b{>i8>-4%}qPTE2BtFrQ$#5`C^Q?%N}-5u*0B)>(yOY-W};_e&q-0^8#hi z9mt?Bi*#l@9wyX}zD_3AYo)``r8)A9eQ2d`4KLCg;x50mD%=0h*HWk$5S5jPAkHb*@|8jFfH389rC1wGF{ftqv3@gj& zk_NoS8=eEKVK@vG&OQu4Xe}H*mjnd;alZ$gh#;-un9X3VfDIQpGsQdf$;zr`n57|E z&0rj_w2P`Zh-e05`vwEn2*-~>+6c4#hQ*iHRW5cJsdZ^cT`yZIkNFm7ZZ(HO z)K2^KrYw8YBJ3y8_l*<#)+oH=#R-IgbYcY-f=<)VrbIVkL+ss(v0Cey<~fu!th(5N zoO4AhmDJ?tlM#{jn)=C(nDyc_hwIY10$7Q;sj}+wJFJv1`;TZe&hm@gzw3-Qdf2pvSI09|uIbCQFn054YxcKSK`gFn^%i4tG=dAeV*c`M= zVt}@-Tu&_u^4E@+cf6kxhVKw<&omq=OkP?c)}hr)B75Dz^+JZ{#6S`PQNo}L2|Ra> zPU7luZa`Pmg56V6xsA5eO*~I2MvsZdtKLATrm9T;$_g|_`W<}H#_YStPmGy)sbH^C zNMzjZLNgQ3wU^r?2%U$!N4Qjcblr_siL>`R@5{7_xBWgvRfCfPj(qf02UqLZAFT1_;rMq41AKw`@4UUd&&SzdT@#JRo4t@xRTCEsRj)8E{o zcFwVC3)@Xr=@!xc=@1TCxxf32Q%jjO$IG|hju*o&u-eW^u&t|CZb!6$J{FCZ0@=P$ zQz$lN^|=Dgo-NkNrHs$ondTmGRC+tX*Y|fg*)2}}cWQMhA=PKboou@__|f#O^`~%! z&2j1XNUE1}I2WgG^`Zq&D!KbSi`V%5ab>Q{zT>`HiPhob?j;q}vnY)fp4KL1jYWG&2Hp~;v_#S$IuWQNu`K<-j-o=LN zU9%=4E|^6dxP^@vIp?Vcav8d3bI~SYZcilQMcI;Zfe^KWAOrCYfhXn@>lXpmq8dCf zqnZ_6(Ok+`0Tf1$)}ZSNnt^&RU-S9twQXkY7M$g#POl7kU4Q0iiZ~XyZli@D9q8s| zRs64hI5n2uW{tzY-eV5=xp^W3kR>xjWXUq2MqcwYGypqYxvY&&qIgKvi#~Y~Mz2fF zZuisEr&^emd{m2!LP|3&&9pbsKV-sV0G39rERYSanzP_Gm;z03>zGzO-iKp^z zVp-XKy!9CWVmg+Tq?;&T7VE5Jqg?=SH%pDgT=^jC3R=UdefMvC6`zo~tUi04ynsfy z1-~sdGNnlVq3dkrbIt0TJ~*=LKnI%K{6T~N4`W4K$LcE$#Ke!9Jg7{aydYdKL+$X)gcasSl=8&=5A`7KifIH8J(g9mMJfGF-2neDXWML- z&iW{1-T-yHE2M^8GU6$jI=^|%)?z?^efTn$<+I|M)_dz2hnXt^wRD;yGUMOj3)F(I zk90;f+auW&hW&nU7}RV%)s_sk(K zijF5De>!YdmL{i$Dn8LFv2Ig0VE%kH%9}Lb%@MhtK)!d^{1H}SJm&0HZn~5abK41k z-~IzpV;_(1N=k?>+*)XN&QzD??!H1@v0aFbh-F6toh(G@t^rq7fqzT*(~7iw-0*++ z^qcfgG(lNOE8FjqVCiCQP5~=l)&)qN7&$sW?LWQz?W5ysB#QAwMsanFHC`n!&y}|U z@CJP?ZR#*DPSh$}Bx=bR7dU0pS~pO4mtSiM=-sGUyv=**!lX6hTIX_1ennAeRE!TJ z6)KWdN9~_y5f=HIjsjoPiT%MTsoQXzNc@?q8LY*O9l{ZdDotbpZ zT+Dx#d}@N+o;VsL(YQ2!q|sJmS!%2m&;2-Gal|v*Qd4HGDv~}wH_e9q!C3NDIN3ZK zBlk$!-cKhjPy2YZYWP!;Z^gxS*HLnr$EMikOlRz;k+qj}<8&|^K9rfNCx6$_io-=3 z4Q9M>pXkDV4>R)WL&-;tnPdK~_n3#+1>Yj3&d^OxODtE4Gh1=Ft(AwAv~hnwyE%#s zCaV>~@&wD$5=(_cDcrTp1KkC+Z)ty6pw`+NXGJ~-`Ioe}bzBs65__>l_8;R*InexY zI@&84#WG3*Hzrm-f^vrPMl?=s&UU>jZ|?q?@*&sQRmCm|o4Ex*3@>-0UpjAZGp^)>pNG)$72 zd{tFU{Y(G1@n*4yYTr;#|J@q+jCbCXkpib&hQ=wB|4wK64)1W6o{IkG34*5W2v1dY zzllH#aMSN6SW(EDE-l>HW+M27VpBZ9?eT^$Y;E`{_7gPzj127bzN zdbl}Dw?cnmA#wso8jzZT|)@Qi?b9ia9ASN@wBPPdN}L6+Y0{MngNd;w2xZTNx&&gy+NZYV^?Zrw#o zt9jx2<41@1=g-z*WWA!%|5PpAYR6;~{s?EM`*k}bw+M25WgDa#7Jkq!x|4@z$-4KV zj@IA8;!Ji2a$Hjo<03wapxyd=q9w{c3>q^XrebCAGU$@cUsbAAcpH%4=gg)<9rrz} zXCCI9*pEnN-D=xnK0-pPEhWEY*kpa`dKjd2D5jLFl~E)%HoFl zYb&zIzF4ep@t#t^uR)_KtbfU|V|y-d-H=Y}gGLy)-``ZBs;wrI)XkI&%8_OrT9R06 zq_-KRG(<2%we17y_+;V5J{7?^HanCdaK0Emy(RAaH(eZKROkamQ|E4>&Vki{m|c{LR$Ot?h>>~Z{H2i3Y_y{ zNkr~`*^^^_i=j~hD_#6J{q{OE&xy`VViezli#s&8!KVH=|2#;`E8Z@*M=|C#`78oMq$y-qHpFx#iXp#?pobS z*KU;PgS(t9TK&AIGmtffj?3dHWjOI0^@im;ImI@yR}`)5hXmaM@(m3=oz9)*Hj8ZEp?q)3 zQsOgZvh{PYL?82p+D9D9m+5~n1EINC;;$H9_evIJaUBTiRbwfM$?X*;KI$C<>sMZr zF_#nq{PL#KQ zCgIDEU(V)=6EN~?ZT`6*BBb=z%B2W-T70k4&|1G}()ab~7eQn&y?b$}iCd4fK`9*W zu8!Xkf-*-xMy&+7L+Lo*53eTGS`0n<52Sr27FW7BRNm+IM09*r!L@;9EUvuFot4^w za~iW#N_{$2S08KG$C2OVfqg@O2wHeZ8+H$qjhw&s7&x_a7)GA2x30w!+E6T1cQBMi zadv$9HM?Zvw(yQ@|8=7nE)&0yL2g;h(O$WGtF}xFfZ-4y2ocum_*Gix6<|fw@exs7 z{CKApWE1LH86d-$!&A3_^+Il-$cgHPzz65L%0u*H-*uY7f1p>i5;O!i;Rz=<9NnJD zDd99*Jwjh-|4dBQxD=X)q)V&StbT8BzaeypYfGT3e^2k)d;gQdYp~E!V4IdHx+IIP z`>EymP{jM|rU-Yd^VmvCX((=Upf6%Zh3Wt|%aPPcY?U02Sew~xbP+)hN&n;{Q|TKZ z3mY{hCh*!f%Z=E;YrZ{Mp@VgLxVTS=qgfZ);){dyyD3at4geJcfG`w+@#Q(V0ftiA zr+$D>pdAhn89@K^39iBv3O>M>0YjHOeg7<=qzG(X0RresT%>S-giw4R+LYRqy3z~q zXM4OL{8p`yMVjykj8A7Q;34bmDD+z{es9x$uS@Qkp{Fr;S@E4b+3S* z*s(I)k{{t;9j9eVDPI56AUI_~aO;mM!e?;@Gw8k_oeEMM5MrDHcVgElx>&HKCNO z#Govq7WoYqK9DRtS}wr9f}Yq7pEDUTwWh{DaSd{1e$(Xjf!2eKppOmAq5=qGA;@j5@|skdZcO~AMpLdw9-P+#sFfTJU!;6 zmcmEXb!ZmXP8)$Tn6{L;xG*Ma7&sna4P|lfPhpAZC~M}6$MDDw$IOaa5r24@4}PH6 zJ?G}7M(XIR`?aCDXRPxY3F1nI__+mDc|k+$(%@)`jSmn3OAJ+~M?px%pTtZr(VV1*#;bn=$)CRm88j7fkUXERJ!<||3?F@~ad~V1fuh8F1 zW+r|;hcelq`7fj-+Rtf$242swoxtY*Kv6OZn{lAer(y(c{LD%EfI~Bu(2gvXY$;cI zPSKgxEH-Z;Wu@cRbpXe4Q)f!#%R{& zTq|6PNgny970tMuvMwc*DcfN8^CI4Fy%=FmU(6=Pm1{l;7t#A!S%6C?zY$uX0s;|- z;?qk-{$QSCo~nKj%36(r8&SeOS@o(dVc63O6;UM0?>b+Rhns+5MJlxy!0J zsq<&QG$TpMM-OE24tU2!iFp14!5g}I{*Is51wVI9CxA4Bp4a;bjWMqHzYi`d=N~Aq z)1Rr~=$YPbZSBtbW-z??UNK$MYj{nyRr3;&^PD z|B-U`kEtea&--`IVTgU9umy}5|p!hQXg%}uWT(pyS#`>LhG9{Tp_2k;GTSXu!A z&XLo(;0v*H-p3Sy3~R(H{&nUc;%r@gu4!o<15QpX8j&F8_O0B<$OpQrrR8XjouClS zfTmkxgxCOi&$eK#Jm~7C@-J;ilZ)5Dsnc~w^{MC4#UP{f-T?2`60w3#Hht2hp!qit z0}it`v0~_()a7UGpPAl^ECj2Hg*N6Lb6HZ6kiq2?JrV
k$howPkbRp-pu*i*;Rn}!Z)glW<{8E;PBk5O z697t`b&3yNcZHWc7C1b^ho&O9GaujBRhj?5N#_JZnFj12VlLaubqDu?O|V-69kW~$ zl=9TYckrDUz77l~5uKDh$4Yq#?=t($a9r@Zp`r%D>We2=aY>EdKX}=ze;QNA3l*jBnWELw8<4sB55Q{*wyD%wtp(9!tKm)V{-0B zJ3Nen9nOL}R1}NlFIRRW?>s{)?F*YN<4kq3_4xu@3fuy~fw|d<3c}dXg1qk-Kja5M zv3GOG3JuZx0TKH|q^htyKLXLD3%6zfroR7?)ZPIA9hHC~>3quM7|Bv#B}^j%78*FR z4WO&3W5xmlGKC3P3`+oNUJN%gz77Eh8FZjO4ws?T?l*?16ifsWRR}PS_tF$zT(a&v-MJ zbRrUyhY`|mU}5_!9Rm(dgDEbLIolQBd^-94!&R3Q^bIG{wIifigRMf*jDiVPBV%r* zz}z=sd=G!IU2-N@ydD_YWJ-Uz&-8o9=MsJ$ctRz~>cjiCYEHClacnr3`0Y7^qNo{M zT<+Dx!)LF-JL$E*yb0T8CEy_5lm1=W74A96C$_%~otPY5YIvOefI>-FzGUVHllYFElc zY`UM7nsEmu6&sbiH2tmV>HjUvjPEad7D2!cAkx2zq#2ipGXOc%-fcJCo79m6ziOOD zL-`>BBKzbtbmLRF0Sp1n*e6nkFs8Kh9ckEuy7>#wjar%jI?iHG&`HsZuCw5Ct& zJHpYhMZ5NRZg$WSt7LVMnW8k2GyJp4xsS7R1?9#Dol)upK_a*wdp$Lho>;ZpL23PS zQ~lKC2k$HAIF@Z}arLl`HE6kQIT{cDrAQXj-iM{CelVUF5tnJ@iC2HC{ ze0AD=_b5_BcgUA2FfKQB+~f73ke2)WvnFTSr%RHoxNIQ7Q#0j%;z_pg>Y}Dcwkpq; zKSTz|>MfH1{?kI`o=)i<^G?-YWmCj*?d5J=?CZz!>FvnsdtRWOA#R8^euED46bdDf|E^FBP} z&9RC%k>$IQ7&isbiQEedK_F`yQF>3HR9M(vRNx=xwS8M_-W8CplT9)};fUxsNC&{R zccf~}qRGFcFP)s=M~@Z?>*Jz7NDj9<+_(!{tM)^(3 z`XWO9zUS2~&R0<|;P8zJomiLdT^{t)ZvFe6Yv-JRfr27*g{?#0&)?Z_l%~Jf<<|X* z&cEGyCxpQCVhq zq&f=VG!l(oQ)Cu55fycNA<(jDDJ`Ola7ukA;H0ii1kq2%Xe-Qt#$*upie-qjmFDt_ zW%~gK7X4_ZC`^owPxUL%0=HAd!V!eH4Ev4%jJO0yg7Sa@q*6g;7=T8dpe_P;uMtj> zh@kd}2?+lnUZwTyofI8h)5U{&rP~^AFO@KUw%` ztW*Y88gA090ab;wl6uOZSfjGQb=)}4m)NInO<2_URE%+nUZ^jrpJ}DKIes0`%BCF> zm2P0CCTM&kxvFZblv2)|zBHj@jqP(y$_}gy(}(X+B^GMXiJKLKi54cqbjYm}V`2`@ z(cc8b4mP-0C&gc`tAq$SnG%%Xk0R)58ssl>GW<(RYS!`(@i6b4@LY3W<5+nDE9=8&{{ z!TUq%&%ZIu*um|jX4&YUw>^voCe!>9`;Z9EgF405*bPVzgm}#%w2se#Da8P)x~|GY z(3t1E3g))BP5#*QfDe2{ZnJScb+Zj{ldS$I3XJvVAO=lMmrhm>dovpw#)@;&IJ_&s{SPTS7?l@LRTo;z55mJ?K71QJE7)>MD00bX9 zMLtmA=#qXaIaUT6Vguw=>K`&^tC8McS+(a*Tu>Va2OHm*ZRLZT$qUmg?6G%J;1N2% zu-6}??X1M|fHvET#@EARtmW$5OkAerobkIc`wy`7rZdr0-xMeDmc*)Pmf1u%<|xy2 z-KkLjA-$Ogx<54zWeOg3PJKsqPuND0xJiBA8iPNLUSl?N(&RZ;`S&%i9?`WTi@N-c zFMdQxGO&Jh*Y1RI+w*Bjf-p|CnJ5l_HPRJWCL!*!ejW&^610x?8QEFnZ8J%Q6MH0k zdYCla!X@J(2b{7(XR6bZ1ZERo?v1dUx}e8*Bc4QRh*e*Mlfi#XH4XEP^gkW2y3lC>fJg*E|&_T<6|)DFno{9+cMt;U9_ z3M6Bs6+1q2%w;lTL2YbWSA|Kp>=OvGeUWPy`GfT`LmBCE#4*D!`j`cq?sG&&aQ20w zIuWI}x~ru)Jz;Jcs?Cu~YwGF;)d6L?KIsnxAv>)`eVyPgA~-m|o~E|UWa_y2P%Xbb z**{j8@7Fl?XGU?;wTRo?p5~XkeRm-{837I+qT^$}XJZhg$4*9UcwDwkToC{=OV^T@ zIUJPZ${U|rv39>Sl$K{hIi(g6YP9exd<9_rp`ATN8fAaxnNnEg##^v?y zdlRYHWBWv_FnUbEAFj@wwLvd`6(Lf3&z;djN4`r+M1z}_)FTtk3U6=8M5ktlDG4IM zzJ--@r0VNm^EV_~R@Ff0?8 zDiygs!c-J0o$lYO>r4oM;oD}z?10M=0tPHh%c z`e&}mY739y+V~%e8l*E9!{taUy+N5lF&uu=?>t)j)IW)K5Ylxbom~mh#WoHck(N3m&akc^sH<8JegX;O;XWvw)@wi8T*E68JtR`jni8-A12b0 z%VciyMcG8MbI|Wcr>X1mKV<(Pqylj!0Ls%LcdfrCdQT!i*ZawO~v7HVcgo!+HDp0^xW4z>Us_HGl zJ;h=GqK$4yfg52!-D4dCBH{#Cs!ff6S3-lxF*2*#P@{S2!s?e zYu2%u)ILRKBSxD?G-V2;lVz$CJJ;eng(V5Lw2u*1yZ~a@ic1HZ=D@{|P)>Krbdx3&YDjW!|oa?w`6I7F+7Ao8r_u_oNowkA^NW!D^&zciH zL;DphC`RA{#PLe;iHMGhGjA*x5K7fP8wy+ls-vdiKxqNU@LVErxJzi$K=$sOQ(<#de7{ZkF%*^F@t71DW2!U6(HZNy z8VJX`DNHX*^2O-V_KJw_t{4CVLZu7Nzpv9ekCotqG9Xw^2EjcXu|xpOdQKKdgixpN z5V~5UgajzQBB{|e+?u1fSTOYoE|DT_KB@G~EYrE3DLw!)EaD*Yr;s9A2byJ!lm>q4 z5d950K%W((2F@I{M+g#dlOM3M{*g0*8~j^J>zE>bY0k*IVaooRp^(9*L}I{@E3#{T-Uum(_Rhq%BtBEF(yD~MA-wb4bU+RdW(dAB2Yo#K;R*v!vDbU)`0ZE^%@xP#5qr2>Kp`t7b?{q zAwR~^(3t+=Ku{X)C-MNduGITf`%JgOu|m6kurOAe8vxcf>F6b!;BhOngXdy#b(AUo zucRvvWcvUAGxwQlWRl#?nPbSAYp$hi!Ym|H<|;>ysEi~nmLn7qWA4cric%se+T2I( zb8?oWQhk0e-`{_G?|Q%9uh;YSd_A9!=kZ_wT*wOPY6@hTz;~8NrGY7eRX_j>7p8){m z`9K`O9Pm3+Gbl=~mh#|7P)ck@YHsVkhWX5{i73ixVxf2;vyBjwk6$9g!AN590=Af^ zz0C7escs1jiuk;rGmmLn7FHDxQeKkV+hLDdBKz#F?`y0g003DVFI?m`?=tf4}f}RV8iMWR!!!38tp8tI z02mKTitDk;bNjE$X_0LVkR=kPLM)m zo&Eo?S$Z<(Nmx!P$`uz&R`gu~rjLzn>j_vBSXn+>_bp5#sMWwOtFNO}Pxz{^p`aNL zAV7UtAwbwnsTT;A(*9wi0>z-`F#P zB1bo{%?hD+P+akVsr(Ukp%3%G1_guEVF?R8b|+z~CZNW-gXlXY&w<@QXKFS&98#39@Rq?CEmme~N7O)KH@@zJ9dHg_CP zf?)>B8D>|=u2>;o@hFYE@B&z45p`c%${SSk1EX;wO$_T$LhFKhFwrPu6L8`xe*bEQ z$-?V1ueKcqeDI#+2c10CAPMdaBKUUnAlWA76ez_m#9y@SQCsrR&%&F#PLvwcxRdIT znO&i_Yc?hX`ZqI4PswI907nkJk$)~OkO<_oEFAk<=^B-$bjfjlc?Z`D7 zZ}u{|um`(yXl^q4%eCE*4*e)+2S2*6>Za)4xu$^;kN6qH3~Ah4a>^4M9cKS(F0IpO zbF@5%&cJQmWbSukk2>FPhzTlk^Xomkd$5P#=fM9#%;{auEA#hVLh92o+Ha%=|Qz{LkaImqmmGQ$t08K+5^pY zWf$5jCP8;ue!o{oJ7R~dzZaY)+FLSAIfq{d^QAm|SGp{zy{Q^sTgmz+mcBNx^IJz2 zgtnE+t_cKnvhB_-u4U!kvLXzyl)FMtN_?x1FmJnmY0-{8;i5YKIc4NYRene;+1PFM z`=Xdc?to~^CUkSLuD_!Gl21{6Vn|D~-{G^VTFK@g6!>G38qIj5_8j$o@qM6gTKYZO zTqrJM{gZr=W*LrdTK6D{G5JNp-m*t`9T;qSa1Hh|>zMw+5TYl4XG9fnF|sK}?EQMi|lL!p97 z0hW^vluV2gIhf=&QCHtlyUhrs8crA4KM!C#d{{x9)0}^6mow4a+s(QUq|Mq~6^(OcEC<)m3lcF>j)>vT*#%bnNusC`J2LF~sov0ak@{kC<$5STZvhh@ zA$z_Cart_px@Y)Pf!t?w;vd5y?e3^^d+t@e2jw(6V?dHiZ6(fYHDI;*HZ)U<{ROr8 z`(B6mznod;s!K)gIBGX?a3}xsAVcQRbJ<1W71^Uf6L}kpls~A_FA_)aVY%NYSSQZc z;N&jzy^4)Xe)^*)__UJiTS9M1d&ocDp~{VkYaAw95*r-x^|(zzpY zH(^Elld3`6&cB;Aqjq|UCN)ecd`yPq8#SymU%w85ThU=3bnhuchnRwTs zn7%sTB9l^ZC1C!s7t}zAG!XOr8$N0Evra>pc%%#NZHRPJTvK`>_QTIiUjc&Qk1g7& z;XMMFhgHMNbYFb#6Tw0*o~zdzuX&xXKdf0>&2h*ruu%dWQEr<9|6-mmSC3yX|C;j0 z>Gsk~@zlhJyBFV2IV*c_LjB&{8+}nLK4MqON@SuXgxo~~EqeledrpBgm&ICD7ETl`ZI-YV!|#wglzz9A4Z{8aEw#BqH8;5I$-xbP_Jr7~+s(-t!y zYyIpx=&OGC)ja^odl61-09zT4QwiO2hDXmNxjDNx*OK4**EuW7g>yE4+{p`TV~?Az z(iHO3!u(7#&WtKI8h8}M3LML?Yx0a9s*}M;1oiR208m!pK`Mo<%zd(`Iy-#Rbc)@z;X zU04y-*Vl6QHJ17o!qU;r_>C0_3Ee5RIP~(p^sT(~yuP`b7PVs_vftgx>Y}`}FX$LF$3S zDnZ}>PTbMfy&F2#O(5qI-JL0upK&o3YG}!)2lD@vJMqpo#p=xjFgs%yzhgB84Pw-YmFDknYepYPau4xa zG`|GnOG%8+@WGKZ+1|x8q%o<8#4N?1AmAD~3~gGfIsvM}>ye7U!h z(nms|um}g2B`Wl^yY(N%kV%v3QdH1vN3VProR*vxdVyOr^XsqI*!Wf#E`~_9 z9^`PYAN1SvJ zW2*1Ng_bS4aL@Vl1t|YP(zP{k6V%ki0R?E**+-zQ^AJWj8Q|!H)GRN!5u#!Xu3li= zA4aVm5zr@}5m=Py-6_bTzt`{}>#C(tYeS_?6mlW(R(8Wp6fBhOHJ)(v2zBT{n`;l&seK^(zqqNHrh zY)&9hpO3DPS^P;Z*oNS{4p%*jRI)u3Y<+4r*LPlCfa|3!32qKCg~Q(-Th>#}OP2@y z>b)1Y$z43r&*^qH_6!kfUj==NBIXb3u5~67Qb=VJd4xObXzjb{U$PfRO;2X!d;O3V zY-UduiX_?LWG9l7%WRhPO0V{;sG$73{VpF#_X!Ye_FD9}hIub3Mf&P@#`Mn}O!gTm zPfT;>$6?N|*U=3e4nEjB>X#4iy0NLeYCIz0_!8e@QV>OD;WN{B#&voZKLSHy(d>CG zE2SN`cdWFDJiD@aV^f-_>;L?cS7Msl~zm>-l&wjrHaLwJ_)cpIYsYsa>Lb*s?F_|3PrD)TZqYJNE+Q7PMmYa?+=sAEPMQbHef1E}<=s zI zYkm>97kL%lM))dT9ZvNLAKVSwbrMDkPIFBkV>=`a;rI(Vo_>*w(%-kj$(GMDn~8c@ zb)l|-uT)tR>T=#gD2i?LNznAF(z^9M+YH9hQ#v;g@JAiaYv~@rJlkA#rM?4?6X7?H zOtUI3)!fn+5YA9yuac|&bk!qx#3=Zz&-Vy((@e*E*Z}?0_2yOiP99CBaq?`Vwv;%E z@>Q}pyUwgx-$~=~od>As1{qq9&EKhuueLg(9Jc79Z7A~j>bU&$hR$_a>$M;fT0?FF z^3Ay#ZA0YH)yWvDdVG~WlPhDYsKn(;c`BX>AwUEK_z;W8YXy-d{#0gk#{cM=e^ycR(M0qpYGD_k%t5ji zs*eGEh{r3IkN`5MWu6>cqk+%8>6XfHfL zwgop9RT9-(iq==$dtGN=khg|DPD7(aa*zJJr22mK>?%rxc`QzfWv$OdDf*M#w*c-` z5@$q&VX(VmSPbf%{gHa$^oyVaVW9w8SuztRA~7!N>=?=;jO+GmnG|_Y%-mqceuheZ zS2=46{u#l!YUhh6E8U0{SDbi+!I^kc>ckQB-#iA`T`IYn+xGzYbP2ix(sE(OB(Ai2 z*!fR^!drP;RC0Tw0iSz6#))(-(%=~#=7d?+c$W;`A6SvL!gJ#h<&-6}+&Yj?{DRGz zNKG5&EMlT88rY)AcTghAS2T#=tJOUEj7Tz~AdlM@LCwUFST-n;Ll7gMqxn?w{ZP0# TTXn<=03uc%zPs=J-^l*~`V6tQ literal 0 HcmV?d00001 diff --git a/unused/newctime.3 b/unused/newctime.3 new file mode 100644 index 00000000000..323201e0c50 --- /dev/null +++ b/unused/newctime.3 @@ -0,0 +1,239 @@ +.TH NEWCTIME 3 +.SH NAME +asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time to ASCII +.SH SYNOPSIS +.nf +.B extern char *tzname[2]; +.PP +.B void tzset() +.PP +.B #include +.PP +.B char *ctime(clock) +.B const time_t *clock; +.PP +.B double difftime(time1, time0) +.B time_t time1; +.B time_t time0; +.PP +.B #include +.PP +.B char *asctime(tm) +.B const struct tm *tm; +.PP +.B struct tm *localtime(clock) +.B const time_t *clock; +.PP +.B struct tm *gmtime(clock) +.B const time_t *clock; +.PP +.B time_t mktime(tm) +.B struct tm *tm; +.PP +.B cc ... -ltz +.fi +.SH DESCRIPTION +.I Ctime\^ +converts a long integer, pointed to by +.IR clock , +representing the time in seconds since +00:00:00 UTC, 1970-01-01, +and returns a pointer to a +string of the form +.br +.ce +.eo +Thu Nov 24 18:22:48 1986\n\0 +.br +.ec +Years requiring fewer than four characters are padded with leading zeroes. +For years longer than four characters, the string is of the form +.br +.ce +.eo +Thu Nov 24 18:22:48 81986\n\0 +.ec +.br +with five spaces before the year. +These unusual formats are designed to make it less likely that older +software that expects exactly 26 bytes of output will mistakenly output +misleading values for out-of-range years. +.PP +.I Localtime\^ +and +.I gmtime\^ +return pointers to ``tm'' structures, described below. +.I Localtime\^ +corrects for the time zone and any time zone adjustments +(such as Daylight Saving Time in the United States). +After filling in the ``tm'' structure, +.I localtime +sets the +.BR tm_isdst 'th +element of +.B tzname +to a pointer to an +ASCII string that's the time zone abbreviation to be used with +.IR localtime 's +return value. +.PP +.I Gmtime\^ +converts to Coordinated Universal Time. +.PP +.I Asctime\^ +converts a time value contained in a +``tm'' structure to a string, +as shown in the above example, +and returns a pointer to the string. +.PP +.I Mktime\^ +converts the broken-down time, +expressed as local time, +in the structure pointed to by +.I tm +into a calendar time value with the same encoding as that of the values +returned by the +.I time +function. +The original values of the +.B tm_wday +and +.B tm_yday +components of the structure are ignored, +and the original values of the other components are not restricted +to their normal ranges. +(A positive or zero value for +.B tm_isdst +causes +.I mktime +to presume initially that summer time (for example, Daylight Saving Time +in the U.S.A.) +respectively, +is or is not in effect for the specified time. +A negative value for +.B tm_isdst +causes the +.I mktime +function to attempt to divine whether summer time is in effect +for the specified time; in this case it does not use a consistent +rule and may give a different answer when later +presented with the same argument.) +On successful completion, the values of the +.B tm_wday +and +.B tm_yday +components of the structure are set appropriately, +and the other components are set to represent the specified calendar time, +but with their values forced to their normal ranges; the final value of +.B tm_mday +is not set until +.B tm_mon +and +.B tm_year +are determined. +.I Mktime\^ +returns the specified calendar time; +If the calendar time cannot be represented, +it returns +.BR -1 . +.PP +.I Difftime\^ +returns the difference between two calendar times, +.RI ( time1 +- +.IR time0 ), +expressed in seconds. +.PP +Declarations of all the functions and externals, and the ``tm'' structure, +are in the +.B \^ +header file. +The structure (of type) +.B struct tm +includes the following fields: +.RS +.PP +.nf +.ta .5i +\w'long tm_gmtoff;\0\0'u + int tm_sec; /\(** seconds (0 - 60) \(**/ + int tm_min; /\(** minutes (0 - 59) \(**/ + int tm_hour; /\(** hours (0 - 23) \(**/ + int tm_mday; /\(** day of month (1 - 31) \(**/ + int tm_mon; /\(** month of year (0 - 11) \(**/ + int tm_year; /\(** year \- 1900 \(**/ + int tm_wday; /\(** day of week (Sunday = 0) \(**/ + int tm_yday; /\(** day of year (0 - 365) \(**/ + int tm_isdst; /\(** is summer time in effect? \(**/ + char \(**tm_zone; /\(** abbreviation of timezone name \(**/ + long tm_gmtoff; /\(** offset from UTC in seconds \(**/ +.fi +.RE +.PP +The +.I tm_zone +and +.I tm_gmtoff +fields exist, and are filled in, only if arrangements to do +so were made when the library containing these functions was +created. +There is no guarantee that these fields will continue to exist +in this form in future releases of this code. +.PP +.I Tm_isdst\^ +is non-zero if summer time is in effect. +.PP +.I Tm_gmtoff +is the offset (in seconds) of the time represented +from UTC, with positive values indicating east +of the Prime Meridian. +.SH FILES +.ta \w'/usr/local/etc/zoneinfo/posixrules\0\0'u +/usr/local/etc/zoneinfo time zone information directory +.br +/usr/local/etc/zoneinfo/localtime local time zone file +.br +/usr/local/etc/zoneinfo/posixrules used with POSIX-style TZ's +.br +/usr/local/etc/zoneinfo/GMT for UTC leap seconds +.sp +If +.B /usr/local/etc/zoneinfo/GMT +is absent, +UTC leap seconds are loaded from +.BR /usr/local/etc/zoneinfo/posixrules . +.SH SEE ALSO +getenv(3), +newstrftime(3), +newtzset(3), +time(2), +tzfile(5) +.SH NOTES +The return values point to static data; +the data is overwritten by each call. +The +.B tm_zone +field of a returned +.B "struct tm" +points to a static array of characters, which +will also be overwritten at the next call +(and by calls to +.IR tzset ). +.PP +.I Asctime\^ +and +.I ctime\^ +behave strangely for years before 1000 or after 9999. +The 1989 and 1999 editions of the C Standard say +that years from \-99 through 999 are converted without +extra spaces, but this conflicts with longstanding +tradition and with this implementation. +Traditional implementations of these two functions are +restricted to years in the range 1900 through 2099. +To avoid this portability mess, new programs should use +.I strftime\^ +instead. +.PP +Avoid using out-of-range values with +.I mktime +when setting up lunch with promptness sticklers in Riyadh. +.\" @(#)newctime.3 8.2 diff --git a/unused/newctime.3.txt b/unused/newctime.3.txt new file mode 100644 index 00000000000..ba311400474 --- /dev/null +++ b/unused/newctime.3.txt @@ -0,0 +1,149 @@ +NAME + + asctime, ctime, difftime, gmtime, localtime, mktime - + convert date and time to ASCII + +SYNOPSIS + extern char *tzname[2]; + + void tzset() + + #include + + char *ctime(clock) + const time_t *clock; + + double difftime(time1, time0) + time_t time1; + time_t time0; + + #include + + char *asctime(tm) + const struct tm *tm; + + struct tm *localtime(clock) + const time_t *clock; + + struct tm *gmtime(clock) + const time_t *clock; + + time_t mktime(tm) + struct tm *tm; + + cc ... -ltz + +DESCRIPTION + Ctime converts a long integer, pointed to by clock, + representing the time in seconds since 00:00:00 UTC, + 1970-01-01, and returns a pointer to a string of the form + Thu Nov 24 18:22:48 1986\n\0 + Years requiring fewer than four characters are padded with + leading zeroes. For years longer than four characters, the + string is of the form + Thu Nov 24 18:22:48 81986\n\0 + with five spaces before the year. These unusual formats are + designed to make it less likely that older software that + expects exactly 26 bytes of output will mistakenly output + misleading values for out-of-range years. + + Localtime and gmtime return pointers to ``tm'' structures, + described below. Localtime corrects for the time zone and + any time zone adjustments (such as Daylight Saving Time in + the United States). After filling in the ``tm'' structure, + localtime sets the tm_isdst'th element of tzname to a + pointer to an ASCII string that's the time zone abbreviation + to be used with localtime's return value. + + Gmtime converts to Coordinated Universal Time. + + Asctime converts a time value contained in a ``tm'' + structure to a string, as shown in the above example, and + returns a pointer to the string. + + Mktime converts the broken-down time, expressed as local + time, in the structure pointed to by tm into a calendar time + value with the same encoding as that of the values returned + by the time function. The original values of the tm_wday + and tm_yday components of the structure are ignored, and the + original values of the other components are not restricted + to their normal ranges. (A positive or zero value for + tm_isdst causes mktime to presume initially that summer time + (for example, Daylight Saving Time in the U.S.A.) + respectively, is or is not in effect for the specified time. + A negative value for tm_isdst causes the mktime function to + attempt to divine whether summer time is in effect for the + specified time; in this case it does not use a consistent + rule and may give a different answer when later presented + with the same argument.) On successful completion, the + values of the tm_wday and tm_yday components of the + structure are set appropriately, and the other components + are set to represent the specified calendar time, but with + their values forced to their normal ranges; the final value + of tm_mday is not set until tm_mon and tm_year are + determined. Mktime returns the specified calendar time; If + the calendar time cannot be represented, it returns -1. + + Difftime returns the difference between two calendar times, + (time1 - time0), expressed in seconds. + + Declarations of all the functions and externals, and the + ``tm'' structure, are in the header file. The + structure (of type) struct tm includes the following fields: + + int tm_sec; /* seconds (0 - 60) */ + int tm_min; /* minutes (0 - 59) */ + int tm_hour; /* hours (0 - 23) */ + int tm_mday; /* day of month (1 - 31) */ + int tm_mon; /* month of year (0 - 11) */ + int tm_year; /* year - 1900 */ + int tm_wday; /* day of week (Sunday = 0) */ + int tm_yday; /* day of year (0 - 365) */ + int tm_isdst; /* is summer time in effect? */ + char *tm_zone; /* abbreviation of timezone name */ + long tm_gmtoff; /* offset from UTC in seconds */ + + The tm_zone and tm_gmtoff fields exist, and are filled in, + only if arrangements to do so were made when the library + containing these functions was created. There is no + guarantee that these fields will continue to exist in this + form in future releases of this code. + + Tm_isdst is non-zero if summer time is in effect. + + Tm_gmtoff is the offset (in seconds) of the time represented + from UTC, with positive values indicating east of the Prime + Meridian. + +FILES + /usr/local/etc/zoneinfo time zone information + directory + /usr/local/etc/zoneinfo/localtime local time zone file + /usr/local/etc/zoneinfo/posixrules used with POSIX-style + TZ's + /usr/local/etc/zoneinfo/GMT for UTC leap seconds + + If /usr/local/etc/zoneinfo/GMT is absent, UTC leap seconds + are loaded from /usr/local/etc/zoneinfo/posixrules. + +SEE ALSO + getenv(3), newstrftime(3), newtzset(3), time(2), tzfile(5) + +NOTES + The return values point to static data; the data is + overwritten by each call. The tm_zone field of a returned + struct tm points to a static array of characters, which will + also be overwritten at the next call (and by calls to + tzset). + + Asctime and ctime behave strangely for years before 1000 or + after 9999. The 1989 and 1999 editions of the C Standard + say that years from -99 through 999 are converted without + extra spaces, but this conflicts with longstanding tradition + and with this implementation. Traditional implementations + of these two functions are restricted to years in the range + 1900 through 2099. To avoid this portability mess, new + programs should use strftime instead. + + Avoid using out-of-range values with mktime when setting up + lunch with promptness sticklers in Riyadh. diff --git a/unused/newstrftime.3 b/unused/newstrftime.3 new file mode 100644 index 00000000000..92392dcc326 --- /dev/null +++ b/unused/newstrftime.3 @@ -0,0 +1,230 @@ +.\" Based on the UCB file whose copyright information appears below. +.\" Copyright (c) 1989, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the American National Standards Committee X3, on Information +.\" Processing Systems. +.\" +.\" 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 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. +.\" +.\" from: @(#)strftime.3 5.12 (Berkeley) 6/29/91 +.\" $Id: strftime.3,v 1.4 1993/12/15 20:33:00 jtc Exp $ +.\" +.TH NEWSTRFTIME 3 +.SH NAME +strftime \- format date and time +.SH SYNOPSIS +.nf +.B #include +.B #include +.PP +.B size_t strftime(buf, maxsize, format, timeptr) +.B char *buf; +.B size_t maxsize; +.B const char *format; +.B const struct tm *timeptr +.PP +.B cc ... -ltz +.fi +.SH DESCRIPTION +The +.I strftime\^ +function formats the information from +.I timeptr\^ +into the buffer +.I buf\^ +according to the string pointed to by +.IR format\^ . +.PP +The +.I format\^ +string consists of zero or more conversion specifications and +ordinary characters. +All ordinary characters are copied directly into the buffer. +A conversion specification consists of a percent sign +.Ql % +and one other character. +.PP +No more than +.I maxsize\^ +characters are be placed into the array. +If the total number of resulting characters, including the terminating +null character, is not more than +.IR maxsize\^ , +.I strftime\^ +returns the number of characters in the array, not counting the +terminating null. +Otherwise, zero is returned. +.PP +Each conversion specification is replaced by the characters as +follows which are then copied into the buffer. +.TP +%A +is replaced by the locale's full weekday name. +.TP +%a +is replaced by the locale's abbreviated weekday name. +.TP +%B +is replaced by the locale's full month name. +.TP +%b or %h +is replaced by the locale's abbreviated month name. +.TP +%C +is replaced by the century (a year divided by 100 and truncated to an integer) +as a decimal number (00-99). +.TP +%c +is replaced by the locale's appropriate date and time representation. +.TP +%D +is replaced by the date in the format %m/%d/%y. +.TP +%d +is replaced by the day of the month as a decimal number (01-31). +.TP +%e +is replaced by the day of month as a decimal number (1-31); +single digits are preceded by a blank. +.TP +%F +is replaced by the date in the format %Y-%m-%d. +.TP +%G +is replaced by the ISO 8601 year with century as a decimal number. +.TP +%g +is replaced by the ISO 8601 year without century as a decimal number (00-99). +.TP +%H +is replaced by the hour (24-hour clock) as a decimal number (00-23). +.TP +%I +is replaced by the hour (12-hour clock) as a decimal number (01-12). +.TP +%j +is replaced by the day of the year as a decimal number (001-366). +.TP +%k +is replaced by the hour (24-hour clock) as a decimal number (0-23); +single digits are preceded by a blank. +.TP +%l +is replaced by the hour (12-hour clock) as a decimal number (1-12); +single digits are preceded by a blank. +.TP +%M +is replaced by the minute as a decimal number (00-59). +.TP +%m +is replaced by the month as a decimal number (01-12). +.TP +%n +is replaced by a newline. +.TP +%p +is replaced by the locale's equivalent of either AM or PM. +.TP +%R +is replaced by the time in the format %H:%M. +.TP +%r +is replaced by the locale's representation of 12-hour clock time +using AM/PM notation. +.TP +%S +is replaced by the second as a decimal number (00-60). +.TP +%s +is replaced by the number of seconds since the Epoch, UTC (see mktime(3)). +.TP +%T +is replaced by the time in the format %H:%M:%S. +.TP +%t +is replaced by a tab. +.TP +%U +is replaced by the week number of the year (Sunday as the first day of +the week) as a decimal number (00-53). +.TP +%u +is replaced by the weekday (Monday as the first day of the week) +as a decimal number (1-7). +.TP +%V +is replaced by the week number of the year (Monday as the first day of +the week) as a decimal number (01-53). If the week containing January +1 has four or more days in the new year, then it is week 1; otherwise +it is week 53 of the previous year, and the next week is week 1. +.TP +%W +is replaced by the week number of the year (Monday as the first day of +the week) as a decimal number (00-53). +.TP +%w +is replaced by the weekday (Sunday as the first day of the week) +as a decimal number (0-6). +.TP +%X +is replaced by the locale's appropriate time representation. +.TP +%x +is replaced by the locale's appropriate date representation. +.TP +%Y +is replaced by the year with century as a decimal number. +.TP +%y +is replaced by the year without century as a decimal number (00-99). +.TP +%Z +is replaced by the time zone name, +or by the empty string if this is not determinable. +.TP +%z +is replaced by the offset from UTC in the format +HHMM or -HHMM as appropriate, +with positive values representing locations east of Greenwich, +or by the empty string if this is not determinable. +.TP +%% +is replaced by a single %. +.TP +%+ +is replaced by the date and time in date(1) format. +.SH SEE ALSO +date(1), +getenv(3), +newctime(3), +newtzset(3), +time(2), +tzfile(5) +.\" @(#)newstrftime.3 8.1 diff --git a/unused/newstrftime.3.txt b/unused/newstrftime.3.txt new file mode 100644 index 00000000000..ea210a869f4 --- /dev/null +++ b/unused/newstrftime.3.txt @@ -0,0 +1,149 @@ +NAME + + strftime - format date and time + +SYNOPSIS + #include + #include + + size_t strftime(buf, maxsize, format, timeptr) + char *buf; + size_t maxsize; + const char *format; + const struct tm *timeptr + + cc ... -ltz + +DESCRIPTION + The strftime function formats the information from timeptr + into the buffer buf according to the string pointed to by + format. + + The format string consists of zero or more conversion + specifications and ordinary characters. All ordinary + characters are copied directly into the buffer. A + conversion specification consists of a percent sign and one + other character. + + No more than maxsize characters are be placed into the + array. If the total number of resulting characters, + including the terminating null character, is not more than + maxsize, strftime returns the number of characters in the + array, not counting the terminating null. Otherwise, zero + is returned. + + Each conversion specification is replaced by the characters + as follows which are then copied into the buffer. + + %A is replaced by the locale's full weekday name. + + %a is replaced by the locale's abbreviated weekday name. + + %B is replaced by the locale's full month name. + + %b or %h + is replaced by the locale's abbreviated month name. + + %C is replaced by the century (a year divided by 100 and + truncated to an integer) as a decimal number (00-99). + + %c is replaced by the locale's appropriate date and time + representation. + + %D is replaced by the date in the format %m/%d/%y. + + %d is replaced by the day of the month as a decimal number + (01-31). + + %e is replaced by the day of month as a decimal number + (1-31); single digits are preceded by a blank. + %F is replaced by the date in the format %Y-%m-%d. + + %G is replaced by the ISO 8601 year with century as a + decimal number. + + %g is replaced by the ISO 8601 year without century as a + decimal number (00-99). + %H is replaced by the hour (24-hour clock) as a decimal + number (00-23). + + %I is replaced by the hour (12-hour clock) as a decimal + number (01-12). + + %j is replaced by the day of the year as a decimal number + (001-366). + + %k is replaced by the hour (24-hour clock) as a decimal + number (0-23); single digits are preceded by a blank. + + %l is replaced by the hour (12-hour clock) as a decimal + number (1-12); single digits are preceded by a blank. + + %M is replaced by the minute as a decimal number (00-59). + + %m is replaced by the month as a decimal number (01-12). + + %n is replaced by a newline. + + %p is replaced by the locale's equivalent of either AM or + PM. + + %R is replaced by the time in the format %H:%M. + + %r is replaced by the locale's representation of 12-hour + clock time using AM/PM notation. + + %S is replaced by the second as a decimal number (00-60). + + %s is replaced by the number of seconds since the Epoch, + UTC (see mktime(3)). + + %T is replaced by the time in the format %H:%M:%S. + + %t is replaced by a tab. + + %U is replaced by the week number of the year (Sunday as + the first day of the week) as a decimal number (00-53). + + %u is replaced by the weekday (Monday as the first day of + the week) as a decimal number (1-7). + + %V is replaced by the week number of the year (Monday as + the first day of the week) as a decimal number (01-53). + If the week containing January 1 has four or more days + in the new year, then it is week 1; otherwise it is + week 53 of the previous year, and the next week is week + 1. + + %W is replaced by the week number of the year (Monday as + the first day of the week) as a decimal number (00-53). + + %w is replaced by the weekday (Sunday as the first day of + the week) as a decimal number (0-6). + + %X is replaced by the locale's appropriate time + representation. + %x is replaced by the locale's appropriate date + representation. + + %Y is replaced by the year with century as a decimal + number. + + %y is replaced by the year without century as a decimal + number (00-99). + + %Z is replaced by the time zone name, or by the empty + string if this is not determinable. + + %z is replaced by the offset from UTC in the format +HHMM + or -HHMM as appropriate, with positive values + representing locations east of Greenwich, or by the + empty string if this is not determinable. + + %% is replaced by a single %. + + %+ is replaced by the date and time in date(1) format. + +SEE ALSO + date(1), getenv(3), newctime(3), newtzset(3), time(2), + tzfile(5) diff --git a/unused/newtzset.3 b/unused/newtzset.3 new file mode 100644 index 00000000000..e19ad7033e1 --- /dev/null +++ b/unused/newtzset.3 @@ -0,0 +1,237 @@ +.TH NEWTZSET 3 +.SH NAME +tzset \- initialize time conversion information +.SH SYNOPSIS +.nf +.B void tzset() +.PP +.B cc ... -ltz +.fi +.SH DESCRIPTION +.I Tzset +uses the value of the environment variable +.B TZ +to set time conversion information used by +.IR localtime . +If +.B TZ +does not appear in the environment, +the best available approximation to local wall clock time, as specified +by the +.IR tzfile (5)-format +file +.B localtime +in the system time conversion information directory, is used by +.IR localtime . +If +.B TZ +appears in the environment but its value is a null string, +Coordinated Universal Time (UTC) is used (without leap second +correction). If +.B TZ +appears in the environment and its value is not a null string: +.IP +if the value begins with a colon, it is used as a pathname of a file +from which to read the time conversion information; +.IP +if the value does not begin with a colon, it is first used as the +pathname of a file from which to read the time conversion information, +and, if that file cannot be read, is used directly as a specification of +the time conversion information. +.PP +When +.B TZ +is used as a pathname, if it begins with a slash, +it is used as an absolute pathname; otherwise, +it is used as a pathname relative to a system time conversion information +directory. +The file must be in the format specified in +.IR tzfile (5). +.PP +When +.B TZ +is used directly as a specification of the time conversion information, +it must have the following syntax (spaces inserted for clarity): +.IP +\fIstd\|offset\fR[\fIdst\fR[\fIoffset\fR][\fB,\fIrule\fR]] +.PP +Where: +.RS +.TP 15 +.IR std " and " dst +Three or more bytes that are the designation for the standard +.RI ( std ) +or summer +.RI ( dst ) +time zone. Only +.I std +is required; if +.I dst +is missing, then summer time does not apply in this locale. +Upper- and lowercase letters are explicitly allowed. Any characters +except a leading colon +.RB ( : ), +digits, comma +.RB ( , ), +minus +.RB ( \(mi ), +plus +.RB ( \(pl ), +and ASCII NUL are allowed. +.TP +.I offset +Indicates the value one must add to the local time to arrive at +Coordinated Universal Time. The +.I offset +has the form: +.RS +.IP +\fIhh\fR[\fB:\fImm\fR[\fB:\fIss\fR]] +.RE +.IP +The minutes +.RI ( mm ) +and seconds +.RI ( ss ) +are optional. The hour +.RI ( hh ) +is required and may be a single digit. The +.I offset +following +.I std +is required. If no +.I offset +follows +.IR dst , +summer time is assumed to be one hour ahead of standard time. One or +more digits may be used; the value is always interpreted as a decimal +number. The hour must be between zero and 24, and the minutes (and +seconds) \(em if present \(em between zero and 59. If preceded by a +.RB `` \(mi '', +the time zone shall be east of the Prime Meridian; otherwise it shall be +west (which may be indicated by an optional preceding +.RB `` \(pl ''). +.TP +.I rule +Indicates when to change to and back from summer time. The +.I rule +has the form: +.RS +.IP +\fIdate\fB/\fItime\fB,\fIdate\fB/\fItime\fR +.RE +.IP +where the first +.I date +describes when the change from standard to summer time occurs and the +second +.I date +describes when the change back happens. Each +.I time +field describes when, in current local time, the change to the other +time is made. +.IP +The format of +.I date +is one of the following: +.RS +.TP 10 +.BI J n +The Julian day +.I n +.RI "(1\ \(<=" "\ n\ " "\(<=\ 365). +Leap days are not counted; that is, in all years \(em including leap +years \(em February 28 is day 59 and March 1 is day 60. It is +impossible to explicitly refer to the occasional February 29. +.TP +.I n +The zero-based Julian day +.RI "(0\ \(<=" "\ n\ " "\(<=\ 365). +Leap days are counted, and it is possible to refer to February 29. +.TP +.BI M m . n . d +The +.IR d' th +day +.RI "(0\ \(<=" "\ d\ " "\(<=\ 6) +of week +.I n +of month +.I m +of the year +.RI "(1\ \(<=" "\ n\ " "\(<=\ 5, +.RI "1\ \(<=" "\ m\ " "\(<=\ 12, +where week 5 means ``the last +.I d +day in month +.IR m '' +which may occur in either the fourth or the fifth week). Week 1 is the +first week in which the +.IR d' th +day occurs. Day zero is Sunday. +.RE +.IP "" 15 +The +.I time +has the same format as +.I offset +except that no leading sign +.RB (`` \(mi '' +or +.RB `` \(pl '') +is allowed. The default, if +.I time +is not given, is +.BR 02:00:00 . +.RE +.LP +If no +.I rule +is present in +.BR TZ , +the rules specified +by the +.IR tzfile (5)-format +file +.B posixrules +in the system time conversion information directory are used, with the +standard and summer time offsets from UTC replaced by those specified by +the +.I offset +values in +.BR TZ . +.PP +For compatibility with System V Release 3.1, a semicolon +.RB ( ; ) +may be used to separate the +.I rule +from the rest of the specification. +.PP +If the +.B TZ +environment variable does not specify a +.IR tzfile (5)-format +and cannot be interpreted as a direct specification, +UTC is used. +.SH FILES +.ta \w'/usr/local/etc/zoneinfo/posixrules\0\0'u +/usr/local/etc/zoneinfo time zone information directory +.br +/usr/local/etc/zoneinfo/localtime local time zone file +.br +/usr/local/etc/zoneinfo/posixrules used with POSIX-style TZ's +.br +/usr/local/etc/zoneinfo/GMT for UTC leap seconds +.sp +If +.B /usr/local/etc/zoneinfo/GMT +is absent, +UTC leap seconds are loaded from +.BR /usr/local/etc/zoneinfo/posixrules . +.SH SEE ALSO +getenv(3), +newctime(3), +newstrftime(3), +time(2), +tzfile(5) +.\" @(#)newtzset.3 8.1 diff --git a/unused/newtzset.3.txt b/unused/newtzset.3.txt new file mode 100644 index 00000000000..9d7d02233ee --- /dev/null +++ b/unused/newtzset.3.txt @@ -0,0 +1,153 @@ +NAME + + tzset - initialize time conversion information + +SYNOPSIS + void tzset() + + cc ... -ltz + +DESCRIPTION + Tzset uses the value of the environment variable TZ to set + time conversion information used by localtime. If TZ does + not appear in the environment, the best available + approximation to local wall clock time, as specified by the + tzfile(5)-format file localtime in the system time + conversion information directory, is used by localtime. If + TZ appears in the environment but its value is a null + string, Coordinated Universal Time (UTC) is used (without + leap second correction). If TZ appears in the environment + and its value is not a null string: + + if the value begins with a colon, it is used as a + pathname of a file from which to read the time + conversion information; + + if the value does not begin with a colon, it is first + used as the pathname of a file from which to read the + time conversion information, and, if that file cannot + be read, is used directly as a specification of the + time conversion information. + + When TZ is used as a pathname, if it begins with a slash, it + is used as an absolute pathname; otherwise, it is used as a + pathname relative to a system time conversion information + directory. The file must be in the format specified in + tzfile(5). + + When TZ is used directly as a specification of the time + conversion information, it must have the following syntax + (spaces inserted for clarity): + + stdoffset[dst[offset][,rule]] + + Where: + + std and dst Three or more bytes that are the + designation for the standard (std) or + summer (dst) time zone. Only std is + required; if dst is missing, then summer + time does not apply in this locale. + Upper- and lowercase letters are + explicitly allowed. Any characters + except a leading colon (:), digits, + comma (,), minus (-), plus (+), and + ASCII NUL are allowed. + + offset Indicates the value one must add to the + local time to arrive at Coordinated + Universal Time. The offset has the + form: + + hh[:mm[:ss]] + + The minutes (mm) and seconds (ss) are + optional. The hour (hh) is required and + may be a single digit. The offset + following std is required. If no offset + follows dst, summer time is assumed to + be one hour ahead of standard time. One + or more digits may be used; the value is + always interpreted as a decimal number. + The hour must be between zero and 24, + and the minutes (and seconds) -- if + present -- between zero and 59. If + preceded by a ``-'', the time zone shall + be east of the Prime Meridian; otherwise + it shall be west (which may be indicated + by an optional preceding ``+''). + + rule Indicates when to change to and back + from summer time. The rule has the + form: + + date/time,date/time + + where the first date describes when the + change from standard to summer time + occurs and the second date describes + when the change back happens. Each time + field describes when, in current local + time, the change to the other time is + made. + + The format of date is one of the + following: + + Jn The Julian day n + (1 <= n <= 365). Leap days + are not counted; that is, in + all years -- including leap + years -- February 28 is day 59 + and March 1 is day 60. It is + impossible to explicitly refer + to the occasional February 29. + + n The zero-based Julian day + (0 <= n <= 365). Leap days + are counted, and it is + possible to refer to February + 29. + + Mm.n.d The d'th day (0 <= d <= 6) of + week n of month m of the year + (1 <= n <= 5, 1 <= m <= 12, + where week 5 means ``the last + d day in month m'' which may + occur in either the fourth or + the fifth week). Week 1 is + the first week in which the + d'th day occurs. Day zero is + Sunday. + + The time has the same format as offset + except that no leading sign (``-'' or + ``+'') is allowed. The default, if time + is not given, is 02:00:00. + + If no rule is present in TZ, the rules specified by the + tzfile(5)-format file posixrules in the system time + conversion information directory are used, with the standard + and summer time offsets from UTC replaced by those specified + by the offset values in TZ. + For compatibility with System V Release 3.1, a semicolon (;) + may be used to separate the rule from the rest of the + specification. + + If the TZ environment variable does not specify a + tzfile(5)-format and cannot be interpreted as a direct + specification, UTC is used. + +FILES + /usr/local/etc/zoneinfo time zone information + directory + /usr/local/etc/zoneinfo/localtime local time zone file + /usr/local/etc/zoneinfo/posixrules used with POSIX-style + TZ's + /usr/local/etc/zoneinfo/GMT for UTC leap seconds + + If /usr/local/etc/zoneinfo/GMT is absent, UTC leap seconds + are loaded from /usr/local/etc/zoneinfo/posixrules. + +SEE ALSO + getenv(3), newctime(3), newstrftime(3), time(2), tzfile(5) diff --git a/unused/time2posix.3.txt b/unused/time2posix.3.txt new file mode 100644 index 00000000000..1bcf168e2e6 --- /dev/null +++ b/unused/time2posix.3.txt @@ -0,0 +1,83 @@ +NAME + + time2posix, posix2time - convert seconds since the Epoch + +SYNOPSIS + #include + #include + + time_t time2posix(t) + time_t t + + time_t posix2time(t) + time_t t + + cc ... -ltz + +DESCRIPTION + IEEE Standard 1003.1 (POSIX) legislates that a time_t value + of 536457599 shall correspond to "Wed Dec 31 23:59:59 UTC + 1986." This effectively implies that POSIX time_t's cannot + include leap seconds and, therefore, that the system time + must be adjusted as each leap occurs. + + If the time package is configured with leap-second support + enabled, however, no such adjustment is needed and time_t + values continue to increase over leap events (as a true + `seconds since...' value). This means that these values + will differ from those required by POSIX by the net number + of leap seconds inserted since the Epoch. + + Typically this is not a problem as the type time_t is + intended to be (mostly) opaque--time_t values should only be + obtained-from and passed-to functions such as time(2), + localtime(3), mktime(3), and difftime(3). However, POSIX + gives an arithmetic expression for directly computing a + time_t value from a given date/time, and the same + relationship is assumed by some (usually older) + applications. Any programs creating/dissecting time_t's + using such a relationship will typically not handle + intervals over leap seconds correctly. + + The time2posix and posix2time functions are provided to + address this time_t mismatch by converting between local + time_t values and their POSIX equivalents. This is done by + accounting for the number of time-base changes that would + have taken place on a POSIX system as leap seconds were + inserted or deleted. These converted values can then be + used in lieu of correcting the older applications, or when + communicating with POSIX-compliant systems. + + Time2posix is single-valued. That is, every local time_t + corresponds to a single POSIX time_t. Posix2time is less + well-behaved: for a positive leap second hit the result is + not unique, and for a negative leap second hit the + corresponding POSIX time_t doesn't exist so an adjacent + value is returned. Both of these are good indicators of the + inferiority of the POSIX representation. + + The following table summarizes the relationship between a + time T and it's conversion to, and back from, the POSIX + representation over the leap second inserted at the end of + June, 1993. + DATE TIME T X=time2posix(T) posix2time(X) + 93/06/30 23:59:59 A+0 B+0 A+0 + 93/06/30 23:59:60 A+1 B+1 A+1 or A+2 + 93/07/01 00:00:00 A+2 B+1 A+1 or A+2 + 93/07/01 00:00:01 A+3 B+2 A+3 + + A leap second deletion would look like... + + DATE TIME T X=time2posix(T) posix2time(X) + ??/06/30 23:59:58 A+0 B+0 A+0 + ??/07/01 00:00:00 A+1 B+2 A+1 + ??/07/01 00:00:01 A+2 B+3 A+2 + + [Note: posix2time(B+1) => A+0 or A+1] + + If leap-second support is not enabled, local time_t's and + POSIX time_t's are equivalent, and both time2posix and + posix2time degenerate to the identity function. + +SEE ALSO + difftime(3), localtime(3), mktime(3), time(2) diff --git a/zic/tz-art.htm b/unused/tz-art.htm similarity index 65% rename from zic/tz-art.htm rename to unused/tz-art.htm index 56f78ace2e0..352c408b66c 100644 --- a/zic/tz-art.htm +++ b/unused/tz-art.htm @@ -1,23 +1,22 @@ - - - + + - + Time and the Arts

Time and the Arts

-@(#)tz-art.htm 7.53 +@(#)tz-art.htm 8.11

Please send corrections to this web page to the time zone mailing list.

See also Sources for Time Zone and Daylight Saving Time Data.

-
+

Data on recordings of "Save That Time," Russ Long, Serrob Publishing, BMI:

@@ -83,7 +82,7 @@ Marion Simon, percussion
AMG Ratingunrated
Penguin Rating3 stars
-
+

Also of note:

@@ -160,6 +159,99 @@ Richard Teitelbaum, modular moog and micromoog synthesizer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -173,13 +265,40 @@ is available at http://fourmilab.ch/etexts/www/tdm80j An on-line English-language translation of the book is available at http://www.literature.org/Works/Jules-Verne/eighty + + + + + + + + + + + + + + + - +
ArtistHolly Cole Trio
ADO Ratingblack dot
AMG Ratingunrated
 
ArtistCharles Gayle
CDTime Zones
Copyright Date2006
LabelTompkins Square
IDTSQ2839
Total Time49:06
PersonnelCharles Gayle, piano
ADO Rating1 star
AMG Rating4.5 stars
 
ArtistThe Get Up Kids
CDEudora
Copyright Date2001
LabelVagrant
ID357
Total Time65:12
NotesIncludes the song "Central Standard Time." Thanks to Colin Bowern for this information.
AMG Rating2.5 stars
 
ArtistColdplay
SongClocks
Copyright Date2003
LabelCapitol Records
ID52608
Total Time4:13
NotesWon the 2004 Record of the Year honor at the +Grammy Awards. Co-written and performed by Chris Martin, +great-great-grandson of DST inventor William Willett. The song's first +line is "Lights go out and I can't be saved".
 
ArtistIrving Kahal and Harry Richman
SongThere Ought to be a Moonlight Saving Time
Copyright Date1931
NotesThis musical standard was a #1 hit for Guy Lombardo +in 1931, and was also performed by Maurice Chevalier, Blossom Dearie +and many others. The phrase "Moonlight saving time" also appears in +the 1995 country song "Not Enough Hours in the Night" written by Aaron +Barker, Kim Williams and Rob Harbin and performed by Doug +Supernaw.
 
ArtistThe Microscopic Septet
CDLobster Leaps In
Copyright Date2008
LabelCuneiform
ID272
Total Time73:05
NotesIncludes the song "Twilight Time Zone."
AMG Rating3.5 stars
ADO Rating2 stars
 
ArtistBob Dylan
CDThe Time They Are A-Changin'
Copyright Date1964
LabelColumbia
IDCK-8905
Total Time45:36
AMG Rating4.5 stars
ADO Rating1.5 stars
NotesThe title song is also available on "Bob Dylan's Greatest Hits" and "The Essential Bob Dylan."
 
TV episode titleThe Lost Hour
TV seriesEerie, Indiana
TV episode number10
NetworkNBC
Air date1991-12-01
NotesDespite Indiana's then-lack of DST, Marshall changes his clock with unusual consequences.
 
TV episode titleTime Tunnel
TV seriesThe Adventures of Pete & Pete
TV episode number5, season 2
NetworkNickelodeon
Air date1994-10-23
NotesThe two Petes travel back in time an hour on the day that DST ends.
 
TV episode titleKing-Size Homer
TV seriesThe Simpsons
TV episode number135
NetworkFox
Air date1995-11-05
NotesHomer, working from home, remarks "8:58, first +time I've ever been early for work. Except for all those daylight +savings days. Lousy farmers."
 
ArtistJules Verne
BookLe Tour du Monde en Quatre-Vingts Jours (Around the World in Eighty Days)
 
ArtistUmberto Eco
BookThe Island of the Day Before +(L'isola del giorno prima)
Copyright Date1994
Notes +"...the story of a 17th century Italian nobleman trapped near an island +on the International Date Line. Time and time zones play an integral +part in the novel." (Paul Eggert, 2006-04-22) +
 
ArtistDavid Jebb
Book +The Thirteenth Time Zone
Notes +"It's fiction, but it's based on his experiences and travels." (Paul Eggert, 2006-04-22) +
 
ArtistJohn Dunning
BookTwo +O'Clock, Eastern Wartime
Copyright Date2001
Notes +Mystery, history, daylight saving time, and old-time radio. +
 
FilmBell Science - About Time
NotesThe Frank Baxter/Richard Deacon extravaganza -Information on ordering is available at -http://www.videoflicks.com/VF2/1035/1035893.ihtml
NotesThe Frank Baxter/Richard Deacon extravaganza. +Information is available at +http://www.videoflicks.com/titles/1035/1035893.htm
-
+
  • An episode of "The Adventures of Superman" entitled "The Mysterious @@ -225,14 +344,19 @@ zones?" was a $32,000 question on the 2001-05-23 United States airing of "Who Wants to Be a Millionaire?" At this rate, the million-dollar time-zone question should have been asked 2002-06-04.
  • +
  • +A private jet's mid-flight change of time zones distorts Alison Dubois' +premonition in the "We Had a Dream" episode of "Medium" +(originally aired 2007-02-28). +
-
+
  • "We're been using the five-cent nickle in this country since 1492. Now that's pretty near 100 years, daylight savings [sic]." (Groucho Marx as Captain Spaulding in "Animal Crackers", 1930, -as noted by Will Fitzerald, wfitzgerald@ameritech.net) +as noted by Will Fitzerald)
  • "Good news." diff --git a/unused/tz-link.htm b/unused/tz-link.htm new file mode 100644 index 00000000000..0cd9e28a305 --- /dev/null +++ b/unused/tz-link.htm @@ -0,0 +1,648 @@ + + + +Sources for Time Zone and Daylight Saving Time Data + + + + + + + + + + +

    Sources for Time Zone and Daylight Saving Time Data

    +
    +@(#)tz-link.htm 8.18 +
    +

    +Please send corrections to this web page to the +time zone mailing list.

    +

    The tz database

    +

    +The public-domain +time zone database contains code and data +that represent the history of local time +for many representative locations around the globe. +It is updated periodically to reflect changes made by political bodies +to time zone +boundaries, UTC offsets, and +daylight-saving +rules. +This database (often called tz or zoneinfo) +is used by several implementations, +including +the +GNU +C Library used in +GNU/Linux, +FreeBSD, +NetBSD, +OpenBSD, +Cygwin, +DJGPP, +AIX, +Mac OS X, +OpenVMS, +Oracle Database, +Solaris, +Tru64, and +UnixWare.

    +

    +Each location in the database represents a national region where all +clocks keeping local time have agreed since 1970. +Locations are identified by continent or ocean and then by the name of +the location, which is typically the largest city within the region. +For example, America/New_York +represents most of the US eastern time zone; +America/Phoenix represents most of Arizona, which +uses mountain time without daylight saving time (DST); +America/Detroit represents most of Michigan, which uses +eastern time but with different DST rules in 1975; +and other entries represent smaller regions like Starke County, +Indiana, which switched from central to eastern time in 1991 +and switched back in 2006. +To use the database on an extended POSIX +implementation set the TZ environment variable to +the location's full name, e.g., TZ="America/New_York".

    +

    +In the tz database's +FTP distribution +the code is in the file tzcodeC.tar.gz, +where C is the code's version; +similarly, the data are in tzdataD.tar.gz, +where D is the data's version. +The following shell commands download +these files to a GNU/Linux or similar host; +see the downloaded +README file for what to do next.

    +
    wget 'ftp://elsie.nci.nih.gov/pub/tz*.tar.gz'
    +gzip -dc tzcode*.tar.gz | tar -xf -
    +gzip -dc tzdata*.tar.gz | tar -xf -
    +
    +

    +The code lets you compile the tz source files into +machine-readable binary files, one for each location. It also lets +you read a tz binary file and interpret time stamps for that +location.

    +

    +The data are by no means authoritative. If you find errors, please +send changes to the time zone +mailing list. You can also browse recent +messages sent to the mailing list, subscribe to it, +retrieve the full archive of old +messages (in gzip compressed format), or retrieve archived older versions of code +and data; there is also a smaller HTTP +mirror.

    +

    +The Web has several other sources for time zone and daylight saving time data. +Here are some recent links that may be of interest. +

    +

    Web pages using recent versions of the tz database

    +

    +These are listed roughly in ascending order of complexity and fanciness. +

    + +

    Other time zone database formats

    + +

    Other tz compilers

    + +

    Other tz binary file readers

    +
      +
    • The GNU C +Library +has an independent, thread-safe implementation of +a tz binary file reader. +This library is freely available under the + +GNU Lesser General Public License +(LGPL), +and is widely used in GNU/Linux systems.
    • +
    • ZoneInfo.java +is a tz binary file reader written in Java. +It is freely available under the LGPL.
    • +
    • Tcl, mentioned above, also contains a +tz binary file reader.
    • +
    +

    Other tz-based time zone software

    +
      +
    • FoxClocks +is an extension for Mozilla +Toolkit applications like Firefox, Thunderbird, and +Sunbird. +It displays multiple clocks in the application window, and has a mapping +interface to Google Earth. +It is freely available under the GPL.
    • +
    • International +clock (intclock) is a multi-timezone clock for +GNU/Linux and similar systems. It is freely available +under the GPL.
    • +
    • PublicDomain +has a copy of a recent tz database, accessed via a C# library. As its +name suggests, it is in the public domain. Only current time stamps +are well supported; historical data are compiled into the runtime but +are not easily accessible.
    • +
    • Sun Java releases since 1.4 +contain a copy of a subset of a recent tz database in a +Java-specific format.
    • +
    • Time Zone is +a WordPress plugin. It is freely +available under a BSD-style license.
    • +
    • VelaTerra is +a Mac OS X program. Its developers +offer free +licenses to tz contributors.
    • +
    • World Time Explorer is a +Microsoft Windows program.
    • +
    +

    Other time zone databases

    + +

    Maps

    + +

    Time zone boundaries

    + +

    Civil time concepts and history

    + +

    National histories of legal time

    +
    +
    Australia
    +
    The Parliamentary Library has commissioned research +note on daylight saving time in Australia. +The Bureau of Meteorology publishes a list of +Implementation Dates of Daylight Savings Time within Australia.
    +
    Belgium
    +
    The Royal Observatory of Belgium maintains a table of time in Belgium (in Dutch).
    +
    Brazil
    +
    The Time Service Department of the National Observatory +records Brazil's daylight saving time decrees (in +Portuguese).
    +
    Canada
    +
    The Institute for National Measurement Standards publishes current +and some older information about Time +Zones & Daylight Saving Time.
    +
    Chile
    +
    The Chilean Hydrographic and Oceanographic Service publishes a history of +official time (in Spanish).
    +
    Germany
    +
    The National Institute for Science and Technology maintains the Realisation of +Legal Time in Germany.
    +
    Israel
    +
    The Interior Ministry periodically issues announcements (in Hebrew).
    +
    Mexico
    +
    The Investigation and Analysis Service of the Mexican Library of +Congress has published a history of Mexican local time (in Spanish).
    +
    Malaysia
    +
    See Singapore below.
    +
    Netherlands
    +
    Legal time in the Netherlands (in Dutch) +covers the history of local time in the Netherlands from ancient times.
    +
    New Zealand
    +
    The Department of Internal Affairs maintains a brief history About +Daylight Saving. The privately-maintained History of New Zealand +time has more details.
    +
    Norway
    +
    The Norwegian Meteorological Institute lists +Summer +time in Norway (in Norwegian), citing the +Institute of Theoretical Astrophysics, Oslo.
    +
    Singapore
    +
    Why +is Singapore in the "Wrong" Time Zone? details the +history of legal time in Singapore and Malaysia.
    +
    United Kingdom
    +
    History of +legal time in Britain discusses in detail the country +with perhaps the best-documented history of clock adjustments. +The National Physical Laboratory also maintains an Archive +of Summer time dates.
    +
    +

    Precision timekeeping

    + +

    Time notation

    +
      +
    • +A Summary of +the International Standard Date and Time Notation is a good +summary of +ISO +8601:2004 -- Data elements and interchange formats -- Information +interchange -- Representation of dates and times.
    • +
    • +XML +Schema: Datatypes - dateTime specifies a format inspired by +ISO 8601 that is in common use in XML data.
    • +
    • +Internet +Message Format (Internet RFC 2822) §3.3 +specifies the time notation used in email and HTTP +headers.
    • +
    • +Date and Time +on the Internet: Timestamps (Internet RFC 3339) +specifies an ISO 8601 +profile for use in new Internet +protocols.
    • +
    • +Date & Time +Formats on the Web surveys web- and Internet-oriented date and time +formats.
    • +
    • +The +Best of Dates, the Worst of Dates covers many problems encountered +by software developers when handling dates and time stamps.
    • +
    • The Unicode Common Locale Data Repository +(CLDR) Project has localizations for time zone names, +abbreviations, identifiers, and formats. For example, it contains +French translations for "Eastern European Summer Time", "EEST", and +"Bucharest". By-Type +Chart: names.metazone shows these values for many locales. +ICU contains a mechanism for using this data.
    • +
    • Alphabetic time zone abbreviations should not be used as unique +identifiers for UTC offsets as they are ambiguous in +practice. For example, "EST" denotes 5 hours behind +UTC in English-speaking North America, but it denotes 10 +or 11 hours ahead of UTC in Australia; and +French-speaking North Americans prefer +"HNE" to +"EST". For POSIX the tz +database contains English abbreviations for all time stamps but in +many cases these are merely inventions of the database +maintainers.
    • +
    • Numeric time zone abbreviations typically count hours east of +UTC, e.g., +09 for Japan and +-10 for Hawaii. However, the POSIX +TZ environment variable uses the opposite convention. For +example, one might use TZ="JST-9" and +TZ="HST10" for Japan and Hawaii, respectively. If the +tz database is available, it is usually better to use +settings like TZ="Asia/Tokyo" and +TZ="Pacific/Honolulu" instead, as this should avoid +confusion, handle old time stamps better, and insulate you better from +any future changes to the rules. One should never set +POSIX TZ to a value like +"GMT-9", though, since this would falsely claim that +local time is nine hours ahead of UTC and the time zone +is called "GMT".
    • +
    +

    Related indexes

    + + + diff --git a/unused/tzfile.5.txt b/unused/tzfile.5.txt new file mode 100644 index 00000000000..953851233d6 --- /dev/null +++ b/unused/tzfile.5.txt @@ -0,0 +1,106 @@ +NAME + + tzfile - time zone information + +SYNOPSIS + #include + +DESCRIPTION + The time zone information files used by tzset(3) begin with + the magic characters "TZif" to identify then as time zone + information files, followed by a character identifying the + version of the file's format (as of 2005, either an ASCII + NUL or a '2') followed by fifteen bytes containing zeroes + reserved for future use, followed by six four-byte values of + type long, written in a ``standard'' byte order (the high- + order byte of the value is written first). These values + are, in order: + + tzh_ttisgmtcnt + The number of UTC/local indicators stored in the file. + + tzh_ttisstdcnt + The number of standard/wall indicators stored in the + file. + + tzh_leapcnt + The number of leap seconds for which data is stored in + the file. + + tzh_timecnt + The number of "transition times" for which data is + stored in the file. + + tzh_typecnt + The number of "local time types" for which data is + stored in the file (must not be zero). + + tzh_charcnt + The number of characters of "time zone abbreviation + strings" stored in the file. + + The above header is followed by tzh_timecnt four-byte values + of type long, sorted in ascending order. These values are + written in ``standard'' byte order. Each is used as a + transition time (as returned by time(2)) at which the rules + for computing local time change. Next come tzh_timecnt one- + byte values of type unsigned char; each one tells which of + the different types of ``local time'' types described in the + file is associated with the same-indexed transition time. + These values serve as indices into an array of ttinfo + structures (with tzh_typecnt entries) that appears next in + the file; these structures are defined as follows: + + struct ttinfo { + long tt_gmtoff; + int tt_isdst; + unsigned int tt_abbrind; + }; + + Each structure is written as a four-byte value for tt_gmtoff + of type long, in a standard byte order, followed by a one- + byte value for tt_isdst and a one-byte value for tt_abbrind. + In each structure, tt_gmtoff gives the number of seconds to + be added to UTC, tt_isdst tells whether tm_isdst should be + set by localtime (3) and tt_abbrind serves as an index into + the array of time zone abbreviation characters that follow + the ttinfo structure(s) in the file. + + Then there are tzh_leapcnt pairs of four-byte values, + written in standard byte order; the first value of each pair + gives the time (as returned by time(2)) at which a leap + second occurs; the second gives the total number of leap + seconds to be applied after the given time. The pairs of + values are sorted in ascending order by time. + + Then there are tzh_ttisstdcnt standard/wall indicators, each + stored as a one-byte value; they tell whether the transition + times associated with local time types were specified as + standard time or wall clock time, and are used when a time + zone file is used in handling POSIX-style time zone + environment variables. + + Finally there are tzh_ttisgmtcnt UTC/local indicators, each + stored as a one-byte value; they tell whether the transition + times associated with local time types were specified as UTC + or local time, and are used when a time zone file is used in + handling POSIX-style time zone environment variables. + + Localtime uses the first standard-time ttinfo structure in + the file (or simply the first ttinfo structure in the + absence of a standard-time structure) if either tzh_timecnt + is zero or the time argument is less than the first + transition time recorded in the file. + + For version-2-format time zone files, the above header and + data is followed by a second header and data, identical in + format except that eight bytes are used for each transition + time or leap second time. After the second header and data + comes a newline-enclosed, POSIX-TZ-environment-variable- + style string for use in handling instants after the last + transition time stored in the file (with nothing between the + newlines if there is no POSIX representation for such + instants). + +SEE ALSO + newctime(3) diff --git a/unused/tzselect.8 b/unused/tzselect.8 new file mode 100644 index 00000000000..949d9f7bf35 --- /dev/null +++ b/unused/tzselect.8 @@ -0,0 +1,41 @@ +.TH TZSELECT 8 +.SH NAME +tzselect \- select a time zone +.SH SYNOPSIS +.B tzselect +.SH DESCRIPTION +The +.B tzselect +program asks the user for information about the current location, +and outputs the resulting time zone description to standard output. +The output is suitable as a value for the TZ environment variable. +.PP +All interaction with the user is done via standard input and standard error. +.SH "ENVIRONMENT VARIABLES" +.TP +\f3AWK\fP +Name of a Posix-compliant +.I awk +program (default: +.BR awk ). +.TP +\f3TZDIR\fP +Name of the directory containing time zone data files (default: +.BR /usr/local/etc/zoneinfo ). +.SH FILES +.TP +\f2TZDIR\fP\f3/iso3166.tab\fP +Table of ISO 3166 2-letter country codes and country names. +.TP +\f2TZDIR\fP\f3/zone.tab\fP +Table of country codes, latitude and longitude, TZ values, and +descriptive comments. +.TP +\f2TZDIR\fP\f3/\fP\f2TZ\fP +Time zone data file for time zone \f2TZ\fP. +.SH "EXIT STATUS" +The exit status is zero if a time zone was successfully obtained from the user, +nonzero otherwise. +.SH "SEE ALSO" +newctime(3), tzfile(5), zdump(8), zic(8) +.\" @(#)tzselect.8 8.1 diff --git a/unused/tzselect.8.txt b/unused/tzselect.8.txt new file mode 100644 index 00000000000..a492401b821 --- /dev/null +++ b/unused/tzselect.8.txt @@ -0,0 +1,41 @@ +NAME + + tzselect - select a time zone + +SYNOPSIS + tzselect + +DESCRIPTION + The tzselect program asks the user for information about the + current location, and outputs the resulting time zone + description to standard output. The output is suitable as a + value for the TZ environment variable. + + All interaction with the user is done via standard input and + standard error. + +ENVIRONMENT VARIABLES + AWK Name of a Posix-compliant awk program (default: awk). + + TZDIR + Name of the directory containing time zone data files + (default: /usr/local/etc/zoneinfo). + +FILES + TZDIR/iso3166.tab + Table of ISO 3166 2-letter country codes and country + names. + + TZDIR/zone.tab + Table of country codes, latitude and longitude, TZ + values, and descriptive comments. + + TZDIR/TZ + Time zone data file for time zone TZ. + +EXIT STATUS + The exit status is zero if a time zone was successfully + obtained from the user, nonzero otherwise. + +SEE ALSO + newctime(3), tzfile(5), zdump(8), zic(8) diff --git a/unused/tzselect.ksh b/unused/tzselect.ksh new file mode 100644 index 00000000000..7b805336ab5 --- /dev/null +++ b/unused/tzselect.ksh @@ -0,0 +1,323 @@ +#! /bin/ksh + +VERSION='@(#)tzselect.ksh 8.2' + +# Ask the user about the time zone, and output the resulting TZ value to stdout. +# Interact with the user via stderr and stdin. + +# Contributed by Paul Eggert. + +# Porting notes: +# +# This script requires several features of the Korn shell. +# If your host lacks the Korn shell, +# you can use either of the following free programs instead: +# +# +# Bourne-Again shell (bash) +# +# +# +# Public domain ksh +# +# +# This script also uses several features of modern awk programs. +# If your host lacks awk, or has an old awk that does not conform to Posix.2, +# you can use either of the following free programs instead: +# +# +# GNU awk (gawk) +# +# +# +# mawk +# + + +# Specify default values for environment variables if they are unset. +: ${AWK=awk} +: ${TZDIR=$(pwd)} + +# Check for awk Posix compliance. +($AWK -v x=y 'BEGIN { exit 123 }') /dev/null 2>&1 +[ $? = 123 ] || { + echo >&2 "$0: Sorry, your \`$AWK' program is not Posix compatible." + exit 1 +} + +if [ "$1" = "--help" ]; then + cat <&2 "$0: time zone files are not set up correctly" + exit 1 + } +done + +newline=' +' +IFS=$newline + + +# Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout. +case $(echo 1 | (select x in x; do break; done) 2>/dev/null) in +?*) PS3= +esac + + +# Begin the main loop. We come back here if the user wants to retry. +while + + echo >&2 'Please identify a location' \ + 'so that time zone rules can be set correctly.' + + continent= + country= + region= + + + # Ask the user for continent or ocean. + + echo >&2 'Please select a continent or ocean.' + + select continent in \ + Africa \ + Americas \ + Antarctica \ + 'Arctic Ocean' \ + Asia \ + 'Atlantic Ocean' \ + Australia \ + Europe \ + 'Indian Ocean' \ + 'Pacific Ocean' \ + 'none - I want to specify the time zone using the Posix TZ format.' + do + case $continent in + '') + echo >&2 'Please enter a number in range.';; + ?*) + case $continent in + Americas) continent=America;; + *' '*) continent=$(expr "$continent" : '\([^ ]*\)') + esac + break + esac + done + case $continent in + '') + exit 1;; + none) + # Ask the user for a Posix TZ string. Check that it conforms. + while + echo >&2 'Please enter the desired value' \ + 'of the TZ environment variable.' + echo >&2 'For example, GST-10 is a zone named GST' \ + 'that is 10 hours ahead (east) of UTC.' + read TZ + $AWK -v TZ="$TZ" 'BEGIN { + tzname = "[^-+,0-9][^-+,0-9][^-+,0-9]+" + time = "[0-2]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?" + offset = "[-+]?" time + date = "(J?[0-9]+|M[0-9]+\.[0-9]+\.[0-9]+)" + datetime = "," date "(/" time ")?" + tzpattern = "^(:.*|" tzname offset "(" tzname \ + "(" offset ")?(" datetime datetime ")?)?)$" + if (TZ ~ tzpattern) exit 1 + exit 0 + }' + do + echo >&2 "\`$TZ' is not a conforming" \ + 'Posix time zone string.' + done + TZ_for_date=$TZ;; + *) + # Get list of names of countries in the continent or ocean. + countries=$($AWK -F'\t' \ + -v continent="$continent" \ + -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ + ' + /^#/ { next } + $3 ~ ("^" continent "/") { + if (!cc_seen[$1]++) cc_list[++ccs] = $1 + } + END { + while (getline &2 'Please select a country.' + select country in $countries + do + case $country in + '') echo >&2 'Please enter a number in range.';; + ?*) break + esac + done + + case $country in + '') exit 1 + esac;; + *) + country=$countries + esac + + + # Get list of names of time zone rule regions in the country. + regions=$($AWK -F'\t' \ + -v country="$country" \ + -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ + ' + BEGIN { + cc = country + while (getline &2 'Please select one of the following' \ + 'time zone regions.' + select region in $regions + do + case $region in + '') echo >&2 'Please enter a number in range.';; + ?*) break + esac + done + case $region in + '') exit 1 + esac;; + *) + region=$regions + esac + + # Determine TZ from country and region. + TZ=$($AWK -F'\t' \ + -v country="$country" \ + -v region="$region" \ + -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ + ' + BEGIN { + cc = country + while (getline &2 "$0: time zone files are not set up correctly" + exit 1 + } + esac + + + # Use the proposed TZ to output the current date relative to UTC. + # Loop until they agree in seconds. + # Give up after 8 unsuccessful tries. + + extra_info= + for i in 1 2 3 4 5 6 7 8 + do + TZdate=$(LANG=C TZ="$TZ_for_date" date) + UTdate=$(LANG=C TZ=UTC0 date) + TZsec=$(expr "$TZdate" : '.*:\([0-5][0-9]\)') + UTsec=$(expr "$UTdate" : '.*:\([0-5][0-9]\)') + case $TZsec in + $UTsec) + extra_info=" +Local time is now: $TZdate. +Universal Time is now: $UTdate." + break + esac + done + + + # Output TZ info and ask the user to confirm. + + echo >&2 "" + echo >&2 "The following information has been given:" + echo >&2 "" + case $country+$region in + ?*+?*) echo >&2 " $country$newline $region";; + ?*+) echo >&2 " $country";; + +) echo >&2 " TZ='$TZ'" + esac + echo >&2 "" + echo >&2 "Therefore TZ='$TZ' will be used.$extra_info" + echo >&2 "Is the above information OK?" + + ok= + select ok in Yes No + do + case $ok in + '') echo >&2 'Please enter 1 for Yes, or 2 for No.';; + ?*) break + esac + done + case $ok in + '') exit 1;; + Yes) break + esac +do : +done + +case $SHELL in +*csh) file=.login line="setenv TZ '$TZ'";; +*) file=.profile line="TZ='$TZ'; export TZ" +esac + +echo >&2 " +You can make this change permanent for yourself by appending the line + $line +to the file '$file' in your home directory; then log out and log in again. + +Here is that TZ value again, this time on standard output so that you +can use the $0 command in shell scripts:" + +echo "$TZ" diff --git a/unused/usno1988 b/unused/usno1988 new file mode 100644 index 00000000000..5766d9b057b --- /dev/null +++ b/unused/usno1988 @@ -0,0 +1,111 @@ +# @(#)usno1988 8.1 +# +# From Arthur David Olson (1989-01-19): +# +# Here's some United States Naval Observatory time zone data from +# February 1988. It's here mostly to convince you that the USNO has indeed +# been updating its files (see its 1989 data elsewhere). +# +ANDORRA 1 H AHEAD OF UTC +ARGENTINA 3 H BEHIND UTC +BRASIL WEST 5 H BEHIND UTC (CRUZEIRO DO SUL) +BRASIL CENTRAL 4 H BEHIND UTC (MANAUS) +BRASIL EAST 3 H BEHIND UTC COASTAL STATES, RIO, SP, BRASILIA +BRASIL 2 H BEHIND UTC ATLANTIC ISLANDS +BRAZIL 5 H BEHIND UTC WEST (CRUZEIRO DO SUL) +BRAZIL 4 H BEHIND UTC CENTRAL (MANAUS) +BRAZIL 3 H BEHIND UTC COASTAL STATES, RIO, SP, BRASILIA +BRAZIL 3 H BEHIND UTC FOR MOST MAJOR AIRPORTS. +BRAZIL 2 H BEHIND UTC ATLANTIC ISLANDS +BULGARIA 2 H AHEAD OF UTC WINTER +BULGARIA 3 H AHEAD OF UTC SUMMER MAR31 - SEP 85, 0100 LOCAL +CHINA 8 H AHEAD OF UTC; ALL OF CHINA, INCL TAIWAN +CUBA 5 H BEHIND UTC IN WINTER +CUBA 4 H BEHIND UTC MAY 8 - OCT 8 +CYPRUS 2 H AHEAD UTC IN WINTER +CYPRUS 3 H AHEAD UTC MAR 25 - SEP 30 +DENMARK 1 H AHEAD UTC IN WINTER +DENMARK 2 H AHEAD UTC MAR 31 - SEP 30 , 0200 LOCAL +DENMK. FAEROE IS 1 H AHEAD UTC MAR 31 - SEP 30 , 0200 LOCAL +EGYPT 2 H AHEAD UTC +EGYPT 3 H AHEAD UTC SUMMER (AFTER RAMADAN) +ENGLAND ON UTC IN WINTER; WALES, SCOTLAND, N.I., CH.IS. +ENGLAND 1 H AHEAD OF UTC; SUMMER TIL 28 OCT 0200 LOCAL +FINLAND 2 H AHEAD OF UTC IN WINTER +FINLAND 3 H AHEAD OF UTC MAR 25 - SEP 30 +FRANCE 1 H AHEAD OF UTC IN WINTER +FRANCE 2 H AHEAD OF UTC MAR 31 - SEP 30 , 0100 LOCAL +GREECE 2 H AHEAD OF UTC IN WINTER +GREECE 3 H AHEAD OF UTC IN SUMMER EFF. 31MAR85 02/03 LOCAL +GREECE 3 H AHEAD OF UTC MAR 25 - SEP 30 +GREENLAND 4 H BEHIND UTC IN THULE AIRBASE YEAR ROUND +GREENLAND 3 H BEHIND UTC IN WINTER AT SONDRESTROM +GREENLAND 2 H BEHIND UTC 30 MAR - 30 SEP 2200 LOCAL AT -"- +GREENLAND 2 H BEHIND UTC AROUND SCORESBY SUND +ICELAND ON UTC +IRAN 3.5H AHEAD OF UTC +IRELAND ON UTC IN WINTER +IRELAND 1 H AHEAD OF UTC MAR 31 - OCT 23 0200 LOCAL +ITALY 1 H AHEAD OF UTC IN WINTER +ITALY 2 H AHEAD OF UTC MAR 31 - SEP 30, 0030 LOCAL +JAMAICA 5 H BEHIND UTC IN WINTER +JAMAICA 4 H BEHIND UTC APR 29 - OCT 29 +LIBYA 2 H AHEAD OF UTC +MEXICO BAJA CAL N 8 H BEHIND UTC IN WINTER; NORTH BAJA CAL, TIJUANA +MEXICO BAJA CAL N 7 H BEHIND UTC APR 29 - OCT 29 +MEXICO BAJA CAL S 7 H BEHIND UTC ALL YEAR; MAZATLAN +MEXICO CENTRAL 6 H BEHIND UTC ALL YEAR; MEXICO CITY +MONACO 1 H AHEAD UTC IN WINTER +MONACO 2 H AHEAD UTC MAR 25 - SEP30 +PARAGUAY 4 H BEHIND UTC IN WINTER +PARAGUAY 3 H BEHIND UTC SEP 30 - MAR 30 +POLAND 1 H AHEAD OF UTC IN WINTER +POLAND 2 H AHEAD OF UTC MAR 24 - SEP 0200 LOCAL +PORTUGAL ON UTC IN WINTER +PORTUGAL 1 H AHEAD OF UTC IN SUMMER MAR 31 - SEP 29 0100 LOCAL +PORTUGAL AZORES 1 H BEHIND UTC IN WINTER +PORTUGAL AZORES ON UTC IN SUMMER MAR 31 - SEP 29 +PORTUGAL MADEIRA ON UTC ALL YEAR; +ROMANIA 2 H AHEAD OF UTC IN WINTER +ROMANIA 3 H AHEAD OF UTC APR 3 - SEP 24 +SCOTLAND SEE ENGLAND +SWITZERLAND 1 H AHEAD OF UTC IN WINTER +SWITZERLAND 2 H AHEAD OF UTC MAR 31 - SEP 30 0200 LOCAL +TURKEY 3 H AHEAD OF UTC +USA EASTERN 5 H BEHIND UTC IN WINTER; NEW YORK, WASHINGTON +USA EASTERN 4 H BEHIND UTC APR 29 - OCT 29 +USA CENTRAL 6 H BEHIND UTC IN WINTER; CHICAGO, HOUSTON +USA CENTRAL 5 H BEHIND UTC APR 29 - OCT 29 +USA MOUNTAIN 7 H BEHIND UTC IN WINTER; DENVER +USA MOUNTAIN 6 H BEHIND UTC APR 29 - OCT 29 +USA PACIFIC 8 H BEHIND UTC IN WINTER; L.A., SAN FRANCISCO +USA PACIFIC 7 H BEHIND UTC APR 29 - OCT 29 +USA ALASKA STD 9 H BEHIND UTC IN WINTER; MOST OF ALASKA (AKST) +USA ALASKA STD 8 H BEHIND UTC APR 29 - OCT 29 (AKDT) +USA ALEUTIAN 10 H BEHIND UTC IN WINTER; ISLANDS WEST OF 170W +USA - " - 9 H BEHIND UTC APR 29 - OCT 29 +USA HAWAII 10 H BEHIND UTC ALL YEAR; +USA BERING 11 H BEHIND UTC ALL YEAR; SAMOA, MIDWAY +USSR WEST EUROP 3 H AHEAD OF UTC IN WINTER; LENINGRAD, MOSCOW +USSR WEST EUROP 4 H AHEAD OF UTC APR 1 - SEP 30 +USSR CENTRAL EUR 4 H AHEAD OF UTC IN WINTER; ROSTOV, BAKU +USSR CENTRAL EUR 5 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST EUROP 5 H AHEAD OF UTC IN WINTER; SVERDLOVSK +USSR EAST EUROP 6 H AHEAD OF UTC APR 1 - SEP 30 +USSR WEST SIBERIAN 6 H AHEAD OF UTC IN WINTER; TASHKENT, ALMA ATA +USSR WEST SIBERIAN 7 H AHEAD OF UTC APR 1 - SEP 30 +USSR WEST-CENTRAL 7 H AHEAD OF UTC IN WINTER; NOVOSIBIRSK +USSR WEST-CENTRAL 8 H AHEAD OF UTC APR 1 - SEP 30 +USSR WEST-CENTRAL 8 H AHEAD OF UTC IN WINTER; IRKUTSK +USSR WEST-CENTRAL 9 H AHEAD OF UTC APR 1 - SEP 30 +USSR CENTRAL SIB 9 H AHEAD OF UTC IN WINTER; YAKUTSK +USSR CENTRAL SIB 10 H AHEAD OF UTC APR 1 - SEP 30 +USSR CENTRAL SIB 10 H AHEAD OF UTC IN WINTER; VLADIVOSTOK +USSR CENTRAL SIB 11 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST SIBERIA 11 H AHEAD OF UTC IN WINTER; MAGADAN +USSR EAST SIBERIA 12 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST SIBERIA 12 H AHEAD OF UTC IN WINTER; PETROPAVLOVSK +USSR EAST SIBERIA 13 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST SIBERIA 13 H AHEAD OF UTC IN WINTER; UELEN +USSR EAST SIBERIA 14 H AHEAD OF UTC APR 1 - SEP 30 +WALES SEE ENGLAND diff --git a/unused/usno1989 b/unused/usno1989 new file mode 100644 index 00000000000..e242cb90d37 --- /dev/null +++ b/unused/usno1989 @@ -0,0 +1,452 @@ +# @(#)usno1989 8.1 +# +# From Arthur David Olson (1989-01-19): +# +# Here's time zone information from the United States Naval Observatory; +# no corrections have been made, and there are some obvious challenges. +# The USNO warns: +# DUE TO FREQUENT CHANGES IN THE LOCAL LAWS GOVERNING DAYLIGHT +# SAVING TIME, WE CANNOT GUARANTEE THE ACCURACY OF THIS +# INFORMATION. PLEASE ALERT US TO ANY DISCREPANCY YOU MAY +# DISCOVER. +# +AFGHANISTAN 4.5H AHEAD OF UTC +ALBANIA 1 H AHEAD OF UTC +ALBANIA 2 H AHEAD OF UTC MAR 27 - SEP 24 +ALBANIA (ESTIMATED) +ALGERIA 1 H AHEAD OF UTC +AMERICAN SAMOA 11 H BEHIND UTC +ANDORRA 1 H AHEAD OF UTC +ANDORRA 2 H AHEAD OF UTC MAR 27 - SEP 24 +ANDORRA (ESTIMATED) +ANGOLA 1 H AHEAD OF UTC +ARGENTINA 3 H BEHIND UTC +ARUBA 4 H BEHIND UTC ALSO BONAIRE, CURACAO, +ARUBA ST.MAARTEN +AUSTRALIA WEST 8 H AHEAD OF UTC PERTH, EXMOUTH +AUSTRALIA N.T. 9.5H AHEAD OF UTC DARWIN NO ADVANCED TIME +AUSTRALIA N.T. IN SUMMER +AUSTRALIA SOUTH 9.5H AHEAD OF UTC ADELAIDE +AUSTRALIA INCLUDING BROKEN HILL, NSW +AUSTRALIA SOUTH 10.5H AHEAD OF UTC ADELAIDE OCT 30, '88-MAR +AUSTRALIA SOUTH 18, '89 INCLUDING BROKEN +AUSTRIALIA SOUTH HILL, NSW +AUSTRALIA QUEENL 10 H AHEAD OF UTC +AUSTRALIA NSW 10 H AHEAD OF UTC SYDNEY +AUSTRALIA NSW 11 H AHEAD OF UTC SYDNEY OCT 30, '88-MAR 18, +AUSTRALIA NSW '89 +AUSTRALIA TASM. 10 H AHEAD OF UTC HOBART +AUSTRALIA TASM. 11 H AHEAD OF UTC HOBART OCT 30, '88-MAR 18, +AUSTRALIA TASM. '89 +AUSTRIA 1 H AHEAD OF UTC +AUSTRIA 2 H AHEAD OF UTC MAR 27 - SEPT 24 +AZORES SEE PORTUGAL +BAHAMAS 5 H BEHIND UTC EXCLUDING TURKS AND CAICOS +BAHAMAS ISLANDS) +BAHAMAS 4 H BEHIND UTC APR 3 - OCT 29 (SAME +BAHAMAS EXCLUSION) +BAHRAIN 3 H AHEAD OF UTC +BANGLADESH 6 H AHEAD OF UTC +BARBADOS 4 H BEHIND UTC +BELGIUM 1 H AHEAD OF UTC +BELGIUM 2 H AHEAD OF UTC MAR 27 - SEP 24 +BELIZE 6 H BEHIND UTC +BENIN PEOPLES REP 1 H AHEAD OF UTC DAHOMEY +BERMUDA 4 H BEHIND UTC +BERMUDA 3 H BEHIND UTC APR 3 - OCT 29 +BHUTAN 6 H AHEAD OF UTC +BOLIVIA 4 H BEHIND UTC +BONAIRE 4 H BEHIND UTC ALSO ARUBA,CURACAO, +BONAIRE ST.MAARTEN, SABA +BOTSWANA 2 H AHEAD OF UTC +BRAZIL WEST 5 H BEHIND UTC TERRITORY OF ACRE +BRAZIL WEST 4 H BEHIND UTC ACRE OCT 23, '88-FEB 11, +BRAZIL '89 (ESTIMATED) +BRAZIL CENTRAL 4 H BEHIND UTC MANAUS +BRAZIL CENTRAL 3 H BEHIND UTC MANAUS OCT 23, '88-FEB 11, +BRAZIL CENTRAL '89 (ESTIMATED) +BRAZIL EAST 3 H BEHIND UTC COASTAL STATES, RIO, SAO +BRAZIL EAST PAULO, BRASILIA +BRAZIL EAST 2 H BEHIND UTC COASTAL STATES, RIO, SAO +BRAZIL PAULO, BRASILIA OCT 23, +BRAZIL '88-FEB 11, '89 +BRAZIL (ESTIMATED) +BRAZIL 2 H BEHIND UTC ATLANTIC ISLANDS, FERNANDO +BRAZIL DE NORONHA +BRAZIL 1 H BEHIND UTC OCT 23, '88-FEB 11, '89 +BRAZIL (ESTIMATED) +BRAZIL 3 H BEHIND UTC FOR MOST MAJOR AIRPORTS. +BRITISH VIRGIN I. 4 H BEHIND UTC +BRUNEI 8 H AHEAD OF UTC +BULGARIA 2 H AHEAD OF UTC +BULGARIA 3 H AHEAD OF UTC MAR 27 - SEP 24 +BURKINA FASO ON UTC +BURMA 6.5H AHEAD OF UTC +BURUNDI 2 H AHEAD OF UTC +CAMBODIA SEE KAMPUCHEA +CAMEROON 1 H AHEAD OF UTC +CANADA NEW FDL 3.5H BEHIND UTC ST.JOHN'S +CANADA NEW FDL 1.5H BEHIND UTC APR 3 - OCT 29 +CANADA ATLANTIC 4 H BEHIND UTC HALIFAX +CANADA ATLANTIC 3 H BEHIND UTC APR 3 - OCT 29 +CANADA EASTERN 5 H BEHIND UTC TORONTO, MONTREAL, OTTAWA +CANADA EASTERN 4 H BEHIND UTC APR 3 - OCT 29 +CANADA CENTRAL 6 H BEHIND UTC REGINA, WINNIPEG +CANADA CENTRAL 5 H BEHIND UTC APR 3 - OCT 29 +CANADA MOUNTAIN 7 H BEHIND UTC CALGARY, EDMONTON +CANADA MOUNTAIN 6 H BEHIND UTC APR 3 - OCT 29 +CANADA PACIFIC 8 H BEHIND UTC VANCOUVER +CANADA PACIFIC 7 H BEHIND UTC APR 3 - OCT 29 +CANADA YUKON SAME AS PACIFIC DAWSON +CAPE VERDE 1 H BEHIND UTC +CAYMAN ISLANDS 5 H BEHIND UTC +CAROLINE ISLAND 10 H AHEAD OF UTC EXCLUDING PONAPE IS., +CAROLINE ISLAND KUSAIE, AND PINGELAP +CENTRAL AFRICA 1 H AHEAD OF UTC +CEYLON 5.5H AHEAD OF UTC, SEE SRI LANKA +CHAD 1 H AHEAD OF UTC +CHANNEL ISLANDS SEE ENGLAND +CHILE 4 H BEHIND UTC CONTINENTAL +CHILE 3 H BEHIND UTC OCT 9, '88-MAR 11, '89 +CHILE 6 H BEHIND UTC EASTER ISLAND +CHILE 5 H BEHIND UTC OCT 9, '88-MAR 11, '89 +CHINA 8 H AHEAD OF UTC ALL OF CHINA, INCL TAIWAN +CHINA 9 H AHEAD OF UTC APR 17 - SEP 10 +COCOS (Keeling) I. 6.5H AHEAD OF UTC +COLOMBIA 5 H BEHIND UTC +COMOROS 3 H AHEAD OF UTC +CONGO 1 H AHEAD OF UTC +COOK ISLANDS 10 H BEHIND UTC +COOK ISLANDS 9.5H BEHIND UTC OCT 30, '88-MAR 24, '89 +COOK ISLANDS (ESTIMATED) +COSTA RICA 6 H BEHIND UTC +COTE D'IVOIRE ON UTC +CUBA 5 H BEHIND UTC +CUBA 4 H BEHIND UTC MAR 20 - OCT 8 +CURACAO 4 H BEHIND UTC ALSO BONAIRE, ARUBA, +CURACAO ST.MAARTEN +CYPRUS 2 H AHEAD OF UTC +CYPRUS 3 H AHEAD OF UTC MAR 27 - SEP 24 +CZECHOSLOVAKIA 1 H AHEAD OF UTC +CZECHOSLOVAKIA 2 H AHEAD OF UTC MAR 27 - SEP 24 +DENMARK 1 H AHEAD OF UTC +DENMARK 2 H AHEAD OF UTC MAR 27 - SEP 24 +DENMK. FAEROE IS 1 H AHEAD OF UTC MAR 27 - SEP 24 +DJIBOUTI 3 H AHEAD OF UTC +DOMINICA 4 H BEHIND UTC +DOMINICAN REP 4 H BEHIND UTC +ECUADOR 5 H BEHIND UTC CONTINENTAL +ECUADOR 6 H BEHIND UTC GALAPAGOS ISLANDS +EGYPT 2 H AHEAD OF UTC +EGYPT 3 H AHEAD OF UTC MAY 17 - SEP 30 (AFTER +EGYPT RAMADAN) +EL SALVADOR 6 H BEHIND UTC +ENGLAND ON UTC (WALES, SCOTLAND, N.I., +ENGLAND CH. IS.) +ENGLAND 1 H AHEAD OF UTC MAR 27 - OCT 22 +ENEZUELA 4 H BEHIND UTC +EQUITORIAL GUINEA 1 H AHEAD OF UTC +ETHIOPIA 3 H AHEAD OF UTC +FALKLAND ISLANDS 4 H BEHIND UTC +FALKLAND ISLANDS 3 H BEHIND UTC SEP 11, '88-APR 15, '89 +FALKLAND ISLANDS (ESTIMATED) +FAROE ISLAND ON UTC +FAROE ISLAND 1 H AHEAD OF UTC MAR 27 - SEP 24 +FIJI 12 H AHEAD OF UTC +FINLAND 2 H AHEAD OF UTC +FINLAND 3 H AHEAD OF UTC MAR 27 - SEP 24 +FRANCE 1 H AHEAD OF UTC +FRANCE 2 H AHEAD OF UTC MAR 27 - SEP 24 +FRENCH GUIANA 3 H BEHIND UTC +FRENCH POLYNESIA 9 H BEHIND UTC GAMBIER ISLAND +FRENCH POLYNESIA 9.5H BEHIND UTC MARQUESAS ISLANDS +FRENCH POLYNESIA 10 H BEHIND UTC SOCIETY ISLANDS, TUBUAI +FRENCH POLYNESIA ISLANDS, TUAMOTU ISLAND, +FRENCH POLYNESIA TAHITI +GABON 1 H AHEAD OF UTC +GAMBIA ON UTC +GERMANY ALL 1 H AHEAD OF UTC +GERMANY ALL 2 H AHEAD OF UTC MAR 27 - SEP 24 +GHANA ON UTC +GIBRALTAR 1 H AHEAD OF UTC +GIBRALTAR 2 H AHEAD OF UTC MAR 27 - SEP 24 +GREECE 2 H AHEAD OF UTC +GREECE 3 H AHEAD OF UTC MAR 27 - SEP 24 +GREENLAND 4 H BEHIND UTC THULE AIRBASE YEAR ROUND +GREENLAND 3 H BEHIND UTC ANGMAGSSALIK AND W. COAST +GREENLAND 2 H BEHIND UTC MAR 27 - SEP 24 +GREENLAND 1 H BEHIND UTC SCORESBYSUND +GREENLAND ON UTC MAR 27 - SEP 24 +GRENADA 4 H BEHIND UTC +GUADELOUPE 4 H BEHIND UTC ST. BARTHELEMY, NORTHERN +GUADELOUPE ST. MARTIN MARTINIQUE +GUAM 10 H AHEAD OF UTC +GUATEMALA 6 H BEHIND UTC +GUINEA ON UTC +GUINEA BISSAU ON UTC +GUINEA REPUBLIC ON UTC +GUINEA EQUATORIAL 1 H AHEAD OF UTC +GUYANA 3 H BEHIND UTC +HAITI 5 H BEHIND UTC +HAITI 4 H BEHIND UTC APR 3 - OCT 29 +HOLLAND SEE NETHERLANDS +HONDURAS 6 H BEHIND UTC +HONG KONG 8 H AHEAD OF UTC +HUNGARY 1 H AHEAD OF UTC +HUNGARY 2 H AHEAD OF UTC MAR 27 - SEP 24 +ICELAND ON UTC +INDIA 5.5H AHEAD OF UTC INCLUDING ANDAMAN ISLANDS +INDONESIA WEST 7 H AHEAD OF UTC SUMATRA, JAVA, BALI, +INDONESIA WEST JAKARTA +INDONESIA CENTRAL 8 H AHEAD OF UTC KALIMANTAN, SULAWESI +INDONESIA EAST 9 H AHEAD OF UTC IRIAN, BARAT +IRAN 3.5H AHEAD OF UTC +IRAQ 3 H AHEAD OF UTC +IRAQ 4 H AHEAD OF UTC APR 1 - SEP 30 +IRELAND ON UTC +IRELAND 1 H AHEAD OF UTC MAR 27 - OCT 22 +ISRAEL 2 H AHEAD OF UTC +ISRAEL 3 H AHEAD OF UTC APR 10 - SEP 3 +ITALY 1 H AHEAD OF UTC +ITALY 2 H AHEAD OF UTC MAR 27 - SEP 24 +IVORY COAST ON UTC +IWAN 8 H AHEAD OF UTC +JAMAICA 5 H BEHIND UTC +JAPAN 9 H AHEAD OF UTC +JOHNSTON ISLAND 10 H BEHIND UTC +JORDAN 2 H AHEAD OF UTC +JORDAN 3 H AHEAD OF UTC APR 1 - OCT 6 +KAMPUCHEA 7 H AHEAD OF UTC +KENYA 3 H AHEAD OF UTC +KIRIBATI, REP OF 12 H AHEAD OF UTC CANTON, ENDERBURY ISLANDS +KIRIBATI, REP OF 11 H AHEAD OF UTC CHRISTMAS ISLAND +KOREA 9 H AHEAD OF UTC +KOREA, REP OF 9 H AHEAD OF UTC +KOREA, REP OF 10 H AHEAD OF UTC MAY 8 - OCT 8 +KUWAIT 3 H AHEAD OF UTC +KUSAIE, PINGELAP 12 H AHEAD OF UTC INCLUDING MARSHALL IS., +KUSAIE, PINGELAP EXCLUDING KWAJALEIN) +KWAJALEIN 12 H BEHIND UTC +LAOS 7 H AHEAD OF UTC +LEBANON 2 H AHEAD OF UTC +LEBANON 3 H AHEAD OF UTC JUN 1 - OCT 31 +LEEWARD ISLANDS 4 H BEHIND UTC ANTIGUA, DOMINICA, +LEEWARD ISLANDS MONTSERRAT, ST. +LEEWARD ISLAANDS CHRISTOPHER, ST. KITTS, +LEEWARD ISLANDS NEVIS, ANGUILLA +LESOTHO 2 H AHEAD OF UTC +LIBERIA ON UTC +LIBYAN ARAB 1 H AHEAD OF UTC JAMAHIRIYA/LIBYA +LIBYAN ARAB 2 H AHEAD OF UTC APR 1 - SEP 30 JAMAHIRIYA/LIBYA +LIECHTENSTEIN 1 H AHEAD OF UTC +LIECHTENSTEIN 2 H AHEAD OF UTC MAR 27 - SEP 24 +LUXEMBOURG 1 H AHEAD OF UTC +LUXEMBOURG 2 H AHEAD OF UTC MAR 27 - SEP 24 +MACAO 8 H AHEAD OF UTC +MADAGASCAR 3 H AHEAD OF UTC +MADEIRA SEE PORTUGAL +MALAWI 2 H AHEAD OF UTC +MALAYSIA 8 H AHEAD OF UTC +MALDIVES 5 H AHEAD OF UTC +MALI ON UTC +MALTA 1 H AHEAD OF UTC +MALTA 2 H AHEAD OF UTC MAR 27 - SEP 24 +MARTINIQUE 4 H BEHIND UTC +MAURITANIA ON UTC +MAURITIUS 4 H AHEAD OF UTC +MARIANA ISLAND 10 H AHEAD OF UTC EXCLUDING GUAM +MEXICO BAJA CAL N 7 H BEHIND UTC BAJA CALIFORNIA SUR AND +MEXICO BAJA CAL N N. PACIFIC COAST (STATES +MEXICO BAJA CAL N OF SINALOA AND SONORA) +MEXICO BAJA CAL N 8 H BEHIND UTC ABOVE 28TH PARALLAL APR 3 +MEXICO BAJA CAL N - OCT 29 +MEXICO BAJA CAL N 7 H BEHIND UTC ABOVE 28TH PARALLAL APR 3 +MEXICO BAJA CAL N - 0CT 29 +MEXICO 6 H BEHIND UTC STATES OF DURANGO, +MEXICO COAHUILA, NUEVO LEON, +MEXICO TAMAULIPAS +MEXICO 5 H BEHIND UTC STATES OF DURANGO, +MEXICO COAHUILA, NUEVO LEON, +MEXICO TAMAULIPAS APR 3 - OCT 29 +MEXICO 6 H BEHIND UTC GENERAL MEXICO, STATES OF +MEXICO CAMPECHE, QUINTANA ROO AND +MEXICO YUCATAN +MIDWAY ISLAND 11 H BEHIND UTC +MONACO 1 H AHEAD OF UTC +MONACO 2 H AHEAD OF UTC MAR 27 - SEP 24 +MONGOLIA 8 H AHEAD OF UTC +MONGOLIA 9 H AHEAD OF UTC MAR 27 - SEP 24 +MONTSERRAT 4 H BEHIND UTC +MOROCCO ON UTC +MOZAMBIQUE 2 H AHEAD OF UTC +NAMIBIA 2 H AHEAD OF UTC +NAURU, REP OF 12 H AHEAD OF UTC +NEPAL 5H45M AHEAD OF UTC +NETHERLANDS 1 H AHEAD OF UTC +NETHERLANDS 2 H AHEAD OF UTC MAR 27 - SEP 24 +NETHERLANDS 4 H BEHIND UTC ANTILLES AND SOUTHERN ST. +NETHERLANDS MAARTEN +NEW CALEDONIA 11 H AHEAD OF UTC +NEW HEBRIDES SEE VANUATU +NEW ZEALAND 12 H AHEAD OF UTC (EXCLUDING CHATHAM ISLAND) +NEW ZEALAND 13 H AHEAD OF UTC OCT 30, '88-MAR 4, '89 +NEW ZEALAND 12H45M AHEAD OF UTC CHATHAM ISLAND +NICARAGUA 6 H BEHIND UTC +NIGER 1 H AHEAD OF UTC +NIGERIA 1 H AHEAD OF UTC +NIUE ISLAND 11 H BEHIND UTC +NORFOLK ISLAND 11H30M AHEAD OF UTC +NORTHERN IRELAND ON UTC WALES, SCOTLAND, N.I., +NORTHERN IRELAND CH.IS. +NORTHERN IRELAND 1 H AHEAD OF UTC MAR 27 - OCT 22 +NORWAY 1 H AHEAD OF UTC +NORWAY 2 H AHEAD OF UTC MAR 27 - SEP 24 +OGO ON UTC +OMAN 4 H AHEAD OF UTC +PACIFIC ISLAND T.T. +PALAU ISLAND 9 H AHEAD OF UTC +PAKISTAN 5 H AHEAD OF UTC +PANAMA 5 H BEHIND UTC +PAPUA NEW GUINEA 10 H AHEAD OF UTC INCLUDING BOUGAINVILLE +PAPUA NEW GUINEA ISLAND +PARAGUAY 4 H BEHIND UTC +PARAGUAY 3 H BEHIND UTC OCT 1, '88-MAR 31, '89 +PERU 5 H BEHIND UTC +PHILIPPINES 8 H AHEAD OF UTC +PONAPE ISLAND 11 H AHEAD OF UTC +POLAND 1 H AHEAD OF UTC +POLAND 2 H AHEAD OF UTC MAR 27 - SEP 24 +PORTUGAL MAINLAND ON UTC +PORTUGAL MAINLAND 1 H AHEAD OF UTC MAR 27 - SEP 24 +PORTUGAL AZORES 1 H BEHIND UTC +PORTUGAL AZORES ON UTC MAR 27 - SEP 24 +PORTUGAL MADEIRA ON UTC +PORTUGAL MADEIRA 1 H AHEAD OF UTC MAR 27 - SEP 24 +PUERTO RICO 4 H BEHIND UTC +QATAR 3 H AHEAD OF UTC +ROMANIA 2 H AHEAD OF UTC +ROMANIA 3 H AHEAD OF UTC MAR 27 - SEP 24 +RUSSIA SEE USSR +RWANDA 2 H AHEAD OF UTC +SABA 4 H BEHIND UTC ALSO BONAIRE, CURACAO, +SAMOA 11 H BEHIND UTC +SAN MARINO 1 H AHEAD OF UTC +SAN MARINO 2 H AHEAD OF UTC MAR 27 - SEP 24 +SAN SALVADOR 6 H BEHIND UTC +SAO TOME ISLAND ON UTC AND PRINCIPE ISLAND +SAUDI ARABIA 3 H AHEAD OF UTC +SCOTLAND SEE ENGLAND +SENEGAL ON UTC +SEYCHELLES 4 H AHEAD OF UTC +SIERRA LEONE ON UTC +SINGAPORE 8 H AHEAD OF UTC +SOLOMON ISLANDS 11 H AHEAD OF UTC EXCLUDING BOUGAINVILLE +SOLOMON ISLANDS ISLAND +SOMALI 3 H AHEAD OF UTC +SOUTH AFRICA 2 H AHEAD OF UTC +SPAIN CANARY IS ON UTC +SPAIN CANARY IS 1 H AHEAD OF UTC MAR 27 - SEP 24 +SPAIN 1 H AHEAD OF UTC CONTINENTAL, BALEARIC AND +SPAIN MALLORCA ISLANDS +SPAIN 2 H AHEAD OF UTC CONTINENTAL, BALEARIC AND +SPAIN MALLORCA ISLANDS MAR 27 - +SPAIN SEP 24 +SPAIN MAINLAND 1 H AHEAD OF UTC MELILLA +SPAIN MAINLAND 2 H AHEAD OF UTC MAR 27 - SEP 24 +SRI LANKA 5H30M AHEAD OF UTC +ST.MAARTEN +ST.KITTS-NEVIS 4 H BEHIND UTC +ST.LUCIA 4 H BEHIND UTC +ST.PIERRE 3 H BEHIND UTC INCLUDING MIQUELON +ST.PIERRE 2 H BEHIND UTC INLCUDING MIQUELON APR 3 +ST.PIERRE - OCT 29 +ST.VINCENT 4 H BEHIND UTC INCLUDING THE GRENADINES +ST. HELENA ON UTC +SURINAME 3 H BEHIND UTC +SWAZILAND 2 H AHEAD OF UTC +SWEDEN 1 H AHEAD OF UTC +SWEDEN 2 H AHEAD OF UTC MAR 27 - SEP 24 +SWITZERLAND 1 H AHEAD OF UTC +SWITZERLAND 2 H AHEAD OF UTC MAR 27 - SEP 24 +SYRIA 2 H AHEAD OF UTC +SYRIA 3 H AHEAD OF UTC MAR 15 - OCT 30 +TAHITI 10 H BEHIND UTC +TANZANIA 3 H AHEAD OF UTC +THAILAND 7 H AHEAD OF UTC +TRINIDAD / TOBAGO 4 H BEHIND UTC +TUNISIA 1 H AHEAD OF UTC +TUNISIA 2 H AHEAD OF UTC APR 10 - SEP 24 +TURKEY 2 H AHEAD OF UTC +TURKEY 3 H AHEAD OF UTC MAR 27 - SEP 24 +TURKS AND CAICOS 5 H BEHIND UTC +TURKS AND CAICOS 4 H BEHIND UTC APR 3 - OCT 29 +TUVALU 12 H AHEAD OF UTC +UDAN 2 H AHEAD OF UTC +UGANDA 3 H AHEAD OF UTC +UNITED ARAB EMIR. 4 H AHEAD OF UTC ABU DHABI, DUBAI, SHARJAH, +UNITED ARAB EMIR RAS AL KHAIMAH +UNITED KINGDOM ON UTC WALES, SCOTLAND, N.I., CH. +UNITED KINGDOM IS. +UNITED KINGDOM 1 H AHEAD OF UTC MAR 27 - OCT 22 +UNITED STATES SEE USA +UPPER VOLTA ON UTC +URUGUAY 3 H BEHIND UTC +URUGUAY 2 H BEHIND UTC DEC 11, '88-FEB 25, '89 +URAGUAY (ESTIMATED) +USA EASTERN 5 H BEHIND UTC NEW YORK, WASHINGTON +USA EASTERN 4 H BEHIND UTC APR 3 - OCT 30 +USA CENTRAL 6 H BEHIND UTC CHICAGO, HOUSTON +USA CENTRAL 5 H BEHIND UTC APR 3 - OCT 30 +USA MOUNTAIN 7 H BEHIND UTC DENVER +USA MOUNTAIN 6 H BEHIND UTC APR 3 - OCT 30 +USA PACIFIC 8 H BEHIND UTC L.A., SAN FRANCISCO +USA PACIFIC 7 H BEHIND UTC APR 3 - OCT 30 +USA ALASKA STD 9 H BEHIND UTC MOST OF ALASKA (AKST) +USA ALASKA STD 8 H BEHIND UTC APR 3 - OCT 30 (AKDT) +USA ALEUTIAN 10 H BEHIND UTC ISLANDS WEST OF 170W +USA - " - 9 H BEHIND UTC APR 3 - OCT 30 +USA HAWAII 10 H BEHIND UTC +USA BERING 11 H BEHIND UTC SAMOA, MIDWAY +USA FOR SPECIFIC INFO ON USA ZONES/TIMES CALL DOT 202-426-4520 +USSR WEST EUROP 3 H AHEAD OF UTC LENINGRAD, MOSCOW +USSR WEST EUROP 4 H AHEAD OF UTC APR 1 - SEP 30 +USSR CENTRAL EUR 4 H AHEAD OF UTC ROSTOV, BAKU +USSR CENTRAL EUR 5 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST EUROP 5 H AHEAD OF UTC SVERDLOVSK +USSR EAST EUROP 6 H AHEAD OF UTC APR 1 - SEP 30 +USSR WEST SIBERIAN 6 H AHEAD OF UTC TASHKENT, ALMA ATA +USSR WEST SIBERIAN 7 H AHEAD OF UTC APR 1 - SEP 30 +USSR WEST-CENTRAL 7 H AHEAD OF UTC NOVOSIBIRSK +USSR WEST-CENTRAL 8 H AHEAD OF UTC APR 1 - SEP 30 +USSR WEST-CENTRAL 8 H AHEAD OF UTC IRKUTSK +USSR WEST-CENTRAL 9 H AHEAD OF UTC APR 1 - SEP 30 +USSR CENTRAL SIB 9 H AHEAD OF UTC YAKUTSK +USSR CENTRAL SIB 10 H AHEAD OF UTC APR 1 - SEP 30 +USSR CENTRAL SIB 10 H AHEAD OF UTC VLADIVOSTOK +USSR CENTRAL SIB 11 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST SIBERIA 11 H AHEAD OF UTC MAGADAN +USSR EAST SIBERIA 12 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST SIBERIA 12 H AHEAD OF UTC PETROPAVLOVSK +USSR EAST SIBERIA 13 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST SIBERIA 13 H AHEAD OF UTC UELEN +USSR EAST SIBERIA 14 H AHEAD OF UTC APR 1 - SEP 30 +VANUATU 11 H AHEAD OF UTC (NEW HEBRIDES) +VANUATU 12 H AHEAD OF UTC SEP 25, '88-MAR 25, '89 +VANUATU (ESTIMATED) +VATICAN 1 H AHEAD OF UTC +VATICAN 2 H AHEAD OF UTC MAR 27 - SEP 24 +VIETNAM 7 H AHEAD OF UTC +VIRGIN ISLANDS 4 H BEHIND UTC ST.CROIX, ST.THOMAS, +VIRGIN ISLANDS ST.JOHN +WAKE ISLAND 12 H AHEAD OF UTC +WALES SEE ENGLAND +WALLIS/FUTUNA IS. 12 H AHEAD OF UTC +WINDWARD ISLANDS 4 H BEHIND UTC GRENADA, ST. LUCIA +YEMEN 3 H AHEAD OF UTC BOTH REPUBLICS +YUGOSLAVIA 1 H AHEAD OF UTC +YUGOSLAVIA 2 H AHEAD OF UTC MAR 27 - SEP 24 +ZAIRE EAST 1 H AHEAD OF UTC KINSHASA MBANDAKA +ZAIRE WEST 2 H AHEAD OF UTC LUBUMBASHI, KASAI, KIVU, +ZAIRE WEST HAUT-ZAIRE, SHABA +ZAMBIA 2 H AHEAD OF UTC +ZIMBABWE 2 H AHEAD OF UTC diff --git a/unused/usno1989a b/unused/usno1989a new file mode 100644 index 00000000000..b197b85bb1d --- /dev/null +++ b/unused/usno1989a @@ -0,0 +1,452 @@ +# @(#)usno1989a 8.1 +# +# From Arthur David Olson (1994-02-07): +# +# Here's time zone information from the United States Naval Observatory, +# with corrections from Paul Eggert. +# The USNO warns: +# DUE TO FREQUENT CHANGES IN THE LOCAL LAWS GOVERNING DAYLIGHT +# SAVING TIME, WE CANNOT GUARANTEE THE ACCURACY OF THIS +# INFORMATION. PLEASE ALERT US TO ANY DISCREPANCY YOU MAY +# DISCOVER. +# +AFGHANISTAN 4.5H AHEAD OF UTC +ALBANIA 1 H AHEAD OF UTC +ALBANIA 2 H AHEAD OF UTC MAR 27 - SEP 24 +ALBANIA (ESTIMATED) +ALGERIA 1 H AHEAD OF UTC +AMERICAN SAMOA 11 H BEHIND UTC +ANDORRA 1 H AHEAD OF UTC +ANDORRA 2 H AHEAD OF UTC MAR 27 - SEP 24 +ANDORRA (ESTIMATED) +ANGOLA 1 H AHEAD OF UTC +ARGENTINA 3 H BEHIND UTC +ARUBA 4 H BEHIND UTC ALSO BONAIRE, CURACAO, +ARUBA ST.MAARTEN +AUSTRALIA WEST 8 H AHEAD OF UTC PERTH, EXMOUTH +AUSTRALIA N.T. 9.5H AHEAD OF UTC DARWIN NO ADVANCED TIME +AUSTRALIA N.T. IN SUMMER +AUSTRALIA SOUTH 9.5H AHEAD OF UTC ADELAIDE +AUSTRALIA INCLUDING BROKEN HILL, NSW +AUSTRALIA SOUTH 10.5H AHEAD OF UTC ADELAIDE OCT 30, '88-MAR +AUSTRALIA SOUTH 18, '89 INCLUDING BROKEN +AUSTRIALIA SOUTH HILL, NSW +AUSTRALIA QUEENL 10 H AHEAD OF UTC +AUSTRALIA NSW 10 H AHEAD OF UTC SYDNEY +AUSTRALIA NSW 11 H AHEAD OF UTC SYDNEY OCT 30, '88-MAR 18, +AUSTRALIA NSW '89 +AUSTRALIA TASM. 10 H AHEAD OF UTC HOBART +AUSTRALIA TASM. 11 H AHEAD OF UTC HOBART OCT 30, '88-MAR 18, +AUSTRALIA TASM. '89 +AUSTRIA 1 H AHEAD OF UTC +AUSTRIA 2 H AHEAD OF UTC MAR 27 - SEPT 24 +AZORES SEE PORTUGAL +BAHAMAS 5 H BEHIND UTC EXCLUDING TURKS AND CAICOS +BAHAMAS ISLANDS) +BAHAMAS 4 H BEHIND UTC APR 3 - OCT 29 (SAME +BAHAMAS EXCLUSION) +BAHRAIN 3 H AHEAD OF UTC +BANGLADESH 6 H AHEAD OF UTC +BARBADOS 4 H BEHIND UTC +BELGIUM 1 H AHEAD OF UTC +BELGIUM 2 H AHEAD OF UTC MAR 27 - SEP 24 +BELIZE 6 H BEHIND UTC +BENIN PEOPLES REP 1 H AHEAD OF UTC DAHOMEY +BERMUDA 4 H BEHIND UTC +BERMUDA 3 H BEHIND UTC APR 3 - OCT 29 +BHUTAN 6 H AHEAD OF UTC +BOLIVIA 4 H BEHIND UTC +BONAIRE 4 H BEHIND UTC ALSO ARUBA,CURACAO, +BONAIRE ST.MAARTEN, SABA +BOTSWANA 2 H AHEAD OF UTC +BRAZIL WEST 5 H BEHIND UTC TERRITORY OF ACRE +BRAZIL WEST 4 H BEHIND UTC ACRE OCT 23, '88-FEB 11, +BRAZIL '89 (ESTIMATED) +BRAZIL CENTRAL 4 H BEHIND UTC MANAUS +BRAZIL CENTRAL 3 H BEHIND UTC MANAUS OCT 23, '88-FEB 11, +BRAZIL CENTRAL '89 (ESTIMATED) +BRAZIL EAST 3 H BEHIND UTC COASTAL STATES, RIO, SAO +BRAZIL EAST PAULO, BRASILIA +BRAZIL EAST 2 H BEHIND UTC COASTAL STATES, RIO, SAO +BRAZIL PAULO, BRASILIA OCT 23, +BRAZIL '88-FEB 11, '89 +BRAZIL (ESTIMATED) +BRAZIL 2 H BEHIND UTC ATLANTIC ISLANDS, FERNANDO +BRAZIL DE NORONHA +BRAZIL 1 H BEHIND UTC OCT 23, '88-FEB 11, '89 +BRAZIL (ESTIMATED) +BRAZIL 3 H BEHIND UTC FOR MOST MAJOR AIRPORTS. +BRITISH VIRGIN I. 4 H BEHIND UTC +BRUNEI 8 H AHEAD OF UTC +BULGARIA 2 H AHEAD OF UTC +BULGARIA 3 H AHEAD OF UTC MAR 27 - SEP 24 +BURKINA FASO ON UTC +BURMA 6.5H AHEAD OF UTC +BURUNDI 2 H AHEAD OF UTC +CAMBODIA SEE KAMPUCHEA +CAMEROON 1 H AHEAD OF UTC +CANADA NEW FDL 3.5H BEHIND UTC ST.JOHN'S +CANADA NEW FDL 1.5H BEHIND UTC APR 3 - OCT 29 +CANADA ATLANTIC 4 H BEHIND UTC HALIFAX +CANADA ATLANTIC 3 H BEHIND UTC APR 3 - OCT 29 +CANADA EASTERN 5 H BEHIND UTC TORONTO, MONTREAL, OTTAWA +CANADA EASTERN 4 H BEHIND UTC APR 3 - OCT 29 +CANADA CENTRAL 6 H BEHIND UTC REGINA, WINNIPEG +CANADA CENTRAL 5 H BEHIND UTC APR 3 - OCT 29 +CANADA MOUNTAIN 7 H BEHIND UTC CALGARY, EDMONTON +CANADA MOUNTAIN 6 H BEHIND UTC APR 3 - OCT 29 +CANADA PACIFIC 8 H BEHIND UTC VANCOUVER +CANADA PACIFIC 7 H BEHIND UTC APR 3 - OCT 29 +CANADA YUKON SAME AS PACIFIC DAWSON +CAPE VERDE 1 H BEHIND UTC +CAYMAN ISLANDS 5 H BEHIND UTC +CAROLINE ISLAND 10 H AHEAD OF UTC EXCLUDING PONAPE IS., +CAROLINE ISLAND KUSAIE, AND PINGELAP +CENTRAL AFRICA 1 H AHEAD OF UTC +CEYLON 5.5H AHEAD OF UTC, SEE SRI LANKA +CHAD 1 H AHEAD OF UTC +CHANNEL ISLANDS SEE ENGLAND +CHILE 4 H BEHIND UTC CONTINENTAL +CHILE 3 H BEHIND UTC OCT 9, '88-MAR 11, '89 +CHILE 6 H BEHIND UTC EASTER ISLAND +CHILE 5 H BEHIND UTC OCT 9, '88-MAR 11, '89 +CHINA 8 H AHEAD OF UTC ALL OF CHINA, INCL TAIWAN +CHINA 9 H AHEAD OF UTC APR 17 - SEP 10 +COCOS (Keeling) I. 6.5H AHEAD OF UTC +COLOMBIA 5 H BEHIND UTC +COMOROS 3 H AHEAD OF UTC +CONGO 1 H AHEAD OF UTC +COOK ISLANDS 10 H BEHIND UTC +COOK ISLANDS 9.5H BEHIND UTC OCT 30, '88-MAR 24, '89 +COOK ISLANDS (ESTIMATED) +COSTA RICA 6 H BEHIND UTC +COTE D'IVOIRE ON UTC +CUBA 5 H BEHIND UTC +CUBA 4 H BEHIND UTC MAR 20 - OCT 8 +CURACAO 4 H BEHIND UTC ALSO BONAIRE, ARUBA, +CURACAO ST.MAARTEN +CYPRUS 2 H AHEAD OF UTC +CYPRUS 3 H AHEAD OF UTC MAR 27 - SEP 24 +CZECHOSLOVAKIA 1 H AHEAD OF UTC +CZECHOSLOVAKIA 2 H AHEAD OF UTC MAR 27 - SEP 24 +DENMARK 1 H AHEAD OF UTC +DENMARK 2 H AHEAD OF UTC MAR 27 - SEP 24 +DENMK. FAEROE IS 1 H AHEAD OF UTC MAR 27 - SEP 24 +DJIBOUTI 3 H AHEAD OF UTC +DOMINICA 4 H BEHIND UTC +DOMINICAN REP 4 H BEHIND UTC +ECUADOR 5 H BEHIND UTC CONTINENTAL +ECUADOR 6 H BEHIND UTC GALAPAGOS ISLANDS +EGYPT 2 H AHEAD OF UTC +EGYPT 3 H AHEAD OF UTC MAY 17 - SEP 30 (AFTER +EGYPT RAMADAN) +EL SALVADOR 6 H BEHIND UTC +ENGLAND ON UTC (WALES, SCOTLAND, N.I., +ENGLAND CH. IS.) +ENGLAND 1 H AHEAD OF UTC MAR 27 - OCT 22 +EQUATORIAL GUINEA 1 H AHEAD OF UTC +ETHIOPIA 3 H AHEAD OF UTC +FALKLAND ISLANDS 4 H BEHIND UTC +FALKLAND ISLANDS 3 H BEHIND UTC SEP 11, '88-APR 15, '89 +FALKLAND ISLANDS (ESTIMATED) +FAROE ISLAND ON UTC +FAROE ISLAND 1 H AHEAD OF UTC MAR 27 - SEP 24 +FIJI 12 H AHEAD OF UTC +FINLAND 2 H AHEAD OF UTC +FINLAND 3 H AHEAD OF UTC MAR 27 - SEP 24 +FRANCE 1 H AHEAD OF UTC +FRANCE 2 H AHEAD OF UTC MAR 27 - SEP 24 +FRENCH GUIANA 3 H BEHIND UTC +FRENCH POLYNESIA 9 H BEHIND UTC GAMBIER ISLAND +FRENCH POLYNESIA 9.5H BEHIND UTC MARQUESAS ISLANDS +FRENCH POLYNESIA 10 H BEHIND UTC SOCIETY ISLANDS, TUBUAI +FRENCH POLYNESIA ISLANDS, TUAMOTU ISLAND, +FRENCH POLYNESIA TAHITI +GABON 1 H AHEAD OF UTC +GAMBIA ON UTC +GERMANY ALL 1 H AHEAD OF UTC +GERMANY ALL 2 H AHEAD OF UTC MAR 27 - SEP 24 +GHANA ON UTC +GIBRALTAR 1 H AHEAD OF UTC +GIBRALTAR 2 H AHEAD OF UTC MAR 27 - SEP 24 +GREECE 2 H AHEAD OF UTC +GREECE 3 H AHEAD OF UTC MAR 27 - SEP 24 +GREENLAND 4 H BEHIND UTC THULE AIRBASE YEAR ROUND +GREENLAND 3 H BEHIND UTC ANGMAGSSALIK AND W. COAST +GREENLAND 2 H BEHIND UTC MAR 27 - SEP 24 +GREENLAND 1 H BEHIND UTC SCORESBYSUND +GREENLAND ON UTC MAR 27 - SEP 24 +GRENADA 4 H BEHIND UTC +GUADELOUPE 4 H BEHIND UTC ST. BARTHELEMY, NORTHERN +GUADELOUPE ST. MARTIN MARTINIQUE +GUAM 10 H AHEAD OF UTC +GUATEMALA 6 H BEHIND UTC +GUINEA ON UTC +GUINEA BISSAU ON UTC +GUINEA REPUBLIC ON UTC +GUINEA EQUATORIAL 1 H AHEAD OF UTC +GUYANA 3 H BEHIND UTC +HAITI 5 H BEHIND UTC +HAITI 4 H BEHIND UTC APR 3 - OCT 29 +HOLLAND SEE NETHERLANDS +HONDURAS 6 H BEHIND UTC +HONG KONG 8 H AHEAD OF UTC +HUNGARY 1 H AHEAD OF UTC +HUNGARY 2 H AHEAD OF UTC MAR 27 - SEP 24 +ICELAND ON UTC +INDIA 5.5H AHEAD OF UTC INCLUDING ANDAMAN ISLANDS +INDONESIA WEST 7 H AHEAD OF UTC SUMATRA, JAVA, BALI, +INDONESIA WEST JAKARTA +INDONESIA CENTRAL 8 H AHEAD OF UTC KALIMANTAN, SULAWESI +INDONESIA EAST 9 H AHEAD OF UTC IRIAN, BARAT +IRAN 3.5H AHEAD OF UTC +IRAQ 3 H AHEAD OF UTC +IRAQ 4 H AHEAD OF UTC APR 1 - SEP 30 +IRELAND ON UTC +IRELAND 1 H AHEAD OF UTC MAR 27 - OCT 22 +ISRAEL 2 H AHEAD OF UTC +ISRAEL 3 H AHEAD OF UTC APR 10 - SEP 3 +ITALY 1 H AHEAD OF UTC +ITALY 2 H AHEAD OF UTC MAR 27 - SEP 24 +IVORY COAST ON UTC +JAMAICA 5 H BEHIND UTC +JAPAN 9 H AHEAD OF UTC +JOHNSTON ISLAND 10 H BEHIND UTC +JORDAN 2 H AHEAD OF UTC +JORDAN 3 H AHEAD OF UTC APR 1 - OCT 6 +KAMPUCHEA 7 H AHEAD OF UTC +KENYA 3 H AHEAD OF UTC +KIRIBATI, REP OF 12 H AHEAD OF UTC CANTON, ENDERBURY ISLANDS +KIRIBATI, REP OF 11 H AHEAD OF UTC CHRISTMAS ISLAND +KOREA 9 H AHEAD OF UTC +KOREA, REP OF 9 H AHEAD OF UTC +KOREA, REP OF 10 H AHEAD OF UTC MAY 8 - OCT 8 +KUWAIT 3 H AHEAD OF UTC +KUSAIE, PINGELAP 12 H AHEAD OF UTC INCLUDING MARSHALL IS., +KUSAIE, PINGELAP EXCLUDING KWAJALEIN) +KWAJALEIN 12 H BEHIND UTC +LAOS 7 H AHEAD OF UTC +LEBANON 2 H AHEAD OF UTC +LEBANON 3 H AHEAD OF UTC JUN 1 - OCT 31 +LEEWARD ISLANDS 4 H BEHIND UTC ANTIGUA, DOMINICA, +LEEWARD ISLANDS MONTSERRAT, ST. +LEEWARD ISLAANDS CHRISTOPHER, ST. KITTS, +LEEWARD ISLANDS NEVIS, ANGUILLA +LESOTHO 2 H AHEAD OF UTC +LIBERIA ON UTC +LIBYAN ARAB 1 H AHEAD OF UTC JAMAHIRIYA/LIBYA +LIBYAN ARAB 2 H AHEAD OF UTC APR 1 - SEP 30 JAMAHIRIYA/LIBYA +LIECHTENSTEIN 1 H AHEAD OF UTC +LIECHTENSTEIN 2 H AHEAD OF UTC MAR 27 - SEP 24 +LUXEMBOURG 1 H AHEAD OF UTC +LUXEMBOURG 2 H AHEAD OF UTC MAR 27 - SEP 24 +MACAO 8 H AHEAD OF UTC +MADAGASCAR 3 H AHEAD OF UTC +MADEIRA SEE PORTUGAL +MALAWI 2 H AHEAD OF UTC +MALAYSIA 8 H AHEAD OF UTC +MALDIVES 5 H AHEAD OF UTC +MALI ON UTC +MALTA 1 H AHEAD OF UTC +MALTA 2 H AHEAD OF UTC MAR 27 - SEP 24 +MARTINIQUE 4 H BEHIND UTC +MAURITANIA ON UTC +MAURITIUS 4 H AHEAD OF UTC +MARIANA ISLANDS 10 H AHEAD OF UTC EXCLUDING GUAM +MEXICO BAJA CAL N 7 H BEHIND UTC BAJA CALIFORNIA SUR AND +MEXICO BAJA CAL N N. PACIFIC COAST (STATES +MEXICO BAJA CAL N OF SINALOA AND SONORA) +MEXICO BAJA CAL N 8 H BEHIND UTC ABOVE 28TH PARALLAL APR 3 +MEXICO BAJA CAL N - OCT 29 +MEXICO BAJA CAL N 7 H BEHIND UTC ABOVE 28TH PARALLAL APR 3 +MEXICO BAJA CAL N - 0CT 29 +MEXICO 6 H BEHIND UTC STATES OF DURANGO, +MEXICO COAHUILA, NUEVO LEON, +MEXICO TAMAULIPAS +MEXICO 5 H BEHIND UTC STATES OF DURANGO, +MEXICO COAHUILA, NUEVO LEON, +MEXICO TAMAULIPAS APR 3 - OCT 29 +MEXICO 6 H BEHIND UTC GENERAL MEXICO, STATES OF +MEXICO CAMPECHE, QUINTANA ROO AND +MEXICO YUCATAN +MIDWAY ISLAND 11 H BEHIND UTC +MONACO 1 H AHEAD OF UTC +MONACO 2 H AHEAD OF UTC MAR 27 - SEP 24 +MONGOLIA 8 H AHEAD OF UTC +MONGOLIA 9 H AHEAD OF UTC MAR 27 - SEP 24 +MONTSERRAT 4 H BEHIND UTC +MOROCCO ON UTC +MOZAMBIQUE 2 H AHEAD OF UTC +NAMIBIA 2 H AHEAD OF UTC +NAURU, REP OF 12 H AHEAD OF UTC +NEPAL 5H45M AHEAD OF UTC +NETHERLANDS 1 H AHEAD OF UTC +NETHERLANDS 2 H AHEAD OF UTC MAR 27 - SEP 24 +NETHERLANDS 4 H BEHIND UTC ANTILLES AND SOUTHERN ST. +NETHERLANDS MAARTEN +NEW CALEDONIA 11 H AHEAD OF UTC +NEW HEBRIDES SEE VANUATU +NEW ZEALAND 12 H AHEAD OF UTC (EXCLUDING CHATHAM ISLAND) +NEW ZEALAND 13 H AHEAD OF UTC OCT 30, '88-MAR 4, '89 +NEW ZEALAND 12H45M AHEAD OF UTC CHATHAM ISLAND +NICARAGUA 6 H BEHIND UTC +NIGER 1 H AHEAD OF UTC +NIGERIA 1 H AHEAD OF UTC +NIUE ISLAND 11 H BEHIND UTC +NORFOLK ISLAND 11H30M AHEAD OF UTC +NORTHERN IRELAND ON UTC WALES, SCOTLAND, N.I., +NORTHERN IRELAND CH.IS. +NORTHERN IRELAND 1 H AHEAD OF UTC MAR 27 - OCT 22 +NORWAY 1 H AHEAD OF UTC +NORWAY 2 H AHEAD OF UTC MAR 27 - SEP 24 +OMAN 4 H AHEAD OF UTC +PACIFIC ISLAND T.T. +PALAU ISLANDS 9 H AHEAD OF UTC +PAKISTAN 5 H AHEAD OF UTC +PANAMA 5 H BEHIND UTC +PAPUA NEW GUINEA 10 H AHEAD OF UTC INCLUDING BOUGAINVILLE +PAPUA NEW GUINEA ISLAND +PARAGUAY 4 H BEHIND UTC +PARAGUAY 3 H BEHIND UTC OCT 1, '88-MAR 31, '89 +PERU 5 H BEHIND UTC +PHILIPPINES 8 H AHEAD OF UTC +PONAPE ISLAND 11 H AHEAD OF UTC +POLAND 1 H AHEAD OF UTC +POLAND 2 H AHEAD OF UTC MAR 27 - SEP 24 +PORTUGAL MAINLAND ON UTC +PORTUGAL MAINLAND 1 H AHEAD OF UTC MAR 27 - SEP 24 +PORTUGAL AZORES 1 H BEHIND UTC +PORTUGAL AZORES ON UTC MAR 27 - SEP 24 +PORTUGAL MADEIRA ON UTC +PORTUGAL MADEIRA 1 H AHEAD OF UTC MAR 27 - SEP 24 +PUERTO RICO 4 H BEHIND UTC +QATAR 3 H AHEAD OF UTC +ROMANIA 2 H AHEAD OF UTC +ROMANIA 3 H AHEAD OF UTC MAR 27 - SEP 24 +RUSSIA SEE USSR +RWANDA 2 H AHEAD OF UTC +SABA 4 H BEHIND UTC ALSO BONAIRE, CURACAO, +SAMOA 11 H BEHIND UTC +SAN MARINO 1 H AHEAD OF UTC +SAN MARINO 2 H AHEAD OF UTC MAR 27 - SEP 24 +SAN SALVADOR 6 H BEHIND UTC +SAO TOME ISLAND ON UTC AND PRINCIPE ISLAND +SAUDI ARABIA 3 H AHEAD OF UTC +SCOTLAND SEE ENGLAND +SENEGAL ON UTC +SEYCHELLES 4 H AHEAD OF UTC +SIERRA LEONE ON UTC +SINGAPORE 8 H AHEAD OF UTC +SOLOMON ISLANDS 11 H AHEAD OF UTC EXCLUDING BOUGAINVILLE +SOLOMON ISLANDS ISLAND +SOMALI 3 H AHEAD OF UTC +SOUTH AFRICA 2 H AHEAD OF UTC +SPAIN CANARY IS ON UTC +SPAIN CANARY IS 1 H AHEAD OF UTC MAR 27 - SEP 24 +SPAIN 1 H AHEAD OF UTC CONTINENTAL, BALEARIC AND +SPAIN MALLORCA ISLANDS +SPAIN 2 H AHEAD OF UTC CONTINENTAL, BALEARIC AND +SPAIN MALLORCA ISLANDS MAR 27 - +SPAIN SEP 24 +SPAIN MAINLAND 1 H AHEAD OF UTC MELILLA +SPAIN MAINLAND 2 H AHEAD OF UTC MAR 27 - SEP 24 +SRI LANKA 5H30M AHEAD OF UTC +ST. MAARTEN +ST. KITTS-NEVIS 4 H BEHIND UTC +ST. LUCIA 4 H BEHIND UTC +ST. PIERRE 3 H BEHIND UTC INCLUDING MIQUELON +ST. PIERRE 2 H BEHIND UTC INLCUDING MIQUELON APR 3 +ST. PIERRE - OCT 29 +ST. VINCENT 4 H BEHIND UTC INCLUDING THE GRENADINES +ST. HELENA ON UTC +SUDAN 2 H AHEAD OF UTC +SURINAME 3 H BEHIND UTC +SWAZILAND 2 H AHEAD OF UTC +SWEDEN 1 H AHEAD OF UTC +SWEDEN 2 H AHEAD OF UTC MAR 27 - SEP 24 +SWITZERLAND 1 H AHEAD OF UTC +SWITZERLAND 2 H AHEAD OF UTC MAR 27 - SEP 24 +SYRIA 2 H AHEAD OF UTC +SYRIA 3 H AHEAD OF UTC MAR 15 - OCT 30 +TAHITI 10 H BEHIND UTC +TAIWAN 8 H AHEAD OF UTC +TANZANIA 3 H AHEAD OF UTC +THAILAND 7 H AHEAD OF UTC +TOGO ON UTC +TRINIDAD / TOBAGO 4 H BEHIND UTC +TUNISIA 1 H AHEAD OF UTC +TUNISIA 2 H AHEAD OF UTC APR 10 - SEP 24 +TURKEY 2 H AHEAD OF UTC +TURKEY 3 H AHEAD OF UTC MAR 27 - SEP 24 +TURKS AND CAICOS 5 H BEHIND UTC +TURKS AND CAICOS 4 H BEHIND UTC APR 3 - OCT 29 +TUVALU 12 H AHEAD OF UTC +UGANDA 3 H AHEAD OF UTC +UNITED ARAB EMIR. 4 H AHEAD OF UTC ABU DHABI, DUBAI, SHARJAH, +UNITED ARAB EMIR RAS AL KHAIMAH +UNITED KINGDOM ON UTC WALES, SCOTLAND, N.I., CH. +UNITED KINGDOM IS. +UNITED KINGDOM 1 H AHEAD OF UTC MAR 27 - OCT 22 +UNITED STATES SEE USA +UPPER VOLTA ON UTC +URUGUAY 3 H BEHIND UTC +URUGUAY 2 H BEHIND UTC DEC 11, '88-FEB 25, '89 +URAGUAY (ESTIMATED) +USA EASTERN 5 H BEHIND UTC NEW YORK, WASHINGTON +USA EASTERN 4 H BEHIND UTC APR 3 - OCT 30 +USA CENTRAL 6 H BEHIND UTC CHICAGO, HOUSTON +USA CENTRAL 5 H BEHIND UTC APR 3 - OCT 30 +USA MOUNTAIN 7 H BEHIND UTC DENVER +USA MOUNTAIN 6 H BEHIND UTC APR 3 - OCT 30 +USA PACIFIC 8 H BEHIND UTC L.A., SAN FRANCISCO +USA PACIFIC 7 H BEHIND UTC APR 3 - OCT 30 +USA ALASKA STD 9 H BEHIND UTC MOST OF ALASKA (AKST) +USA ALASKA STD 8 H BEHIND UTC APR 3 - OCT 30 (AKDT) +USA ALEUTIAN 10 H BEHIND UTC ISLANDS WEST OF 170W +USA - " - 9 H BEHIND UTC APR 3 - OCT 30 +USA HAWAII 10 H BEHIND UTC +USA BERING 11 H BEHIND UTC SAMOA, MIDWAY +USA FOR SPECIFIC INFO ON USA ZONES/TIMES CALL DOT 202-426-4520 +USSR WEST EUROP 3 H AHEAD OF UTC LENINGRAD, MOSCOW +USSR WEST EUROP 4 H AHEAD OF UTC APR 1 - SEP 30 +USSR CENTRAL EUR 4 H AHEAD OF UTC ROSTOV, BAKU +USSR CENTRAL EUR 5 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST EUROP 5 H AHEAD OF UTC SVERDLOVSK +USSR EAST EUROP 6 H AHEAD OF UTC APR 1 - SEP 30 +USSR WEST SIBERIAN 6 H AHEAD OF UTC TASHKENT, ALMA ATA +USSR WEST SIBERIAN 7 H AHEAD OF UTC APR 1 - SEP 30 +USSR WEST-CENTRAL 7 H AHEAD OF UTC NOVOSIBIRSK +USSR WEST-CENTRAL 8 H AHEAD OF UTC APR 1 - SEP 30 +USSR WEST-CENTRAL 8 H AHEAD OF UTC IRKUTSK +USSR WEST-CENTRAL 9 H AHEAD OF UTC APR 1 - SEP 30 +USSR CENTRAL SIB 9 H AHEAD OF UTC YAKUTSK +USSR CENTRAL SIB 10 H AHEAD OF UTC APR 1 - SEP 30 +USSR CENTRAL SIB 10 H AHEAD OF UTC VLADIVOSTOK +USSR CENTRAL SIB 11 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST SIBERIA 11 H AHEAD OF UTC MAGADAN +USSR EAST SIBERIA 12 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST SIBERIA 12 H AHEAD OF UTC PETROPAVLOVSK +USSR EAST SIBERIA 13 H AHEAD OF UTC APR 1 - SEP 30 +USSR EAST SIBERIA 13 H AHEAD OF UTC UELEN +USSR EAST SIBERIA 14 H AHEAD OF UTC APR 1 - SEP 30 +VANUATU 11 H AHEAD OF UTC (NEW HEBRIDES) +VANUATU 12 H AHEAD OF UTC SEP 25, '88-MAR 25, '89 +VANUATU (ESTIMATED) +VATICAN 1 H AHEAD OF UTC +VATICAN 2 H AHEAD OF UTC MAR 27 - SEP 24 +VENEZUELA 4 H BEHIND UTC +VIETNAM 7 H AHEAD OF UTC +VIRGIN ISLANDS 4 H BEHIND UTC ST.CROIX, ST.THOMAS, +VIRGIN ISLANDS ST.JOHN +WAKE ISLAND 12 H AHEAD OF UTC +WALES SEE ENGLAND +WALLIS/FUTUNA IS. 12 H AHEAD OF UTC +WINDWARD ISLANDS 4 H BEHIND UTC GRENADA, ST. LUCIA +YEMEN 3 H AHEAD OF UTC BOTH REPUBLICS +YUGOSLAVIA 1 H AHEAD OF UTC +YUGOSLAVIA 2 H AHEAD OF UTC MAR 27 - SEP 24 +ZAIRE EAST 1 H AHEAD OF UTC KINSHASA MBANDAKA +ZAIRE WEST 2 H AHEAD OF UTC LUBUMBASHI, KASAI, KIVU, +ZAIRE WEST HAUT-ZAIRE, SHABA +ZAMBIA 2 H AHEAD OF UTC +ZIMBABWE 2 H AHEAD OF UTC diff --git a/unused/usno1995 b/unused/usno1995 new file mode 100644 index 00000000000..8b9ec8d601d --- /dev/null +++ b/unused/usno1995 @@ -0,0 +1,326 @@ +# @(#)usno1995 8.1 +# +# From Arthur David Olson (1995-12-21): +# +# Here's time zone information from the United States Naval Observatory +# via http://tycho.usno.navy.mil/tzones.html. See USNO's note at the end. +World Time Zones +For selected countries, the local standard time offset from UTC is given, +with daylight savings time where observed. +Time: Thu Dec 21 17:43:00 utc 1995 +Afghanistan: +4.5 hours +Albania: +1 hours (Local summer +2 hours) +Algeria: +1 hours (Local summer +2 hours) +American Samoa: -11 hours +Andorra: +1 hours (Local summer +2 hours) +Angola: +1 hours +Anguilla: -4 hours +Antarctica: -2 hours (Local summer -3 hours) +Antigua: -4 hours +Argentina: -3 hours +Argentina western prov: -4 hours +Armenia: +4 hours (Local summer +5 hours) +Aruba: -4 hours +Ascension: 0 hours +Australia Northern Territory: +9.5 hours +Australia Lord Howe Island: +10.5 hours (Local summer +11 hours) +Australia New South Wales: +10 hours (Local summer +11 hours) +Australia Queensland: +10 hours +Australia Victoria: +10 hours (Local summer +11 hours) +Australia Australian Captial Territory: +10 hours (Local summer +11 hours) +Australia South: +9.5 hours (Local summer +10.5 hours) +Australia Tasmania: +10 hours (Local summer +11 hours) +Australia Western: +8 hours +Austria: +1 hours (Local summer +2 hours) +Azerbajian: +3 hours +Azores: -1 hours (Local summer 0 hours) +Bahamas: -5 hours (Local summer -4 hours) +Bahrain: +3 hours +Balearic Islands: +1 hours (Local summer +2 hours) +Bangladesh: +6 hours +Barbados: -4 hours +Belarus: +2 hours (Local summer +3 hours) +Belgium: +1 hours (Local summer +2 hours) +Belize: -6 hours +Benin: +1 hours +Bermuda: -4 hours (Local summer -3 hours) +Bhutan: +6 hours +Bolivia: -4 hours +Bonaire: -4 hours +Bosnia Hercegovina: +1 hours (Local summer +2 hours) +Botswana: +2 hours +Brazil Acre: -4 hours (Local summer -5 hours) +Brazil Atlantic Islands: -1 hours (Local summer -2 hours) +Brazil East: -3 hours (Local summer -1 hours) +Brazil West: -4 hours (Local summer -3 hours) +British Virgin Islands: -4 hours +Brunei: +8 hours +Bulgaria: +2 hours (Local summer +3 hours) +Burkina Faso: 0 hours +Burundi: +2 hours +Cambodia: +7 hours +Cameroon: +1 hours +Canada Central: -6 hours (Local summer -5 hours) +Canada Eastern: -5 hours (Local summer -4 hours) +Canada Mountain: -7 hours (Local summer -6 hours) +Canada Yukon & Pacific: -8 hours (Local summer -7 hours) +Canada Atlantic: -4 hours (Local summer -3 hours) +Canada Newfoundland: -3.5 hours (Local summer -2.5 hours) +Canary Islands: 0 hours (Local summer +1 hours) +Canton Enderbury Islands: -11 hours +Cape Verde: -1 hours +Caroline Island: +11 hours +Cayman Islands: -5 hours +Central African Rep: +1 hours +Chad: +1 hours +Channel Islands: 0 hours (Local summer +1 hours) +Chatham Island: +12.75 hours (Local summer +13.75 hours) +Chile: -4 hours (Local summer -3 hours) +China People's Rep: +8 hours +Christmas Islands: -10 hours +Cocos (Keeling) Islands: ( hours (Local summer ) hours) +Colombia: -5 hours +Congo: +1 hours +Cook Islands: -10 hours +Costa Rica: -6 hours +Cote d'Ivoire: 0 hours +Croatia: +1 hours (Local summer +2 hours) +Cuba: -5 hours (Local summer -4 hours) +Curacao: -4 hours +Cyprus: +2 hours (Local summer +3 hours) +Czech Republic: +1 hours (Local summer +2 hours) +Dahomey: +1 hours +Denmark: +1 hours (Local summer +2 hours) +Djibouti: +3 hours +Dominica: -4 hours +Dominican Republic: -4 hours +Easter Island: -6 hours (Local summer -5 hours) +Ecuador: -5 hours +Egypt: +2 hours (Local summer +3 hours) +El Salvador: -6 hours +England: 0 hours (Local summer +1 hours) +Equitorial Guinea: +1 hours +Eritrea: +3 hours +Estonia: +2 hours (Local summer +3 hours) +Ethiopia: +3 hours +Falkland Islands: -4 hours (Local summer -3 hours) +Faroe Island: 0 hours (Local summer +1 hours) +Fiji: +12 hours +Finland: +2 hours (Local summer +3 hours) +France: +1 hours (Local summer +2 hours) +French Guiana: -3 hours +French Polynesia: -10 hours +Gabon: +1 hours +Galapagos Islands: -6 hours +Gambia: 0 hours +Gambier Island: -9 hours +Georgia: +4 hours +Germany: +1 hours (Local summer +2 hours) +Ghana: 0 hours +Gibraltar: +1 hours (Local summer +2 hours) +Greece: +2 hours (Local summer +3 hours) +Greenland: -3 hours (Local summer -2 hours) +Greenland Thule: -4 hours (Local summer -3 hours) +Greenland Scoresbysun: -1 hours (Local summer 0 hours) +Grenada: -4 hours +Grenadines: -4 hours +Guadeloupe: -4 hours +Guam: +10 hours +Guatemala: -6 hours +Guinea: 0 hours +Guinea Bissau: - hours (Local summer 0 hours) +Guyana: -3 hours +Haiti: -5 hours (Local summer -4 hours) +Honduras: -6 hours +Hong kong: +8 hours +Hungary: +1 hours (Local summer +2 hours) +Iceland: 0 hours +India: +5.5 hours +Indonesia Central: +8 hours +Indonesia East: +9 hours +Indonesia West: +7 hours +Iran: +3.5 hours +Iraq: +3 hours (Local summer +4 hours) +Ireland Republic of: 0 hours (Local summer +1 hours) +Israel: +2 hours (Local summer +3 hours) +Italy: +1 hours (Local summer +2 hours) +Jamaica: -5 hours +Japan: +9 hours +Johnston Island: -10 hours +Jordan: +2 hours (Local summer +3 hours) +Kazakhstan: +6 hours (Local summer +7 hours) +Kenya: +3 hours +Kiribati: +12 hours +Korea Dem Republic of: +9 hours +Korea Republic of: +9 hours +Kusaie: +12 hours +Kuwait: +3 hours +Kwajalein: -12 hours +Kyrgyzstan: +5 hours (Local summer +6 hours) +Laos: +7 hours +Latvia: +2 hours (Local summer +3 hours) +Lebanon: +2 hours (Local summer +3 hours) +Leeward Islands: -4 hours +Lesotho: +2 hours +Liberia: 0 hours +Libya: +2 hours +Lithuania: +2 hours (Local summer +3 hours) +Luxembourg: +1 hours (Local summer +2 hours) +Macedonia: +1 hours (Local summer +2 hours) +Madagascar: +3 hours +Madeira: 0 hours (Local summer +1 hours) +Malawi: +2 hours +Malaysia: +8 hours +Maldives: +5 hours +Mali: 0 hours +Mallorca Islands: +1 hours (Local summer +2 hours) +Malta: +1 hours (Local summer +2 hours) +Mariana Island: +10 hours +Marquesas Islands: -9.5 hours +Marshall Islands: +12 hours +Martinique: -4 hours +Mauritania: 0 hours +Mauritius: +4 hours +Mayotte: +3 hours +Melilla: +1 hours (Local summer +2 hours) +Mexico: -6 hours +Mexico Baja Calif Norte: -8 hours (Local summer -7 hours) +Mexico Nayarit: -7 hours +Mexico Sinaloa: -7 hours +Mexico Sonora: -7 hours +Midway Island: -11 hours +Moldova: +2 hours (Local summer +3 hours) +Moldovian Rep Pridnestrovye: +2 hours (Local summer +3 hours) +Monaco: +1 hours (Local summer +2 hours) +Mongolia: +8 hours +Morocco: 0 hours +Mozambique: +2 hours +Myanmar: +6.5 hours +Namibia: +1 hours (Local summer +2 hours) +Nauru Republic of: +12 hours +Nepal: +5.75 hours +Netherlands: +1 hours (Local summer +2 hours) +Netherlands Antilles: -4 hours +Nevis Montserrat: -4 hours +New Caledonia: +11 hours +New Hebrides: +11 hours +New Zealand: +12 hours (Local summer +13 hours) +Nicaragua: -6 hours (Local summer -5 hours) +Niger: +1 hours +Nigeria: +1 hours +Niue Island: -11 hours +Norfolk Island: +11.5 hours +Northern Ireland: 0 hours (Local summer +1 hours) +Northern Mariana Islands: +10 hours +Norway: +1 hours (Local summer +2 hours) +Oman: +4 hours +Pakistan: +5 hours +Palau: +9 hours +Panama: -5 hours +Papua New Guinea: +10 hours +Paraguay: -4 hours (Local summer -3 hours) +Peru: -5 hours +Philippines: +8 hours +Pingelap: +12 hours +Poland: +1 hours (Local summer +2 hours) +Ponape Island: +11 hours +Portugal: +1 hours (Local summer +2 hours) +Principe Island: 0 hours +Puerto Rico: -4 hours +Qatar: +3 hours +Reunion: +4 hours +Romania: +2 hours (Local summer +3 hours) +Russian Federation zone eight: +9 hours (Local summer +10 hours) +Russian Federation zone eleven: +12 hours (Local summer +13 hours) +Russian Federation zone five: +6 hours (Local summer +7 hours) +Russian Federation zone four: +5 hours (Local summer +6 hours) +Russian Federation zone nine: +10 hours (Local summer +11 hours) +Russian Federation zone one: +2 hours (Local summer +3 hours) +Russian Federation zone seven: +8 hours (Local summer +9 hours) +Russian Federation zone six: +7 hours (Local summer +8 hours) +Russian Federation zone ten: +11 hours (Local summer +12 hours) +Russian Federation zone three: +4 hours (Local summer +5 hours) +Russian Federation zone two: +4 hours (Local summer +5 hours) +Rwanda: +2 hours +Saba: -4 hours +Samoa: -11 hours +San Marino: +1 hours (Local summer +2 hours) +Sao Tome e Principe: 0 hours +Saudi Arabia: +3 hours +Scotland: 0 hours +Senegal: 0 hours +Seychelles: +4 hours +Sierra Leone: 0 hours +Singapore: +8 hours +Slovakia: +1 hours (Local summer +2 hours) +Slovenia: +1 hours (Local summer +2 hours) +Society Island: -10 hours +Solomon Islands: +11 hours +Somalia: +3 hours +South Africa: +2 hours +Spain: +1 hours (Local summer +2 hours) +Sri Lanka: +5.5 hours +St Christopher: -4 hours +St Croix: -4 hours +St Helena: 0 hours +St John: -4 hours +St Kitts Nevis: -4 hours +St Lucia: -4 hours +St Maarten: -4 hours +St Pierre & Miquelon: -3 hours (Local summer -2 hours) +St Thomas: -4 hours +St Vincent: -4 hours +Sudan: +2 hours +Suriname: -3 hours +Swaziland: +2 hours +Sweden: +1 hours (Local summer +2 hours) +Switzerland: +1 hours (Local summer +2 hours) +Syria: +2 hours (Local summer +3 hours) +Tahiti: -10 hours +Taiwan: +8 hours +Tajikistan: +6 hours +Tanzania: +3 hours +Thailand: +7 hours +Togo: 0 hours +Tonga: +13 hours +Trinidad and Tobago: -4 hours +Tuamotu Island: -10 hours +Tubuai Island: -10 hours +Tunisia: +1 hours +Turkey: +2 hours (Local summer +3 hours) +Turkmenistan: +5 hours +Turks and Caicos Islands: -5 hours (Local summer -4 hours) +Tuvalu: +12 hours +Uganda: +3 hours +Ukraine: +2 hours (Local summer +3 hours) +United Arab Emirates: +4 hours +United Kingdom: 0 hours (Local summer +1 hours) +USA Central: -6 hours (Local summer -5 hours) +USA Eastern: -5 hours (Local summer -4 hours) +USA Mountain: -7 hours (Local summer -6 hours) +USA Arizona: -7 hours +USA Indiana East: -5 hours +USA Pacific: -8 hours (Local summer -7 hours) +USA Alaska: -9 hours (Local summer -8 hours) +USA Hawaii Aleutian: - hours (Local summer -10 hours) +Uruguay: -3 hours +Uzbekistan: +5 hours +Vanuatu: +11 hours (Local summer +12 hours) +Vatican City: +1 hours (Local summer +2 hours) +Venezuela: -4 hours +Vietnam: +7 hours +Virgin Islands: -4 hours +Wake Island: +12 hours +Wales: 0 hours (Local summer +1 hours) +Wallis and Futuna Islands: +12 hours +Windward Islands: -4 hours +Yemen: +3 hours +Yugoslavia: +1 hours (Local summer +2 hours) +Zaire Kasai: +2 hours +Zaire Kinshasa Mbandaka: +1 hours +Zaire Haut Zaire: +2 hours +Zaire Kivu: +2 hours +Zaire Shaba: +2 hours +Zambia: +2 hours +Zimbabwe: +2 hours +All timezone information is non-authoritative... diff --git a/unused/usno1997 b/unused/usno1997 new file mode 100644 index 00000000000..e18fcdfcdcb --- /dev/null +++ b/unused/usno1997 @@ -0,0 +1,327 @@ +# @(#)usno1997 8.1 +# +# From Arthur David Olson (1997-03-07): +# +# Here's time zone information from the United States Naval Observatory +# via http://tycho.usno.navy.mil/tzones.html. See USNO's note at the end. +Unofficial Time Zone Information +World Time Zones +For selected countries, the local standard time offset from UTC is given, with daylight savings time where observed. +Time: Fri Mar 7 22:38:58 UTC 1997 +Afghanistan: +4.5 hours +Albania: +1 hours (Local summer +2 hours) +Algeria: +1 hours (Local summer +2 hours) +American Samoa: -11 hours +Andorra: +1 hours (Local summer +2 hours) +Angola: +1 hours +Anguilla: -4 hours +Antarctica: -2 hours (Local summer -3 hours) +Antigua: -4 hours +Argentina: -3 hours +Argentina western prov: -4 hours +Armenia: +4 hours (Local summer +5 hours) +Aruba: -4 hours +Ascension: 0 hours +Australia Northern Territory: +9.5 hours +Australia Lord Howe Island: +10.5 hours (Local summer +11 hours) +Australia New South Wales: +10 hours (Local summer +11 hours) +Australia Queensland: +10 hours +Australia Victoria: +10 hours (Local summer +11 hours) +Australia Australian Captial Territory: +10 hours (Local summer +11 hours) +Australia South: +9.5 hours (Local summer +10.5 hours) +Australia Tasmania: +10 hours (Local summer +11 hours) +Australia Western: +8 hours +Austria: +1 hours (Local summer +2 hours) +Azerbajian: +3 hours +Azores: -1 hours (Local summer 0 hours) +Bahamas: -5 hours (Local summer -4 hours) +Bahrain: +3 hours +Balearic Islands: +1 hours (Local summer +2 hours) +Bangladesh: +6 hours +Barbados: -4 hours +Belarus: +2 hours (Local summer +3 hours) +Belgium: +1 hours (Local summer +2 hours) +Belize: -6 hours +Benin: +1 hours +Bermuda: -4 hours (Local summer -3 hours) +Bhutan: +6 hours +Bolivia: -4 hours +Bonaire: -4 hours +Bosnia Hercegovina: +1 hours (Local summer +2 hours) +Botswana: +2 hours +Brazil Acre: -4 hours (Local summer -5 hours) +Brazil Atlantic Islands: -1 hours (Local summer -2 hours) +Brazil East: -3 hours (Local summer -1 hours) +Brazil West: -4 hours (Local summer -3 hours) +British Virgin Islands: -4 hours +Brunei: +8 hours +Bulgaria: +2 hours (Local summer +3 hours) +Burkina Faso: 0 hours +Burundi: +2 hours +Cambodia: +7 hours +Cameroon: +1 hours +Canada Central: -6 hours (Local summer -5 hours) +Canada Eastern: -5 hours (Local summer -4 hours) +Canada Mountain: -7 hours (Local summer -6 hours) +Canada Yukon & Pacific: -8 hours (Local summer -7 hours) +Canada Atlantic: -4 hours (Local summer -3 hours) +Canada Newfoundland: -3.5 hours (Local summer -2.5 hours) +Canary Islands: 0 hours (Local summer +1 hours) +Canton Enderbury Islands: -11 hours +Cape Verde: -1 hours +Caroline Island: +11 hours +Cayman Islands: -5 hours +Central African Rep: +1 hours +Chad: +1 hours +Channel Islands: 0 hours (Local summer +1 hours) +Chatham Island: +12.75 hours (Local summer +13.75 hours) +Chile: -4 hours (Local summer -3 hours) +China People's Rep: +8 hours +Christmas Islands: -10 hours +Cocos (Keeling) Islands: ( hours (Local summer ) hours) +Colombia: -5 hours +Congo: +1 hours +Cook Islands: -10 hours +Costa Rica: -6 hours +Cote d'Ivoire: 0 hours +Croatia: +1 hours (Local summer +2 hours) +Cuba: -5 hours (Local summer -4 hours) +Curacao: -4 hours +Cyprus: +2 hours (Local summer +3 hours) +Czech Republic: +1 hours (Local summer +2 hours) +Dahomey: +1 hours +Denmark: +1 hours (Local summer +2 hours) +Djibouti: +3 hours +Dominica: -4 hours +Dominican Republic: -4 hours +Easter Island: -6 hours (Local summer -5 hours) +Ecuador: -5 hours +Egypt: +2 hours (Local summer +3 hours) +El Salvador: -6 hours +England: 0 hours (Local summer +1 hours) +Equitorial Guinea: +1 hours +Eritrea: +3 hours +Estonia: +2 hours (Local summer +3 hours) +Ethiopia: +3 hours +Falkland Islands: -4 hours (Local summer -3 hours) +Faroe Island: 0 hours (Local summer +1 hours) +Fiji: +12 hours +Finland: +2 hours (Local summer +3 hours) +France: +1 hours (Local summer +2 hours) +French Guiana: -3 hours +French Polynesia: -10 hours +Gabon: +1 hours +Galapagos Islands: -5 hours +Gambia: 0 hours +Gambier Island: -9 hours +Georgia: +4 hours +Germany: +1 hours (Local summer +2 hours) +Ghana: 0 hours +Gibraltar: +1 hours (Local summer +2 hours) +Greece: +2 hours (Local summer +3 hours) +Greenland: -3 hours (Local summer -2 hours) +Greenland Thule: -4 hours (Local summer -3 hours) +Greenland Scoresbysun: -1 hours (Local summer 0 hours) +Grenada: -4 hours +Grenadines: -4 hours +Guadeloupe: -4 hours +Guam: +10 hours +Guatemala: -6 hours +Guinea: 0 hours +Guinea Bissau: - hours (Local summer 0 hours) +Guyana: -3 hours +Haiti: -5 hours (Local summer -4 hours) +Honduras: -6 hours +Hong kong: +8 hours +Hungary: +1 hours (Local summer +2 hours) +Iceland: 0 hours +India: +5.5 hours +Indonesia Central: +8 hours +Indonesia East: +9 hours +Indonesia West: +7 hours +Iran: +3.5 hours +Iraq: +3 hours (Local summer +4 hours) +Ireland Republic of: 0 hours (Local summer +1 hours) +Israel: +2 hours (Local summer +3 hours) +Italy: +1 hours (Local summer +2 hours) +Jamaica: -5 hours +Japan: +9 hours +Johnston Island: -10 hours +Jordan: +2 hours (Local summer +3 hours) +Kazakhstan: +6 hours (Local summer +7 hours) +Kenya: +3 hours +Kiribati: +12 hours +Korea Dem Republic of: +9 hours +Korea Republic of: +9 hours +Kusaie: +12 hours +Kuwait: +3 hours +Kwajalein: -12 hours +Kyrgyzstan: +5 hours (Local summer +6 hours) +Laos: +7 hours +Latvia: +2 hours (Local summer +3 hours) +Lebanon: +2 hours (Local summer +3 hours) +Leeward Islands: -4 hours +Lesotho: +2 hours +Liberia: 0 hours +Libya: +2 hours +Lithuania: +2 hours (Local summer +3 hours) +Luxembourg: +1 hours (Local summer +2 hours) +Macedonia: +1 hours (Local summer +2 hours) +Madagascar: +3 hours +Madeira: 0 hours (Local summer +1 hours) +Malawi: +2 hours +Malaysia: +8 hours +Maldives: +5 hours +Mali: 0 hours +Mallorca Islands: +1 hours (Local summer +2 hours) +Malta: +1 hours (Local summer +2 hours) +Mariana Island: +10 hours +Marquesas Islands: -9.5 hours +Marshall Islands: +12 hours +Martinique: -4 hours +Mauritania: 0 hours +Mauritius: +4 hours +Mayotte: +3 hours +Melilla: +1 hours (Local summer +2 hours) +Mexico: -6 hours +Mexico Baja Calif Norte: -8 hours (Local summer -7 hours) +Mexico Nayarit: -7 hours +Mexico Sinaloa: -7 hours +Mexico Sonora: -7 hours +Midway Island: -11 hours +Moldova: +2 hours (Local summer +3 hours) +Moldovian Rep Pridnestrovye: +2 hours (Local summer +3 hours) +Monaco: +1 hours (Local summer +2 hours) +Mongolia: +8 hours +Morocco: 0 hours +Mozambique: +2 hours +Myanmar: +6.5 hours +Namibia: +1 hours (Local summer +2 hours) +Nauru Republic of: +12 hours +Nepal: +5.75 hours +Netherlands: +1 hours (Local summer +2 hours) +Netherlands Antilles: -4 hours +Nevis Montserrat: -4 hours +New Caledonia: +11 hours +New Hebrides: +11 hours +New Zealand: +12 hours (Local summer +13 hours) +Nicaragua: -6 hours (Local summer -5 hours) +Niger: +1 hours +Nigeria: +1 hours +Niue Island: -11 hours +Norfolk Island: +11.5 hours +Northern Ireland: 0 hours (Local summer +1 hours) +Northern Mariana Islands: +10 hours +Norway: +1 hours (Local summer +2 hours) +Oman: +4 hours +Pakistan: +5 hours +Palau: +9 hours +Panama: -5 hours +Papua New Guinea: +10 hours +Paraguay: -4 hours (Local summer -3 hours) +Peru: -5 hours +Philippines: +8 hours +Pingelap: +12 hours +Poland: +1 hours (Local summer +2 hours) +Ponape Island: +11 hours +Portugal: +1 hours (Local summer +2 hours) +Principe Island: 0 hours +Puerto Rico: -4 hours +Qatar: +3 hours +Reunion: +4 hours +Romania: +2 hours (Local summer +3 hours) +Russian Federation zone eight: +9 hours (Local summer +10 hours) +Russian Federation zone eleven: +12 hours (Local summer +13 hours) +Russian Federation zone five: +6 hours (Local summer +7 hours) +Russian Federation zone four: +5 hours (Local summer +6 hours) +Russian Federation zone nine: +10 hours (Local summer +11 hours) +Russian Federation zone one: +2 hours (Local summer +3 hours) +Russian Federation zone seven: +8 hours (Local summer +9 hours) +Russian Federation zone six: +7 hours (Local summer +8 hours) +Russian Federation zone ten: +11 hours (Local summer +12 hours) +Russian Federation zone three: +4 hours (Local summer +5 hours) +Russian Federation zone two: +4 hours (Local summer +5 hours) +Rwanda: +2 hours +Saba: -4 hours +Samoa: -11 hours +San Marino: +1 hours (Local summer +2 hours) +Sao Tome e Principe: 0 hours +Saudi Arabia: +3 hours +Scotland: 0 hours (Local summer +1 hours) +Senegal: 0 hours +Seychelles: +4 hours +Sierra Leone: 0 hours +Singapore: +8 hours +Slovakia: +1 hours (Local summer +2 hours) +Slovenia: +1 hours (Local summer +2 hours) +Society Island: -10 hours +Solomon Islands: +11 hours +Somalia: +3 hours +South Africa: +2 hours +Spain: +1 hours (Local summer +2 hours) +Sri Lanka: +5.5 hours +St Christopher: -4 hours +St Croix: -4 hours +St Helena: 0 hours +St John: -4 hours +St Kitts Nevis: -4 hours +St Lucia: -4 hours +St Maarten: -4 hours +St Pierre & Miquelon: -3 hours (Local summer -2 hours) +St Thomas: -4 hours +St Vincent: -4 hours +Sudan: +2 hours +Suriname: -3 hours +Swaziland: +2 hours +Sweden: +1 hours (Local summer +2 hours) +Switzerland: +1 hours (Local summer +2 hours) +Syria: +2 hours (Local summer +3 hours) +Tahiti: -10 hours +Taiwan: +8 hours +Tajikistan: +6 hours +Tanzania: +3 hours +Thailand: +7 hours +Togo: 0 hours +Tonga: +13 hours +Trinidad and Tobago: -4 hours +Tuamotu Island: -10 hours +Tubuai Island: -10 hours +Tunisia: +1 hours +Turkey: +2 hours (Local summer +3 hours) +Turkmenistan: +5 hours +Turks and Caicos Islands: -5 hours (Local summer -4 hours) +Tuvalu: +12 hours +Uganda: +3 hours +Ukraine: +2 hours (Local summer +3 hours) +United Arab Emirates: +4 hours +United Kingdom: 0 hours (Local summer +1 hours) +USA Central: -6 hours (Local summer -5 hours) +USA Eastern: -5 hours (Local summer -4 hours) +USA Mountain: -7 hours (Local summer -6 hours) +USA Arizona: -7 hours +USA Indiana East: -5 hours +USA Pacific: -8 hours (Local summer -7 hours) +USA Alaska: -9 hours (Local summer -8 hours) +USA Aleutian: -10 hours +USA Hawaii: -10 hours +Uruguay: -3 hours +Uzbekistan: +5 hours +Vanuatu: +11 hours (Local summer +12 hours) +Vatican City: +1 hours (Local summer +2 hours) +Venezuela: -4 hours +Vietnam: +7 hours +Virgin Islands: -4 hours +Wake Island: +12 hours +Wales: 0 hours (Local summer +1 hours) +Wallis and Futuna Islands: +12 hours +Windward Islands: -4 hours +Yemen: +3 hours +Yugoslavia: +1 hours (Local summer +2 hours) +Zaire Kasai: +2 hours +Zaire Kinshasa Mbandaka: +1 hours +Zaire Haut Zaire: +2 hours +Zaire Kivu: +2 hours +Zaire Shaba: +2 hours +Zambia: +2 hours +Zimbabwe: +2 hours +All timezone information is non-authoritative... diff --git a/unused/usno1998 b/unused/usno1998 new file mode 100644 index 00000000000..c3c6991aa61 --- /dev/null +++ b/unused/usno1998 @@ -0,0 +1,327 @@ +# @(#)usno1998 8.1 +# +# From Arthur David Olson (1998-05-26): +# +# Here's time zone information from the United States Naval Observatory +# via http://tycho.usno.navy.mil/tzones.html. See USNO's note at the end. +Unofficial Time Zone Information +World Time Zones +For selected countries, the local standard time offset from UTC is given, with daylight savings time where observed. +Time: Mon May 25 21:14:24 UTC 1998 +Afghanistan: +4.5 hours +Albania: +1 hours (Local summer +2 hours) +Algeria: +1 hours (Local summer +2 hours) +American Samoa: -11 hours +Andorra: +1 hours (Local summer +2 hours) +Angola: +1 hours +Anguilla: -4 hours +Antarctica: -2 hours (Local summer -3 hours) +Antigua: -4 hours +Argentina: -3 hours +Argentina western prov: -4 hours +Armenia: +4 hours (Local summer +5 hours) +Aruba: -4 hours +Ascension: 0 hours +Australia Northern Territory: +9.5 hours +Australia Lord Howe Island: +10.5 hours (Local summer +11 hours) +Australia New South Wales: +10 hours (Local summer +11 hours) +Australia Queensland: +10 hours +Australia Victoria: +10 hours (Local summer +11 hours) +Australia Australian Captial Territory: +10 hours (Local summer +11 hours) +Australia South: +9.5 hours (Local summer +10.5 hours) +Australia Tasmania: +10 hours (Local summer +11 hours) +Australia Western: +8 hours +Austria: +1 hours (Local summer +2 hours) +Azerbajian: +3 hours +Azores: -1 hours (Local summer 0 hours) +Bahamas: -5 hours (Local summer -4 hours) +Bahrain: +3 hours +Balearic Islands: +1 hours (Local summer +2 hours) +Bangladesh: +6 hours +Barbados: -4 hours +Belarus: +2 hours (Local summer +3 hours) +Belgium: +1 hours (Local summer +2 hours) +Belize: -6 hours +Benin: +1 hours +Bermuda: -4 hours (Local summer -3 hours) +Bhutan: +6 hours +Bolivia: -4 hours +Bonaire: -4 hours +Bosnia Hercegovina: +1 hours (Local summer +2 hours) +Botswana: +2 hours +Brazil Acre: -4 hours (Local summer -5 hours) +Brazil Atlantic Islands: -1 hours (Local summer -2 hours) +Brazil East: -3 hours (Local summer -1 hours) +Brazil West: -4 hours (Local summer -3 hours) +British Virgin Islands: -4 hours +Brunei: +8 hours +Bulgaria: +2 hours (Local summer +3 hours) +Burkina Faso: 0 hours +Burundi: +2 hours +Cambodia: +7 hours +Cameroon: +1 hours +Canada Central: -6 hours (Local summer -5 hours) +Canada Eastern: -5 hours (Local summer -4 hours) +Canada Mountain: -7 hours (Local summer -6 hours) +Canada Yukon & Pacific: -8 hours (Local summer -7 hours) +Canada Atlantic: -4 hours (Local summer -3 hours) +Canada Newfoundland: -3.5 hours (Local summer -2.5 hours) +Canary Islands: 0 hours (Local summer +1 hours) +Canton Enderbury Islands: -11 hours +Cape Verde: -1 hours +Caroline Island: +11 hours +Cayman Islands: -5 hours +Central African Rep: +1 hours +Chad: +1 hours +Channel Islands: 0 hours (Local summer +1 hours) +Chatham Island: +12.75 hours (Local summer +13.75 hours) +Chile: -4 hours (Local summer -3 hours) +China People's Rep: +8 hours +Christmas Islands: -10 hours +Cocos (Keeling) Islands: ( hours (Local summer ) hours) +Colombia: -5 hours +Congo: +1 hours +Cook Islands: -10 hours +Costa Rica: -6 hours +Cote d'Ivoire: 0 hours +Croatia: +1 hours (Local summer +2 hours) +Cuba: -5 hours (Local summer -4 hours) +Curacao: -4 hours +Cyprus: +2 hours (Local summer +3 hours) +Czech Republic: +1 hours (Local summer +2 hours) +Dahomey: +1 hours +Denmark: +1 hours (Local summer +2 hours) +Djibouti: +3 hours +Dominica: -4 hours +Dominican Republic: -4 hours +Easter Island: -6 hours (Local summer -5 hours) +Ecuador: -5 hours +Egypt: +2 hours (Local summer +3 hours) +El Salvador: -6 hours +England: 0 hours (Local summer +1 hours) +Equitorial Guinea: +1 hours +Eritrea: +3 hours +Estonia: +2 hours (Local summer +3 hours) +Ethiopia: +3 hours +Falkland Islands: -4 hours (Local summer -3 hours) +Faroe Island: 0 hours (Local summer +1 hours) +Fiji: +12 hours +Finland: +2 hours (Local summer +3 hours) +France: +1 hours (Local summer +2 hours) +French Guiana: -3 hours +French Polynesia: -10 hours +Gabon: +1 hours +Galapagos Islands: -5 hours +Gambia: 0 hours +Gambier Island: -9 hours +Georgia: +4 hours +Germany: +1 hours (Local summer +2 hours) +Ghana: 0 hours +Gibraltar: +1 hours (Local summer +2 hours) +Greece: +2 hours (Local summer +3 hours) +Greenland: -3 hours (Local summer -2 hours) +Greenland Thule: -4 hours (Local summer -3 hours) +Greenland Scoresbysun: -1 hours (Local summer 0 hours) +Grenada: -4 hours +Grenadines: -4 hours +Guadeloupe: -4 hours +Guam: +10 hours +Guatemala: -6 hours +Guinea: 0 hours +Guinea Bissau: - hours (Local summer 0 hours) +Guyana: -3 hours +Haiti: -5 hours (Local summer -4 hours) +Honduras: -6 hours +Hong kong: +8 hours +Hungary: +1 hours (Local summer +2 hours) +Iceland: 0 hours +India: +5.5 hours +Indonesia Central: +8 hours +Indonesia East: +9 hours +Indonesia West: +7 hours +Iran: +3.5 hours +Iraq: +3 hours (Local summer +4 hours) +Ireland Republic of: 0 hours (Local summer +1 hours) +Israel: +2 hours (Local summer +3 hours) +Italy: +1 hours (Local summer +2 hours) +Jamaica: -5 hours +Japan: +9 hours +Johnston Island: -10 hours +Jordan: +2 hours (Local summer +3 hours) +Kazakhstan: +6 hours (Local summer +7 hours) +Kenya: +3 hours +Kiribati: +12 hours +Korea Dem Republic of: +9 hours +Korea Republic of: +9 hours +Kusaie: +12 hours +Kuwait: +3 hours +Kwajalein: -12 hours +Kyrgyzstan: +5 hours (Local summer +6 hours) +Laos: +7 hours +Latvia: +2 hours (Local summer +3 hours) +Lebanon: +2 hours (Local summer +3 hours) +Leeward Islands: -4 hours +Lesotho: +2 hours +Liberia: 0 hours +Libya: +2 hours +Lithuania: +2 hours (Local summer +3 hours) +Luxembourg: +1 hours (Local summer +2 hours) +Macedonia: +1 hours (Local summer +2 hours) +Madagascar: +3 hours +Madeira: 0 hours (Local summer +1 hours) +Malawi: +2 hours +Malaysia: +8 hours +Maldives: +5 hours +Mali: 0 hours +Mallorca Islands: +1 hours (Local summer +2 hours) +Malta: +1 hours (Local summer +2 hours) +Mariana Island: +10 hours +Marquesas Islands: -9.5 hours +Marshall Islands: +12 hours +Martinique: -4 hours +Mauritania: 0 hours +Mauritius: +4 hours +Mayotte: +3 hours +Melilla: +1 hours (Local summer +2 hours) +Mexico: -6 hours +Mexico Baja Calif Norte: -8 hours (Local summer -7 hours) +Mexico Nayarit: -7 hours +Mexico Sinaloa: -7 hours +Mexico Sonora: -7 hours +Midway Island: -11 hours +Moldova: +2 hours (Local summer +3 hours) +Moldovian Rep Pridnestrovye: +2 hours (Local summer +3 hours) +Monaco: +1 hours (Local summer +2 hours) +Mongolia: +8 hours +Morocco: 0 hours +Mozambique: +2 hours +Myanmar: +6.5 hours +Namibia: +1 hours (Local summer +2 hours) +Nauru Republic of: +12 hours +Nepal: +5.75 hours +Netherlands: +1 hours (Local summer +2 hours) +Netherlands Antilles: -4 hours +Nevis Montserrat: -4 hours +New Caledonia: +11 hours +New Hebrides: +11 hours +New Zealand: +12 hours (Local summer +13 hours) +Nicaragua: -6 hours (Local summer -5 hours) +Niger: +1 hours +Nigeria: +1 hours +Niue Island: -11 hours +Norfolk Island: +11.5 hours +Northern Ireland: 0 hours (Local summer +1 hours) +Northern Mariana Islands: +10 hours +Norway: +1 hours (Local summer +2 hours) +Oman: +4 hours +Pakistan: +5 hours +Palau: +9 hours +Panama: -5 hours +Papua New Guinea: +10 hours +Paraguay: -4 hours (Local summer -3 hours) +Peru: -5 hours +Philippines: +8 hours +Pingelap: +12 hours +Poland: +1 hours (Local summer +2 hours) +Ponape Island: +11 hours +Portugal: +1 hours (Local summer +2 hours) +Principe Island: 0 hours +Puerto Rico: -4 hours +Qatar: +3 hours +Reunion: +4 hours +Romania: +2 hours (Local summer +3 hours) +Russian Federation zone eight: +9 hours (Local summer +10 hours) +Russian Federation zone eleven: +12 hours (Local summer +13 hours) +Russian Federation zone five: +6 hours (Local summer +7 hours) +Russian Federation zone four: +5 hours (Local summer +6 hours) +Russian Federation zone nine: +10 hours (Local summer +11 hours) +Russian Federation zone one: +2 hours (Local summer +3 hours) +Russian Federation zone seven: +8 hours (Local summer +9 hours) +Russian Federation zone six: +7 hours (Local summer +8 hours) +Russian Federation zone ten: +11 hours (Local summer +12 hours) +Russian Federation zone three: +4 hours (Local summer +5 hours) +Russian Federation zone two: +4 hours (Local summer +5 hours) +Rwanda: +2 hours +Saba: -4 hours +Samoa: -11 hours +San Marino: +1 hours (Local summer +2 hours) +Sao Tome e Principe: 0 hours +Saudi Arabia: +3 hours +Scotland: 0 hours (Local summer +1 hours) +Senegal: 0 hours +Seychelles: +4 hours +Sierra Leone: 0 hours +Singapore: +8 hours +Slovakia: +1 hours (Local summer +2 hours) +Slovenia: +1 hours (Local summer +2 hours) +Society Island: -10 hours +Solomon Islands: +11 hours +Somalia: +3 hours +South Africa: +2 hours +Spain: +1 hours (Local summer +2 hours) +Sri Lanka: +5.5 hours +St Christopher: -4 hours +St Croix: -4 hours +St Helena: 0 hours +St John: -4 hours +St Kitts Nevis: -4 hours +St Lucia: -4 hours +St Maarten: -4 hours +St Pierre & Miquelon: -3 hours (Local summer -2 hours) +St Thomas: -4 hours +St Vincent: -4 hours +Sudan: +2 hours +Suriname: -3 hours +Swaziland: +2 hours +Sweden: +1 hours (Local summer +2 hours) +Switzerland: +1 hours (Local summer +2 hours) +Syria: +2 hours (Local summer +3 hours) +Tahiti: -10 hours +Taiwan: +8 hours +Tajikistan: +6 hours +Tanzania: +3 hours +Thailand: +7 hours +Togo: 0 hours +Tonga: +13 hours +Trinidad and Tobago: -4 hours +Tuamotu Island: -10 hours +Tubuai Island: -10 hours +Tunisia: +1 hours +Turkey: +2 hours (Local summer +3 hours) +Turkmenistan: +5 hours +Turks and Caicos Islands: -5 hours (Local summer -4 hours) +Tuvalu: +12 hours +Uganda: +3 hours +Ukraine: +2 hours (Local summer +3 hours) +United Arab Emirates: +4 hours +United Kingdom: 0 hours (Local summer +1 hours) +USA Central: -6 hours (Local summer -5 hours) +USA Eastern: -5 hours (Local summer -4 hours) +USA Mountain: -7 hours (Local summer -6 hours) +USA Arizona: -7 hours +USA Indiana East: -5 hours +USA Pacific: -8 hours (Local summer -7 hours) +USA Alaska: -9 hours (Local summer -8 hours) +USA Aleutian: -10 hours +USA Hawaii: -10 hours +Uruguay: -3 hours +Uzbekistan: +5 hours +Vanuatu: +11 hours (Local summer +12 hours) +Vatican City: +1 hours (Local summer +2 hours) +Venezuela: -4 hours +Vietnam: +7 hours +Virgin Islands: -4 hours +Wake Island: +12 hours +Wales: 0 hours (Local summer +1 hours) +Wallis and Futuna Islands: +12 hours +Windward Islands: -4 hours +Yemen: +3 hours +Yugoslavia: +1 hours (Local summer +2 hours) +Zaire Kasai: +2 hours +Zaire Kinshasa Mbandaka: +1 hours +Zaire Haut Zaire: +2 hours +Zaire Kivu: +2 hours +Zaire Shaba: +2 hours +Zambia: +2 hours +Zimbabwe: +2 hours +All timezone information is non-authoritative... diff --git a/unused/workman.sh b/unused/workman.sh new file mode 100644 index 00000000000..cdf5b7311a8 --- /dev/null +++ b/unused/workman.sh @@ -0,0 +1,29 @@ +#! /bin/sh + +# @(#)workman.sh 8.1 + +# Tell groff not to emit SGR escape sequences (ANSI color escapes). +GROFF_NO_SGR=1 +export GROFF_NO_SGR + +echo ".am TH +.hy 0 +.na +.. +.rm }H +.rm }F" | nroff -man - ${1+"$@"} | perl -ne ' + chomp; + s/.\010//g; + s/\s*$//; + if (/^$/) { + $sawblank = 1; + next; + } else { + if ($sawblank && $didprint) { + print "\n"; + $sawblank = 0; + } + print "$_\n"; + $didprint = 1; + } +' diff --git a/unused/zdump.8.txt b/unused/zdump.8.txt new file mode 100644 index 00000000000..78c647f7636 --- /dev/null +++ b/unused/zdump.8.txt @@ -0,0 +1,43 @@ +NAME + + zdump - time zone dumper + +SYNOPSIS + zdump [ --version ] [ -v ] [ -c [loyear,]hiyear ] [ zonename + ... ] + +DESCRIPTION + Zdump prints the current time in each zonename named on the + command line. + + These options are available: + + --version + Output version information and exit. + + -v For each zonename on the command line, print the time + at the lowest possible time value, the time one day + after the lowest possible time value, the times both + one second before and exactly at each detected time + discontinuity, the time at one day less than the + highest possible time value, and the time at the + highest possible time value, Each line ends with + isdst=1 if the given time is Daylight Saving Time or + isdst=0 otherwise. + + -c [loyear,]hiyear + Cut off verbose output near the start of the given + year(s). By default, the program cuts off verbose + output near the starts of the years -500 and 2500. + +LIMITATIONS + The -v option may not be used on systems with floating-point + time_t values that are neither float nor double. + + Time discontinuities are found by sampling the results + returned by localtime at twelve-hour intervals. This works + in all real-world cases; one can construct artificial time + zones for which this fails. + +SEE ALSO + newctime(3), tzfile(5), zic(8) diff --git a/unused/zic.8.txt b/unused/zic.8.txt new file mode 100644 index 00000000000..3607ca768b1 --- /dev/null +++ b/unused/zic.8.txt @@ -0,0 +1,308 @@ +NAME + + zic - time zone compiler + +SYNOPSIS + zic [ --version ] [ -v ] [ -d directory ] [ -l localtime ] [ + -p posixrules ] [ -L leapsecondfilename ] [ -s ] [ -y + command ] [ filename ... ] + +DESCRIPTION + Zic reads text from the file(s) named on the command line + and creates the time conversion information files specified + in this input. If a filename is -, the standard input is + read. + + These options are available: + + --version + Output version information and exit. + + -d directory + Create time conversion information files in the named + directory rather than in the standard directory named + below. + + -l timezone + Use the given time zone as local time. Zic will act as + if the input contained a link line of the form + + Link timezone localtime + + -p timezone + Use the given time zone's rules when handling POSIX- + format time zone environment variables. Zic will act + as if the input contained a link line of the form + + Link timezone posixrules + + -L leapsecondfilename + Read leap second information from the file with the + given name. If this option is not used, no leap second + information appears in output files. + + -v Complain if a year that appears in a data file is + outside the range of years representable by time(2) + values. Also complain if a time of 24:00 (which cannot + be handled by pre-1998 versions of zic) appears in the + input. + + -s Limit time values stored in output files to values that + are the same whether they're taken to be signed or + unsigned. You can use this option to generate SVVS- + compatible files. + + -y command + Use the given command rather than yearistype when + checking year types (see below). + + Input lines are made up of fields. Fields are separated + from one another by any number of white space characters. + Leading and trailing white space on input lines is ignored. + An unquoted sharp character (#) in the input introduces a + comment which extends to the end of the line the sharp + character appears on. White space characters and sharp + characters may be enclosed in double quotes (") if they're + to be used as part of a field. Any line that is blank + (after comment stripping) is ignored. Non-blank lines are + expected to be of one of three types: rule lines, zone + lines, and link lines. + + A rule line has the form + + Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S + + For example: + + Rule US 1967 1973 - Apr lastSun 2:00 1:00 D + + The fields that make up a rule line are: + + NAME Gives the (arbitrary) name of the set of rules this + rule is part of. + + FROM Gives the first year in which the rule applies. Any + integer year can be supplied; the Gregorian calendar + is assumed. The word minimum (or an abbreviation) + means the minimum year representable as an integer. + The word maximum (or an abbreviation) means the + maximum year representable as an integer. Rules can + describe times that are not representable as time + values, with the unrepresentable times ignored; this + allows rules to be portable among hosts with + differing time value types. + + TO Gives the final year in which the rule applies. In + addition to minimum and maximum (as above), the word + only (or an abbreviation) may be used to repeat the + value of the FROM field. + + TYPE Gives the type of year in which the rule applies. + If TYPE is - then the rule applies in all years + between FROM and TO inclusive. If TYPE is something + else, then zic executes the command + yearistype year type + to check the type of a year: an exit status of zero + is taken to mean that the year is of the given type; + an exit status of one is taken to mean that the year + is not of the given type. + + IN Names the month in which the rule takes effect. + Month names may be abbreviated. + + ON Gives the day on which the rule takes effect. + Recognized forms include: + + 5 the fifth of the month + lastSun the last Sunday in the month + lastMon the last Monday in the month + Sun>=8 first Sunday on or after the eighth + Sun<=25 last Sunday on or before the 25th + + Names of days of the week may be abbreviated or + spelled out in full. Note that there must be no + spaces within the ON field. + AT Gives the time of day at which the rule takes + effect. Recognized forms include: + + 2 time in hours + 2:00 time in hours and minutes + 15:00 24-hour format time (for times after noon) + 1:28:14 time in hours, minutes, and seconds + - equivalent to 0 + + where hour 0 is midnight at the start of the day, + and hour 24 is midnight at the end of the day. Any + of these forms may be followed by the letter w if + the given time is local "wall clock" time, s if the + given time is local "standard" time, or u (or g or + z) if the given time is universal time; in the + absence of an indicator, wall clock time is assumed. + + SAVE Gives the amount of time to be added to local + standard time when the rule is in effect. This + field has the same format as the AT field (although, + of course, the w and s suffixes are not used). + + LETTER/S + Gives the "variable part" (for example, the "S" or + "D" in "EST" or "EDT") of time zone abbreviations to + be used when this rule is in effect. If this field + is -, the variable part is null. + + A zone line has the form + + Zone NAME GMTOFF RULES/SAVE FORMAT [UNTILYEAR [MONTH [DAY [TIME]]]] + + For example: + + Zone Australia/Adelaide 9:30 Aus CST 1971 Oct 31 2:00 + + The fields that make up a zone line are: + + NAME The name of the time zone. This is the name used in + creating the time conversion information file for the + zone. + + GMTOFF + The amount of time to add to UTC to get standard time + in this zone. This field has the same format as the + AT and SAVE fields of rule lines; begin the field with + a minus sign if time must be subtracted from UTC. + + RULES/SAVE + The name of the rule(s) that apply in the time zone + or, alternately, an amount of time to add to local + standard time. If this field is - then standard time + always applies in the time zone. + + FORMAT + The format for time zone abbreviations in this time + zone. The pair of characters %s is used to show where + the "variable part" of the time zone abbreviation + goes. Alternately, a slash (/) separates standard and + daylight abbreviations. + + UNTILYEAR [MONTH [DAY [TIME]]] + The time at which the UTC offset or the rule(s) change + for a location. It is specified as a year, a month, a + day, and a time of day. If this is specified, the + time zone information is generated from the given UTC + offset and rule change until the time specified. The + month, day, and time of day have the same format as + the IN, ON, and AT fields of a rule; trailing fields + can be omitted, and default to the earliest possible + value for the missing fields. + + The next line must be a "continuation" line; this has + the same form as a zone line except that the string + "Zone" and the name are omitted, as the continuation + line will place information starting at the time + specified as the "until" information in the previous + line in the file used by the previous line. + Continuation lines may contain "until" information, + just as zone lines do, indicating that the next line + is a further continuation. + + A link line has the form + + Link LINK-FROM LINK-TO + + For example: + + Link Europe/Istanbul Asia/Istanbul + + The LINK-FROM field should appear as the NAME field in some + zone line; the LINK-TO field is used as an alternate name + for that zone. + + Except for continuation lines, lines may appear in any order + in the input. + + Lines in the file that describes leap seconds have the + following form: + + Leap YEAR MONTH DAY HH:MM:SS CORR R/S + + For example: + + Leap 1974 Dec 31 23:59:60 + S + + The YEAR, MONTH, DAY, and HH:MM:SS fields tell when the leap + second happened. The CORR field should be "+" if a second + was added or "-" if a second was skipped. The R/S field + should be (an abbreviation of) "Stationary" if the leap + second time given by the other fields should be interpreted + as UTC or (an abbreviation of) "Rolling" if the leap second + time given by the other fields should be interpreted as + local wall clock time. + +EXTENDED EXAMPLE + Here is an extended example of zic input, intended to + illustrate many of its features. + + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S + Rule Swiss 1940 only - Nov 2 0:00 1:00 S + Rule Swiss 1940 only - Dec 31 0:00 0 - + Rule Swiss 1941 1942 - May Sun>=1 2:00 1:00 S + Rule Swiss 1941 1942 - Oct Sun>=1 0:00 0 + Rule EU 1977 1980 - Apr Sun>=1 1:00u 1:00 S + Rule EU 1977 only - Sep lastSun 1:00u 0 - + Rule EU 1978 only - Oct 1 1:00u 0 - + 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 - + + # Zone NAME GMTOFF RULES FORMAT UNTIL + Zone Europe/Zurich 0:34:08 - LMT 1848 Sep 12 + 0:29:44 - BMT 1894 Jun + 1:00 Swiss CE%sT 1981 + 1:00 EU CE%sT + + Link Europe/Zurich Switzerland + + In this example, the zone is named Europe/Zurich but it has + an alias as Switzerland. Zurich was 34 minutes and 8 + seconds west of GMT until 1848-09-12 at 00:00, when the + offset changed to 29 minutes and 44 seconds. After + 1894-06-01 at 00:00 Swiss daylight saving rules (defined + with lines beginning with "Rule Swiss") apply, and the GMT + offset became one hour. From 1981 to the present, EU + daylight saving rules have applied, and the UTC offset has + remained at one hour. + + In 1940, daylight saving time applied from November 2 at + 00:00 to December 31 at 00:00. In 1941 and 1942, daylight + saving time applied from the first Sunday in May at 02:00 to + the first Sunday in October at 00:00. The pre-1981 EU + daylight-saving rules have no effect here, but are included + for completeness. Since 1981, daylight saving has begun on + the last Sunday in March at 01:00 UTC. Until 1995 it ended + the last Sunday in September at 01:00 UTC, but this changed + to the last Sunday in October starting in 1996. + + For purposes of display, "LMT" and "BMT" were initially + used, respectively. Since Swiss rules and later EU rules + were applied, the display name for the timezone has been CET + for standard time and CEST for daylight saving time. + +NOTES + For areas with more than two types of local time, you may + need to use local standard time in the AT field of the + earliest transition time's rule to ensure that the earliest + transition time recorded in the compiled file is correct. + + If, for a particular zone, a clock advance caused by the + start of daylight saving coincides with and is equal to a + clock retreat caused by a change in UTC offset, zic produces + a single transition to daylight saving at the new UTC offset + (without any change in wall clock time). To get separate + transitions use multiple zone continuation lines specifying + transition instants using universal time. + +FILE + /usr/local/etc/zoneinfo standard directory used for + created files + +SEE ALSO + newctime(3), tzfile(5), zdump(8) diff --git a/unused/zoneinfo2tdf.pl b/unused/zoneinfo2tdf.pl new file mode 100755 index 00000000000..f34ca3e99c3 --- /dev/null +++ b/unused/zoneinfo2tdf.pl @@ -0,0 +1,54 @@ +#! /usr/bin/perl -w + +# @(#)zoneinfo2tdf.pl 8.2 + +# Courtesy Ken Pizzini. + +use strict; + +#This file released to the public domain. + +#Note: error checking is poor --- only trust the output if the input +#has been checked by zic. + +my $contZone = ''; +while (<>) { + my $origline = $_; + my @fields = (); + while (s/^\s*((?:"[^"]*"|[^\s#])+)//) { + push @fields, $1; + } + next unless @fields; + + my $type = lc($fields[0]); + if ($contZone) { + @fields >= 3 or warn "bad continuation line"; + unshift @fields, '+', $contZone; + $type = 'zone'; + } + + $contZone = ''; + if ($type eq 'zone') { + # Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL] + my $nfields = @fields; + $nfields >= 5 or warn "bad zone line"; + if ($nfields > 6) { + #this splice is optional, depending on one's preference + #(one big date-time field, or componentized date and time): + splice(@fields, 5, $nfields-5, "@fields[5..$nfields-1]"); + } + $contZone = $fields[1] if @fields > 5; + } elsif ($type eq 'rule') { + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S + @fields == 10 or warn "bad rule line"; + } elsif ($type eq 'link') { + # Link LINK-FROM LINK-TO + @fields == 3 or warn "bad link line"; + } elsif ($type eq 'leap') { + # Leap YEAR MONTH DAY HH:MM:SS CORR R/S + @fields == 7 or warn "bad leap line"; + } else { + warn "Fubar at input line $.: $origline"; + } + print join("\t", @fields), "\n"; +} diff --git a/zic/Music b/zic/Music deleted file mode 100644 index 9fb0cecacca..00000000000 --- a/zic/Music +++ /dev/null @@ -1,81 +0,0 @@ -@(#)Music 7.4 - -Data on recordings of "Save That Time," Russ Long, Serrob Publishing, BMI: --------------------------------------------------------------------------- -Artist: Karrin Allyson -CD: I Didn't Know About You -Copyright Date: 1993 -Label: Concord Jazz, Inc. -ID: CCD-4543 -Track Time: 3:44 -Personnel: Karrin Allyson, vocal - Russ Long, piano - Gerald Spaits, bass - Todd Strait, drums -Notes: CD notes "additional lyric by Karrin Allyson; - arranged by Russ Long and Karrin Allyson" -Rating: 1 star --------------------------------------------------------------------------- -Artist: Kevin Mahogany -CD: Double Rainbow -Copyright Date: 1993 -Label: Enja Records -ID: ENJ-7097 2 -Track Time: 6:27 -Personnel: Kevin Mahogany, vocal - Kenny Barron, piano - Ray Drummond, bss - Ralph Moore, tenor saxophone - Lewis Nash, drums -Rating: 1.5 stars --------------------------------------------------------------------------- -Artist: Joe Williams -CD: Here's to Life -Copyright Date: 1994 -Label: Telarc International Corporation -ID: CD-83357 -Track Time: 3:58 -Personnel: Joe Williams, vocal - The Robert Farnon [39 piece] Orchestra -Rating: black dot --------------------------------------------------------------------------- -Artist: Charles Fambrough -CD: Keeper of the Spirit -Copyright Date: 1995 -Label: AudioQuest Music -ID: AQ-CD1033 -Track Time: 7:07 -Personnel: Charles Fambrough, bass - Joel Levine, tenor recorder - Edward Simon, piano - Lenny White, drums - Marion Simon, percussion -Rating: 2 stars -========================================================================== -Also of note: -Artist: Milt Hinton -CD: Old Man Time -Date: 1993 -Label: Chiaroscuro -ID: CR(D) 310 -Total Time: 149:38 (two CDs) -Personnel: Milt Hinton, bass - Doc Cheatham, Dizzy Gillespie, Clark Terry, trumpet - Al Grey, trombone - Eddier Barefield, Joe Camel (Flip Phillips), Buddy Tate, - clarinet and saxophone - John Bunch, Red Richards, Norman Simmons, Derek Smith, - Ralph Sutton, piano - Danny Barker, Al Casey, guitar - Gus Johnson, Gerryck King, Bob Rosengarden, Jackie Williams, - drums - Lionel Hampton, vibraphone - Cab Calloway, Joe Williams, vocal - Buck Clayton, arrangements -Notes: tunes include Old Man Time, Time After Time, - Sometimes I'm Happy, - A Hot Time in the Old Town Tonight, - Four or Five Times, Now's the Time, - Time on My Hands, This Time It's Us, - and Good Time Charlie -Rating: 3 stars diff --git a/zic/README b/zic/README index 985a5118468..c0cc92853d0 100644 --- a/zic/README +++ b/zic/README @@ -1,4 +1,4 @@ -@(#)README 7.11 +@(#)README 8.2 "What time is it?" -- Richard Deacon as The King "Any time you want it to be." -- Frank Baxter as The Scientist @@ -52,8 +52,10 @@ substituting your desired installation directory for "$HOME/tzdir": To use the new functions, use a "-ltz" option when compiling or linking. -Historical local time information has been included here not because it -is particularly useful, but rather to: +Historical local time information has been included here to: + +* provide a compendium of data about the history of civil time + that is useful even if the data are not 100% accurate; * give an idea of the variety of local time rules that have existed in the past and thus an idea of the variety that may be @@ -63,7 +65,9 @@ is particularly useful, but rather to: system. The information in the time zone data files is by no means authoritative; -if you know that the rules are different from those in a file, by all means +the files currently do not even attempt to cover all time stamps before +1970, and there are undoubtedly errors even for time stamps since 1970. +If you know that the rules are different from those in a file, by all means feel free to change file (and please send the changed version to tz@elsie.nci.nih.gov for use in the future). Europeans take note! diff --git a/zic/Theory b/zic/Theory index cbf53b9e7d7..b842fb4b753 100644 --- a/zic/Theory +++ b/zic/Theory @@ -1,4 +1,4 @@ -@(#)Theory 7.15 +@(#)Theory 8.2 ----- Outline ----- @@ -12,26 +12,27 @@ ----- Time and date functions ----- -These time and date functions are upwards compatible with POSIX.1, +These time and date functions are upwards compatible with POSIX, an international standard for UNIX-like systems. -As of this writing, the current edition of POSIX.1 is: +As of this writing, the current edition of POSIX is: - Information technology --Portable Operating System Interface (POSIX (R)) - -- Part 1: System Application Program Interface (API) [C Language] - ISO/IEC 9945-1:1996 - ANSI/IEEE Std 1003.1, 1996 Edition - 1996-07-12 + Standard for Information technology + -- Portable Operating System Interface (POSIX (R)) + -- System Interfaces + IEEE Std 1003.1, 2004 Edition + + -POSIX.1 has the following properties and limitations. +POSIX has the following properties and limitations. -* In POSIX.1, time display in a process is controlled by the - environment variable TZ. Unfortunately, the POSIX.1 TZ string takes +* In POSIX, time display in a process is controlled by the + environment variable TZ. Unfortunately, the POSIX TZ string takes a form that is hard to describe and is error-prone in practice. - Also, POSIX.1 TZ strings can't deal with other (for example, Israeli) + Also, POSIX TZ strings can't deal with other (for example, Israeli) daylight saving time rules, or situations where more than two time zone abbreviations are used in an area. - The POSIX.1 TZ string takes the following form: + The POSIX TZ string takes the following form: stdoffset[dst[offset],date[/time],date[/time]] @@ -40,6 +41,9 @@ POSIX.1 has the following properties and limitations. std and dst are 3 or more characters specifying the standard and daylight saving time (DST) zone names. + Starting with POSIX.1-2001, std and dst may also be + in a quoted form like ""; this allows + "+" and "-" in the names. offset is of the form `[-]hh:[mm[:ss]]' and specifies the offset west of UTC. The default DST offset is one hour @@ -62,14 +66,25 @@ POSIX.1 has the following properties and limitations. and `5' stands for the last week in which day d appears (which may be either the 4th or 5th week). -* In POSIX.1, when a TZ value like "EST5EDT" is parsed, - typically the current US DST rules are used, + Here is an example POSIX TZ string, for US Pacific time using rules + appropriate from 1987 through 2006: + + TZ='PST8PDT,M4.1.0/02:00,M10.5.0/02:00' + + This POSIX TZ string is hard to remember, and mishandles time stamps + before 1987 and after 2006. With this package you can use this + instead: + + TZ='America/Los_Angeles' + +* POSIX does not define the exact meaning of TZ values like "EST5EDT". + Typically the current US DST rules are used to interpret such values, but this means that the US DST rules are compiled into each program that does time conversion. This means that when US time conversion rules change (as in the United States in 1987), all programs that do time conversion must be recompiled to ensure proper results. -* In POSIX.1, there's no tamper-proof way for a process to learn the +* In POSIX, there's no tamper-proof way for a process to learn the system's best idea of local wall clock. (This is important for applications that an administrator wants used only at certain times-- without regard to whether the user has fiddled the "TZ" environment @@ -78,9 +93,9 @@ POSIX.1 has the following properties and limitations. daylight saving time shifts--as might be required to limit phone calls to off-peak hours.) -* POSIX.1 requires that systems ignore leap seconds. +* POSIX requires that systems ignore leap seconds. -These are the extensions that have been made to the POSIX.1 functions: +These are the extensions that have been made to the POSIX functions: * The "TZ" environment variable is used in generating the name of a file from which time zone information is read (or is interpreted a la @@ -108,7 +123,7 @@ These are the extensions that have been made to the POSIX.1 functions: * To handle places where more than two time zone abbreviations are used, the functions "localtime" and "gmtime" set tzname[tmp->tm_isdst] (where "tmp" is the value the function returns) to the time zone - abbreviation to be used. This differs from POSIX.1, where the elements + abbreviation to be used. This differs from POSIX, where the elements of tzname are only changed as a result of calls to tzset. * Since the "TZ" environment variable can now be used to control time @@ -131,8 +146,7 @@ These are the extensions that have been made to the POSIX.1 functions: environment variable; portable applications should not, however, rely on this behavior since it's not the way SVR2 systems behave.) -* These functions can account for leap seconds, thanks to Bradley White - (bww@k.cs.cmu.edu). +* These functions can account for leap seconds, thanks to Bradley White. Points of interest to folks with other systems: @@ -173,9 +187,9 @@ Hewlett Packard, offer a wider selection of functions that provide capabilities beyond those provided here. The absence of such functions from this package is not meant to discourage the development, standardization, or use of such functions. Rather, their absence reflects the decision to make this package -contain valid extensions to POSIX.1, to ensure its broad -acceptability. If more powerful time conversion functions can be standardized, -so much the better. +contain valid extensions to POSIX, to ensure its broad acceptability. If +more powerful time conversion functions can be standardized, so much the +better. ----- Names of time zone rule files ----- @@ -228,6 +242,8 @@ in decreasing order of importance: Include at least one location per time zone rule set per country. One such location is enough. Use ISO 3166 (see the file iso3166.tab) to help decide whether something is a country. + However, uninhabited ISO 3166 regions like Bouvet Island + do not need locations, since local time is not defined there. If all the clocks in a country's region have agreed since 1970, don't bother to include more than one location even if subregions' clocks disagreed before 1970. @@ -263,7 +279,8 @@ in decreasing order of importance: If a name is changed, put its old spelling in the `backward' file. The file `zone.tab' lists the geographical locations used to name -time zone rule files. +time zone rule files. It is intended to be an exhaustive list +of canonical names for geographic regions. Older versions of this package used a different naming scheme, and these older names are still supported. @@ -277,7 +294,7 @@ and `Factory' (see the file `factory'). ----- Time zone abbreviations ----- When this package is installed, it generates time zone abbreviations -like `EST' to be compatible with human tradition and POSIX.1. +like `EST' to be compatible with human tradition and POSIX. Here are the general rules used for choosing time zone abbreviations, in decreasing order of importance: @@ -292,17 +309,16 @@ in decreasing order of importance: preferred "ChST", so the rule has been relaxed. This rule guarantees that all abbreviations could have - been specified by a POSIX.1 TZ string. POSIX.1 + been specified by a POSIX TZ string. POSIX requires at least three characters for an - abbreviation. POSIX.1-1996 says that an abbreviation + abbreviation. POSIX through 2000 says that an abbreviation cannot start with ':', and cannot contain ',', '-', - '+', NUL, or a digit. Draft 7 of POSIX 1003.1-200x - changes this rule to say that an abbreviation can - contain only '-', '+', and alphanumeric characters in - the current locale. To be portable to both sets of + '+', NUL, or a digit. POSIX from 2001 on changes this + rule to say that an abbreviation can contain only '-', '+', + and alphanumeric characters from the portable character set + in the current locale. To be portable to both sets of rules, an abbreviation must therefore use only ASCII - letters, as these are the only letters that are - alphabetic in all locales. + letters. Use abbreviations that are in common use among English-speakers, e.g. `EST' for Eastern Standard Time in North America. @@ -328,8 +344,9 @@ in decreasing order of importance: and then append `T', `ST', etc. as before; e.g. `VLAST' for VLAdivostok Summer Time. - Use "zzz" for locations while uninhabited. The mnemonic is that - these locations are, in some sense, asleep. + Use UTC (with time zone abbreviation "zzz") for locations while + uninhabited. The "zzz" mnemonic is that these locations are, + in some sense, asleep. Application writers should note that these abbreviations are ambiguous in practice: e.g. `EST' has a different meaning in Australia than @@ -343,10 +360,10 @@ abbreviations like `EST'; this avoids the ambiguity. Calendrical issues are a bit out of scope for a time zone database, but they indicate the sort of problems that we would run into if we extended the time zone database further into the past. An excellent -resource in this area is Nachum Dershowitz and Edward M. Reingold, - -Calendrical Calculations -, Cambridge University Press (1997). Other information and +resource in this area is Edward M. Reingold and Nachum Dershowitz, + +Calendrical Calculations: The Millennium Edition +, Cambridge University Press (2001). Other information and sources are given below. They sometimes disagree. @@ -359,7 +376,7 @@ and (in Paris only) 1871-05-06 through 1871-05-23. Russia -From Chris Carrier <72157.3334@CompuServe.COM> (1996-12-02): +From Chris Carrier (1996-12-02): On 1929-10-01 the Soviet Union instituted an ``Eternal Calendar'' with 30-day months plus 5 holidays, with a 5-day week. On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the @@ -374,7 +391,7 @@ by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377. But: From: Petteri Sulonen (via Usenet) Date: 14 Jan 1999 00:00:00 GMT -Message-ID: +... If your source is correct, how come documents between 1929 -- 1940 were still dated using the conventional, Gregorian calendar? @@ -387,7 +404,7 @@ Executive Committee of the Supreme Soviet, if you like. Sweden (and Finland) -From: msb@sq.com (Mark Brader) +From: Mark Brader Subject: Re: Gregorian reform -- a part of locale? @@ -415,11 +432,11 @@ kalendervasen" by Lars-Olof Lode'n (no date was given).) Grotefend's data -From: "Michael Palmer" [with one obvious typo fixed] +From: "Michael Palmer" [with one obvious typo fixed] Subject: Re: Gregorian Calendar (was Re: Another FHC related question Newsgroups: soc.genealogy.german Date: Tue, 9 Feb 1999 02:32:48 -800 -Message-ID: <199902091032.CAA09644@netcom10.netcom.com> +... The following is a(n incomplete) listing, arranged chronologically, of European states, with the date they converted from the Julian to the @@ -546,7 +563,7 @@ Sources: Michael Allison and Robert Schmunk, "Technical Notes on Mars Solar Time as Adopted by the Mars24 Sunclock" - (2004-03-15). + (2004-07-30). Jia-Rui Chong, "Workdays Fit for a Martian", Los Angeles Times (2004-01-14), pp A1, A20-A21. diff --git a/zic/ialloc.c b/zic/ialloc.c index 8a0c7015789..1fc2035f452 100644 --- a/zic/ialloc.c +++ b/zic/ialloc.c @@ -1,6 +1,11 @@ +/* +** This file is in the public domain, so clarified as of +** 2006-07-17 by Arthur David Olson. +*/ + #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)ialloc.c 8.29"; +static char elsieid[] = "@(#)ialloc.c 8.30"; #endif /* !defined NOID */ #endif /* !defined lint */ diff --git a/zic/private.h b/zic/private.h index c8f45486837..008d468ac78 100644 --- a/zic/private.h +++ b/zic/private.h @@ -4,7 +4,7 @@ /* ** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). +** 1996-06-05 by Arthur David Olson. */ /* @@ -21,10 +21,12 @@ #ifndef lint #ifndef NOID -static char privatehid[] = "@(#)private.h 7.53"; +static char privatehid[] = "@(#)private.h 8.6"; #endif /* !defined NOID */ #endif /* !defined lint */ +#define GRANDPARENTED "Local time zone must be set--see zic manual page" + /* ** Defaults for preprocessor symbols. ** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'. @@ -46,10 +48,6 @@ static char privatehid[] = "@(#)private.h 7.53"; #define HAVE_SETTIMEOFDAY 3 #endif /* !defined HAVE_SETTIMEOFDAY */ -#ifndef HAVE_STRERROR -#define HAVE_STRERROR 1 -#endif /* !defined HAVE_STRERROR */ - #ifndef HAVE_SYMLINK #define HAVE_SYMLINK 1 #endif /* !defined HAVE_SYMLINK */ @@ -87,17 +85,17 @@ static char privatehid[] = "@(#)private.h 7.53"; #include "stdio.h" #include "errno.h" #include "string.h" -#include "limits.h" /* for CHAR_BIT */ +#include "limits.h" /* for CHAR_BIT et al. */ #include "time.h" #include "stdlib.h" -#if HAVE_GETTEXT - 0 +#if HAVE_GETTEXT #include "libintl.h" -#endif /* HAVE_GETTEXT - 0 */ +#endif /* HAVE_GETTEXT */ -#if HAVE_SYS_WAIT_H - 0 +#if HAVE_SYS_WAIT_H #include /* for WIFEXITED and WEXITSTATUS */ -#endif /* HAVE_SYS_WAIT_H - 0 */ +#endif /* HAVE_SYS_WAIT_H */ #ifndef WIFEXITED #define WIFEXITED(status) (((status) & 0xff) == 0) @@ -106,106 +104,82 @@ static char privatehid[] = "@(#)private.h 7.53"; #define WEXITSTATUS(status) (((status) >> 8) & 0xff) #endif /* !defined WEXITSTATUS */ -#if HAVE_UNISTD_H - 0 -#include "unistd.h" /* for F_OK and R_OK */ -#endif /* HAVE_UNISTD_H - 0 */ +#if HAVE_UNISTD_H +#include "unistd.h" /* for F_OK, R_OK, and other POSIX goodness */ +#endif /* HAVE_UNISTD_H */ -#if !(HAVE_UNISTD_H - 0) #ifndef F_OK #define F_OK 0 #endif /* !defined F_OK */ #ifndef R_OK #define R_OK 4 #endif /* !defined R_OK */ -#endif /* !(HAVE_UNISTD_H - 0) */ -/* Unlike 's isdigit, this also works if c < 0 | c > UCHAR_MAX. */ +/* Unlike 's isdigit, this also works if c < 0 | c > UCHAR_MAX. */ #define is_digit(c) ((unsigned)(c) - '0' <= 9) +/* +** Define HAVE_STDINT_H's default value here, rather than at the +** start, since __GLIBC__'s value depends on previously-included +** files. +** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.) +*/ +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H \ + (199901 <= __STDC_VERSION__ || \ + 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__))) +#endif /* !defined HAVE_STDINT_H */ + +#if HAVE_STDINT_H +#include "stdint.h" +#endif /* !HAVE_STDINT_H */ + +#ifndef INT_FAST64_MAX +/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */ +#if defined LLONG_MAX || defined __LONG_LONG_MAX__ +typedef long long int_fast64_t; +#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ +#if (LONG_MAX >> 31) < 0xffffffff +Please use a compiler that supports a 64-bit integer type (or wider); +you may need to compile with "-DHAVE_STDINT_H". +#endif /* (LONG_MAX >> 31) < 0xffffffff */ +typedef long int_fast64_t; +#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */ +#endif /* !defined INT_FAST64_MAX */ + +#ifndef INT32_MAX +#define INT32_MAX 0x7fffffff +#endif /* !defined INT32_MAX */ +#ifndef INT32_MIN +#define INT32_MIN (-1 - INT32_MAX) +#endif /* !defined INT32_MIN */ + /* ** Workarounds for compilers/systems. */ /* -** SunOS 4.1.1 cc lacks prototypes. -*/ - -#ifndef P -#ifdef __STDC__ -#define P(x) x -#endif /* defined __STDC__ */ -#ifndef __STDC__ -#define P(x) () -#endif /* !defined __STDC__ */ -#endif /* !defined P */ - -/* -** SunOS 4.1.1 headers lack EXIT_SUCCESS. -*/ - -#ifndef EXIT_SUCCESS -#define EXIT_SUCCESS 0 -#endif /* !defined EXIT_SUCCESS */ - -/* -** SunOS 4.1.1 headers lack EXIT_FAILURE. -*/ - -#ifndef EXIT_FAILURE -#define EXIT_FAILURE 1 -#endif /* !defined EXIT_FAILURE */ - -/* -** SunOS 4.1.1 headers lack FILENAME_MAX. -*/ - -#ifndef FILENAME_MAX - -#ifndef MAXPATHLEN -#ifdef unix -#include "sys/param.h" -#endif /* defined unix */ -#endif /* !defined MAXPATHLEN */ - -#ifdef MAXPATHLEN -#define FILENAME_MAX MAXPATHLEN -#endif /* defined MAXPATHLEN */ -#ifndef MAXPATHLEN -#define FILENAME_MAX 1024 /* Pure guesswork */ -#endif /* !defined MAXPATHLEN */ - -#endif /* !defined FILENAME_MAX */ - -/* -** SunOS 4.1.1 libraries lack remove. -*/ - -#ifndef remove -extern int unlink P((const char * filename)); -#define remove unlink -#endif /* !defined remove */ - -/* -** Some ancient errno.h implementations don't declare errno. -** But some newer errno.h implementations define it as a macro. +** Some time.h implementations don't declare asctime_r. +** Others might define it as a macro. ** Fix the former without affecting the latter. */ -#ifndef errno -extern int errno; -#endif /* !defined errno */ + +#ifndef asctime_r +extern char * asctime_r(struct tm const *, char *); +#endif /* ** Private function declarations. */ -char * icalloc P((int nelem, int elsize)); -char * icatalloc P((char * old, const char * new)); -char * icpyalloc P((const char * string)); -char * imalloc P((int n)); -void * irealloc P((void * pointer, int size)); -void icfree P((char * pointer)); -void ifree P((char * pointer)); -char * scheck P((const char *string, const char *format)); +char * icalloc(int nelem, int elsize); +char * icatalloc(char * old, const char * new); +char * icpyalloc(const char * string); +char * imalloc(int n); +void * irealloc(void * pointer, int size); +void icfree(char * pointer); +void ifree(char * pointer); +const char * scheck(const char * string, const char * format); /* ** Finally, some convenience items. @@ -227,6 +201,15 @@ char * scheck P((const char *string, const char *format)); #define TYPE_SIGNED(type) (((type) -1) < 0) #endif /* !defined TYPE_SIGNED */ +/* +** Since the definition of TYPE_INTEGRAL contains floating point numbers, +** it cannot be used in preprocessor directives. +*/ + +#ifndef TYPE_INTEGRAL +#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5) +#endif /* !defined TYPE_INTEGRAL */ + #ifndef INT_STRLEN_MAXIMUM /* ** 302 / 1000 is log10(2.0) rounded up. @@ -235,7 +218,8 @@ char * scheck P((const char *string, const char *format)); ** add one more for a minus sign if the type is signed. */ #define INT_STRLEN_MAXIMUM(type) \ - ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type)) + ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ + 1 + TYPE_SIGNED(type)) #endif /* !defined INT_STRLEN_MAXIMUM */ /* @@ -269,11 +253,11 @@ char * scheck P((const char *string, const char *format)); */ #ifndef _ -#if HAVE_GETTEXT - 0 +#if HAVE_GETTEXT #define _(msgid) gettext(msgid) -#else /* !(HAVE_GETTEXT - 0) */ +#else /* !HAVE_GETTEXT */ #define _(msgid) msgid -#endif /* !(HAVE_GETTEXT - 0) */ +#endif /* !HAVE_GETTEXT */ #endif /* !defined _ */ #ifndef TZ_DOMAIN @@ -283,10 +267,30 @@ char * scheck P((const char *string, const char *format)); #if HAVE_INCOMPATIBLE_CTIME_R #undef asctime_r #undef ctime_r -char *asctime_r P((struct tm const *, char *)); -char *ctime_r P((time_t const *, char *)); +char *asctime_r(struct tm const *, char *); +char *ctime_r(time_t const *, char *); #endif /* HAVE_INCOMPATIBLE_CTIME_R */ +#ifndef YEARSPERREPEAT +#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ +#endif /* !defined YEARSPERREPEAT */ + +/* +** The Gregorian year averages 365.2425 days, which is 31556952 seconds. +*/ + +#ifndef AVGSECSPERYEAR +#define AVGSECSPERYEAR 31556952L +#endif /* !defined AVGSECSPERYEAR */ + +#ifndef SECSPERREPEAT +#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR) +#endif /* !defined SECSPERREPEAT */ + +#ifndef SECSPERREPEAT_BITS +#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ +#endif /* !defined SECSPERREPEAT_BITS */ + /* ** UNIX was a registered trademark of The Open Group in 2003. */ diff --git a/zic/scheck.c b/zic/scheck.c index 39feeba7011..74d9b07c149 100644 --- a/zic/scheck.c +++ b/zic/scheck.c @@ -1,6 +1,11 @@ +/* +** This file is in the public domain, so clarified as of +** 2006-07-17 by Arthur David Olson. +*/ + #ifndef lint #ifndef NOID -static char elsieid[] = "@(#)scheck.c 8.15"; +static char elsieid[] = "@(#)scheck.c 8.19"; #endif /* !defined lint */ #endif /* !defined NOID */ @@ -8,7 +13,7 @@ static char elsieid[] = "@(#)scheck.c 8.15"; #include "private.h" -char * +const char * scheck(string, format) const char * const string; const char * const format; @@ -17,11 +22,10 @@ const char * const format; register const char * fp; register char * tp; register int c; - register char * result; + register const char * result; char dummy; - static char nada; - result = &nada; + result = ""; if (string == NULL || format == NULL) return result; fbuf = imalloc((int) (2 * strlen(format) + 4)); diff --git a/zic/tz-link.htm b/zic/tz-link.htm deleted file mode 100644 index 0e630730070..00000000000 --- a/zic/tz-link.htm +++ /dev/null @@ -1,443 +0,0 @@ - - - - -Sources for Time Zone and Daylight Saving Time Data - - - - - - - - - - -

    Sources for Time Zone and Daylight Saving Time Data

    -
    -@(#)tz-link.htm 7.42 -
    -

    -Please send corrections to this web page to the -time zone mailing list. -

    -

    The tz database

    -

    -The public-domain time zone database contains code and data -that represent the history of local time -for many representative locations around the globe. -It is updated periodically to reflect changes made by political bodies -to UTC offsets and daylight-saving rules. -This database (often called tz or zoneinfo) -is used by several implementations, -including -the GNU C Library used in -GNU/Linux, -FreeBSD, -NetBSD, -OpenBSD, -Cygwin, -DJGPP, -HP-UX, -IRIX, -Mac OS X, -OpenVMS, -Solaris, -Tru64, and -UnixWare.

    -

    -Each location in the database represents a national region where all -clocks keeping local time have agreed since 1970. -Locations are identified by continent or ocean and then by the name of -the location, which is typically the largest city within the region. -For example, America/New_York -represents most of the US eastern time zone; -America/Indianapolis represents most of Indiana, which -uses eastern time without daylight saving time (DST); -America/Detroit represents most of Michigan, which uses -eastern time but with different DST rules in 1975; -and other entries represent smaller regions like Starke County, -Kentucky, which switched from central to eastern time in 1991. -To use the database, set the TZ environment variable to -the location's full name, e.g., TZ="America/New_York".

    -

    -In the tz database's -FTP distribution, -the code is in the file tzcodeC.tar.gz, -where C is the code's version; -similarly, the data are in tzdataD.tar.gz, -where D is the data's version. -The following shell commands download -these files to a GNU/Linux or similar host; see the downloaded -README file for what to do next.

    -
    wget 'ftp://elsie.nci.nih.gov/pub/tz*.tar.gz'
    -gzip -dc tzcode*.tar.gz | tar -xf -
    -gzip -dc tzdata*.tar.gz | tar -xf -
    -
    -

    -The code lets you compile the tz source files into -machine-readable binary files, one for each location. It also lets -you read a tz binary file and interpret time stamps for that -location.

    -

    -The data are by no means authoritative. If you find errors, please -send changes to the time zone -mailing list. You can also subscribe to the -mailing list, retrieve the archive of old -messages (in gzip compressed format), or retrieve archived older versions of code -and data.

    -

    -The Web has several other sources for time zone and daylight saving time data. -Here are some recent links that may be of interest. -

    -

    Web pages using recent versions of the tz database

    - -

    Other time zone database formats

    - -

    Other tz compilers

    - -

    Other tz binary file readers

    - -

    Other tz-based time zone conversion software

    - -

    Other time zone databases

    - -

    Maps

    - -

    Time zone boundaries

    - -

    Civil time concepts and history

    - -

    National histories of legal time

    -
    -
    Australia
    -
    The Community Relations Division of the New South Wales (NSW) -Attorney General's Department maintains a history of -daylight saving in NSW.
    -
    Austria
    -
    The Federal Office of Metrology and Surveying publishes a -table of daylight saving time in Austria (in German).
    -
    Belgium
    -
    The Royal Observatory of Belgium maintains a table of time in Belgium (in Dutch).
    -
    Brazil
    -
    The Time Service Department of the National Observatory -records Brazil's daylight saving time decrees (in -Portuguese).
    -
    Canada
    -
    The Institute for National Measurement Standards publishes current -and some older information about Time -Zones and Daylight Saving Time.
    -
    Chile
    -
    WebExhibits publishes a history of official time (in Spanish) originally -written by the Chilean Hydrographic and Oceanographic Service.
    -
    Germany
    -
    The National Institute for Science and Technology maintains the Realisation of -Legal Time in Germany.
    -
    Israel
    -
    The Interior Ministry periodically issues announcements (in Hebrew).
    -
    Mexico
    -
    The Investigation and Analysis Service of the Mexican Library of -Congress has published a history of Mexican local time (in Spanish).
    -
    Malaysia
    -
    See Singapore below.
    -
    Netherlands
    -
    Legal time in the Netherlands (in Dutch) -covers the history of local time in the Netherlands from ancient times.
    -
    New Zealand
    -
    The Department of Internal Affairs maintains a brief history about -daylight saving. The privately-maintained Time Changes in -New Zealand has more details.
    -
    Singapore
    -
    Why -is Singapore in the "Wrong" Time Zone? details the -history of legal time in Singapore and Malaysia.
    -
    United Kingdom
    -
    History of -legal time in Britain discusses in detail the country -with perhaps the best-documented history of clock adjustments. -The National Physical Laboratory also maintains an archive -of summer time dates.
    -
    -

    Precision timekeeping

    - -

    Time notation

    -
      -
    • -A Summary of -the International Standard Date and Time Notation is a good -summary of ISO -8601:1988 - Data elements and interchange formats - Information interchange -- Representation of dates and times (which has been superseded by -ISO 8601:2000).
    • -
    • -Section 3.3 of Internet RFC 2822 -specifies the time notation used in email and HTTP headers.
    • -
    • -Internet RFC -3339 specifies an ISO 8601 profile for use in new Internet -protocols.
    • -
    • -The -Best of Dates, the Worst of Dates covers many problems encountered -by software developers when handling dates and time stamps.
    • -
    • -Alphabetic time zone abbreviations should not be used as unique -identifiers for UTC offsets as they are ambiguous in practice. For -example, "EST" denotes 5 hours behind UTC in English-speaking North -America, but it denotes 10 or 11 hours ahead of UTC in Australia; -and French-speaking North Americans prefer "HNE" to "EST". For -compatibility with POSIX the -tz database contains English abbreviations for all time -stamps but in many cases these are merely inventions of the database -maintainers.
    • -
    -

    Related indexes

    - - - diff --git a/zic/zdump.8 b/zic/zdump.8 index dff68c2d8d8..67cbaead4b5 100644 --- a/zic/zdump.8 +++ b/zic/zdump.8 @@ -10,7 +10,7 @@ zdump \- time zone dumper .B \-v ] [ .B \-c -cutoffyear ] [ zonename ... ] +[loyear,]hiyear ] [ zonename ... ] .SH DESCRIPTION .I Zdump prints the current time in each @@ -38,8 +38,20 @@ if the given time is Daylight Saving Time or .B isdst=0 otherwise. .TP -.BI "\-c " cutoffyear -Cut off the verbose output near the start of the given year. +.BI "\-c " [loyear,]hiyear +Cut off verbose output near the start of the given year(s). +By default, +the program cuts off verbose output near the starts of the years -500 and 2500. +.SH LIMITATIONS +The +.B \-v +option may not be used on systems with floating-point time_t values +that are neither float nor double. +.PP +Time discontinuities are found by sampling the results returned by localtime +at twelve-hour intervals. +This works in all real-world cases; +one can construct artificial time zones for which this fails. .SH "SEE ALSO" newctime(3), tzfile(5), zic(8) -.\" @(#)zdump.8 7.4 +.\" @(#)zdump.8 8.1 diff --git a/zic/zdump.c b/zic/zdump.c index a34caddbdf6..085b33e23d4 100644 --- a/zic/zdump.c +++ b/zic/zdump.c @@ -1,4 +1,4 @@ -static char elsieid[] = "@(#)zdump.c 7.31"; +static char elsieid[] = "@(#)zdump.c 8.8"; /* ** This code has been made independent of the rest of the time @@ -11,6 +11,19 @@ static char elsieid[] = "@(#)zdump.c 7.31"; #include "sys/types.h" /* for time_t */ #include "time.h" /* for struct tm */ #include "stdlib.h" /* for exit, malloc, atoi */ +#include "float.h" /* for FLT_MAX and DBL_MAX */ +#include "ctype.h" /* for isalpha et al. */ +#ifndef isascii +#define isascii(x) 1 +#endif /* !defined isascii */ + +#ifndef ZDUMP_LO_YEAR +#define ZDUMP_LO_YEAR (-500) +#endif /* !defined ZDUMP_LO_YEAR */ + +#ifndef ZDUMP_HI_YEAR +#define ZDUMP_HI_YEAR 2500 +#endif /* !defined ZDUMP_HI_YEAR */ #ifndef MAX_STRING_LENGTH #define MAX_STRING_LENGTH 1024 @@ -61,19 +74,32 @@ static char elsieid[] = "@(#)zdump.c 7.31"; #endif /* !defined DAYSPERNYEAR */ #ifndef isleap -#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) +#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) #endif /* !defined isleap */ -#if HAVE_GETTEXT - 0 +#ifndef isleap_sum +/* +** See tzfile.h for details on isleap_sum. +*/ +#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) +#endif /* !defined isleap_sum */ + +#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) +#define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR) +#define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY) + +#ifndef HAVE_GETTEXT +#define HAVE_GETTEXT 0 +#endif +#if HAVE_GETTEXT #include "locale.h" /* for setlocale */ #include "libintl.h" -#endif /* HAVE_GETTEXT - 0 */ +#endif /* HAVE_GETTEXT */ #ifndef GNUC_or_lint #ifdef lint #define GNUC_or_lint -#endif /* defined lint */ -#ifndef lint +#else /* !defined lint */ #ifdef __GNUC__ #define GNUC_or_lint #endif /* defined __GNUC__ */ @@ -83,8 +109,7 @@ static char elsieid[] = "@(#)zdump.c 7.31"; #ifndef INITIALIZE #ifdef GNUC_or_lint #define INITIALIZE(x) ((x) = 0) -#endif /* defined GNUC_or_lint */ -#ifndef GNUC_or_lint +#else /* !defined GNUC_or_lint */ #define INITIALIZE(x) #endif /* !defined GNUC_or_lint */ #endif /* !defined INITIALIZE */ @@ -96,39 +121,125 @@ static char elsieid[] = "@(#)zdump.c 7.31"; */ #ifndef _ -#if HAVE_GETTEXT - 0 +#if HAVE_GETTEXT #define _(msgid) gettext(msgid) -#else /* !(HAVE_GETTEXT - 0) */ +#else /* !HAVE_GETTEXT */ #define _(msgid) msgid -#endif /* !(HAVE_GETTEXT - 0) */ +#endif /* !HAVE_GETTEXT */ #endif /* !defined _ */ #ifndef TZ_DOMAIN #define TZ_DOMAIN "tz" #endif /* !defined TZ_DOMAIN */ -#ifndef P -#ifdef __STDC__ -#define P(x) x -#endif /* defined __STDC__ */ -#ifndef __STDC__ -#define P(x) () -#endif /* !defined __STDC__ */ -#endif /* !defined P */ - extern char ** environ; -extern int getopt P((int argc, char * const argv[], - const char * options)); +extern int getopt(int argc, char * const argv[], + const char * options); extern char * optarg; extern int optind; extern char * tzname[2]; -static char * abbr P((struct tm * tmp)); -static long delta P((struct tm * newp, struct tm * oldp)); -static time_t hunt P((char * name, time_t lot, time_t hit)); +static time_t absolute_min_time; +static time_t absolute_max_time; static size_t longest; static char * progname; -static void show P((char * zone, time_t t, int v)); +static int warned; + +static char * abbr(struct tm * tmp); +static void abbrok(const char * abbrp, const char * zone); +static long delta(struct tm * newp, struct tm * oldp); +static void dumptime(const struct tm * tmp); +static time_t hunt(char * name, time_t lot, time_t hit); +static void setabsolutes(void); +static void show(char * zone, time_t t, int v); +static const char * tformat(void); +static time_t yeartot(long y); + +#ifndef TYPECHECK +#define my_localtime localtime +#else /* !defined TYPECHECK */ +static struct tm * +my_localtime(tp) +time_t * tp; +{ + register struct tm * tmp; + + tmp = localtime(tp); + if (tp != NULL && tmp != NULL) { + struct tm tm; + register time_t t; + + tm = *tmp; + t = mktime(&tm); + if (t - *tp >= 1 || *tp - t >= 1) { + (void) fflush(stdout); + (void) fprintf(stderr, "\n%s: ", progname); + (void) fprintf(stderr, tformat(), *tp); + (void) fprintf(stderr, " ->"); + (void) fprintf(stderr, " year=%d", tmp->tm_year); + (void) fprintf(stderr, " mon=%d", tmp->tm_mon); + (void) fprintf(stderr, " mday=%d", tmp->tm_mday); + (void) fprintf(stderr, " hour=%d", tmp->tm_hour); + (void) fprintf(stderr, " min=%d", tmp->tm_min); + (void) fprintf(stderr, " sec=%d", tmp->tm_sec); + (void) fprintf(stderr, " isdst=%d", tmp->tm_isdst); + (void) fprintf(stderr, " -> "); + (void) fprintf(stderr, tformat(), t); + (void) fprintf(stderr, "\n"); + } + } + return tmp; +} +#endif /* !defined TYPECHECK */ + +static void +abbrok(abbrp, zone) +const char * const abbrp; +const char * const zone; +{ + register const char * cp; + register char * wp; + + if (warned) + return; + cp = abbrp; + wp = NULL; + while (isascii((unsigned char) *cp) && isalpha((unsigned char) *cp)) + ++cp; + if (cp - abbrp == 0) + wp = _("lacks alphabetic at start"); + else if (cp - abbrp < 3) + wp = _("has fewer than 3 alphabetics"); + else if (cp - abbrp > 6) + wp = _("has more than 6 alphabetics"); + if (wp == NULL && (*cp == '+' || *cp == '-')) { + ++cp; + if (isascii((unsigned char) *cp) && + isdigit((unsigned char) *cp)) + if (*cp++ == '1' && *cp >= '0' && *cp <= '4') + ++cp; + if (*cp != '\0') + wp = _("differs from POSIX standard"); + } + if (wp == NULL) + return; + (void) fflush(stdout); + (void) fprintf(stderr, + _("%s: warning: zone \"%s\" abbreviation \"%s\" %s\n"), + progname, zone, abbrp, wp); + warned = TRUE; +} + +static void +usage(const char *progname, FILE *stream, int status) +{ + (void) fprintf(stream, +_("%s: usage is %s [ --version ] [ --help ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n\ +\n\ +Report bugs to tz@elsie.nci.nih.gov.\n"), + progname, progname); + exit(status); +} int main(argc, argv) @@ -138,72 +249,86 @@ char * argv[]; register int i; register int c; register int vflag; - register char * cutoff; - register int cutyear; - register long cuttime; - char ** fakeenv; + register char * cutarg; + register long cutloyear = ZDUMP_LO_YEAR; + register long cuthiyear = ZDUMP_HI_YEAR; + register time_t cutlotime; + register time_t cuthitime; + register char ** fakeenv; time_t now; time_t t; time_t newt; - time_t hibit; struct tm tm; struct tm newtm; + register struct tm * tmp; + register struct tm * newtmp; - INITIALIZE(cuttime); -#if HAVE_GETTEXT - 0 - (void) setlocale(LC_MESSAGES, ""); + INITIALIZE(cutlotime); + INITIALIZE(cuthitime); +#if HAVE_GETTEXT + (void) setlocale(LC_ALL, ""); #ifdef TZ_DOMAINDIR (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); -#endif /* defined(TEXTDOMAINDIR) */ +#endif /* defined TEXTDOMAINDIR */ (void) textdomain(TZ_DOMAIN); -#endif /* HAVE_GETTEXT - 0 */ +#endif /* HAVE_GETTEXT */ progname = argv[0]; for (i = 1; i < argc; ++i) if (strcmp(argv[i], "--version") == 0) { (void) printf("%s\n", elsieid); - (void) exit(EXIT_SUCCESS); + exit(EXIT_SUCCESS); + } else if (strcmp(argv[i], "--help") == 0) { + usage(progname, stdout, EXIT_SUCCESS); } vflag = 0; - cutoff = NULL; + cutarg = NULL; while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v') if (c == 'v') vflag = 1; - else cutoff = optarg; + else cutarg = optarg; if ((c != EOF && c != -1) || (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { - (void) fprintf(stderr, -_("%s: usage is %s [ --version ] [ -v ] [ -c cutoff ] zonename ...\n"), - argv[0], argv[0]); - (void) exit(EXIT_FAILURE); + usage(progname, stderr, EXIT_FAILURE); } - if (cutoff != NULL) { - int y; + if (vflag) { + if (cutarg != NULL) { + long lo; + long hi; + char dummy; - cutyear = atoi(cutoff); - cuttime = 0; - for (y = EPOCH_YEAR; y < cutyear; ++y) - cuttime += DAYSPERNYEAR + isleap(y); - cuttime *= SECSPERHOUR * HOURSPERDAY; + if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) { + cuthiyear = hi; + } else if (sscanf(cutarg, "%ld,%ld%c", + &lo, &hi, &dummy) == 2) { + cutloyear = lo; + cuthiyear = hi; + } else { +(void) fprintf(stderr, _("%s: wild -c argument %s\n"), + progname, cutarg); + exit(EXIT_FAILURE); + } + } + setabsolutes(); + cutlotime = yeartot(cutloyear); + cuthitime = yeartot(cuthiyear); } (void) time(&now); longest = 0; for (i = optind; i < argc; ++i) if (strlen(argv[i]) > longest) longest = strlen(argv[i]); - for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) - continue; { register int from; register int to; - for (i = 0; environ[i] != NULL; ++i) + for (i = 0; environ[i] != NULL; ++i) continue; fakeenv = (char **) malloc((size_t) ((i + 2) * sizeof *fakeenv)); if (fakeenv == NULL || (fakeenv[0] = (char *) malloc(longest + 4)) == NULL) { (void) perror(progname); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } to = 0; (void) strcpy(fakeenv[to++], "TZ="); @@ -221,85 +346,171 @@ _("%s: usage is %s [ --version ] [ -v ] [ -c cutoff ] zonename ...\n"), show(argv[i], now, FALSE); continue; } - /* - ** Get lowest value of t. - */ - t = hibit; - if (t > 0) /* time_t is unsigned */ - t = 0; + warned = FALSE; + t = absolute_min_time; show(argv[i], t, TRUE); t += SECSPERHOUR * HOURSPERDAY; show(argv[i], t, TRUE); - tm = *localtime(&t); - (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); + if (t < cutlotime) + t = cutlotime; + tmp = my_localtime(&t); + if (tmp != NULL) { + tm = *tmp; + (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); + } for ( ; ; ) { - if (cutoff != NULL && t >= cuttime) + if (t >= cuthitime || t >= cuthitime - SECSPERHOUR * 12) break; newt = t + SECSPERHOUR * 12; - if (cutoff != NULL && newt >= cuttime) - break; - if (newt <= t) - break; - newtm = *localtime(&newt); - if (delta(&newtm, &tm) != (newt - t) || + newtmp = localtime(&newt); + if (newtmp != NULL) + newtm = *newtmp; + if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) : + (delta(&newtm, &tm) != (newt - t) || newtm.tm_isdst != tm.tm_isdst || - strcmp(abbr(&newtm), buf) != 0) { + strcmp(abbr(&newtm), buf) != 0)) { newt = hunt(argv[i], t, newt); - newtm = *localtime(&newt); - (void) strncpy(buf, abbr(&newtm), - (sizeof buf) - 1); + newtmp = localtime(&newt); + if (newtmp != NULL) { + newtm = *newtmp; + (void) strncpy(buf, + abbr(&newtm), + (sizeof buf) - 1); + } } t = newt; tm = newtm; + tmp = newtmp; } - /* - ** Get highest value of t. - */ - t = ~((time_t) 0); - if (t < 0) /* time_t is signed */ - t &= ~hibit; + t = absolute_max_time; t -= SECSPERHOUR * HOURSPERDAY; show(argv[i], t, TRUE); t += SECSPERHOUR * HOURSPERDAY; show(argv[i], t, TRUE); } if (fflush(stdout) || ferror(stdout)) { - (void) fprintf(stderr, "%s: ", argv[0]); - (void) perror(_("Error writing standard output")); - (void) exit(EXIT_FAILURE); + (void) fprintf(stderr, "%s: ", progname); + (void) perror(_("Error writing to standard output")); + exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); + /* If exit fails to exit... */ + return EXIT_FAILURE; +} - /* gcc -Wall pacifier */ - for ( ; ; ) - continue; +static void +setabsolutes(void) +{ + if (0.5 == (time_t) 0.5) { + /* + ** time_t is floating. + */ + if (sizeof (time_t) == sizeof (float)) { + absolute_min_time = (time_t) -FLT_MAX; + absolute_max_time = (time_t) FLT_MAX; + } else if (sizeof (time_t) == sizeof (double)) { + absolute_min_time = (time_t) -DBL_MAX; + absolute_max_time = (time_t) DBL_MAX; + } else { + (void) fprintf(stderr, +_("%s: use of -v on system with floating time_t other than float or double\n"), + progname); + exit(EXIT_FAILURE); + } + } else if (0 > (time_t) -1) { + /* + ** time_t is signed. Assume overflow wraps around. + */ + time_t t = 0; + time_t t1 = 1; + + while (t < t1) { + t = t1; + t1 = 2 * t1 + 1; + } + + absolute_max_time = t; + t = -t; + absolute_min_time = t - 1; + if (t < absolute_min_time) + absolute_min_time = t; + } else { + /* + ** time_t is unsigned. + */ + absolute_min_time = 0; + absolute_max_time = absolute_min_time - 1; + } } static time_t -hunt(name, lot, hit) -char * name; -time_t lot; -time_t hit; +yeartot(y) +const long y; { - time_t t; - struct tm lotm; - struct tm tm; - static char loab[MAX_STRING_LENGTH]; + register long myy; + register long seconds; + register time_t t; - lotm = *localtime(&lot); - (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); - while ((hit - lot) >= 2) { - t = lot / 2 + hit / 2; + myy = EPOCH_YEAR; + t = 0; + while (myy != y) { + if (myy < y) { + seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR; + ++myy; + if (t > absolute_max_time - seconds) { + t = absolute_max_time; + break; + } + t += seconds; + } else { + --myy; + seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR; + if (t < absolute_min_time + seconds) { + t = absolute_min_time; + break; + } + t -= seconds; + } + } + return t; +} + +static time_t +hunt(char *name, time_t lot, time_t hit) +{ + time_t t; + long diff; + struct tm lotm; + register struct tm * lotmp; + struct tm tm; + register struct tm * tmp; + char loab[MAX_STRING_LENGTH]; + + lotmp = my_localtime(&lot); + if (lotmp != NULL) { + lotm = *lotmp; + (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); + } + for ( ; ; ) { + diff = (long) (hit - lot); + if (diff < 2) + break; + t = lot; + t += diff / 2; if (t <= lot) ++t; else if (t >= hit) --t; - tm = *localtime(&t); - if (delta(&tm, &lotm) == (t - lot) && + tmp = my_localtime(&t); + if (tmp != NULL) + tm = *tmp; + if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) : + (delta(&tm, &lotm) == (t - lot) && tm.tm_isdst == lotm.tm_isdst && - strcmp(abbr(&tm), loab) == 0) { + strcmp(abbr(&tm), loab) == 0)) { lot = t; lotm = tm; + lotmp = tmp; } else hit = t; } show(name, lot, TRUE); @@ -308,7 +519,7 @@ time_t hit; } /* -** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta. +** Thanks to Paul Eggert for logic used in delta. */ static long @@ -316,14 +527,14 @@ delta(newp, oldp) struct tm * newp; struct tm * oldp; { - long result; - int tmy; + register long result; + register int tmy; if (newp->tm_year < oldp->tm_year) return -delta(oldp, newp); result = 0; for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy) - result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE); + result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE); result += newp->tm_yday - oldp->tm_yday; result *= HOURSPERDAY; result += newp->tm_hour - oldp->tm_hour; @@ -335,27 +546,36 @@ struct tm * oldp; } static void -show(zone, t, v) -char * zone; -time_t t; -int v; +show(char *zone, time_t t, int v) { - struct tm * tmp; + register struct tm * tmp; (void) printf("%-*s ", (int) longest, zone); - if (v) - (void) printf("%.24s UTC = ", asctime(gmtime(&t))); - tmp = localtime(&t); - (void) printf("%.24s", asctime(tmp)); - if (*abbr(tmp) != '\0') - (void) printf(" %s", abbr(tmp)); if (v) { - (void) printf(" isdst=%d", tmp->tm_isdst); + tmp = gmtime(&t); + if (tmp == NULL) { + (void) printf(tformat(), t); + } else { + dumptime(tmp); + (void) printf(" UTC"); + } + (void) printf(" = "); + } + tmp = my_localtime(&t); + dumptime(tmp); + if (tmp != NULL) { + if (*abbr(tmp) != '\0') + (void) printf(" %s", abbr(tmp)); + if (v) { + (void) printf(" isdst=%d", tmp->tm_isdst); #ifdef TM_GMTOFF - (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); + (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); #endif /* defined TM_GMTOFF */ + } } (void) printf("\n"); + if (tmp != NULL && *abbr(tmp) != '\0') + abbrok(abbr(tmp), zone); } static char * @@ -370,3 +590,84 @@ struct tm * tmp; result = tzname[tmp->tm_isdst]; return (result == NULL) ? &nada : result; } + +/* +** The code below can fail on certain theoretical systems; +** it works on all known real-world systems as of 2004-12-30. +*/ + +static const char * +tformat(void) +{ + if (0.5 == (time_t) 0.5) { /* floating */ + if (sizeof (time_t) > sizeof (double)) + return "%Lg"; + return "%g"; + } + if (0 > (time_t) -1) { /* signed */ + if (sizeof (time_t) > sizeof (long)) + return "%lld"; + if (sizeof (time_t) > sizeof (int)) + return "%ld"; + return "%d"; + } + if (sizeof (time_t) > sizeof (unsigned long)) + return "%llu"; + if (sizeof (time_t) > sizeof (unsigned int)) + return "%lu"; + return "%u"; +} + +static void +dumptime(timeptr) +register const struct tm * timeptr; +{ + static const char wday_name[][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + static const char mon_name[][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + register const char * wn; + register const char * mn; + register int lead; + register int trail; + + if (timeptr == NULL) { + (void) printf("NULL"); + return; + } + /* + ** The packaged versions of localtime and gmtime never put out-of-range + ** values in tm_wday or tm_mon, but since this code might be compiled + ** with other (perhaps experimental) versions, paranoia is in order. + */ + if (timeptr->tm_wday < 0 || timeptr->tm_wday >= + (int) (sizeof wday_name / sizeof wday_name[0])) + wn = "???"; + else wn = wday_name[timeptr->tm_wday]; + if (timeptr->tm_mon < 0 || timeptr->tm_mon >= + (int) (sizeof mon_name / sizeof mon_name[0])) + mn = "???"; + else mn = mon_name[timeptr->tm_mon]; + (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ", + wn, mn, + timeptr->tm_mday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec); +#define DIVISOR 10 + trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR; + lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR + + trail / DIVISOR; + trail %= DIVISOR; + if (trail < 0 && lead > 0) { + trail += DIVISOR; + --lead; + } else if (lead < 0 && trail > 0) { + trail -= DIVISOR; + ++lead; + } + if (lead == 0) + (void) printf("%d", trail); + else (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail)); +} diff --git a/zic/zic.8 b/zic/zic.8 index 86b13544f97..f842927a7b7 100644 --- a/zic/zic.8 +++ b/zic/zic.8 @@ -269,7 +269,7 @@ A zone line has the form .nf .ti +.5i .ta \w'Zone\0\0'u +\w'Australia/Adelaide\0\0'u +\w'GMTOFF\0\0'u +\w'RULES/SAVE\0\0'u +\w'FORMAT\0\0'u -Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL] +Zone NAME GMTOFF RULES/SAVE FORMAT [UNTILYEAR [MONTH [DAY [TIME]]]] .sp For example: .sp @@ -311,15 +311,15 @@ Alternately, a slash (/) separates standard and daylight abbreviations. .TP -.B UNTIL +.B UNTILYEAR [MONTH [DAY [TIME]]] The time at which the UTC offset or the rule(s) change for a location. It is specified as a year, a month, a day, and a time of day. If this is specified, the time zone information is generated from the given UTC offset and rule change until the time specified. The month, day, and time of day have the same format as the IN, ON, and AT -columns of a rule; trailing columns can be omitted, and default to the -earliest possible value for the missing columns. +fields of a rule; trailing fields can be omitted, and default to the +earliest possible value for the missing fields. .IP The next line must be a .q continuation @@ -328,11 +328,11 @@ string .q Zone and the name are omitted, as the continuation line will place information starting at the time specified as the -.B UNTIL -field in the previous line in the file used by the previous line. -Continuation lines may contain an -.B UNTIL -field, just as zone lines do, indicating that the next line is a further +.q until +information in the previous line in the file used by the previous line. +Continuation lines may contain +.q until +information, just as zone lines do, indicating that the next line is a further continuation. .PP A link line has the form @@ -411,14 +411,83 @@ or .q Rolling if the leap second time given by the other fields should be interpreted as local wall clock time. -.SH NOTE +.SH "EXTENDED EXAMPLE" +Here is an extended example of +.I zic +input, intended to illustrate many of its features. +.br +.ne 22 +.nf +.in +2m +.ta \w'# Rule\0\0'u +\w'NAME\0\0'u +\w'FROM\0\0'u +\w'1973\0\0'u +\w'TYPE\0\0'u +\w'Apr\0\0'u +\w'lastSun\0\0'u +\w'2:00\0\0'u +\w'SAVE\0\0'u +.sp +# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S +Rule Swiss 1940 only - Nov 2 0:00 1:00 S +Rule Swiss 1940 only - Dec 31 0:00 0 - +Rule Swiss 1941 1942 - May Sun>=1 2:00 1:00 S +Rule Swiss 1941 1942 - Oct Sun>=1 0:00 0 +.sp .5 +Rule EU 1977 1980 - Apr Sun>=1 1:00u 1:00 S +Rule EU 1977 only - Sep lastSun 1:00u 0 - +Rule EU 1978 only - Oct 1 1:00u 0 - +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 - +.sp +.ta \w'# Zone\0\0'u +\w'Europe/Zurich\0\0'u +\w'0:34:08\0\0'u +\w'RULES/SAVE\0\0'u +\w'FORMAT\0\0'u +# Zone NAME GMTOFF RULES FORMAT UNTIL +Zone Europe/Zurich 0:34:08 - LMT 1848 Sep 12 + 0:29:44 - BMT 1894 Jun + 1:00 Swiss CE%sT 1981 + 1:00 EU CE%sT +.sp +Link Europe/Zurich Switzerland +.sp +.in +.fi +In this example, the zone is named Europe/Zurich but it has an alias +as Switzerland. Zurich was 34 minutes and 8 seconds west of GMT until +1848-09-12 at 00:00, when the offset changed to 29 minutes and 44 +seconds. After 1894-06-01 at 00:00 Swiss daylight saving rules (defined +with lines beginning with "Rule Swiss") apply, and the GMT offset +became one hour. From 1981 to the present, EU daylight saving rules have +applied, and the UTC offset has remained at one hour. +.PP +In 1940, daylight saving time applied from November 2 at 00:00 to +December 31 at 00:00. In 1941 and 1942, daylight saving time applied +from the first Sunday in May at 02:00 to the first Sunday in October +at 00:00. +The pre-1981 EU daylight-saving rules have no effect +here, but are included for completeness. Since 1981, daylight +saving has begun on the last Sunday in March at 01:00 UTC. +Until 1995 it ended the last Sunday in September at 01:00 UTC, +but this changed to the last Sunday in October starting in 1996. +.PP +For purposes of +display, "LMT" and "BMT" were initially used, respectively. Since +Swiss rules and later EU rules were applied, the display name for the +timezone has been CET for standard time and CEST for daylight saving +time. +.SH NOTES For areas with more than two types of local time, you may need to use local standard time in the .B AT field of the earliest transition time's rule to ensure that the earliest transition time recorded in the compiled file is correct. +.PP +If, +for a particular zone, +a clock advance caused by the start of daylight saving +coincides with and is equal to +a clock retreat caused by a change in UTC offset, +.IR zic +produces a single transition to daylight saving at the new UTC offset +(without any change in wall clock time). +To get separate transitions +use multiple zone continuation lines +specifying transition instants using universal time. .SH FILE /usr/local/etc/zoneinfo standard directory used for created files .SH "SEE ALSO" newctime(3), tzfile(5), zdump(8) -.\" @(#)zic.8 7.22 +.\" @(#)zic.8 8.4 diff --git a/zic/zic.c b/zic/zic.c index 1a046ff3ed9..01d9f135bd7 100644 --- a/zic/zic.c +++ b/zic/zic.c @@ -1,9 +1,22 @@ -static char elsieid[] = "@(#)zic.c 7.116"; +/* +** This file is in the public domain, so clarified as of +** 2006-07-17 by Arthur David Olson. +*/ + +static char elsieid[] = "@(#)zic.c 8.19"; #include "private.h" #include "locale.h" #include "tzfile.h" +#define ZIC_VERSION '2' + +typedef int_fast64_t zic_t; + +#ifndef ZIC_MAX_ABBR_LEN_WO_WARN +#define ZIC_MAX_ABBR_LEN_WO_WARN 6 +#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */ + #if HAVE_SYS_STAT_H #include "sys/stat.h" #endif @@ -15,7 +28,7 @@ static char elsieid[] = "@(#)zic.c 7.116"; /* ** On some ancient hosts, predicates like `isspace(C)' are defined -** only if isascii(C) || C == EOF. Modern hosts obey the C Standard, +** only if isascii(C) || C == EOF. Modern hosts obey the C Standard, ** which says they are defined only if C == ((unsigned char) C) || C == EOF. ** Neither the C Standard nor Posix require that `isascii' exist. ** For portability, we check both ancient and modern requirements. @@ -26,6 +39,11 @@ static char elsieid[] = "@(#)zic.c 7.116"; #define isascii(x) 1 #endif +#define OFFSET_STRLEN_MAXIMUM (7 + INT_STRLEN_MAXIMUM(long)) +#define RULE_STRLEN_MAXIMUM 8 /* "Mdd.dd.d" */ + +#define end(cp) (strchr((cp), '\0')) + struct rule { const char * r_filename; int r_linenum; @@ -34,6 +52,8 @@ struct rule { int r_loyear; /* for example, 1986 */ int r_hiyear; /* for example, 1986 */ const char * r_yrtype; + int r_lowasnum; + int r_hiwasnum; int r_month; /* 0..11 */ @@ -50,7 +70,7 @@ struct rule { const char * r_abbrvar; /* variable part of abbreviation */ int r_todo; /* a rule to do (used in outzone) */ - time_t r_temp; /* used in outzone */ + zic_t r_temp; /* used in outzone */ }; /* @@ -76,77 +96,84 @@ struct zone { int z_nrules; struct rule z_untilrule; - time_t z_untiltime; + zic_t z_untiltime; }; -extern int getopt P((int argc, char * const argv[], - const char * options)); -extern int link P((const char * fromname, const char * toname)); +extern int getopt(int argc, char * const argv[], + const char * options); +extern int link(const char * fromname, const char * toname); extern char * optarg; extern int optind; -static void addtt P((time_t starttime, int type)); -static int addtype P((long gmtoff, const char * abbr, int isdst, - int ttisstd, int ttisgmt)); -static void leapadd P((time_t t, int positive, int rolling, int count)); -static void adjleap P((void)); -static void associate P((void)); -static int ciequal P((const char * ap, const char * bp)); -static void convert P((long val, char * buf)); -static void dolink P((const char * fromfile, const char * tofile)); -static void doabbr P((char * abbr, const char * format, - const char * letters, int isdst)); -static void eat P((const char * name, int num)); -static void eats P((const char * name, int num, - const char * rname, int rnum)); -static long eitol P((int i)); -static void error P((const char * message)); -static char ** getfields P((char * buf)); -static long gethms P((const char * string, const char * errstrng, - int signable)); -static void infile P((const char * filename)); -static void inleap P((char ** fields, int nfields)); -static void inlink P((char ** fields, int nfields)); -static void inrule P((char ** fields, int nfields)); -static int inzcont P((char ** fields, int nfields)); -static int inzone P((char ** fields, int nfields)); -static int inzsub P((char ** fields, int nfields, int iscont)); -static int itsabbr P((const char * abbr, const char * word)); -static int itsdir P((const char * name)); -static int lowerit P((int c)); -static char * memcheck P((char * tocheck)); -static int mkdirs P((char * filename)); -static void newabbr P((const char * abbr)); -static long oadd P((long t1, long t2)); -static void outzone P((const struct zone * zp, int ntzones)); -static void puttzcode P((long code, FILE * fp)); -static int rcomp P((const void * leftp, const void * rightp)); -static time_t rpytime P((const struct rule * rp, int wantedy)); -static void rulesub P((struct rule * rp, +static void addtt(zic_t starttime, int type); +static int addtype(long gmtoff, const char * abbr, int isdst, + int ttisstd, int ttisgmt); +static void leapadd(zic_t t, int positive, int rolling, int count); +static void adjleap(void); +static void associate(void); +static int ciequal(const char * ap, const char * bp); +static void convert(long val, char * buf); +static void convert64(zic_t val, char * buf); +static void dolink(const char * fromfield, const char * tofield); +static void doabbr(char * abbr, const char * format, + const char * letters, int isdst, int doquotes); +static void eat(const char * name, int num); +static void eats(const char * name, int num, + const char * rname, int rnum); +static long eitol(int i); +static void error(const char * message); +static char ** getfields(char * buf); +static long gethms(const char * string, const char * errstrng, + int signable); +static void infile(const char * filename); +static void inleap(char ** fields, int nfields); +static void inlink(char ** fields, int nfields); +static void inrule(char ** fields, int nfields); +static int inzcont(char ** fields, int nfields); +static int inzone(char ** fields, int nfields); +static int inzsub(char ** fields, int nfields, int iscont); +static int is32(zic_t x); +static int itsabbr(const char * abbr, const char * word); +static int itsdir(const char * name); +static int lowerit(int c); +static char * memcheck(char * tocheck); +static int mkdirs(char * filename); +static void newabbr(const char * abbr); +static long oadd(long t1, long t2); +static void outzone(const struct zone * zp, int ntzones); +static void puttzcode(long code, FILE * fp); +static void puttzcode64(zic_t code, FILE * fp); +static int rcomp(const void * leftp, const void * rightp); +static zic_t rpytime(const struct rule * rp, int wantedy); +static void rulesub(struct rule * rp, const char * loyearp, const char * hiyearp, const char * typep, const char * monthp, - const char * dayp, const char * timep)); -static void setboundaries P((void)); -static time_t tadd P((time_t t1, long t2)); -static void usage P((void)); -static void writezone P((const char * name)); -static int yearistype P((int year, const char * type)); - -#if !(HAVE_STRERROR - 0) -static char * strerror P((int)); -#endif /* !(HAVE_STRERROR - 0) */ + const char * dayp, const char * timep); +static int stringoffset(char * result, long offset); +static int stringrule(char * result, const struct rule * rp, + long dstoff, long gmtoff); +static void stringzone(char * result, + const struct zone * zp, int ntzones); +static void setboundaries(void); +static zic_t tadd(zic_t t1, long t2); +static void usage(FILE *stream, int status); +static void writezone(const char * name, const char * string); +static int yearistype(int year, const char * type); static int charcnt; static int errors; static const char * filename; static int leapcnt; +static int leapseen; +static int leapminyear; +static int leapmaxyear; static int linenum; -static time_t max_time; +static int max_abbrvar_len; +static int max_format_len; +static zic_t max_time; static int max_year; -static int max_year_representable; -static time_t min_time; +static zic_t min_time; static int min_year; -static int min_year_representable; static int noise; static const char * rfilename; static int rlinenum; @@ -256,8 +283,8 @@ struct lookup { const int l_value; }; -static struct lookup const * byword P((const char * string, - const struct lookup * lp)); +static struct lookup const * byword(const char * string, + const struct lookup * lp); static struct lookup const line_codes[] = { { "Rule", LC_RULE }, @@ -334,7 +361,7 @@ static const int len_years[2] = { }; static struct attype { - time_t at; + zic_t at; unsigned char type; } attypes[TZ_MAX_TIMES]; static long gmtoffs[TZ_MAX_TYPES]; @@ -343,7 +370,7 @@ static unsigned char abbrinds[TZ_MAX_TYPES]; static char ttisstds[TZ_MAX_TYPES]; static char ttisgmts[TZ_MAX_TYPES]; static char chars[TZ_MAX_CHARS]; -static time_t trans[TZ_MAX_LEAPS]; +static zic_t trans[TZ_MAX_LEAPS]; static long corr[TZ_MAX_LEAPS]; static char roll[TZ_MAX_LEAPS]; @@ -360,7 +387,7 @@ char * const ptr; (void) fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, e); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } return ptr; } @@ -374,19 +401,6 @@ char * const ptr; ** Error handling. */ -#if !(HAVE_STRERROR - 0) -static char * -strerror(errnum) -int errnum; -{ - extern char * sys_errlist[]; - extern int sys_nerr; - - return (errnum > 0 && errnum <= sys_nerr) ? - sys_errlist[errnum] : _("Unknown system error"); -} -#endif /* !(HAVE_STRERROR - 0) */ - static void eats(name, num, rname, rnum) const char * const name; @@ -440,11 +454,15 @@ const char * const string; } static void -usage P((void)) +usage(FILE *stream, int status) { - (void) fprintf(stderr, _("%s: usage is %s [ --version ] [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"), - progname, progname); - (void) exit(EXIT_FAILURE); + (void) fprintf(stream, _("%s: usage is %s \ +[ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\ +\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\ +\n\ +Report bugs to tz@elsie.nci.nih.gov.\n"), + progname, progname); + exit(status); } static const char * psxrules; @@ -452,7 +470,6 @@ static const char * lcltime; static const char * directory; static const char * leapsec; static const char * yitcommand; -static int sflag = FALSE; int main(argc, argv) @@ -466,23 +483,30 @@ char * argv[]; #ifdef unix (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH)); #endif /* defined unix */ -#if HAVE_GETTEXT - 0 - (void) setlocale(LC_MESSAGES, ""); +#if HAVE_GETTEXT + (void) setlocale(LC_ALL, ""); #ifdef TZ_DOMAINDIR (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); #endif /* defined TEXTDOMAINDIR */ (void) textdomain(TZ_DOMAIN); -#endif /* HAVE_GETTEXT - 0 */ +#endif /* HAVE_GETTEXT */ progname = argv[0]; + if (TYPE_BIT(zic_t) < 64) { + (void) fprintf(stderr, "%s: %s\n", progname, + _("wild compilation-time specification of zic_t")); + exit(EXIT_FAILURE); + } for (i = 1; i < argc; ++i) if (strcmp(argv[i], "--version") == 0) { (void) printf("%s\n", elsieid); - (void) exit(EXIT_SUCCESS); + exit(EXIT_SUCCESS); + } else if (strcmp(argv[i], "--help") == 0) { + usage(stdout, EXIT_SUCCESS); } while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1) switch (c) { default: - usage(); + usage(stderr, EXIT_FAILURE); case 'd': if (directory == NULL) directory = optarg; @@ -490,7 +514,7 @@ char * argv[]; (void) fprintf(stderr, _("%s: More than one -d option specified\n"), progname); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } break; case 'l': @@ -500,7 +524,7 @@ _("%s: More than one -d option specified\n"), (void) fprintf(stderr, _("%s: More than one -l option specified\n"), progname); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } break; case 'p': @@ -510,7 +534,7 @@ _("%s: More than one -l option specified\n"), (void) fprintf(stderr, _("%s: More than one -p option specified\n"), progname); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } break; case 'y': @@ -520,7 +544,7 @@ _("%s: More than one -p option specified\n"), (void) fprintf(stderr, _("%s: More than one -y option specified\n"), progname); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } break; case 'L': @@ -530,18 +554,18 @@ _("%s: More than one -y option specified\n"), (void) fprintf(stderr, _("%s: More than one -L option specified\n"), progname); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } break; case 'v': noise = TRUE; break; case 's': - sflag = TRUE; + (void) printf("%s: -s ignored\n", progname); break; } if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) - usage(); /* usage message by request */ + usage(stderr, EXIT_FAILURE); /* usage message by request */ if (directory == NULL) directory = TZDIR; if (yitcommand == NULL) @@ -557,7 +581,7 @@ _("%s: More than one -L option specified\n"), for (i = optind; i < argc; ++i) infile(argv[i]); if (errors) - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); associate(); for (i = 0; i < nzones; i = j) { /* @@ -573,6 +597,11 @@ _("%s: More than one -L option specified\n"), for (i = 0; i < nlinks; ++i) { eat(links[i].l_filename, links[i].l_linenum); dolink(links[i].l_from, links[i].l_to); + if (noise) + for (j = 0; j < nlinks; ++j) + if (strcmp(links[i].l_to, + links[j].l_from) == 0) + warning(_("link to link")); } if (lcltime != NULL) { eat("command line", 1); @@ -586,26 +615,26 @@ _("%s: More than one -L option specified\n"), } static void -dolink(fromfile, tofile) -const char * const fromfile; -const char * const tofile; +dolink(fromfield, tofield) +const char * const fromfield; +const char * const tofield; { register char * fromname; register char * toname; - if (fromfile[0] == '/') - fromname = ecpyalloc(fromfile); + if (fromfield[0] == '/') + fromname = ecpyalloc(fromfield); else { fromname = ecpyalloc(directory); fromname = ecatalloc(fromname, "/"); - fromname = ecatalloc(fromname, fromfile); + fromname = ecatalloc(fromname, fromfield); } - if (tofile[0] == '/') - toname = ecpyalloc(tofile); + if (tofield[0] == '/') + toname = ecpyalloc(tofield); else { toname = ecpyalloc(directory); toname = ecatalloc(toname, "/"); - toname = ecatalloc(toname, tofile); + toname = ecatalloc(toname, tofield); } /* ** We get to be careful here since @@ -617,75 +646,54 @@ const char * const tofile; int result; if (mkdirs(toname) != 0) - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); result = link(fromname, toname); -#if (HAVE_SYMLINK - 0) +#if HAVE_SYMLINK if (result != 0 && - access(fromname, F_OK) == 0 && - !itsdir(fromname)) { - const char *s = tofile; - register char * symlinkcontents = NULL; - while ((s = strchr(s+1, '/')) != NULL) - symlinkcontents = ecatalloc(symlinkcontents, "../"); - symlinkcontents = ecatalloc(symlinkcontents, fromfile); + access(fromname, F_OK) == 0 && + !itsdir(fromname)) { + const char *s = tofield; + register char * symlinkcontents = NULL; - result = symlink(symlinkcontents, toname); - if (result == 0) + while ((s = strchr(s+1, '/')) != NULL) + symlinkcontents = + ecatalloc(symlinkcontents, + "../"); + symlinkcontents = + ecatalloc(symlinkcontents, + fromname); + result = symlink(symlinkcontents, + toname); + if (result == 0) warning(_("hard link failed, symbolic link used")); - ifree(symlinkcontents); + ifree(symlinkcontents); } -#endif +#endif /* HAVE_SYMLINK */ if (result != 0) { const char *e = strerror(errno); (void) fprintf(stderr, _("%s: Can't link from %s to %s: %s\n"), progname, fromname, toname, e); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } } ifree(fromname); ifree(toname); } -#ifndef INT_MAX -#define INT_MAX ((int) (((unsigned)~0)>>1)) -#endif /* !defined INT_MAX */ - -#ifndef INT_MIN -#define INT_MIN ((int) ~(((unsigned)~0)>>1)) -#endif /* !defined INT_MIN */ - -/* -** The tz file format currently allows at most 32-bit quantities. -** This restriction should be removed before signed 32-bit values -** wrap around in 2038, but unfortunately this will require a -** change to the tz file format. -*/ - -#define MAX_BITS_IN_FILE 32 -#define TIME_T_BITS_IN_FILE ((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE) +#define TIME_T_BITS_IN_FILE 64 static void -setboundaries P((void)) +setboundaries(void) { - if (TYPE_SIGNED(time_t)) { - min_time = ~ (time_t) 0; - min_time <<= TIME_T_BITS_IN_FILE - 1; - max_time = ~ (time_t) 0 - min_time; - if (sflag) - min_time = 0; - } else { - min_time = 0; - max_time = 2 - sflag; - max_time <<= TIME_T_BITS_IN_FILE - 1; - --max_time; - } - min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year; - max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year; - min_year_representable = min_year; - max_year_representable = max_year; + register int i; + + min_time = -1; + for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i) + min_time *= 2; + max_time = -(min_time + 1); } static int @@ -720,7 +728,7 @@ const void * cp2; } static void -associate P((void)) +associate(void) { register struct zone * zp; register struct rule * rp; @@ -782,7 +790,7 @@ associate P((void)) */ eat(zp->z_filename, zp->z_linenum); zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"), - TRUE); + TRUE); /* ** Note, though, that if there's no rule, ** a '%s' in the format is a bad thing. @@ -792,7 +800,7 @@ associate P((void)) } } if (errors) - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } static void @@ -816,7 +824,7 @@ const char * name; (void) fprintf(stderr, _("%s: Can't open %s: %s\n"), progname, name, e); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } wantcont = FALSE; for (num = 1; ; ++num) { @@ -826,7 +834,7 @@ const char * name; cp = strchr(buf, '\n'); if (cp == NULL) { error(_("line too long")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } *cp = '\0'; fields = getfields(buf); @@ -870,7 +878,7 @@ _("%s: Leap line in non leap seconds file %s\n"), (void) fprintf(stderr, _("%s: panic: Invalid l_value %d\n"), progname, lp->l_value); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } } ifree((char *) fields); @@ -878,14 +886,14 @@ _("%s: panic: Invalid l_value %d\n"), if (ferror(fp)) { (void) fprintf(stderr, _("%s: Error reading %s\n"), progname, filename); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } if (fp != stdin && fclose(fp)) { const char *e = strerror(errno); (void) fprintf(stderr, _("%s: Error closing %s: %s\n"), progname, filename, e); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } if (wantcont) error(_("expected continuation line not found")); @@ -905,7 +913,8 @@ const char * string; const char * const errstring; const int signable; { - int hh, mm, ss, sign; + long hh; + int mm, ss, sign; if (string == NULL || *string == '\0') return 0; @@ -915,27 +924,32 @@ const int signable; sign = -1; ++string; } else sign = 1; - if (sscanf(string, scheck(string, "%d"), &hh) == 1) + if (sscanf(string, scheck(string, "%ld"), &hh) == 1) mm = ss = 0; - else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2) + else if (sscanf(string, scheck(string, "%ld:%d"), &hh, &mm) == 2) ss = 0; - else if (sscanf(string, scheck(string, "%d:%d:%d"), + else if (sscanf(string, scheck(string, "%ld:%d:%d"), &hh, &mm, &ss) != 3) { error(errstring); return 0; } - if ((hh < 0 || hh >= HOURSPERDAY || + if (hh < 0 || mm < 0 || mm >= MINSPERHOUR || - ss < 0 || ss > SECSPERMIN) && - !(hh == HOURSPERDAY && mm == 0 && ss == 0)) { + ss < 0 || ss > SECSPERMIN) { error(errstring); return 0; } - if (noise && hh == HOURSPERDAY) + if (LONG_MAX / SECSPERHOUR < hh) { + error(_("time overflow")); + return 0; + } + if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0) warning(_("24:00 not handled by pre-1998 versions of zic")); - return eitol(sign) * - (eitol(hh * MINSPERHOUR + mm) * - eitol(SECSPERMIN) + eitol(ss)); + if (noise && (hh > HOURSPERDAY || + (hh == HOURSPERDAY && (mm != 0 || ss != 0)))) +warning(_("values over 24 hours not handled by pre-2007 versions of zic")); + return oadd(eitol(sign) * hh * eitol(SECSPERHOUR), + eitol(sign) * (eitol(mm) * eitol(SECSPERMIN) + eitol(ss))); } static void @@ -960,6 +974,8 @@ const int nfields; fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); r.r_name = ecpyalloc(fields[RF_NAME]); r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); + if (max_abbrvar_len < strlen(r.r_abbrvar)) + max_abbrvar_len = strlen(r.r_abbrvar); rules = (struct rule *) (void *) erealloc((char *) rules, (int) ((nrules + 1) * sizeof *rules)); rules[nrules++] = r; @@ -1065,6 +1081,8 @@ const int iscont; } z.z_rule = ecpyalloc(fields[i_rule]); z.z_format = ecpyalloc(fields[i_format]); + if (max_format_len < strlen(z.z_format)) + max_format_len = strlen(z.z_format); hasuntil = nfields > i_untilyear; if (hasuntil) { z.z_untilrule.r_filename = filename; @@ -1085,7 +1103,9 @@ const int iscont; zones[nzones - 1].z_untiltime > min_time && zones[nzones - 1].z_untiltime < max_time && zones[nzones - 1].z_untiltime >= z.z_untiltime) { - error(_("Zone continuation line end time is not after end time of previous line")); + error(_( +"Zone continuation line end time is not after end time of previous line" + )); return FALSE; } } @@ -1109,7 +1129,7 @@ const int nfields; register int i, j; int year, month, day; long dayoff, tod; - time_t t; + zic_t t; if (nfields != LEAP_FIELDS) { error(_("wrong number of fields on Leap line")); @@ -1118,12 +1138,17 @@ const int nfields; dayoff = 0; cp = fields[LP_YEAR]; if (sscanf(cp, scheck(cp, "%d"), &year) != 1) { - /* - * Leapin' Lizards! - */ - error(_("invalid leaping year")); - return; + /* + ** Leapin' Lizards! + */ + error(_("invalid leaping year")); + return; } + if (!leapseen || leapmaxyear < year) + leapmaxyear = year; + if (!leapseen || leapminyear > year) + leapminyear = year; + leapseen = TRUE; j = EPOCH_YEAR; while (j != year) { if (year > j) { @@ -1153,7 +1178,7 @@ const int nfields; return; } dayoff = oadd(dayoff, eitol(day - 1)); - if (dayoff < 0 && !TYPE_SIGNED(time_t)) { + if (dayoff < 0 && !TYPE_SIGNED(zic_t)) { error(_("time before zero")); return; } @@ -1165,7 +1190,7 @@ const int nfields; error(_("time too large")); return; } - t = (time_t) dayoff * SECSPERDAY; + t = (zic_t) dayoff * SECSPERDAY; tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE); cp = fields[LP_CORR]; { @@ -1189,7 +1214,9 @@ const int nfields; return; } if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) { - error(_("illegal Rolling/Stationary field on Leap line")); + error(_( + "illegal Rolling/Stationary field on Leap line" + )); return; } leapadd(tadd(t, tod), positive, lp->l_value, count); @@ -1276,7 +1303,8 @@ const char * const timep; */ cp = loyearp; lp = byword(cp, begin_years); - if (lp != NULL) switch ((int) lp->l_value) { + rp->r_lowasnum = lp == NULL; + if (!rp->r_lowasnum) switch ((int) lp->l_value) { case YR_MINIMUM: rp->r_loyear = INT_MIN; break; @@ -1287,18 +1315,15 @@ const char * const timep; (void) fprintf(stderr, _("%s: panic: Invalid l_value %d\n"), progname, lp->l_value); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) { error(_("invalid starting year")); return; - } else if (noise) { - if (rp->r_loyear < min_year_representable) - warning(_("starting year too low to be represented")); - else if (rp->r_loyear > max_year_representable) - warning(_("starting year too high to be represented")); } cp = hiyearp; - if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) { + lp = byword(cp, end_years); + rp->r_hiwasnum = lp == NULL; + if (!rp->r_hiwasnum) switch ((int) lp->l_value) { case YR_MINIMUM: rp->r_hiyear = INT_MIN; break; @@ -1312,15 +1337,10 @@ const char * const timep; (void) fprintf(stderr, _("%s: panic: Invalid l_value %d\n"), progname, lp->l_value); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) { error(_("invalid ending year")); return; - } else if (noise) { - if (rp->r_loyear < min_year_representable) - warning(_("ending year too low to be represented")); - else if (rp->r_loyear > max_year_representable) - warning(_("ending year too high to be represented")); } if (rp->r_loyear > rp->r_hiyear) { error(_("starting year greater than ending year")); @@ -1335,8 +1355,6 @@ const char * const timep; } rp->r_yrtype = ecpyalloc(typep); } - if (rp->r_loyear < min_year && rp->r_loyear > 0) - min_year = rp->r_loyear; /* ** Day work. ** Accept things such as: @@ -1390,12 +1408,24 @@ const long val; char * const buf; { register int i; - register long shift; + register int shift; for (i = 0, shift = 24; i < 4; ++i, shift -= 8) buf[i] = val >> shift; } +static void +convert64(val, buf) +const zic_t val; +char * const buf; +{ + register int i; + register int shift; + + for (i = 0, shift = 56; i < 8; ++i, shift -= 8) + buf[i] = val >> shift; +} + static void puttzcode(val, fp) const long val; @@ -1407,28 +1437,50 @@ FILE * const fp; (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); } +static void +puttzcode64(val, fp) +const zic_t val; +FILE * const fp; +{ + char buf[8]; + + convert64(val, buf); + (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); +} + static int atcomp(avp, bvp) -void * avp; -void * bvp; +const void * avp; +const void * bvp; { - if (((struct attype *) avp)->at < ((struct attype *) bvp)->at) - return -1; - else if (((struct attype *) avp)->at > ((struct attype *) bvp)->at) - return 1; - else return 0; + const zic_t a = ((const struct attype *) avp)->at; + const zic_t b = ((const struct attype *) bvp)->at; + + return (a < b) ? -1 : (a > b); +} + +static int +is32(x) +const zic_t x; +{ + return INT32_MIN <= x && x <= INT32_MAX; } static void -writezone(name) +writezone(name, string) const char * const name; +const char * const string; { - register FILE * fp; - register int i, j; - static char * fullname; - static struct tzhead tzh; - time_t ats[TZ_MAX_TIMES]; - unsigned char types[TZ_MAX_TIMES]; + register FILE * fp; + register int i, j; + register int leapcnt32, leapi32; + register int timecnt32, timei32; + register int pass; + static char * fullname; + static const struct tzhead tzh0; + static struct tzhead tzh; + zic_t ats[TZ_MAX_TIMES]; + unsigned char types[TZ_MAX_TIMES]; /* ** Sort. @@ -1451,14 +1503,13 @@ const char * const name; while (fromi < timecnt && attypes[fromi].type == 0) ++fromi; /* handled by default rule */ for ( ; fromi < timecnt; ++fromi) { - if (toi != 0 - && ((attypes[fromi].at - + gmtoffs[attypes[toi - 1].type]) - <= (attypes[toi - 1].at - + gmtoffs[toi == 1 ? 0 - : attypes[toi - 2].type]))) { - attypes[toi - 1].type = attypes[fromi].type; - continue; + if (toi != 0 && ((attypes[fromi].at + + gmtoffs[attypes[toi - 1].type]) <= + (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0 + : attypes[toi - 2].type]))) { + attypes[toi - 1].type = + attypes[fromi].type; + continue; } if (toi == 0 || attypes[toi - 1].type != attypes[fromi].type) @@ -1473,6 +1524,36 @@ const char * const name; ats[i] = attypes[i].at; types[i] = attypes[i].type; } + /* + ** Correct for leap seconds. + */ + for (i = 0; i < timecnt; ++i) { + j = leapcnt; + while (--j >= 0) + if (ats[i] > trans[j] - corr[j]) { + ats[i] = tadd(ats[i], corr[j]); + break; + } + } + /* + ** Figure out 32-bit-limited starts and counts. + */ + timecnt32 = timecnt; + timei32 = 0; + leapcnt32 = leapcnt; + leapi32 = 0; + while (timecnt32 > 0 && !is32(ats[timecnt32 - 1])) + --timecnt32; + while (timecnt32 > 0 && !is32(ats[timei32])) { + --timecnt32; + ++timei32; + } + while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1])) + --leapcnt32; + while (leapcnt32 > 0 && !is32(trans[leapi32])) { + --leapcnt32; + ++leapi32; + } fullname = erealloc(fullname, (int) (strlen(directory) + 1 + strlen(name) + 1)); (void) sprintf(fullname, "%s/%s", directory, name); @@ -1484,102 +1565,388 @@ const char * const name; (void) fprintf(stderr, _("%s: Can't remove %s: %s\n"), progname, fullname, e); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } if ((fp = fopen(fullname, "wb")) == NULL) { if (mkdirs(fullname) != 0) - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); if ((fp = fopen(fullname, "wb")) == NULL) { const char *e = strerror(errno); (void) fprintf(stderr, _("%s: Can't create %s: %s\n"), progname, fullname, e); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } } - convert(eitol(typecnt), tzh.tzh_ttisgmtcnt); - convert(eitol(typecnt), tzh.tzh_ttisstdcnt); - convert(eitol(leapcnt), tzh.tzh_leapcnt); - convert(eitol(timecnt), tzh.tzh_timecnt); - convert(eitol(typecnt), tzh.tzh_typecnt); - convert(eitol(charcnt), tzh.tzh_charcnt); - (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); -#define DO(field) (void) fwrite((void *) tzh.field, (size_t) sizeof tzh.field, (size_t) 1, fp) - DO(tzh_magic); - DO(tzh_reserved); - DO(tzh_ttisgmtcnt); - DO(tzh_ttisstdcnt); - DO(tzh_leapcnt); - DO(tzh_timecnt); - DO(tzh_typecnt); - DO(tzh_charcnt); + for (pass = 1; pass <= 2; ++pass) { + register int thistimei, thistimecnt; + register int thisleapi, thisleapcnt; + register int thistimelim, thisleaplim; + int writetype[TZ_MAX_TIMES]; + int typemap[TZ_MAX_TYPES]; + register int thistypecnt; + char thischars[TZ_MAX_CHARS]; + char thischarcnt; + int indmap[TZ_MAX_CHARS]; + + if (pass == 1) { + thistimei = timei32; + thistimecnt = timecnt32; + thisleapi = leapi32; + thisleapcnt = leapcnt32; + } else { + thistimei = 0; + thistimecnt = timecnt; + thisleapi = 0; + thisleapcnt = leapcnt; + } + thistimelim = thistimei + thistimecnt; + thisleaplim = thisleapi + thisleapcnt; + for (i = 0; i < typecnt; ++i) + writetype[i] = thistimecnt == timecnt; + if (thistimecnt == 0) { + /* + ** No transition times fall in the current + ** (32- or 64-bit) window. + */ + if (typecnt != 0) + writetype[typecnt - 1] = TRUE; + } else { + for (i = thistimei - 1; i < thistimelim; ++i) + if (i >= 0) + writetype[types[i]] = TRUE; + /* + ** For America/Godthab and Antarctica/Palmer + */ + if (thistimei == 0) + writetype[0] = TRUE; + } + thistypecnt = 0; + for (i = 0; i < typecnt; ++i) + typemap[i] = writetype[i] ? thistypecnt++ : -1; + for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i) + indmap[i] = -1; + thischarcnt = 0; + for (i = 0; i < typecnt; ++i) { + register char * thisabbr; + + if (!writetype[i]) + continue; + if (indmap[abbrinds[i]] >= 0) + continue; + thisabbr = &chars[abbrinds[i]]; + for (j = 0; j < thischarcnt; ++j) + if (strcmp(&thischars[j], thisabbr) == 0) + break; + if (j == thischarcnt) { + (void) strcpy(&thischars[(int) thischarcnt], + thisabbr); + thischarcnt += strlen(thisabbr) + 1; + } + indmap[abbrinds[i]] = j; + } +#define DO(field) (void) fwrite((void *) tzh.field, \ + (size_t) sizeof tzh.field, (size_t) 1, fp) + tzh = tzh0; + (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); + tzh.tzh_version[0] = ZIC_VERSION; + convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt); + convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt); + convert(eitol(thisleapcnt), tzh.tzh_leapcnt); + convert(eitol(thistimecnt), tzh.tzh_timecnt); + convert(eitol(thistypecnt), tzh.tzh_typecnt); + convert(eitol(thischarcnt), tzh.tzh_charcnt); + DO(tzh_magic); + DO(tzh_version); + DO(tzh_reserved); + DO(tzh_ttisgmtcnt); + DO(tzh_ttisstdcnt); + DO(tzh_leapcnt); + DO(tzh_timecnt); + DO(tzh_typecnt); + DO(tzh_charcnt); #undef DO - for (i = 0; i < timecnt; ++i) { - j = leapcnt; - while (--j >= 0) - if (ats[i] >= trans[j]) { - ats[i] = tadd(ats[i], corr[j]); - break; + for (i = thistimei; i < thistimelim; ++i) + if (pass == 1) + puttzcode((long) ats[i], fp); + else puttzcode64(ats[i], fp); + for (i = thistimei; i < thistimelim; ++i) { + unsigned char uc; + + uc = typemap[types[i]]; + (void) fwrite((void *) &uc, + (size_t) sizeof uc, + (size_t) 1, + fp); + } + for (i = 0; i < typecnt; ++i) + if (writetype[i]) { + puttzcode(gmtoffs[i], fp); + (void) putc(isdsts[i], fp); + (void) putc((unsigned char) indmap[abbrinds[i]], fp); } - puttzcode((long) ats[i], fp); + if (thischarcnt != 0) + (void) fwrite((void *) thischars, + (size_t) sizeof thischars[0], + (size_t) thischarcnt, fp); + for (i = thisleapi; i < thisleaplim; ++i) { + register zic_t todo; + + if (roll[i]) { + if (timecnt == 0 || trans[i] < ats[0]) { + j = 0; + while (isdsts[j]) + if (++j >= typecnt) { + j = 0; + break; + } + } else { + j = 1; + while (j < timecnt && + trans[i] >= ats[j]) + ++j; + j = types[j - 1]; + } + todo = tadd(trans[i], -gmtoffs[j]); + } else todo = trans[i]; + if (pass == 1) + puttzcode((long) todo, fp); + else puttzcode64(todo, fp); + puttzcode(corr[i], fp); + } + for (i = 0; i < typecnt; ++i) + if (writetype[i]) + (void) putc(ttisstds[i], fp); + for (i = 0; i < typecnt; ++i) + if (writetype[i]) + (void) putc(ttisgmts[i], fp); } - if (timecnt > 0) - (void) fwrite((void *) types, (size_t) sizeof types[0], - (size_t) timecnt, fp); - for (i = 0; i < typecnt; ++i) { - puttzcode((long) gmtoffs[i], fp); - (void) putc(isdsts[i], fp); - (void) putc(abbrinds[i], fp); - } - if (charcnt != 0) - (void) fwrite((void *) chars, (size_t) sizeof chars[0], - (size_t) charcnt, fp); - for (i = 0; i < leapcnt; ++i) { - if (roll[i]) { - if (timecnt == 0 || trans[i] < ats[0]) { - j = 0; - while (isdsts[j]) - if (++j >= typecnt) { - j = 0; - break; - } - } else { - j = 1; - while (j < timecnt && trans[i] >= ats[j]) - ++j; - j = types[j - 1]; - } - puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp); - } else puttzcode((long) trans[i], fp); - puttzcode((long) corr[i], fp); - } - for (i = 0; i < typecnt; ++i) - (void) putc(ttisstds[i], fp); - for (i = 0; i < typecnt; ++i) - (void) putc(ttisgmts[i], fp); + (void) fprintf(fp, "\n%s\n", string); if (ferror(fp) || fclose(fp)) { (void) fprintf(stderr, _("%s: Error writing %s\n"), progname, fullname); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } } static void -doabbr(abbr, format, letters, isdst) +doabbr(abbr, format, letters, isdst, doquotes) char * const abbr; const char * const format; const char * const letters; const int isdst; +const int doquotes; { - if (strchr(format, '/') == NULL) { + register char * cp; + register char * slashp; + register int len; + + slashp = strchr(format, '/'); + if (slashp == NULL) { if (letters == NULL) (void) strcpy(abbr, format); else (void) sprintf(abbr, format, letters); - } else if (isdst) - (void) strcpy(abbr, strchr(format, '/') + 1); - else { - (void) strcpy(abbr, format); - *strchr(abbr, '/') = '\0'; + } else if (isdst) { + (void) strcpy(abbr, slashp + 1); + } else { + if (slashp > format) + (void) strncpy(abbr, format, + (unsigned) (slashp - format)); + abbr[slashp - format] = '\0'; + } + if (!doquotes) + return; + for (cp = abbr; *cp != '\0'; ++cp) + if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", *cp) == NULL && + strchr("abcdefghijklmnopqrstuvwxyz", *cp) == NULL) + break; + len = strlen(abbr); + if (len > 0 && *cp == '\0') + return; + abbr[len + 2] = '\0'; + abbr[len + 1] = '>'; + for ( ; len > 0; --len) + abbr[len] = abbr[len - 1]; + abbr[0] = '<'; +} + +static void +updateminmax(x) +const int x; +{ + if (min_year > x) + min_year = x; + if (max_year < x) + max_year = x; +} + +static int +stringoffset(result, offset) +char * result; +long offset; +{ + register int hours; + register int minutes; + register int seconds; + + result[0] = '\0'; + if (offset < 0) { + (void) strcpy(result, "-"); + offset = -offset; + } + seconds = offset % SECSPERMIN; + offset /= SECSPERMIN; + minutes = offset % MINSPERHOUR; + offset /= MINSPERHOUR; + hours = offset; + if (hours >= HOURSPERDAY) { + result[0] = '\0'; + return -1; + } + (void) sprintf(end(result), "%d", hours); + if (minutes != 0 || seconds != 0) { + (void) sprintf(end(result), ":%02d", minutes); + if (seconds != 0) + (void) sprintf(end(result), ":%02d", seconds); + } + return 0; +} + +static int +stringrule(result, rp, dstoff, gmtoff) +char * result; +const struct rule * const rp; +const long dstoff; +const long gmtoff; +{ + register long tod; + + result = end(result); + if (rp->r_dycode == DC_DOM) { + register int month, total; + + if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY) + return -1; + total = 0; + for (month = 0; month < rp->r_month; ++month) + total += len_months[0][month]; + (void) sprintf(result, "J%d", total + rp->r_dayofmonth); + } else { + register int week; + + if (rp->r_dycode == DC_DOWGEQ) { + week = 1 + rp->r_dayofmonth / DAYSPERWEEK; + if ((week - 1) * DAYSPERWEEK + 1 != rp->r_dayofmonth) + return -1; + } else if (rp->r_dycode == DC_DOWLEQ) { + if (rp->r_dayofmonth == len_months[1][rp->r_month]) + week = 5; + else { + week = 1 + rp->r_dayofmonth / DAYSPERWEEK; + if (week * DAYSPERWEEK - 1 != rp->r_dayofmonth) + return -1; + } + } else return -1; /* "cannot happen" */ + (void) sprintf(result, "M%d.%d.%d", + rp->r_month + 1, week, rp->r_wday); + } + tod = rp->r_tod; + if (rp->r_todisgmt) + tod += gmtoff; + if (rp->r_todisstd && rp->r_stdoff == 0) + tod += dstoff; + if (tod < 0) { + result[0] = '\0'; + return -1; + } + if (tod != 2 * SECSPERMIN * MINSPERHOUR) { + (void) strcat(result, "/"); + if (stringoffset(end(result), tod) != 0) + return -1; + } + return 0; +} + +static void +stringzone(result, zpfirst, zonecount) +char * result; +const struct zone * const zpfirst; +const int zonecount; +{ + register const struct zone * zp; + register struct rule * rp; + register struct rule * stdrp; + register struct rule * dstrp; + register int i; + register const char * abbrvar; + + result[0] = '\0'; + zp = zpfirst + zonecount - 1; + stdrp = dstrp = NULL; + for (i = 0; i < zp->z_nrules; ++i) { + rp = &zp->z_rules[i]; + if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX) + continue; + if (rp->r_yrtype != NULL) + continue; + if (rp->r_stdoff == 0) { + if (stdrp == NULL) + stdrp = rp; + else return; + } else { + if (dstrp == NULL) + dstrp = rp; + else return; + } + } + if (stdrp == NULL && dstrp == NULL) { + /* + ** There are no rules running through "max". + ** Let's find the latest rule. + */ + for (i = 0; i < zp->z_nrules; ++i) { + rp = &zp->z_rules[i]; + if (stdrp == NULL || rp->r_hiyear > stdrp->r_hiyear || + (rp->r_hiyear == stdrp->r_hiyear && + rp->r_month > stdrp->r_month)) + stdrp = rp; + } + if (stdrp != NULL && stdrp->r_stdoff != 0) + return; /* We end up in DST (a POSIX no-no). */ + /* + ** Horrid special case: if year is 2037, + ** presume this is a zone handled on a year-by-year basis; + ** do not try to apply a rule to the zone. + */ + if (stdrp != NULL && stdrp->r_hiyear == 2037) + return; + } + if (stdrp == NULL && zp->z_nrules != 0) + return; + abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; + doabbr(result, zp->z_format, abbrvar, FALSE, TRUE); + if (stringoffset(end(result), -zp->z_gmtoff) != 0) { + result[0] = '\0'; + return; + } + if (dstrp == NULL) + return; + doabbr(end(result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE); + if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) + if (stringoffset(end(result), + -(zp->z_gmtoff + dstrp->r_stdoff)) != 0) { + result[0] = '\0'; + return; + } + (void) strcat(result, ","); + if (stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { + result[0] = '\0'; + return; + } + (void) strcat(result, ","); + if (stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { + result[0] = '\0'; + return; } } @@ -1592,7 +1959,7 @@ const int zonecount; register struct rule * rp; register int i, j; register int usestart, useuntil; - register time_t starttime, untiltime; + register zic_t starttime, untiltime; register long gmtoff; register long stdoff; register int year; @@ -1600,8 +1967,17 @@ const int zonecount; register int startttisstd; register int startttisgmt; register int type; - char startbuf[BUFSIZ]; + register char * startbuf; + register char * ab; + register char * envvar; + register int max_abbr_len; + register int max_envvar_len; + max_abbr_len = 2 + max_format_len + max_abbrvar_len; + max_envvar_len = 2 * max_abbr_len + 5 * 9; + startbuf = emalloc(max_abbr_len + 1); + ab = emalloc(max_abbr_len + 1); + envvar = emalloc(max_envvar_len + 1); INITIALIZE(untiltime); INITIALIZE(starttime); /* @@ -1611,11 +1987,57 @@ const int zonecount; typecnt = 0; charcnt = 0; /* - ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au) + ** Thanks to Earl Chew ** for noting the need to unconditionally initialize startttisstd. */ startttisstd = FALSE; startttisgmt = FALSE; + min_year = max_year = EPOCH_YEAR; + if (leapseen) { + updateminmax(leapminyear); + updateminmax(leapmaxyear + (leapmaxyear < INT_MAX)); + } + for (i = 0; i < zonecount; ++i) { + zp = &zpfirst[i]; + if (i < zonecount - 1) + updateminmax(zp->z_untilrule.r_loyear); + for (j = 0; j < zp->z_nrules; ++j) { + rp = &zp->z_rules[j]; + if (rp->r_lowasnum) + updateminmax(rp->r_loyear); + if (rp->r_hiwasnum) + updateminmax(rp->r_hiyear); + } + } + /* + ** Generate lots of data if a rule can't cover all future times. + */ + stringzone(envvar, zpfirst, zonecount); + if (noise && envvar[0] == '\0') { + register char * wp; + +wp = ecpyalloc(_("no POSIX environment variable for zone")); + wp = ecatalloc(wp, " "); + wp = ecatalloc(wp, zpfirst->z_name); + warning(wp); + ifree(wp); + } + if (envvar[0] == '\0') { + if (min_year >= INT_MIN + YEARSPERREPEAT) + min_year -= YEARSPERREPEAT; + else min_year = INT_MIN; + if (max_year <= INT_MAX - YEARSPERREPEAT) + max_year += YEARSPERREPEAT; + else max_year = INT_MAX; + } + /* + ** For the benefit of older systems, + ** generate data from 1900 through 2037. + */ + if (min_year > 1900) + min_year = 1900; + if (max_year < 2037) + max_year = 2037; for (i = 0; i < zonecount; ++i) { /* ** A guess that may well be corrected later. @@ -1633,7 +2055,7 @@ const int zonecount; if (zp->z_nrules == 0) { stdoff = zp->z_stdoff; doabbr(startbuf, zp->z_format, - (char *) NULL, stdoff != 0); + (char *) NULL, stdoff != 0, FALSE); type = addtype(oadd(zp->z_gmtoff, stdoff), startbuf, stdoff != 0, startttisstd, startttisgmt); @@ -1661,9 +2083,8 @@ const int zonecount; } for ( ; ; ) { register int k; - register time_t jtime, ktime; + register zic_t jtime, ktime; register long offset; - char buf[BUFSIZ]; INITIALIZE(ktime); if (useuntil) { @@ -1719,23 +2140,27 @@ const int zonecount; stdoff); doabbr(startbuf, zp->z_format, rp->r_abbrvar, - rp->r_stdoff != 0); + rp->r_stdoff != 0, + FALSE); continue; } if (*startbuf == '\0' && - startoff == oadd(zp->z_gmtoff, - stdoff)) { - doabbr(startbuf, zp->z_format, - rp->r_abbrvar, - rp->r_stdoff != 0); + startoff == oadd(zp->z_gmtoff, + stdoff)) { + doabbr(startbuf, + zp->z_format, + rp->r_abbrvar, + rp->r_stdoff != + 0, + FALSE); } } eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); - doabbr(buf, zp->z_format, rp->r_abbrvar, - rp->r_stdoff != 0); + doabbr(ab, zp->z_format, rp->r_abbrvar, + rp->r_stdoff != 0, FALSE); offset = oadd(zp->z_gmtoff, rp->r_stdoff); - type = addtype(offset, buf, rp->r_stdoff != 0, + type = addtype(offset, ab, rp->r_stdoff != 0, rp->r_todisstd, rp->r_todisgmt); addtt(ktime, type); } @@ -1768,12 +2193,15 @@ error(_("can't determine time zone abbreviation to use just after until time")); starttime = tadd(starttime, -gmtoff); } } - writezone(zpfirst->z_name); + writezone(zpfirst->z_name, envvar); + ifree(startbuf); + ifree(ab); + ifree(envvar); } static void addtt(starttime, type) -const time_t starttime; +const zic_t starttime; int type; { if (starttime <= min_time || @@ -1792,7 +2220,7 @@ int type; } if (timecnt >= TZ_MAX_TIMES) { error(_("too many transitions?!")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } attypes[timecnt].at = starttime; attypes[timecnt].type = type; @@ -1811,15 +2239,15 @@ const int ttisgmt; if (isdst != TRUE && isdst != FALSE) { error(_("internal error - addtype called with bad isdst")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } if (ttisstd != TRUE && ttisstd != FALSE) { error(_("internal error - addtype called with bad ttisstd")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } if (ttisgmt != TRUE && ttisgmt != FALSE) { error(_("internal error - addtype called with bad ttisgmt")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } /* ** See if there's already an entry for this zone type. @@ -1838,7 +2266,11 @@ const int ttisgmt; */ if (typecnt >= TZ_MAX_TYPES) { error(_("too many local time types")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); + } + if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) { + error(_("UTC offset out of range")); + exit(EXIT_FAILURE); } gmtoffs[i] = gmtoff; isdsts[i] = isdst; @@ -1857,7 +2289,7 @@ const int ttisgmt; static void leapadd(t, positive, rolling, count) -const time_t t; +const zic_t t; const int positive; const int rolling; int count; @@ -1866,13 +2298,13 @@ int count; if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { error(_("too many leap seconds")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } for (i = 0; i < leapcnt; ++i) if (t <= trans[i]) { if (t == trans[i]) { error(_("repeated leap second moment")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } break; } @@ -1890,7 +2322,7 @@ int count; } static void -adjleap P((void)) +adjleap(void) { register int i; register long last = 0; @@ -1927,7 +2359,7 @@ const char * const type; (void) fprintf(stderr, _("%s: command was '%s', result was %d\n"), progname, buf, result); for ( ; ; ) - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } static int @@ -2008,8 +2440,9 @@ register char * cp; emalloc((int) ((strlen(cp) + 1) * sizeof *array)); nsubs = 0; for ( ; ; ) { - while (isascii(*cp) && isspace((unsigned char) *cp)) - ++cp; + while (isascii((unsigned char) *cp) && + isspace((unsigned char) *cp)) + ++cp; if (*cp == '\0' || *cp == '#') break; array[nsubs++] = dp = cp; @@ -2019,7 +2452,12 @@ register char * cp; else while ((*dp = *cp++) != '"') if (*dp != '\0') ++dp; - else error(_("Odd number of quotation marks")); + else { + error(_( + "Odd number of quotation marks" + )); + exit(1); + } } while (*cp != '\0' && *cp != '#' && (!isascii(*cp) || !isspace((unsigned char) *cp))); if (isascii(*cp) && isspace((unsigned char) *cp)) @@ -2040,17 +2478,17 @@ const long t2; t = t1 + t2; if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { error(_("time overflow")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } return t; } -static time_t +static zic_t tadd(t1, t2) -const time_t t1; +const zic_t t1; const long t2; { - register time_t t; + register zic_t t; if (t1 == max_time && t2 > 0) return max_time; @@ -2059,7 +2497,7 @@ const long t2; t = t1 + t2; if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { error(_("time overflow")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } return t; } @@ -2069,14 +2507,14 @@ const long t2; ** 1970, 00:00 LOCAL time - in that year that the rule refers to. */ -static time_t +static zic_t rpytime(rp, wantedy) register const struct rule * const rp; register const int wantedy; { register int y, m, i; register long dayoff; /* with a nod to Margaret O. */ - register time_t t; + register zic_t t; if (wantedy == INT_MIN) return min_time; @@ -2106,7 +2544,7 @@ register const int wantedy; --i; else { error(_("use of 2/29 in non leap-year")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } } --i; @@ -2140,16 +2578,15 @@ register const int wantedy; } if (i < 0 || i >= len_months[isleap(y)][m]) { if (noise) - warning(_("rule goes past start/end of month--will not work with pre-2004 versions of zic")); + warning(_("rule goes past start/end of month--\ +will not work with pre-2004 versions of zic")); } } - if (dayoff < 0 && !TYPE_SIGNED(time_t)) - return min_time; if (dayoff < min_time / SECSPERDAY) return min_time; if (dayoff > max_time / SECSPERDAY) return max_time; - t = (time_t) dayoff * SECSPERDAY; + t = (zic_t) dayoff * SECSPERDAY; return tadd(t, rp->r_tod); } @@ -2159,10 +2596,48 @@ const char * const string; { register int i; + if (strcmp(string, GRANDPARENTED) != 0) { + register const char * cp; + register char * wp; + + /* + ** Want one to ZIC_MAX_ABBR_LEN_WO_WARN alphabetics + ** optionally followed by a + or - and a number from 1 to 14. + */ + cp = string; + wp = NULL; + while (isascii((unsigned char) *cp) && + isalpha((unsigned char) *cp)) + ++cp; + if (cp - string == 0) +wp = _("time zone abbreviation lacks alphabetic at start"); + if (noise && cp - string > 3) +wp = _("time zone abbreviation has more than 3 alphabetics"); + if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN) +wp = _("time zone abbreviation has too many alphabetics"); + if (wp == NULL && (*cp == '+' || *cp == '-')) { + ++cp; + if (isascii((unsigned char) *cp) && + isdigit((unsigned char) *cp)) + if (*cp++ == '1' && + *cp >= '0' && *cp <= '4') + ++cp; + } + if (*cp != '\0') +wp = _("time zone abbreviation differs from POSIX standard"); + if (wp != NULL) { + wp = ecpyalloc(wp); + wp = ecatalloc(wp, " ("); + wp = ecatalloc(wp, string); + wp = ecatalloc(wp, ")"); + warning(wp); + ifree(wp); + } + } i = strlen(string) + 1; if (charcnt + i > TZ_MAX_CHARS) { error(_("too many, or too long, time zone abbreviations")); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } (void) strcpy(&chars[charcnt], string); charcnt += eitol(i); @@ -2170,7 +2645,7 @@ const char * const string; static int mkdirs(argname) -char * const argname; +char * argname; { register char * name; register char * cp; @@ -2226,7 +2701,7 @@ const int i; (void) fprintf(stderr, _("%s: %d did not sign extend correctly\n"), progname, i); - (void) exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } return l; } From bbdb4f59542b90bbbfc1d26f8f7beebc12ec578e Mon Sep 17 00:00:00 2001 From: Edwin Groothuis Date: Wed, 27 May 2009 10:10:48 +0000 Subject: [PATCH 005/453] Vendor import of tzcode2009h - Clarify the license for the tzcode: public domain Obtained from: ftp://elsie.nci.nih.gov/pub/ --- libc/stdtime/time2posix.3 | 2 +- unused/Makefile | 5 ++++- unused/date.1 | 4 +++- unused/newctime.3 | 4 +++- unused/newstrftime.3 | 4 +++- unused/newtzset.3 | 4 +++- unused/tz-art.htm | 6 +++++- unused/tz-link.htm | 6 +++++- unused/tzselect.8 | 4 +++- unused/workman.sh | 5 ++++- zic/README | 4 +++- zic/Theory | 6 +++--- zic/zdump.8 | 4 +++- zic/zdump.c | 7 ++++++- zic/zic.8 | 4 +++- 15 files changed, 52 insertions(+), 17 deletions(-) diff --git a/libc/stdtime/time2posix.3 b/libc/stdtime/time2posix.3 index 96959c642ed..64ea048f818 100644 --- a/libc/stdtime/time2posix.3 +++ b/libc/stdtime/time2posix.3 @@ -116,6 +116,6 @@ difftime(3), localtime(3), mktime(3), time(2) -.\" @(#)time2posix.3 8.1 +.\" @(#)time2posix.3 8.2 .\" This file is in the public domain, so clarified as of .\" 1996-06-05 by Arthur David Olson. diff --git a/unused/Makefile b/unused/Makefile index 3865f23766e..dd154b30101 100644 --- a/unused/Makefile +++ b/unused/Makefile @@ -1,4 +1,7 @@ -# @(#)Makefile 8.7 +#
    +# @(#)Makefile	8.8
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
     
     # Change the line below for your time zone (after finding the zone you want in
     # the time zone files, or adding it to a time zone file).
    diff --git a/unused/date.1 b/unused/date.1
    index 3c75ba4337c..a3e00731f95 100644
    --- a/unused/date.1
    +++ b/unused/date.1
    @@ -172,4 +172,6 @@ If
     is absent,
     UTC leap seconds are loaded from
     .BR /usr/local/etc/zoneinfo/posixrules .
    -.\" @(#)date.1	8.1
    +.\" @(#)date.1	8.2
    +.\" This file is in the public domain, so clarified as of
    +.\" 2009-05-17 by Arthur David Olson.
    diff --git a/unused/newctime.3 b/unused/newctime.3
    index 323201e0c50..a0239de5c0a 100644
    --- a/unused/newctime.3
    +++ b/unused/newctime.3
    @@ -236,4 +236,6 @@ instead.
     Avoid using out-of-range values with
     .I mktime
     when setting up lunch with promptness sticklers in Riyadh.
    -.\" @(#)newctime.3	8.2
    +.\" @(#)newctime.3	8.3
    +.\" This file is in the public domain, so clarified as of
    +.\" 2009-05-17 by Arthur David Olson.
    diff --git a/unused/newstrftime.3 b/unused/newstrftime.3
    index 92392dcc326..cd70974b8e1 100644
    --- a/unused/newstrftime.3
    +++ b/unused/newstrftime.3
    @@ -227,4 +227,6 @@ newctime(3),
     newtzset(3),
     time(2),
     tzfile(5)
    -.\" @(#)newstrftime.3	8.1
    +.\" @(#)newstrftime.3	8.2
    +.\" This file is in the public domain, so clarified as of
    +.\" 2009-05-17 by Arthur David Olson.
    diff --git a/unused/newtzset.3 b/unused/newtzset.3
    index e19ad7033e1..07c5e0c605a 100644
    --- a/unused/newtzset.3
    +++ b/unused/newtzset.3
    @@ -234,4 +234,6 @@ newctime(3),
     newstrftime(3),
     time(2),
     tzfile(5)
    -.\" @(#)newtzset.3	8.1
    +.\" @(#)newtzset.3	8.2
    +.\" This file is in the public domain, so clarified as of
    +.\" 2009-05-17 by Arthur David Olson.
    diff --git a/unused/tz-art.htm b/unused/tz-art.htm
    index 352c408b66c..f035833ca61 100644
    --- a/unused/tz-art.htm
    +++ b/unused/tz-art.htm
    @@ -9,9 +9,13 @@ PUBLIC "-//W3C//DTD HTML 4.01//EN"
     
     

    Time and the Arts

    -@(#)tz-art.htm 8.11 +@(#)tz-art.htm 8.12

    +This file is in the public domain, so clarified as of +2009-05-17 by Arthur David Olson. +

    +

    Please send corrections to this web page to the time zone mailing list.

    diff --git a/unused/tz-link.htm b/unused/tz-link.htm index 0cd9e28a305..2c8ff2c8867 100644 --- a/unused/tz-link.htm +++ b/unused/tz-link.htm @@ -18,9 +18,13 @@

    Sources for Time Zone and Daylight Saving Time Data

    -@(#)tz-link.htm 8.18 +@(#)tz-link.htm 8.19

    +This file is in the public domain, so clarified as of +2009-05-17 by Arthur David Olson. +

    +

    Please send corrections to this web page to the time zone mailing list.

    The tz database

    diff --git a/unused/tzselect.8 b/unused/tzselect.8 index 949d9f7bf35..515b0ed51bf 100644 --- a/unused/tzselect.8 +++ b/unused/tzselect.8 @@ -38,4 +38,6 @@ The exit status is zero if a time zone was successfully obtained from the user, nonzero otherwise. .SH "SEE ALSO" newctime(3), tzfile(5), zdump(8), zic(8) -.\" @(#)tzselect.8 8.1 +.\" @(#)tzselect.8 8.2 +.\" This file is in the public domain, so clarified as of +.\" 2009-05-17 by Arthur David Olson. diff --git a/unused/workman.sh b/unused/workman.sh index cdf5b7311a8..2fbb7e211c6 100644 --- a/unused/workman.sh +++ b/unused/workman.sh @@ -1,6 +1,9 @@ #! /bin/sh -# @(#)workman.sh 8.1 +#
    +# @(#)workman.sh	8.2
    +# This file is in the public domain, so clarified as of
    +# 2009-05-17 by Arthur David Olson.
     
     # Tell groff not to emit SGR escape sequences (ANSI color escapes).
     GROFF_NO_SGR=1
    diff --git a/zic/README b/zic/README
    index c0cc92853d0..427b6a01519 100644
    --- a/zic/README
    +++ b/zic/README
    @@ -1,4 +1,6 @@
    -@(#)README	8.2
    +@(#)README	8.3
    +This file is in the public domain, so clarified as of
    +2009-05-17 by Arthur David Olson.
     
     "What time is it?" -- Richard Deacon as The King
     "Any time you want it to be." -- Frank Baxter as The Scientist
    diff --git a/zic/Theory b/zic/Theory
    index b842fb4b753..36b087eb4c5 100644
    --- a/zic/Theory
    +++ b/zic/Theory
    @@ -1,5 +1,6 @@
    -@(#)Theory	8.2
    -
    +@(#)Theory	8.3
    +This file is in the public domain, so clarified as of
    +2009-05-17 by Arthur David Olson.
     
     ----- Outline -----
     
    @@ -9,7 +10,6 @@
     	Calendrical issues
     	Time and time zones on Mars
     
    -
     ----- Time and date functions -----
     
     These time and date functions are upwards compatible with POSIX,
    diff --git a/zic/zdump.8 b/zic/zdump.8
    index 67cbaead4b5..90940a6bce8 100644
    --- a/zic/zdump.8
    +++ b/zic/zdump.8
    @@ -54,4 +54,6 @@ This works in all real-world cases;
     one can construct artificial time zones for which this fails.
     .SH "SEE ALSO"
     newctime(3), tzfile(5), zic(8)
    -.\" @(#)zdump.8	8.1
    +.\" @(#)zdump.8	8.2
    +.\" This file is in the public domain, so clarified as of
    +.\" 2009-05-17 by Arthur David Olson.
    diff --git a/zic/zdump.c b/zic/zdump.c
    index 085b33e23d4..7122bbf8918 100644
    --- a/zic/zdump.c
    +++ b/zic/zdump.c
    @@ -1,4 +1,9 @@
    -static char	elsieid[] = "@(#)zdump.c	8.8";
    +/*
    +** This file is in the public domain, so clarified as of
    +** 2009-05-17 by Arthur David Olson.
    +*/
    +
    +static char	elsieid[] = "@(#)zdump.c	8.9";
     
     /*
     ** This code has been made independent of the rest of the time
    diff --git a/zic/zic.8 b/zic/zic.8
    index f842927a7b7..c66b4a0ea9f 100644
    --- a/zic/zic.8
    +++ b/zic/zic.8
    @@ -490,4 +490,6 @@ specifying transition instants using universal time.
     /usr/local/etc/zoneinfo	standard directory used for created files
     .SH "SEE ALSO"
     newctime(3), tzfile(5), zdump(8)
    -.\" @(#)zic.8	8.4
    +.\" @(#)zic.8	8.5
    +.\" This file is in the public domain, so clarified as of
    +.\" 2009-05-17 by Arthur David Olson.
    
    From 54e87cd8a2a6bdc86c27282a78c87a339b35e4db Mon Sep 17 00:00:00 2001
    From: Edwin Groothuis 
    Date: Tue, 9 Jun 2009 00:14:13 +0000
    Subject: [PATCH 006/453] MFV of tzcode2009i:
    
    Fix link of TZ timezone maps at http://efele.net/maps/tz/
    ---
     unused/tz-link.htm | 7 +++----
     1 file changed, 3 insertions(+), 4 deletions(-)
    
    diff --git a/unused/tz-link.htm b/unused/tz-link.htm
    index 2c8ff2c8867..a584b1f8c20 100644
    --- a/unused/tz-link.htm
    +++ b/unused/tz-link.htm
    @@ -18,7 +18,7 @@
     
     

    Sources for Time Zone and Daylight Saving Time Data

    -@(#)tz-link.htm 8.19 +@(#)tz-link.htm 8.21

    This file is in the public domain, so clarified as of @@ -360,10 +360,9 @@ but the maps are more up to date.

Time zone boundaries

    -
  • A map of the TZ timezones in -the US contains a TZ timezone maps contains a shapefile of the -tz regions in the US.
  • +tz regions in the world.
  • Administrative Divisions of Countries ("Statoids") contains detailed lists of tz-related zone subdivision data.
  • From 5512468ac429a562911d62c6e818e6475b6340c3 Mon Sep 17 00:00:00 2001 From: Edwin Groothuis Date: Tue, 21 Jul 2009 01:59:52 +0000 Subject: [PATCH 007/453] Vendor import of tzdata2009k - Changes in Mauritius and Bangladesh - No leapsecond at the end of December 2009 Obtained from: ftp://elsie.nci.nih.gov/pub/ --- africa | 28 +++++++++++++++++++++++++--- asia | 11 +++++++++-- europe | 4 ++-- leapseconds | 14 +++++++------- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/africa b/africa index 3f92eb4745c..6e268c94781 100644 --- a/africa +++ b/africa @@ -1,5 +1,5 @@ #
    -# @(#)africa	8.21
    +# @(#)africa	8.22
     # This file is in the public domain, so clarified as of
     # 2009-05-17 by Arthur David Olson.
     
    @@ -502,11 +502,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/asia b/asia
    index 2262397fa5c..13a1989251c 100644
    --- a/asia
    +++ b/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/europe b/europe
    index 3f39215bf64..adf20a2828c 100644
    --- a/europe
    +++ b/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/leapseconds b/leapseconds
    index d6343c02096..a3c95efb1c8 100644
    --- a/leapseconds
    +++ b/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.
     
    @@ -56,13 +56,13 @@ Leap	2008	Dec	31	23:59:60	+	S
     # SERVICE DE LA ROTATION TERRESTRE
     # OBSERVATOIRE DE PARIS
     # 61, Av. de l'Observatoire 75014 PARIS (France)
    -# Tel.      : 33 (0) 1 40 51 22 29
    +# Tel.      : 33 (0) 1 40 51 22 26
     # FAX       : 33 (0) 1 40 51 22 91
     # 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
    @@ -70,7 +70,7 @@ Leap	2008	Dec	31	23:59:60	+	S
     #
     # INFORMATION ON UTC - TAI
     #
    -# NO positive leap second will be introduced at the end of June 2009.
    +# 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 :		
     #
    @@ -82,6 +82,6 @@ Leap	2008	Dec	31	23:59:60	+	S
     # will be no time step at the next possible date.
     #
     # Daniel GAMBIS
    -# Head			
    -# Earth Orientation Center of the IERS
    +# Director			
    +# Earth Orientation Center of IERS
     # Observatoire de Paris, France
    
    From 4f9074da93347bbe3167e16ebd27d5bd0e592729 Mon Sep 17 00:00:00 2001
    From: Edwin Groothuis 
    Date: Tue, 21 Jul 2009 02:13:57 +0000
    Subject: [PATCH 008/453] Vendor import of tzcode2009k
    
    zic.c:
        Do not end a binary file with a POSIX-style time zone string
        for locations that end up in permanent DST (thanks to Andreas
        Schwab).
    
    tz-art.htm
        Add notes on "A Matter of Life and Death"
        (thanks to Dave Cantor).
    
    tz-link.htm
        Remove seemingly obsolete public.planetmirror.com/pub/timezone
        link (thanks to Nathan Stratton Treadway).
    
    Obtained from:	ftp://elsie.nci.nih.gov/pub/
    ---
     unused/tz-art.htm  | 13 ++++++++++++-
     unused/tz-link.htm |  7 ++-----
     zic/zic.c          |  4 ++--
     3 files changed, 16 insertions(+), 8 deletions(-)
    
    diff --git a/unused/tz-art.htm b/unused/tz-art.htm
    index f035833ca61..cba330e0b76 100644
    --- a/unused/tz-art.htm
    +++ b/unused/tz-art.htm
    @@ -9,7 +9,7 @@ PUBLIC "-//W3C//DTD HTML 4.01//EN"
     
     

    Time and the Arts

    -@(#)tz-art.htm 8.12 +@(#)tz-art.htm 8.13

    This file is in the public domain, so clarified as of @@ -353,6 +353,17 @@ A private jet's mid-flight change of time zones distorts Alison Dubois' premonition in the "We Had a Dream" episode of "Medium" (originally aired 2007-02-28). +

  • +In the 1946 "A Matter of Life and Death," +there is a reference to British Double Summer Time. +The time does not play a large part in the plot; +it's just a passing reference to the time when one of the +characters was supposed to have died (but didn't). +The IMDb page is at + +http://us.imdb.com/title/tt0038733/ +. (Dave Cantor) +

    diff --git a/unused/tz-link.htm b/unused/tz-link.htm index a584b1f8c20..fe58bf78530 100644 --- a/unused/tz-link.htm +++ b/unused/tz-link.htm @@ -18,7 +18,7 @@

    Sources for Time Zone and Daylight Saving Time Data

    -@(#)tz-link.htm 8.21 +@(#)tz-link.htm 8.22

    This file is in the public domain, so clarified as of @@ -114,10 +114,7 @@ retrieve the full archive of old messages (in gzip compressed format), or retrieve archived older versions of code -and data; there is also a smaller HTTP -mirror.

    +and data.

    The Web has several other sources for time zone and daylight saving time data. Here are some recent links that may be of interest. diff --git a/zic/zic.c b/zic/zic.c index 01d9f135bd7..484638a2cb5 100644 --- a/zic/zic.c +++ b/zic/zic.c @@ -3,7 +3,7 @@ ** 2006-07-17 by Arthur David Olson. */ -static char elsieid[] = "@(#)zic.c 8.19"; +static char elsieid[] = "@(#)zic.c 8.20"; #include "private.h" #include "locale.h" @@ -1921,7 +1921,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); From 1b501e53f31162b977a0eff8cca3f9d75c8847aa Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Wed, 12 Aug 2009 10:26:03 +0000 Subject: [PATCH 009/453] Put minimum alignment on the dpcpu and vnet section so that ld when adding the __start_ symbol knows the expected section alignment and can place the __start_ symbol correctly. These sections will not support symbols with super-cache line alignment requirements. For full details, see posting to freebsd-current, 2009-08-10, Message-ID: <20090810133111.C93661@maildrop.int.zabbadoz.net>. Debugging and testing patches by: Kamigishi Rei (spambox haruhiism.net), np, lstewart, jhb, kib, rwatson Tested by: Kamigishi Rei, lstewart Reviewed by: kib Approved by: re --- sys/net/vnet.h | 8 +++++--- sys/sys/pcpu.h | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sys/net/vnet.h b/sys/net/vnet.h index 01d824d68b2..d441af19970 100644 --- a/sys/net/vnet.h +++ b/sys/net/vnet.h @@ -185,12 +185,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) 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. From d19d55a76f0760550f80c6473e87866d244e49e7 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Wed, 12 Aug 2009 10:41:37 +0000 Subject: [PATCH 010/453] Update procstat(1) for the fact that devfs paths are no longer unsupported. Approved by: re (kib) --- usr.bin/procstat/procstat.1 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 From c1aee612187e145b01bf9d11b2baf91b885e5b44 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Wed, 12 Aug 2009 10:44:13 +0000 Subject: [PATCH 011/453] Reverse misordered unlock and lock in at_control for netatalk phase I addresses. Submitted by: Russell Cattelan Approved by: re (kib) --- sys/netatalk/at_control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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; From 9eb3e4639aa10e1473c15b1ec3d3265342d640cc Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Wed, 12 Aug 2009 10:45:45 +0000 Subject: [PATCH 012/453] Correctly audit real gids following changes to the audit record argument interface. Approved by: re (kib) --- sys/security/audit/audit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 { \ From 3a67af38ba24cdf225a521d181e278c8b98722b9 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Wed, 12 Aug 2009 10:46:48 +0000 Subject: [PATCH 013/453] Update posix1e-related man pages, especially as relates to MAC, to more accurately reflect the last ten years of work. Approved by: re (kib) --- lib/libc/posix1e/Makefile.inc | 4 +- lib/libc/posix1e/mac.3 | 175 ++++++++++++++++------------------ lib/libc/posix1e/mac_free.3 | 9 +- lib/libc/posix1e/mac_get.3 | 1 + lib/libc/posix1e/mac_set.3 | 1 + lib/libc/posix1e/mac_text.3 | 1 + lib/libc/posix1e/posix1e.3 | 116 +++++++++------------- 7 files changed, 140 insertions(+), 167 deletions(-) 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/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. From 96a65baf76f204e48f2f94554a0b9e2792f6682b Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Wed, 12 Aug 2009 11:55:26 +0000 Subject: [PATCH 014/453] Apply the ntp-related part of r195626 to the correct part of the tree -- the mkver which is used in builds is the one in usr.sbin/ntp/scripts, not the one in contrib/ntp/scripts. Pointy hat to: cperciva Approved by: re (rwatson) --- usr.sbin/ntp/scripts/mkver | 2 -- 1 file changed, 2 deletions(-) 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 From 281c86a4ef9997daea4b8d9f29179d16265e4b86 Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Wed, 12 Aug 2009 12:00:21 +0000 Subject: [PATCH 015/453] Update DDB show vnet command to print all used and available information. Reviewed by: rwatson, zec Approved by: re --- sys/net/vnet.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/sys/net/vnet.c b/sys/net/vnet.c index 7866bb98c90..17bcbc6fb51 100644 --- a/sys/net/vnet.c +++ b/sys/net/vnet.c @@ -615,14 +615,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 From f2140faed1768ec06df512db8e5a57dc51d8a8d5 Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Wed, 12 Aug 2009 12:06:16 +0000 Subject: [PATCH 016/453] Add ddb show dpcpu_off command to ease dpcpu memory debugging. While show pcpu prints pc_dynamic this also prints the original memory address as well as the maths. Once dpcpu goes NUMA this is considered to help debugging as well. Reviewed by: rwatson Approved by: re --- sys/kern/subr_pcpu.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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) From 829d7315d79f41f0393e26d57a8e802f1f492e27 Mon Sep 17 00:00:00 2001 From: "Simon L. B. Nielsen" Date: Wed, 12 Aug 2009 12:10:00 +0000 Subject: [PATCH 017/453] Remove symlinks in OpenSSL's testing framework. These are not required for normal build, and doesn't export well to CVS. If they are needed later a script will be added to recreate the symlinks when needed at build time. Approved by: re (rwatson) --- crypto/openssl/apps/md4.c | 1 - crypto/openssl/test/bftest.c | 1 - crypto/openssl/test/bntest.c | 1 - crypto/openssl/test/casttest.c | 1 - crypto/openssl/test/destest.c | 1 - crypto/openssl/test/dhtest.c | 1 - crypto/openssl/test/dsatest.c | 1 - crypto/openssl/test/ecdhtest.c | 1 - crypto/openssl/test/ecdsatest.c | 1 - crypto/openssl/test/ectest.c | 1 - crypto/openssl/test/enginetest.c | 1 - crypto/openssl/test/evp_test.c | 1 - crypto/openssl/test/exptest.c | 1 - crypto/openssl/test/fips_aesavs.c | 1 - crypto/openssl/test/fips_desmovs.c | 1 - crypto/openssl/test/fips_dsatest.c | 1 - crypto/openssl/test/fips_dssvs.c | 1 - crypto/openssl/test/fips_hmactest.c | 1 - crypto/openssl/test/fips_randtest.c | 1 - crypto/openssl/test/fips_rngvs.c | 1 - crypto/openssl/test/fips_rsagtest.c | 1 - crypto/openssl/test/fips_rsastest.c | 1 - crypto/openssl/test/fips_rsavtest.c | 1 - crypto/openssl/test/fips_shatest.c | 1 - crypto/openssl/test/fips_test_suite.c | 1 - crypto/openssl/test/hmactest.c | 1 - crypto/openssl/test/ideatest.c | 1 - crypto/openssl/test/jpaketest.c | 1 - crypto/openssl/test/md2test.c | 1 - crypto/openssl/test/md4test.c | 1 - crypto/openssl/test/md5test.c | 1 - crypto/openssl/test/mdc2test.c | 1 - crypto/openssl/test/randtest.c | 1 - crypto/openssl/test/rc2test.c | 1 - crypto/openssl/test/rc4test.c | 1 - crypto/openssl/test/rc5test.c | 1 - crypto/openssl/test/rmdtest.c | 1 - crypto/openssl/test/rsa_test.c | 1 - crypto/openssl/test/sha1test.c | 1 - crypto/openssl/test/sha256t.c | 1 - crypto/openssl/test/sha512t.c | 1 - crypto/openssl/test/shatest.c | 1 - crypto/openssl/test/ssltest.c | 1 - 43 files changed, 43 deletions(-) delete mode 120000 crypto/openssl/apps/md4.c delete mode 120000 crypto/openssl/test/bftest.c delete mode 120000 crypto/openssl/test/bntest.c delete mode 120000 crypto/openssl/test/casttest.c delete mode 120000 crypto/openssl/test/destest.c delete mode 120000 crypto/openssl/test/dhtest.c delete mode 120000 crypto/openssl/test/dsatest.c delete mode 120000 crypto/openssl/test/ecdhtest.c delete mode 120000 crypto/openssl/test/ecdsatest.c delete mode 120000 crypto/openssl/test/ectest.c delete mode 120000 crypto/openssl/test/enginetest.c delete mode 120000 crypto/openssl/test/evp_test.c delete mode 120000 crypto/openssl/test/exptest.c delete mode 120000 crypto/openssl/test/fips_aesavs.c delete mode 120000 crypto/openssl/test/fips_desmovs.c delete mode 120000 crypto/openssl/test/fips_dsatest.c delete mode 120000 crypto/openssl/test/fips_dssvs.c delete mode 120000 crypto/openssl/test/fips_hmactest.c delete mode 120000 crypto/openssl/test/fips_randtest.c delete mode 120000 crypto/openssl/test/fips_rngvs.c delete mode 120000 crypto/openssl/test/fips_rsagtest.c delete mode 120000 crypto/openssl/test/fips_rsastest.c delete mode 120000 crypto/openssl/test/fips_rsavtest.c delete mode 120000 crypto/openssl/test/fips_shatest.c delete mode 120000 crypto/openssl/test/fips_test_suite.c delete mode 120000 crypto/openssl/test/hmactest.c delete mode 120000 crypto/openssl/test/ideatest.c delete mode 120000 crypto/openssl/test/jpaketest.c delete mode 120000 crypto/openssl/test/md2test.c delete mode 120000 crypto/openssl/test/md4test.c delete mode 120000 crypto/openssl/test/md5test.c delete mode 120000 crypto/openssl/test/mdc2test.c delete mode 120000 crypto/openssl/test/randtest.c delete mode 120000 crypto/openssl/test/rc2test.c delete mode 120000 crypto/openssl/test/rc4test.c delete mode 120000 crypto/openssl/test/rc5test.c delete mode 120000 crypto/openssl/test/rmdtest.c delete mode 120000 crypto/openssl/test/rsa_test.c delete mode 120000 crypto/openssl/test/sha1test.c delete mode 120000 crypto/openssl/test/sha256t.c delete mode 120000 crypto/openssl/test/sha512t.c delete mode 120000 crypto/openssl/test/shatest.c delete mode 120000 crypto/openssl/test/ssltest.c 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/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 From 57aea6dfb8f2379f93733bdbf485d15c2fdf0a3a Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Wed, 12 Aug 2009 12:12:23 +0000 Subject: [PATCH 018/453] Make the kernel compile without IP networking by moving a variable under a proper #ifdef. Approved by: re (rwatson) --- sys/kern/kern_jail.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index cf5dfd8b856..282a4d8c95b 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -472,10 +472,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; #if defined(INET) || defined(INET6) + struct prison *tppr; void *op; #endif unsigned long hid; From 50580ef7b3e3d84ff2175acc588ee04ffe602984 Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Wed, 12 Aug 2009 12:29:07 +0000 Subject: [PATCH 019/453] Do not truncate IPv6 addresses when printing them in the jls -av 7.x multi-IP jail backward compat output. Reported by: ed Tested by: ed Reviewed by: rwatson Approved by: re --- usr.sbin/jls/jls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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", From fb6891522e75ad9c52d0227c44a6e9c4dcf6f83e Mon Sep 17 00:00:00 2001 From: Robert Noland Date: Wed, 12 Aug 2009 12:50:15 +0000 Subject: [PATCH 020/453] Add some additional radeon pci ids to drm. Approved by: re (kib) MFC after: 0 days --- sys/dev/drm/drm_pciids.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sys/dev/drm/drm_pciids.h b/sys/dev/drm/drm_pciids.h index 4562e5f722e..a10469ade08 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"}, \ @@ -350,6 +353,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 +370,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 \ From 2aadd82afe51e16d0ee732f919d847ec40c379be Mon Sep 17 00:00:00 2001 From: Robert Noland Date: Wed, 12 Aug 2009 12:57:02 +0000 Subject: [PATCH 021/453] Add support for radeon RS880 IGP chips to drm. Approved by: re (kib) MFC after: 0 days --- sys/dev/drm/drm_pciids.h | 5 +++++ sys/dev/drm/r600_cp.c | 18 +++++++++++++----- sys/dev/drm/radeon_drv.h | 1 + 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/sys/dev/drm/drm_pciids.h b/sys/dev/drm/drm_pciids.h index a10469ade08..3b2347ed5b6 100644 --- a/sys/dev/drm/drm_pciids.h +++ b/sys/dev/drm/drm_pciids.h @@ -330,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"}, \ diff --git a/sys/dev/drm/r600_cp.c b/sys/dev/drm/r600_cp.c index 64e98ce41e6..8c33eb6f483 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; diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h index ae1166f023b..5914b13b5dd 100644 --- a/sys/dev/drm/radeon_drv.h +++ b/sys/dev/drm/radeon_drv.h @@ -145,6 +145,7 @@ enum radeon_family { CHIP_RV635, CHIP_RV670, CHIP_RS780, + CHIP_RS880, CHIP_RV770, CHIP_RV740, CHIP_RV730, From 8b28fd0239d3492feaa82d77d8e60a54b1d880fc Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 12 Aug 2009 14:37:57 +0000 Subject: [PATCH 022/453] Fix references to the kernel distributions to use the correct names (uppercase). PR: docs/137415 Submitted by: Yuri Gorchakov Approved by: re (rwatson, kib) MFC after: 3 days --- usr.sbin/sysinstall/install.c | 2 +- usr.sbin/sysinstall/sysinstall.8 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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/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 From 0990c0a12cbe0c7d6388270ab33717b348100217 Mon Sep 17 00:00:00 2001 From: Rick Macklem Date: Wed, 12 Aug 2009 16:27:51 +0000 Subject: [PATCH 023/453] Add a check for a NULL mbuf ptr at the beginning of xdrmbuf_inline() so that it returns failure instead of crashing when "m->m_len" is executed and m == NULL. The mbuf ptr can be NULL when a call to xdrmbuf_getbytes() gets the bytes it needs, but they are at the end of a short RPC reply. When this happens, xdrmbuf_getbytes() returns success, but advances the mbuf ptr (xdrs->x_private) to m_next, which is NULL. If this is followed by a call to xdrmbuf_getlong(), it calls xdrmbuf_inline(), which would cause a crash by accessing "m->m_len". Tested by: pho, serenity at exscape dot org Approved by: re (rwatson), kib (mentor) --- sys/xdr/xdr_mbuf.c | 2 ++ 1 file changed, 2 insertions(+) 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 { From a36599cce745ccc5dbf04d6f5b3fd1b2141a4a7f Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Wed, 12 Aug 2009 17:28:53 +0000 Subject: [PATCH 024/453] Always embed pointer to BPF JIT function in BPF descriptor to avoid inconsistency when opt_bpf.h is not included. Reviewed by: rwatson Approved by: re (rwatson) --- sys/net/bpf.c | 18 ++++++++++++------ sys/net/bpf_buffer.c | 1 - sys/net/bpf_zerocopy.c | 1 - sys/net/bpfdesc.h | 4 +--- 4 files changed, 13 insertions(+), 11 deletions(-) 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 */ From 09b03548391f8691538e3a6a0af8e412b6a692e9 Mon Sep 17 00:00:00 2001 From: Qing Li Date: Wed, 12 Aug 2009 19:15:26 +0000 Subject: [PATCH 025/453] A piece of code was added to install a host route when an IPv6 interface address is configured with a /128 prefix. This is no longer necessary due to r192011. In fact that code conflicts with r192011. This patch removes the host route installation when detecting the /128 prefix, and instead let the code added by r192011 to install the loopback route for that IPv6 interface address. Reviewed by: bz Approved by: re --- sys/netinet6/in6.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index c099da70e89..c4333ed60a6 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1750,21 +1750,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); From 692eebe092e81927e190dd5eeb4f65d2324ea3fa Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Wed, 12 Aug 2009 21:03:16 +0000 Subject: [PATCH 026/453] First (early) draft of net80211 documentation. Note this is focused on driver writers (as opposed to folks adding to net80211). Reviewed by: wkoszek Approved by: re (rwatson) --- share/man/man9/Makefile | 106 ++-- share/man/man9/ieee80211.9 | 731 +++++++++++++++++++-------- share/man/man9/ieee80211_amrr.9 | 194 +++++++ share/man/man9/ieee80211_beacon.9 | 115 +++++ share/man/man9/ieee80211_bmiss.9 | 91 ++++ share/man/man9/ieee80211_crypto.9 | 277 +++++++--- share/man/man9/ieee80211_ddb.9 | 72 +++ share/man/man9/ieee80211_input.9 | 135 ++--- share/man/man9/ieee80211_ioctl.9 | 92 ---- share/man/man9/ieee80211_node.9 | 452 ++++++++--------- share/man/man9/ieee80211_output.9 | 255 ++++++---- share/man/man9/ieee80211_proto.9 | 228 +++++++-- share/man/man9/ieee80211_radiotap.9 | 356 +++++++------ share/man/man9/ieee80211_regdomain.9 | 143 ++++++ share/man/man9/ieee80211_scan.9 | 350 +++++++++++++ share/man/man9/ieee80211_vap.9 | 154 ++++++ 16 files changed, 2746 insertions(+), 1005 deletions(-) create mode 100644 share/man/man9/ieee80211_amrr.9 create mode 100644 share/man/man9/ieee80211_beacon.9 create mode 100644 share/man/man9/ieee80211_bmiss.9 create mode 100644 share/man/man9/ieee80211_ddb.9 delete mode 100644 share/man/man9/ieee80211_ioctl.9 create mode 100644 share/man/man9/ieee80211_regdomain.9 create mode 100644 share/man/man9/ieee80211_scan.9 create mode 100644 share/man/man9/ieee80211_vap.9 diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 844e117eddc..3148d5eed1c 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 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_amrr.9 b/share/man/man9/ieee80211_amrr.9 new file mode 100644 index 00000000000..acd70da3dec --- /dev/null +++ b/share/man/man9/ieee80211_amrr.9 @@ -0,0 +1,194 @@ +.\" +.\" Copyright (c) 2009 Sam Leffler, Errno Consulting +.\" 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$ +.\" +.Dd August 4, 2009 +.Dt IEEE8021_AMRR 9 +.Os +.Sh NAME +.Nm ieee80211_amrr +.Nd 802.11 network driver transmit rate control support +.Sh SYNOPSIS +.In net80211/ieee80211_amrr.h +.Ft void +.Fo ieee80211_amrr_init +.Fa "struct ieee80211_amrr *" +.Fa "struct ieee80211vap *" +.Fa "int amin" +.Fa "int amax" +.Fa "int interval" +.Fc +.\" +.Ft void +.Fn ieee80211_amrr_cleanup "struct ieee80211_amrr *" +.\" +.Ft void +.Fn ieee80211_amrr_setinterval "struct ieee80211_amrr *" "int interval" +.\" +.Ft void +.Fo ieee80211_amrr_node_init +.Fa "struct ieee80211_amrr *" +.Fa "struct ieee80211_amrr_node *" +.Fa "struct ieee80211_node *" +.Fc +.\" +.Ft int +.Fo ieee80211_amrr_choose +.Fa "struct ieee80211_node *" +.Fa "struct ieee80211_amrr_node *" +.Fc +.\" +.Ft void +.Fo ieee80211_amrr_tx_complete +.Fa "struct ieee80211_amrr_node *" +.Fa "int ok" +.Fa "int retries" +.Fc +.\" +.Ft void +.Fo ieee80211_amrr_tx_update +.Fa "struct ieee80211_amrr_node *" +.Fa "int txnct" +.Fa "int success" +.Fa "int retrycnt" +.Fc +.Sh DESCRIPTION +.Nm +is an implementation of the AMRR transmit rate control algorithm +for drivers that use the +.Nm net80211 +software layer. +A rate control algorithm is responsible for choosing the transmit +rate for each frame. +To maximize throughput algorithms try to use the highest rate that +is appropriate for the operating conditions. +The rate will vary as conditions change; the distance between two stations +may change, transient noise may be present that affects signal quality, +etc. +.Nm +uses very simple information from a driver to do it's job: +whether a frame was successfully delivered and how many transmit +attempts were made. +While this enables its use with virtually any wireless device it +limits it's effectiveness--do not expect it to function well in +difficult environments and/or respond quickly to changing conditions. +.Pp +.Nm +requires per-vap state and per-node state for each station it is to +select rates for. +The API's are designed for drivers to pre-allocate state in the +driver-private extension areas of each vap and node. +For example the +.Xr ral 4 +driver defines a vap as: +.Bd -literal -offset indent +struct rt2560_vap { + struct ieee80211vap ral_vap; + struct ieee80211_beacon_offsets ral_bo; + struct ieee80211_amrr amrr; + + int (*ral_newstate)(struct ieee80211vap *, + enum ieee80211_state, int); +}; +.Ed +.Pp +The +.Vt amrr +structure member holds the per-vap state for +.Nm +and +.Xr ral 4 +initializes it in the vap create method with: +.Bd -literal -offset indent +ieee80211_amrr_init(&rvp->amrr, vap, + IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, + IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, + 500 /* ms */); +.Ed +.Pp +The node is defined as: +.Bd -literal -offset indent +struct rt2560_node { + struct ieee80211_node ni; + struct ieee80211_amrr_node amrr; +}; +.Ed +.Pp +with initialization done in the driver's +.Vt iv_newassoc +method: +.Bd -literal -offset indent +static void +rt2560_newassoc(struct ieee80211_node *ni, int isnew) +{ + struct ieee80211vap *vap = ni->ni_vap; + + ieee80211_amrr_node_init(&RT2560_VAP(vap)->amrr, + &RT2560_NODE(ni)->amrr, ni); +} +.Ed +.Pp +Once +.Nm +state is setup, transmit rates are requested by calling +.Fn ieee80211_amrr_choose +in the transmit path; e.g.: +.Bd -literal -offset indent +tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; +if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { + rate = tp->mcastrate; +} else if (m0->m_flags & M_EAPOL) { + rate = tp->mgmtrate; +} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { + rate = tp->ucastrate; +} else { + (void) ieee80211_amrr_choose(ni, &RT2560_NODE(ni)->amrr); + rate = ni->ni_txrate; +} +.Ed +.Pp +Note a rate is chosen only for unicast data frames when a fixed +transmit rate is not configured; the other cases are handled with +the +.Nm net80211 +transmit parameters. +Note also that +.Fn ieee80211_amrr_choose +writes the chosen rate in +.Vt ni_txrate ; +this eliminates copying the value as it is exported to user applications so +they can display the current transmit rate in status. +.Pp +The remaining work a driver must do is feed status back to +.Nm +when a frame transmit completes using +.Fn ieee80211_amrr_tx_complete . +Drivers that poll a device to retrieve statistics can use +.Fn ieee80211_amrr_tx_update +(instead or in addition). +.Sh SEE ALSO +.Xr ieee80211 9 , +.Xr ieee80211_output 9 , diff --git a/share/man/man9/ieee80211_beacon.9 b/share/man/man9/ieee80211_beacon.9 new file mode 100644 index 00000000000..444c433491a --- /dev/null +++ b/share/man/man9/ieee80211_beacon.9 @@ -0,0 +1,115 @@ +.\" +.\" Copyright (c) 2009 Sam Leffler, Errno Consulting +.\" 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$ +.\" +.Dd August 4, 2009 +.Dt IEEE80211_BEACON 9 +.Os +.Sh NAME +.Nm ieee80211_beacon +.Nd 802.11 beacon support +.Sh SYNOPSIS +.In net80211/ieee80211_var.h +.Pp +.Ft "struct mbuf *" +.Fo ieee80211_beacon_alloc +.Fa "struct ieee80211_node *" +.Fa "struct ieee80211_beacon_offsets *" +.Fc +.\" +.Ft int +.Fo ieee80211_beacon_update +.Fa "struct ieee80211_node *" +.Fa "struct ieee80211_beacon_offsets *" +.Fa "struct mbuf *" +.Fa "int mcast" +.Fc +.\" +.Ft void +.Fn ieee80211_beacon_notify "struct ieee80211vap *" "int what" +.Sh DESCRIPTION +The +.Nm net80211 +software layer provides a support framework for drivers that includes +a template-based mechanism for dynamic update of beacon frames transmit +in hostap, adhoc, and mesh operating modes. +Drivers should use +.Fn ieee80211_beacon_alloc +to create an initial beacon frame. +The +.Vt ieee80211_beacon_offsets +structure holds information about the beacon contents that is used +to optimize updates done with +.Fn ieee80211_beacon_update . +.Pp +Update calls should only be done when something changes that +affects the contents of the beacon frame. +When this happens the +.Dv iv_update_beacon +method is invoked and a driver-supplied routine must do the right thing. +For devices that involve the host to transmit each +beacon frame this work may be as simple as marking a bit in the +.Vt ieee80211_beacon_offsets +structure: +.Bd -literal +static void +ath_beacon_update(struct ieee80211vap *vap, int item) +{ + struct ieee80211_beacon_offsets *bo = &ATH_VAP(vap)->av_boff; + setbit(bo->bo_flags, item); +} +.Ed +.Pp +with the +.Fn ieee80211_beacon_update +call done before the next beacon is to be sent. +.Pp +Devices that off-load beacon generation may instead choose to use +this callback to push updates immediately to the device. +Exactly how that is accomplished is unspecified. +One possibility is to update the beacon frame contents and extract +the appropriate information element, but other scenarios are possible. +.Sh MULTI-VAP BEACON SCHEDULING +Drivers that support multiple vaps that can each beacon need to consider +how to schedule beacon frames. +There are two possibilities at the moment: +.Em burst +all beacons at TBTT or +.Em stagger beacons +over the beacon interval. +Bursting beacon frames may result in aperiodic delivery that can affect +power save operation of associated stations. +Applying some jitter (e.g. by randomly ordering burst frames) may be +sufficient to combat this and typically this is not an issue unless +stations are using aggressive power save techniques +such as U-APSD (sometimes employed by VoIP phones). +Staggering frames requires more interrupts and device support that +may not be available. +Staggering beacon frames is usually superior to bursting frames, up to +about eight vaps, at which point the overhead becomes significant and +the channel becomes noticeably busy anyway. +.Sh SEE ALSO +.Xr ieee80211 9 . diff --git a/share/man/man9/ieee80211_bmiss.9 b/share/man/man9/ieee80211_bmiss.9 new file mode 100644 index 00000000000..e227ac07744 --- /dev/null +++ b/share/man/man9/ieee80211_bmiss.9 @@ -0,0 +1,91 @@ +.\" +.\" Copyright (c) 2009 Sam Leffler, Errno Consulting +.\" 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$ +.\" +.Dd August 4, 2009 +.Dt IEEE80211_BMISS 9 +.Os +.Sh NAME +.Nm ieee80211_bmiss +.Nd 802.11 beacon miss support +.Sh SYNOPSIS +.In net80211/ieee80211_var.h +.Pp +.Ft void +.Fn ieee80211_beacon_miss "struct ieee80211com *" +.Sh DESCRIPTION +The +.Nm net80211 +software layer provides a support framework for drivers that includes +handling beacon miss events in station mode. +Drivers can dispatch beacon miss events that are recognized in hardware or +.Nm net80211 +can detect beacon miss if the driver dispatches received beacon frames +through the normal receive path. +Software beacon miss support is especially useful when multiple vaps +are operating and any hardware beacon miss support is not available +(e.g. operating as an access point together with one or more station +mode vaps). +.Pp +Drivers should dispatch beacon miss events recognized in the driver with +.Fn ieee80211_beacon_miss . +This causes some number of ProbeRequest frames to be sent to the +access point to check if the association is still alive. +If no response is received and roaming mode is set to +.Dv IEEE80211_ROAMING_AUTO +then +.Nm net80211 +will try to re-associate and if that fails +trigger a scan to look for the access point or another suitable AP. +When the +.Nm net80211 +state machine is being operated manually, e.g. by +.Xr wpa_supplicant 8 , +then applications are notified of the state change and are responsible +for handling the work of scanning for a new access point. +The number of beacon miss events (without a ProbeResponse) is user +settable with the +.Dv IEEE80211_IOC_BMISSTHRESHOLD +request. +.Pp +Software beacon miss detection is enabled per-vap by setting the +.Dv IEEE80211_FEXT_SWBMISS +flag. +Typically this is done when a vap is setup +when the +.Dv IEEE80211_CLONE_NOBEACONS +option is supplied to the clone operation. +But drivers may also force this when they know they need help detecting +beacon miss. +When beacon miss is detected in software the event is dispatched without +driver involvement. +Note that software beacon miss handling is not limited to station mode; +it can be used in any operating mode where beacons from a peer station +are received. +.Sh SEE ALSO +.Xr ieee80211 9 , +.Xr ieee80211_vap 9 , +.Xr wpa_supplicant 8 , 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_ddb.9 b/share/man/man9/ieee80211_ddb.9 new file mode 100644 index 00000000000..19232a78d34 --- /dev/null +++ b/share/man/man9/ieee80211_ddb.9 @@ -0,0 +1,72 @@ +.\" +.\" Copyright (c) 2009 Sam Leffler, Errno Consulting +.\" 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$ +.\" +.Dd August 4, 2009 +.Dt IEEE80211_DDB 9 +.Os +.Sh NAME +.Nm ieee80211_ddb +.Nd 802.11 ddb support +.Sh SYNOPSIS +.Bd -ragged +.Cd options DDB +.Ed +.Pp +.Bd -ragged +.Cd show vap [addr] +.Cd show all vaps +.Cd show com [addr] +.Cd show sta [addr] +.Cd show statab [addr] +.Cd show mesh [addr] +.Ed +.Sh DESCRIPTION +The +.Nm net80211 +layer includes +.Xr ddb 4 +support for displaying important data structures. +This is especially important because wireless applications are often +built for embedded environments where cross-machine or post-mortem +debugging facilities like +.Xr kgdb 1 +infeasible. +.Pp +The most commonly used command is +.Bd -literal -offset indent +show all vaps/a +.Ed +.Pp +which dumps the contents of all +.Vt ieee80211vap , +.Vt ieee80211com , +and +.Vt ieee80211_node +data structures in the system. +.Sh SEE ALSO +.Xr ddb 4 , +.Xr ieee80211 9 . 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/ieee80211_regdomain.9 b/share/man/man9/ieee80211_regdomain.9 new file mode 100644 index 00000000000..0611ec37cbb --- /dev/null +++ b/share/man/man9/ieee80211_regdomain.9 @@ -0,0 +1,143 @@ +.\" +.\" Copyright (c) 2009 Sam Leffler, Errno Consulting +.\" 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$ +.\" +.Dd August 4, 2009 +.Dt IEEE80211_REGDOMAIN 9 +.Os +.Sh NAME +.Nm ieee80211_regdomain +.Nd 802.11 regulatory support +.Sh SYNOPSIS +.In net80211/ieee80211_var.h +.In net80211/ieee80211_regdomain.h +.Pp +.Ft int +.Fo ieee80211_init_channels +.Fa "struct ieee80211com *" +.Fa "const struct ieee80211_regdomain *" +.Fa "const uint8_t bands[]" +.Fc +.\" +.Ft void +.Fo ieee80211_sort_channels +.Fa "struct ieee80211_channel *" +.Fa "int nchans" +.Fc +.\" +.Ft "struct ieee80211_appie *" +.Fn ieee80211_alloc_countryie "struct ieee80211com *" +.Sh DESCRIPTION +The +.Nm net80211 +software layer provides a support framework for drivers that includes +comprehensive regulatory support. +.Nm net80211 +provides mechanisms that enforce +.Em "regulatory policy" +by privileged user applications. +.Pp +Drivers define a device's capabilities and can +intercept and control regulatory changes requested through +.Nm net80211 . +The initial regulatory state, including the channel list, must be +filled in by the driver before calling +.Fn ieee80211_ifattach . +The channel list should reflect the set of channels the device is +.Em calibrated +for use on. +This list may also be requested later through the +.Vt ic_getradiocaps +method in the +.Vt ieee80211com +structure. +The +.Fn ieee80211_init_channels +function is provided as a rudimentary fallback for drivers that do not +(or cannot) fill in a proper channel list. +Default regulatory state is supplied such as the regulatory SKU, +ISO country code, location (e.g. indoor, outdoor), and a set of +frequency bands the device is capable of operating on. +.Nm net80211 +populates the channel table in +.Vt ic_channels +with a default set of channels and capabilities. +Note this mechanism should be used with care as any mismatch between +the channel list created and the device's capabilities can result +in runtime errors (e.g. a request to operate on a channel the device +does not support). +The SKU and country information are used for generating 802.11h protocol +elements and related operation such as for 802.11d; mis-setup by a +driver is not fatal, only potentially confusing. +.Pp +Devices that do not have a fixed/default regulatory state can set +the regulatory SKU to +.Dv SKU_DEBUG +and country code to +.Dv CTRY_DEFAULT +and leave proper setup to user applications. +If default settings are known they can be installed and/or an event +can be dispatched to user space using +.Fn ieee80211_notify_country +so that +.Xr devd 8 +will do the appropriate setup work at system boot (or device insertion). +.Pp +The channel table is sorted to optimize lookups using the +.Fn ieee80211_sort_channels +routine. +This should be done whenever the channel table contents are modified. +.Pp +The +.Fn ieee80211_alloc_countrie +function allocates an information element as specified by 802.11h. +Because this is expensive to generate it is cached in +.Vt ic_countryie +and generated only when regulatory state changes. +Drivers that call +.Fn ieee80211_alloc_countryie +directly should not help with this caching; doing so may confuse the +.Nm net80211 +layer. +.Sh DRIVER REGULATORY CONTROL +Drivers can control regulatory change requests by overriding the +.Vt ic_setregdomain +method that checks change requests. +While drivers can reject any request that does not meet its requirements +it is recommended that one be lenient in what is accepted and, whenever +possible, instead of rejecting a request, alter it to be correct. +For example, if the transmit power cap for a channel is too high the +driver can either reject the request or (better) reduce the cap to be +compliant. +Requests that include unacceptable channels should cause the request +to be rejected as otherwise a mismatch may be created between application +state and the state managed by +.Nm net80211 . +The exact rules by which to operate are still being codified. +.Sh SEE ALSO +.Xr regdomain 5 , +.Xr ifconfig 8 , +.Xr ieee80211 9 . diff --git a/share/man/man9/ieee80211_scan.9 b/share/man/man9/ieee80211_scan.9 new file mode 100644 index 00000000000..8e1897cf1a6 --- /dev/null +++ b/share/man/man9/ieee80211_scan.9 @@ -0,0 +1,350 @@ +.\" +.\" Copyright (c) 2009 Sam Leffler, Errno Consulting +.\" 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$ +.\" +.Dd August 4, 2009 +.Dt IEEE80211_SCAN 9 +.Os +.Sh NAME +.Nm ieee80211_scan +.Nd 802.11 scanning support +.Sh SYNOPSIS +.In net80211/ieee80211_var.h +.Pp +.Ft int +.Fo ieee80211_start_scan +.Fa "struct ieee80211vap *" +.Fa "int flags" +.Fa "u_int duration" +.Fa "u_int mindwell" +.Fa "u_int maxdwell" +.Fa "u_int nssid" +.Fa "const struct ieee80211_scan_ssid ssids[]" +.Fc +.\" +.Ft int +.Fo ieee80211_check_scan +.Fa "struct ieee80211vap *" +.Fa "int flags" +.Fa "u_int duration" +.Fa "u_int mindwell" +.Fa "u_int maxdwell" +.Fa "u_int nssid" +.Fa "const struct ieee80211_scan_ssid ssids[]" +.Fc +.\" +.Ft int +.Fn ieee80211_check_scan_current "struct ieee80211vap *" +.\" +.Ft int +.Fn ieee80211_bg_scan "struct ieee80211vap *" "int" +.\" +.Ft int +.Fn ieee80211_cancel_scan "struct ieee80211vap *" +.\" +.Ft int +.Fn ieee80211_cancel_scan_any "struct ieee80211vap *" +.\" +.Ft int +.Fn ieee80211_scan_next "struct ieee80211vap *" +.\" +.Ft int +.Fn ieee80211_scan_done "struct ieee80211vap *" +.\" +.Ft int +.Fn ieee80211_probe_curchan "struct ieee80211vap *" "int" +.\" +.Ft void +.Fo ieee80211_add_scan +.Fa "struct ieee80211vap *" +.Fa "const struct ieee80211_scanparams *" +.Fa "const struct ieee80211_frame *" +.Fa "int subtype" +.Fa "int rssi" +.Fa "int noise" +.Fc +.\" +.Ft void +.Fn ieee80211_scan_timeout "struct ieee80211com *" +.\" +.Ft void +.Fo ieee80211_scan_assoc_fail +.Fa "struct ieee80211vap *" +.Fa "const uint8_t mac[IEEE80211_ADDR_LEN]" +.Fa "int reason" +.Fc +.\" +.Ft void +.Fn ieee80211_scan_flush "struct ieee80211vap *" +.\" +.Ft void +.Fo ieee80211_scan_iterate +.Fa "struct ieee80211vap *" +.Fa "ieee80211_scan_iter_func" +.Fa "void *" +.Fc +.\" +.Ft void +.Fn ieee80211_scan_dump_channels "const struct ieee80211_scan_state *" +.\" +.Ft void +.Fo ieee80211_scanner_register +.Fa "enum ieee80211_opmode" +.Fa "const struct ieee80211_scanner *" +.Fc +.\" +.Ft void +.Fo ieee80211_scanner_unregister +.Fa "enum ieee80211_opmode" +.Fa "const struct ieee80211_scanner *" +.Fc +.\" +.Ft void +.Fn ieee80211_scanner_unregister_all "const struct ieee80211_scanner *" +.\" +.Ft const struct ieee80211_scanner * +.Fn ieee80211_scanner_get "enum ieee80211_opmode" +.Sh DESCRIPTION +The +.Nm net80211 +software layer provides an extensible framework for scanning. +Scanning is the procedure by which a station locates a BSS to join +(in infrastructure and IBSS mode), or a channel to use (when operating +as an AP or an IBSS master). +Scans are either +.Dq active +or +.Dq passive . +An active scan causes one or more ProbeRequest frames to be sent on +visiting each channel. +A passive request causes each channel in the scan set to be visited but +no frames to be transmitted; the station only listens for traffic. +Note that active scanning may still need to listen for traffic before +sending ProbeRequest frames depending on regulatory constraints. +.Pp +A scan operation involves constructing a set of channels to inspect +(the scan set), +visiting each channel and collecting information +(e.g. what BSS are present), +and then analyzing the results to make decisions such as which BSS to join. +This process needs to be as fast as possible so +.Nm net80211 +does things like intelligently construct scan sets and dwell on a channel +only as long as necessary. +Scan results are cached and the scan cache is used to avoid scanning when +possible and to enable roaming between access points when operating +in infrastructure mode. +.Pp +Scanning is handled by pluggable modules that implement +.Em policy +per-operating mode. +The core scanning support provides an infrastructure to support these +modules and exports a common API to the rest of the +.Nm net80211 +layer. +Policy modules decide what channels to visit, what state to record to +make decisions, and selects the final station/channel to return as the +result of a scan. +.Pp +Scanning is done synchronously when initially bringing a vap to +an operational state and optionally in the background to maintain +the scan cache for doing roaming and rogue AP monitoring. +Scanning is not tied to the +.Nm net80211 +state machine that governs vaps except for linkage to the +.Dv IEEE80211_S_SCAN +state. +One one vap at a time may be scanning; this scheduling policy +is handle in +.Fn ieee80211_new_state +and is transparent to scanning code. +.Pp +Scanning is controlled by a set of parameters that (potentially) +constrains the channel set and any desired SSID's and BSSID's. +.Nm net80211 +comes with a standard scanner module that works with all available +operating modes and supports +.Dq background scanning +and +.Dq roaming +operation. +.Sh SCANNER MODULES +Scanning modules use a registration mechanism to hook into the +.Nm net80211 +layer. +Use +.Fn ieee80211_scanner_register +to register a scan module for a particular operating mode and +.Fn ieee80211_scanner_unregister +or +.Fn ieee80211_scanner_unregister_all +to clear entries (typically on module unload). +Only one scanner module can be registered at any time for an operating mode. +.Sh DRIVER SUPPORT +Scanning operations are usually managed by the +.Nm net80211 +layer. +Drivers must provide +.Vt ic_scan_start +and +.Vt ic_scan_stop +methods that are called at the start of a scan and when the +work is done; these should handle work such as enabling receive +of Beacon and ProbeResponse frames and disable any BSSID matching. +The +.Vt ic_set_channel +method is used to change channels while scanning. +.Nm net80211 +will generate ProbeRequest frames and transmit them using the +.Nm ic_raw_xmit +method. +Frames received while scanning are dispatched to +.Nm net80211 +using the normal receive path. +Devices that off-load scan work to firmware most easily mesh with +.Nm net80211 +by operating on a channel-at-a-time basis as this defers control to +.Nm net80211's +scan machine scheduler. +But multi-channel scanning +is supported if the driver manually dispatches results using +.Fn ieee80211_add_scan +routine to enter results into the scan cache. +.Sh SCAN REQUESTS +Scan requests occur by way of the +.Dv IEEE80211_SCAN_REQUEST +ioctl or through a change in a vap's state machine that requires +scanning. +In both cases the scan cache can be checked first and, if it is deemed +suitably +.Dq warm +then it's contents are used without leaving the current channel. +To start a scan without checking the cache +.Fn ieee80211_start_scan +can be called; otherwise +.Fn ieee80211_check_scan +can be used to first check the scan cache, kicking off a scan if +the cache contents are out of date. +There is also +.Fn ieee80211_check_scan_current +which is a shorthand for using previously set scan parameters for +checking the scan cache and then scanning. +.Pp +Background scanning is done using +.Fn ieee80211_bg_scan +in a co-routine fashion. +The first call to this routine will start a background scan that +runs for a limited period of time before returning to the BSS channel. +Subsequent calls advance through the scan set until all channels are +visited. +Typically these later calls are timed to allow receipt of +frames buffered by an access point for the station. +.Pp +A scan operation can be canceled using +.Fn ieee80211_cancel_scan +if it was initiated by the specified vap, or +.Fn ieee80211_cancel_scan_any +to force termination regardless which vap started it. +These requests are mostly used by +.Nm net80211 +in the transmit path to cancel background scans when frames are to be sent. +Drivers should not need to use these calls (or most of the calls described +on this page). +.Pp +The +.Fn ieee80211_scan_next +and +.Fn ieee80211_scan_done +routines do explicit iteration through the scan set and should +not normally be used by drivers. +.Fn ieee80211_probe_curchan +handles the work of transmitting ProbeRequest frames when visiting +a channel during an active scan. +When the channel attributes are marked with +.Dv IEEE80211_CHAN_PASSIVE +this function will arrange that before any frame is transmitted 802.11 +traffic is first received (in order to comply with regulatory constraints). +.Pp +Min/max dwell time parameters are used to constrain time spent visiting +a channel. +The maximum dwell time constrains the time spent listening for traffic. +The minimum dwell time is used to reduce this time--when it is reached +and one or more frames have been received then an immediate channel +change will be done. +Drivers can override this behaviour through the +.Vt iv_scan_mindwell +method. +.Sh SCAN CACHE MANAGEMENT +The scan cache contents are managed by the scan policy module and +are opaque outside this module. +The +.Nm net80211 +scan framework defines API's for interacting. +The validity of the scan cache contents are controlled by +.Vt iv_scanvalid +which is exported to user space through the +.Dv IEEE80211_SCAN_VALID +request. +.Pp +The cache contents can be explicitly flushed with +.Fn ieee80211_scan_flush +or by setting the +.Dv IEEE80211_SCAN_FLUSH +flag when starting a scan operation. +.Pp +Scan cache entries are created with the +.Fn ieee80211_add_scan +routine; usually on receipt of Beacon or ProbeResponse frames. +Existing entries are typically updated based on the latest information +though some information such as RSSI and noise floor readings may be +combined to present an average. +.Pp +The cache contents is aged through +.Fn ieee80211_scan_timeout +calls. +Typically these happen together with other station table activity; every +.Dv IEEE80211_INACT_WAIT +seconds (default 15). +.Pp +Individual cache entries are marked usable with +.Fn ieee80211_scan_assoc_success +and faulty with +.Fn ieee80211_scan_assoc_fail +with the latter taking an argument to identify if there was no response +to Authentication/Association requests or if a negative response was +received (which might hasten cache eviction or blacklist the entry). +.Pp +The cache contents can be viewed using the +.Fn ieee80211_scan_iterate +call. +Cache entries are exported in a public format that is exported to user +applications through the +.Dv IEEE80211_SCAN_RESULTS +request. +.Sh SEE ALSO +.Xr ioctl 2 , +.Xr ieee80211 9 . +.Xr ieee80211_proto 9 . diff --git a/share/man/man9/ieee80211_vap.9 b/share/man/man9/ieee80211_vap.9 new file mode 100644 index 00000000000..fc06fff3b9f --- /dev/null +++ b/share/man/man9/ieee80211_vap.9 @@ -0,0 +1,154 @@ +.\" +.\" Copyright (c) 2009 Sam Leffler, Errno Consulting +.\" 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$ +.\" +.Dd August 4, 2009 +.Dt IEEE8021_VAP 9 +.Os +.Sh NAME +.Nm net80211_vap +.Nd 802.11 network layer virtual radio support +.Sh SYNOPSIS +.In net80211/ieee80211_var.h +.Ft int +.Fo ieee80211_vap_setup +.Fa "struct ieee80211com *" +.Fa "struct ieee80211vap *" +.Fa "const char name[IFNAMSIZ]" +.Fa "int unit" +.Fa "int opmode" +.Fa "int flags" +.Fa "const uint8_t bssid[IEEE80211_ADDR_LEN]" +.Fa "const uint8_t macaddr[IEEE80211_ADDR_LEN]" +.Fc +.\" +.Ft int +.Fo ieee80211_vap_attach +.Fa "struct ieee80211vap *" +.Fa "ifm_change_cb_t media_change" +.Fa "ifm_stat_cb_t media_stat" +.Fc +.\" +.Ft void +.Fn ieee80211_vap_detach "struct ieee80211vap *" +.Sh DESCRIPTION +The +.Nm net80211 +software layer provides a support framework for drivers that includes +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. +.Pp +The virtual radio interface defined by the +.Nm net80211 +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. +.Pp +The virtual radio architecture splits state between a single per-device +.Vt ieee80211com +structure and one or more +.Vt ieee80211vap +structures. +Vaps are created with the +.Dv SIOCIFCREATE2 +request. +This results in a call into the driver's +.Vt ic_vap_create +method where the driver can decide if the request should be accepted. +.Pp +The vap creation process is done in three steps. +First the driver allocates the data structure with +.Xr malloc 9 . +This data structure must have an +.Vt ieee80211vap +structure at the front but is usually extended with driver-private state. +Next the vap is setup with a call to +.Fn ieee80211_vap_setup . +This request initializes +.Nm net80211 +state but does not activate the interface. +The driver can then override methods setup by +.Nm net80211 +and setup driver resources before finally calling +.Fn ieee80211_vap_attach +to complete the process. +Both these calls must be done without holding any driver locks as +work may require the process block/sleep. +.Pp +A vap is deleted when an +.Dv SIOCIFDESTROY +ioctl request is made or when the device detaches (causing all +associated vaps to automatically be deleted). +Delete requests cause the +.Vt ic_vap_delete +method to be called. +Drivers must quiesce the device before calling +.Fn ieee80211_vap_detach +to deactivate the vap and isolate it from activities such as requests +from user applications. +The driver can then reclaim resources held by the vap and re-enable +device operation. +The exact procedure for quiesceing a device is unspecified but typically +it involves blocking interrupts and stopping transmit and receive +processing. +.Sh MULTI-VAP OPERATION +Drivers are responsible for deciding if multiple vaps can be created +and how to manage them. +Whether or not multiple concurrent vaps can be supported depends on a +device's capabilities. +For example, multiple hostap vaps can usually be supported but many +devices do not support assigning each vap a unique BSSID. +If a device supports hostap operation it can usually support concurrent +station mode vaps but possibly with limitations such as losing support +for hardware beacon miss support. +Devices that are capable of hostap operation and can send and receive +4-address frames should be able to support WDS vaps together with an +ap vap. +But in contrast some devices cannot support WDS vaps without at least one +ap vap (this however can be finessed by forcing the ap vap to not transmit +beacon frames). +All devices should support the creation of any number of monitor mode vaps +concurrent with other vaps but it is the responsibility of the driver to +allow this. +.Pp +An important consequence of supporting multiple concurrent vaps is that +a driver's +.Vt iv_newstate +method must be written to handle being called for each vap. +Where necessary, drivers must track private state for all vaps +and not just the one whose state is being changed (e.g. for +handling beacon timers the driver may need to know if all vaps +that beacon are stopped before stopping the hardware timers). +.Sh SEE ALSO +.Xr ieee80211 9 , +.Xr ifnet 9 , +.Xr malloc 9 . From ab501dd65ddd51857f3f0db42e1b4854eaf164e2 Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Wed, 12 Aug 2009 21:19:19 +0000 Subject: [PATCH 027/453] Drain link state event changes posted during vap destroy. This is a band-aid for the general problem that if_link_state_change can be called between if_detach and if_free leaving a task queued that has been free'd. Spotted by: thompsa Reviewed by: rwatson Approved by: re (rwatson) --- sys/net80211/ieee80211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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); From 5cc3786c64c96a7322439fd9ae357dcb74efaafc Mon Sep 17 00:00:00 2001 From: Matt Jacob Date: Thu, 13 Aug 2009 01:17:26 +0000 Subject: [PATCH 028/453] Have at least *some* default WWN to fall back on, otherwise Sun branded FC cards won't configure. Reviewed by: Ken, Scott Approved by: re --- sys/dev/isp/isp_freebsd.c | 4 ++++ 1 file changed, 4 insertions(+) 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; } From 9517e866259191fcd39434a97ad849a9b59b9b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Thu, 13 Aug 2009 06:07:38 +0000 Subject: [PATCH 029/453] Update and remove CVS-specific items Approved by: re (kib) --- contrib/bzip2/FREEBSD-vendor | 2 -- contrib/netcat/FREEBSD-vendor | 2 -- contrib/openpam/FREEBSD-vendor | 2 -- crypto/openssh/FREEBSD-vendor | 4 +--- 4 files changed, 1 insertion(+), 9 deletions(-) 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/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/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 From e7fba5c772d272c314bd52a95d9088a8e9a07914 Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Thu, 13 Aug 2009 09:11:47 +0000 Subject: [PATCH 030/453] Start respecting WITHOUT_INET6. Make regression/priv compile again after the multi-IP jail changes. Note that we are still using the legacy jail(2) rather than the jail_set(2)/jail(3) syscall. Add an IPv4, and an IPv6 loopback address in case we compile with INET6 enabled. Make the priv_vfs_extattr_system compile on amd64 as well using the proper length modifier to printf(3) for ssize_t. Reviewed by: rwatson Approved by: re (kib) --- tools/regression/priv/Makefile | 6 ++++++ tools/regression/priv/main.c | 19 ++++++++++++++++-- tools/regression/priv/priv_netinet_ipsec.c | 20 +++++++++++++++---- .../regression/priv/priv_vfs_extattr_system.c | 2 +- 4 files changed, 40 insertions(+), 7 deletions(-) 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); From 20b0cdb749a0a8e31a98f6624168d88de77b638f Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Thu, 13 Aug 2009 09:29:52 +0000 Subject: [PATCH 031/453] Put multiple instructions into a block when iterating; unbreaks NET_RT_DUMP, which otherwise only returned information of AF_MAX. This was broken in r193232 (save your time - my bug, my fix). PR: kern/137700 Reported by: Larry Baird (lab gta.com) Tested by: Larry Baird (lab gta.com) Reviewed by: zec, lstewart, qing Approved by: re (kib) --- sys/net/rtsock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 645cf7e54eb..8fb889908f9 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1473,7 +1473,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 +1482,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) RADIX_NODE_HEAD_UNLOCK(rnh); } else if (af != 0) error = EAFNOSUPPORT; + } break; case NET_RT_IFLIST: From eb79e1c76e18c7b72e7f16668319010d7e03ddae Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Thu, 13 Aug 2009 10:26:34 +0000 Subject: [PATCH 032/453] Make it possible to change the vnet sysctl variables on jails with their own virtual network stack. Jails only inheriting a network stack cannot change anything that cannot be changed from within a prison. Reviewed by: rwatson, zec Approved by: re (kib) --- sys/kern/kern_jail.c | 23 +++++++++++++++++++++++ sys/kern/kern_sysctl.c | 12 ++++++++++-- sys/net/vnet.h | 18 +++++++++++------- sys/sys/jail.h | 1 + sys/sys/sysctl.h | 1 + 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 282a4d8c95b..8f185833e8a 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); @@ -3308,6 +3312,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_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/net/vnet.h b/sys/net/vnet.h index d441af19970..91de07a1093 100644 --- a/sys/net/vnet.h +++ b/sys/net/vnet.h @@ -232,21 +232,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/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/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) /* From abd370a36b5dc75614c13475971e5a7b262799e1 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Thu, 13 Aug 2009 12:28:30 +0000 Subject: [PATCH 033/453] Remove CDDL warning. Approved by: re (kib), core --- sys/cddl/compat/opensolaris/kern/opensolaris.c | 4 ---- 1 file changed, 4 deletions(-) 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 From 87a61ebd4cfbe4402b30dd32ebc3adf00fd2594d Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Thu, 13 Aug 2009 14:59:04 +0000 Subject: [PATCH 034/453] Rather than replicating the maths from the kernel, use the value the kernel calculated directly as we already read it with struct vnet. This will make kvm_vnet.c more resilent in case of possible kernel changes. Reviewed by: rwatson Approved by: re (kib) --- lib/libkvm/kvm_vnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } From cbb3cb151c7ad5b841955cd91b8caa74f427f0f9 Mon Sep 17 00:00:00 2001 From: Rafal Jaworowski Date: Thu, 13 Aug 2009 15:56:09 +0000 Subject: [PATCH 035/453] Use correct wbinv operation in pmap_l2cache_wbinv_range(). Submitted by: Michal Hajduk Reviewed by: stas Approved by: re (kib) Obtained from: Semihalf --- sys/arm/arm/pmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From dc6fbf65451a86f6c9bc72434dfe3415afac78da Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Thu, 13 Aug 2009 17:09:45 +0000 Subject: [PATCH 036/453] * Completely Remove the option STOP_NMI from the kernel. This option has proven to have a good effect when entering KDB by using a NMI, but it completely violates all the good rules about interrupts disabled while holding a spinlock in other occasions. This can be the cause of deadlocks on events where a normal IPI_STOP is expected. * Adds an new IPI called IPI_STOP_HARD on all the supported architectures. This IPI is responsible for sending a stop message among CPUs using a privileged channel when disponible. In other cases it just does match a normal IPI_STOP. Right now the IPI_STOP_HARD functionality uses a NMI on ia32 and amd64 architectures, while on the other has a normal IPI_STOP effect. It is responsibility of maintainers to eventually implement an hard stop when necessary and possible. * Use the new IPI facility in order to implement a new userend SMP kernel function called stop_cpus_hard(). That is specular to stop_cpu() but it does use the privileged channel for the stopping facility. * Let KDB use the newly introduced function stop_cpus_hard() and leave stop_cpus() for all the other cases * Disable interrupts on CPU0 when starting the process of APs suspension. * Style cleanup and comments adding This patch should fix the reboot/shutdown deadlocks many users are constantly reporting on mailing lists. Please don't forget to update your config file with the STOP_NMI option removal Reviewed by: jhb Tested by: pho, bz, rink Approved by: re (kib) --- UPDATING | 6 ++ sys/amd64/amd64/local_apic.c | 13 +++- sys/amd64/amd64/mp_machdep.c | 100 ++++++++++--------------------- sys/amd64/amd64/trap.c | 2 - sys/amd64/conf/GENERIC | 1 - sys/amd64/conf/NOTES | 5 -- sys/amd64/conf/XENHVM | 1 - sys/amd64/include/apicvar.h | 6 +- sys/amd64/include/smp.h | 5 +- sys/conf/options.amd64 | 1 - sys/conf/options.i386 | 1 - sys/conf/options.pc98 | 1 - sys/i386/conf/GENERIC | 1 - sys/i386/conf/NOTES | 1 - sys/i386/i386/local_apic.c | 13 +++- sys/i386/i386/mp_machdep.c | 99 ++++++++++-------------------- sys/i386/i386/trap.c | 2 - sys/i386/include/apicvar.h | 7 +-- sys/i386/include/smp.h | 6 +- sys/i386/xen/mp_machdep.c | 2 - sys/ia64/ia64/interrupt.c | 2 + sys/ia64/include/smp.h | 1 + sys/kern/kern_shutdown.c | 10 +++- sys/kern/subr_kdb.c | 7 ++- sys/kern/subr_smp.c | 25 ++++++-- sys/mips/include/smp.h | 1 + sys/mips/mips/mp_machdep.c | 7 ++- sys/pc98/conf/NOTES | 4 -- sys/powerpc/include/smp.h | 1 + sys/powerpc/powerpc/mp_machdep.c | 8 ++- sys/sparc64/include/smp.h | 1 + sys/sun4v/include/smp.h | 1 + sys/sys/smp.h | 1 + 33 files changed, 148 insertions(+), 194 deletions(-) diff --git a/UPDATING b/UPDATING index add10f3a78b..8c31a898e50 100644 --- a/UPDATING +++ b/UPDATING @@ -22,6 +22,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW: to maximize performance. (To disable malloc debugging, run ln -s aj /etc/malloc.conf.) +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. + 20090719: Bump the shared library version numbers for all libraries that do not use symbol versioning as part of the 8.0-RELEASE cycle. diff --git a/sys/amd64/amd64/local_apic.c b/sys/amd64/amd64/local_apic.c index 14559f3aa45..cd3073caf99 100644 --- a/sys/amd64/amd64/local_apic.c +++ b/sys/amd64/amd64/local_apic.c @@ -1238,8 +1238,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/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/trap.c b/sys/amd64/amd64/trap.c index fee3caf6a9d..323e8d1677a 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 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..73fff6c006f 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 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/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.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/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/local_apic.c b/sys/i386/i386/local_apic.c index 6b350e29794..2cc6a450482 100644 --- a/sys/i386/i386/local_apic.c +++ b/sys/i386/i386/local_apic.c @@ -1248,8 +1248,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/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/trap.c b/sys/i386/i386/trap.c index e9671046060..354d791c6f4 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 diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h index a03c083705c..a13766f95f9 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 */ /* 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/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c index 3aa03cef41f..bae07d4f608 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 */ 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/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/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/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_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/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/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/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/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/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 From 763fae7918a4b9114569288039fe29a6e8a92ec6 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Thu, 13 Aug 2009 23:18:45 +0000 Subject: [PATCH 037/453] ntroduce mfiutil, a basic utility for managing LSI SAS-RAID & Dell PERC5/6 controllers. Controller, array, and drive status can be checked, basic attributes can be changed, and arrays and spares can be created and deleted. Controller firmware can also be flashed. This does not replace MegaCLI, found in ports, as that is officially sanctioned and supported by LSI and includes vastly more functionality. However, mfiutil is open source and guaranteed to provide basic functionality, which can be especially useful if you have a problem and can't get MegaCLI to work. Approved by: re Obtained from: Yahoo! Inc. --- etc/mtree/BSD.include.dist | 2 + include/Makefile | 2 +- sys/dev/mfi/mfi_ioctl.h | 2 + sys/dev/mfi/mfireg.h | 219 +++++-- usr.sbin/Makefile | 1 + usr.sbin/mfiutil/Makefile | 17 + usr.sbin/mfiutil/README | 104 +++ usr.sbin/mfiutil/mfi_cmd.c | 351 ++++++++++ usr.sbin/mfiutil/mfi_config.c | 1164 +++++++++++++++++++++++++++++++++ usr.sbin/mfiutil/mfi_drive.c | 624 ++++++++++++++++++ usr.sbin/mfiutil/mfi_evt.c | 667 +++++++++++++++++++ usr.sbin/mfiutil/mfi_flash.c | 199 ++++++ usr.sbin/mfiutil/mfi_patrol.c | 305 +++++++++ usr.sbin/mfiutil/mfi_show.c | 560 ++++++++++++++++ usr.sbin/mfiutil/mfi_volume.c | 412 ++++++++++++ usr.sbin/mfiutil/mfiutil.1 | 574 ++++++++++++++++ usr.sbin/mfiutil/mfiutil.c | 134 ++++ usr.sbin/mfiutil/mfiutil.h | 147 +++++ 18 files changed, 5446 insertions(+), 38 deletions(-) create mode 100644 usr.sbin/mfiutil/Makefile create mode 100644 usr.sbin/mfiutil/README create mode 100644 usr.sbin/mfiutil/mfi_cmd.c create mode 100644 usr.sbin/mfiutil/mfi_config.c create mode 100644 usr.sbin/mfiutil/mfi_drive.c create mode 100644 usr.sbin/mfiutil/mfi_evt.c create mode 100644 usr.sbin/mfiutil/mfi_flash.c create mode 100644 usr.sbin/mfiutil/mfi_patrol.c create mode 100644 usr.sbin/mfiutil/mfi_show.c create mode 100644 usr.sbin/mfiutil/mfi_volume.c create mode 100644 usr.sbin/mfiutil/mfiutil.1 create mode 100644 usr.sbin/mfiutil/mfiutil.c create mode 100644 usr.sbin/mfiutil/mfiutil.h 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/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/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/usr.sbin/Makefile b/usr.sbin/Makefile index f57ff3a1daf..37d24f853cc 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -94,6 +94,7 @@ SUBDIR= ${_ac} \ manctl \ memcontrol \ mergemaster \ + mfiutil \ mixer \ ${_mld6query} \ mlxcontrol \ diff --git a/usr.sbin/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile new file mode 100644 index 00000000000..173048719d0 --- /dev/null +++ b/usr.sbin/mfiutil/Makefile @@ -0,0 +1,17 @@ +# $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 + +CFLAGS+= -fno-builtin-strftime +WARNS?=3 + +LDADD= -lutil + +# Here be dragons +.ifdef DEBUG +CFLAGS+= -DDEBUG +.endif + +.include diff --git a/usr.sbin/mfiutil/README b/usr.sbin/mfiutil/README new file mode 100644 index 00000000000..15e16bb0cdd --- /dev/null +++ b/usr.sbin/mfiutil/README @@ -0,0 +1,104 @@ +# $FreeBSD$ + +This package includes a mfiutil command for administering mfi(4) controllers +on FreeBSD. + +Version 1.0.13 + * Cleaned up warnings in preparation for integration with FreeBSD + +Version 1.0.12 + * Add 'drive clear' command to wipe drives with all 0x00 characters + +Version 1.0.11 + * Display serial number for drives + * Display location info for drives with 'show config' + +Version 1.0.10 + * Display min and max stripe size supported by adapters. + * Added support for examining the controller event log. + +Version 1.0.9 + * Display stripe size for volumes. + * Added support for setting the stripe size for new volumes. + * Fix a regression in 1.0.8 that broke creation of RAID-5 and RAID-50 + arrays. + +Version 1.0.8 + * Added support for RAID-60 arrays. + * Added 'flash' command to support firmware flashing. + +Version 1.0.7 + * Renamed 'clear config' to 'clear, 'create volume' to 'create', + 'delete volume' to 'delete', 'create spare' to 'add', and + 'delete spare' to 'remove'. The old names still work. + * Added support for RAID-6 arrays. + +Version 1.0.6 + * Added 'show patrol', 'patrol', 'start patrol', and 'stop patrol' + commands to manage patrol reads. + +Version 1.0.5 + * Added 'create volume' and 'delete volume' commands to manage volumes. + * Added 'clear config' command to clear entire configuration. + * Added more detailed error reporting based on firmware status codes. + * Renamed 'progress' command to 'drive progress'. + * Added 'volume progress' command to display progress of volume-level + activites such as background inits. + * Fixed 'create spare' to properly add global spares. + +Version 1.0.4 + * Added 'create spare' and 'delete spare' commands to manage hot spares. + * Added 'good' command to mark unconfigured bad drives as good. + * Display more information about hot spares in 'show config' + * Allow physical drives to be specified via Exx:Syy similar to megacli + * Display onboard memory size in 'show adapter' + +Version 1.0.3 + * Added 'cache' command to manage cache settings for volumes. + * Added 'name' command to name volumes. + * Added manpage. + +Version 1.0.2 + * Added 'show adapter' and 'show battery' commands. + * Added RAID level of volumes to 'show config' and 'show volumes'. + * Added drive model info to 'show config' and 'show drives'. + * Added package firmware version to 'show firmware'. + * Added read and write cache status to 'show volumes'. + * Map volume IDs to mfidX device names on newer kernels. + +Version 1.0.1 + * Added 'show firmware' command + +Version 1.0.0 + * Initial release + +usage: mfiutil [-u unit] ... + +Commands include: + version + show adapter - display controller information + show battery - display battery information + show config - display RAID configuration + show drives - list physical drives + show firmware - list firmware images + show volumes - list logical volumes + show patrol - display patrol read status + fail - fail a physical drive + good - mark a bad physical drive as good + rebuild - mark failed drive ready for rebuild + drive progress - display status of active operations + start rebuild + abort rebuild + locate - toggle drive LED + cache [command [setting]] + name + volume progress - display status of active operations + clear - clear volume configuration + create [-v] [,[,...]] [[,[,...]] + delete + add [volume] - add a hot spare + remove - remove a hot spare + patrol [interval [start]] + start patrol - start a patrol read + stop patrol - stop a patrol read + flash 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..ec3ea26e61b --- /dev/null +++ b/usr.sbin/mfiutil/mfi_drive.c @@ -0,0 +1,624 @@ +/*- + * 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; + long val; + uint8_t encl, slot; + 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 (val = 0; val < list->count; val++) { + if (list->addr[val].scsi_dev_type != 0) + continue; + + if (((encl == 0xff && + list->addr[val].encl_device_id == 0xffff) || + list->addr[val].encl_index == encl) && + list->addr[val].slot_number == slot) { + *device_id = list->addr[val].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.1 b/usr.sbin/mfiutil/mfiutil.1 new file mode 100644 index 00000000000..d7860ab06dd --- /dev/null +++ b/usr.sbin/mfiutil/mfiutil.1 @@ -0,0 +1,574 @@ +.\" 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 June 17, 2008 +.Dt MFIUTIL 1 +.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 . +Note that this second method only works on OS versions +.Dv 6.2-YAHOO-20070510 +and later. +.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 BUGS +On 64-bit OS versions +.Dv 6.2-YAHOO-20070514 +and earlier, +the +.Xr mfi 4 +driver does not properly report firmware errors to 32-bit versions of +.Nm . +As a result, +some commands may fail even though they do not report any errors. 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__ */ From 72034f5548912d016dfa622e2afdf6dc9df18cb9 Mon Sep 17 00:00:00 2001 From: Julian Elischer Date: Fri, 14 Aug 2009 10:09:45 +0000 Subject: [PATCH 038/453] Fix ipfw crash on uid or gid check. Receiving any ip packet for which there is no existing socket will crash if ipfw has a uid or gid test rule, as the uid/gid of the non existent owner of said non existent socket is tested. Brooks introduced this error as part of his >16 gids patch. It appears to be a cut-n-paste error from similar code a few lines before. The old code used the 'pcb' variable here, but in the new code that switched the 'inp' variable, which is often NULL and what is tested in the code further up. The rest of the multi-gid patch for ipfw seems solid (and cleaner than previous code). Reviewed by: brooks Approved by: re (rwatson) --- sys/netinet/ipfw/ip_fw2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c index da6593c46ce..31065daa308 100644 --- a/sys/netinet/ipfw/ip_fw2.c +++ b/sys/netinet/ipfw/ip_fw2.c @@ -2057,7 +2057,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); From 8f408451517a56ea44b3fbffbd329f49de534aea Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Fri, 14 Aug 2009 10:57:28 +0000 Subject: [PATCH 039/453] Correctly handle unlock for !MAKEENTRY case, after successfull attempt of lock upgrade cache shall be unlocked from write. Reported by: Lucius Windschuh Reviewed by: kan Approved by: re (rwatson) --- sys/kern/vfs_cache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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; From aabd624cf40d266ee368b268fada2e4534dcd9c9 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Fri, 14 Aug 2009 10:57:57 +0000 Subject: [PATCH 040/453] Add the address of the lock to the KTR_LOCK trace. Tested by: pho Approved by: re (rwatson) --- sys/sys/lock.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 { \ From 48bd6d4a4956c80d1aba9a45ad935f6e8ab703ee Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Fri, 14 Aug 2009 10:59:17 +0000 Subject: [PATCH 041/453] In nfs_upgrade_vnlock(), assert that the vnode is locked. It is for all pathes, as far as I see and testing seems to confirm it. Comparision of old_lock with LK_SHARED make sense only if vnode is locked by current thread. When downgrading, pass LK_RETRY to the vn_lock(), since otherwise vn_lock() unlocks the doomed vnode, causing extra unlock. Reported and tested by: pho Approved by: re (rwatson) MFC after: 3 weeks --- sys/nfsclient/nfs_subs.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) 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); } } From 165a3b418f68af52dfe2a1b4df1233ab908e6f06 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Fri, 14 Aug 2009 11:00:38 +0000 Subject: [PATCH 042/453] When a UFS node is truncated to the zero length, e.g. by explicit truncate(2) call, or by being removed or truncated on open, either new softupdate freeblks structure is allocated to track the freed blocks of the node, or truncation is done syncronously when too many SU dependencies are accumulated. The decision does not take into account the allocated freeblks dependencies, allowing workloads that do huge amount of truncations to exhaust the kernel memory. Take the number of allocated freeblks into consideration for softdep_slowdown(). Reported by: pluknet gmail com Diagnosed and tested by: pho Approved by: re (rwatson) MFC after: 1 month --- sys/ufs/ffs/ffs_softdep.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 72522b2594e..5f162806d1e 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); } From 6d600732ebfcb814df88e9e29e66619262609bc4 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Fri, 14 Aug 2009 12:30:10 +0000 Subject: [PATCH 043/453] Fix is 32bit bug missed in testing. Approved by: re --- usr.sbin/mfiutil/mfi_drive.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/usr.sbin/mfiutil/mfi_drive.c b/usr.sbin/mfiutil/mfi_drive.c index ec3ea26e61b..104422814ea 100644 --- a/usr.sbin/mfiutil/mfi_drive.c +++ b/usr.sbin/mfiutil/mfi_drive.c @@ -75,8 +75,9 @@ int mfi_lookup_drive(int fd, char *drive, uint16_t *device_id) { struct mfi_pd_list *list; - long val; uint8_t encl, slot; + long val; + u_int i; char *cp; /* Look for a raw device id first. */ @@ -117,15 +118,15 @@ mfi_lookup_drive(int fd, char *drive, uint16_t *device_id) return (errno); } - for (val = 0; val < list->count; val++) { - if (list->addr[val].scsi_dev_type != 0) + for (i = 0; i < list->count; i++) { + if (list->addr[i].scsi_dev_type != 0) continue; if (((encl == 0xff && - list->addr[val].encl_device_id == 0xffff) || - list->addr[val].encl_index == encl) && - list->addr[val].slot_number == slot) { - *device_id = list->addr[val].device_id; + 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); } From fc58801ccc318e391722e23c01826884edd25bf9 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Fri, 14 Aug 2009 13:13:12 +0000 Subject: [PATCH 044/453] Add mptutil, a basic utility for managing MPT SCSI/SATA/SAS controllers. Drive and controller status can be reported, basic attributes changed, and arrays and spares can be created and deleted. Approved by: re Obtained from: Yahoo! Inc. --- usr.sbin/Makefile | 1 + usr.sbin/mptutil/Makefile | 19 + usr.sbin/mptutil/mpt_cam.c | 569 ++++++++++++++++ usr.sbin/mptutil/mpt_cmd.c | 639 ++++++++++++++++++ usr.sbin/mptutil/mpt_config.c | 1160 +++++++++++++++++++++++++++++++++ usr.sbin/mptutil/mpt_drive.c | 395 +++++++++++ usr.sbin/mptutil/mpt_evt.c | 155 +++++ usr.sbin/mptutil/mpt_show.c | 559 ++++++++++++++++ usr.sbin/mptutil/mpt_volume.c | 248 +++++++ usr.sbin/mptutil/mptutil.8 | 383 +++++++++++ usr.sbin/mptutil/mptutil.c | 123 ++++ usr.sbin/mptutil/mptutil.h | 178 +++++ 12 files changed, 4429 insertions(+) create mode 100644 usr.sbin/mptutil/Makefile create mode 100644 usr.sbin/mptutil/mpt_cam.c create mode 100644 usr.sbin/mptutil/mpt_cmd.c create mode 100644 usr.sbin/mptutil/mpt_config.c create mode 100644 usr.sbin/mptutil/mpt_drive.c create mode 100644 usr.sbin/mptutil/mpt_evt.c create mode 100644 usr.sbin/mptutil/mpt_show.c create mode 100644 usr.sbin/mptutil/mpt_volume.c create mode 100644 usr.sbin/mptutil/mptutil.8 create mode 100644 usr.sbin/mptutil/mptutil.c create mode 100644 usr.sbin/mptutil/mptutil.h diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 37d24f853cc..160b122571a 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -104,6 +104,7 @@ SUBDIR= ${_ac} \ ${_mount_smbfs} \ ${_moused} \ ${_mptable} \ + mptutil \ mtest \ mtree \ ${_named} \ 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..fcc34e8a162 --- /dev/null +++ b/usr.sbin/mptutil/mptutil.8 @@ -0,0 +1,383 @@ +.\" +.\" 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 22, 2008 +.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 +Deleting volumes usually provokes a kernel crash in OS versions older than +.Dv 6.3-YAHOO-20080722 . +.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. 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__ */ From 75a1f6cf5f0927ae1c894af6bdd37b6209afec6d Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Fri, 14 Aug 2009 13:24:44 +0000 Subject: [PATCH 045/453] Make sysinstall recognize /dev/ada* disk devices. The description string "SATA disk device" reflects the current state of /dev/ada*; this may be changed in the future if other drive types start appearing as /dev/ada*. Submitted by: randi Details about what disks can appear as /dev/ada* supplied by: scottl Approved by: re (rwatson) --- usr.sbin/sysinstall/devices.c | 1 + 1 file changed, 1 insertion(+) 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), From eac295c9a0fb3edbc842749833fab072722656e4 Mon Sep 17 00:00:00 2001 From: Remko Lodder Date: Fri, 14 Aug 2009 18:18:51 +0000 Subject: [PATCH 046/453] Remove bogus char cast. PR: 118014 Submitted by: Gardner Bell Approved by: re (rwatson), imp (mentor, implicit) MFC after: immediate --- usr.sbin/arp/arp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From b03ddec95f14af316c897ca9be31fd80dbb31198 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 14 Aug 2009 20:35:42 +0000 Subject: [PATCH 048/453] Add the ability to build a release from an SVN checkout instead of a CVS checkout. If SVNROOT is specified, then the source tree will be checked out from that SVN repository instead of using CVS. ports and docs still use CVS. If SVNROOT is not specified, then the source tree will be checked out using CVS. An explicit SVN branch can be specified using SVNBRANCH (e.g. SVNBRANCH=stable/8). If SVNBRANCH is not set but RELEASETAG is set to a CVS branch (such as RELENG_8) the appropriate SVN branch will be inferred from the CVS branch using svnbranch.awk. Note that there are still several open questions about using SVN instead of CVS in the release process. However, this does enable one to build a release from an SVN repository if needed. Approved by: re (kensmith) --- release/Makefile | 55 +++++++++++++++++++++++++++++++++++++++---- release/svnbranch.awk | 28 ++++++++++++++++++++++ 2 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 release/svnbranch.awk diff --git a/release/Makefile b/release/Makefile index 22f250af064..fd3cb929d3c 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. @@ -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/7 +# # 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 diff --git a/release/svnbranch.awk b/release/svnbranch.awk new file mode 100644 index 00000000000..0fc86200c04 --- /dev/null +++ b/release/svnbranch.awk @@ -0,0 +1,28 @@ +# $FreeBSD$ + +BEGIN { + FS = "_" +} + +/RELENG_.*_RELEASE/ { + if (NF == 5) { + printf "release/%s.%s.%s", $2, $3, $4 + exit + } +} + +/RELENG_.*/ { + if (NF == 3) { + printf "releng/%s.%s", $2, $3 + exit + } + + if (NF == 2) { + printf "stable/%s", $2 + exit + } +} + +// { + printf "unknown_branch" +} From 21157ad3b1a7b0b37816f3ab79444d02c487dfc1 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 14 Aug 2009 21:05:08 +0000 Subject: [PATCH 049/453] Adjust the handling of the local APIC PMC interrupt vector: - Provide lapic_disable_pmc(), lapic_enable_pmc(), and lapic_reenable_pmc() routines in the local APIC code that the hwpmc(4) driver can use to manage the local APIC PMC interrupt vector. - Do not enable the local APIC PMC interrupt vector by default when HWPMC_HOOKS is enabled. Instead, the hwpmc(4) driver explicitly enables the interrupt when it is succesfully initialized and disables the interrupt when it is unloaded. This avoids enabling the interrupt on unsupported CPUs which may result in spurious NMIs. Reported by: rnoland Reviewed by: jkoshy Approved by: re (kib) MFC after: 2 weeks --- sys/amd64/amd64/local_apic.c | 86 ++++++++++++++++++++++++++++++++++-- sys/amd64/include/apicvar.h | 3 ++ sys/amd64/include/pmc_mdep.h | 1 - sys/dev/hwpmc/hwpmc_core.c | 7 ++- sys/dev/hwpmc/hwpmc_piv.c | 5 ++- sys/dev/hwpmc/hwpmc_ppro.c | 5 ++- sys/dev/hwpmc/hwpmc_x86.c | 22 +++------ sys/i386/i386/local_apic.c | 86 ++++++++++++++++++++++++++++++++++-- sys/i386/include/apicvar.h | 3 ++ sys/i386/include/pmc_mdep.h | 1 - 10 files changed, 191 insertions(+), 28 deletions(-) diff --git a/sys/amd64/amd64/local_apic.c b/sys/amd64/amd64/local_apic.c index cd3073caf99..13bd7743cb9 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 diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h index 73fff6c006f..9d6d538de1d 100644 --- a/sys/amd64/include/apicvar.h +++ b/sys/amd64/include/apicvar.h @@ -201,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); @@ -212,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/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/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c index 214e42cb4b0..f84e0f1548c 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 @@ -1771,7 +1774,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 +1898,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/i386/i386/local_apic.c b/sys/i386/i386/local_apic.c index 2cc6a450482..5e79aa805c5 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 diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h index a13766f95f9..b15452b1d81 100644 --- a/sys/i386/include/apicvar.h +++ b/sys/i386/include/apicvar.h @@ -230,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); @@ -241,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/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); From 8d518523cc6a833a75eab9e1f7fc8b14371bb536 Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Fri, 14 Aug 2009 21:46:54 +0000 Subject: [PATCH 050/453] Add a new macro to test that a variable could be loaded atomically. Check that the given variable is at most uintptr_t in size and that it is aligned. Note: ASSERT_ATOMIC_LOAD() uses ALIGN() to check for adequate alignment -- however, the function of ALIGN() is to guarantee alignment, and therefore may lead to stronger alignment enforcement than necessary for types that are smaller than sizeof(uintptr_t). Add checks to mtx, rw and sx locks init functions to detect possible breakage. This was used during debugging of the problem fixed with r196118 where a pointer was on an un-aligned address in the dpcpu area. In collaboration with: rwatson Reviewed by: rwatson Approved by: re (kib) --- sys/kern/kern_mutex.c | 2 ++ sys/kern/kern_rwlock.c | 2 ++ sys/kern/kern_sx.c | 2 ++ sys/sys/systm.h | 4 ++++ 4 files changed, 10 insertions(+) diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index fc342c53ef4..f625098f248 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -783,6 +783,8 @@ 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(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_rwlock.c b/sys/kern/kern_rwlock.c index c07f595cb5a..e2342506a0e 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -174,6 +174,8 @@ 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(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_sx.c b/sys/kern/kern_sx.c index 04c2c984150..15c1c9bdf16 100644 --- a/sys/kern/kern_sx.c +++ b/sys/kern/kern_sx.c @@ -205,6 +205,8 @@ 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(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) diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 1956a8f122f..2e8b9adb458 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -89,6 +89,10 @@ extern int maxusers; /* system tune hint */ #define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] #endif +#define ASSERT_ATOMIC_LOAD(var,msg) \ + KASSERT(sizeof(var) <= sizeof(uintptr_t) && \ + ALIGN(&(var)) == (uintptr_t)&(var), 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 From 67addcde86327926b90dcf17fe46792813894962 Mon Sep 17 00:00:00 2001 From: Marko Zec Date: Fri, 14 Aug 2009 22:41:39 +0000 Subject: [PATCH 051/453] Make VNET_DEBUG a standalone compile-time option, i.e. decouple it from INVARIANTS. Reviewed by: bz Approved by: re (rwatson), julian (mentor) --- sys/conf/options | 3 ++- sys/net/vnet.h | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sys/conf/options b/sys/conf/options index 41c80b5434c..ac2d87c0195 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -821,8 +821,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/net/vnet.h b/sys/net/vnet.h index 91de07a1093..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)) { \ From f92ae4d70643544c22f2b35dc776b6e8b25896d5 Mon Sep 17 00:00:00 2001 From: Marko Zec Date: Fri, 14 Aug 2009 22:43:25 +0000 Subject: [PATCH 052/453] SCTP is not yet compatible with options VIMAGE kernels although it compiles with VIMAGE defined, so explicitly disallow building such kernels. Reviewed by: rrs Approved by: re (rwatson), julian (mentor) --- sys/netinet/sctp_os_bsd.h | 4 ++++ 1 file changed, 4 insertions(+) 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 From 9abb4862792dbcc7b65d5d6647821e03ea111579 Mon Sep 17 00:00:00 2001 From: Marko Zec Date: Fri, 14 Aug 2009 22:46:45 +0000 Subject: [PATCH 053/453] Appease VNET_DEBUG - in if_vmove we temporarily switch i.e. recurse from one vnet to another which is OK, so no need to flood the console with warnings here. Approved by: re (rwatson), julian (mentor) --- sys/net/if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net/if.c b/sys/net/if.c index 3ac7db05c14..5d108981cdd 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -920,7 +920,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) { From 3ef5e21d0131947fc762df0bed814e2f3a50e4f7 Mon Sep 17 00:00:00 2001 From: Qing Li Date: Fri, 14 Aug 2009 23:44:59 +0000 Subject: [PATCH 054/453] In function ip_output(), the cached route is flushed when there is a mismatch between the cached entry and the intended destination. The cached rtentry{} is flushed but the associated llentry{} is not. This causes the wrong destination MAC address being used in the output packets. The fix is to flush the llentry{} when rtentry{} is cleared. Reviewed by: kmacy, rwatson Approved by: re --- sys/netinet/ip_output.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index bf2a5f8bb53..33ba8383043 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 @@ -201,9 +202,12 @@ again: if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || dst->sin_family != AF_INET || dst->sin_addr.s_addr != ip->ip_dst.s_addr)) { - if (!nortfree) + if (!nortfree) { RTFREE(ro->ro_rt); + LLE_FREE(ro->ro_lle); + } ro->ro_rt = (struct rtentry *)NULL; + ro->ro_lle = (struct llentry *)NULL; } #ifdef IPFIREWALL_FORWARD if (ro->ro_rt == NULL && fwd_tag == NULL) { From 70ff501c96bb4f21032811977b41705fc058569e Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 15 Aug 2009 11:47:05 +0000 Subject: [PATCH 055/453] Add mptutil(8) and mfiutil(1) to 'SEE ALSO' sections in mpt(4) and mfi(4). Approved by: re (rwatson) --- share/man/man4/mfi.4 | 3 ++- share/man/man4/mpt.4 | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/share/man/man4/mfi.4 b/share/man/man4/mfi.4 index 2288ecbbe6e..5025336bfe4 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 @@ -102,6 +102,7 @@ management interface An attempt was made to remove a mounted volume. .El .Sh SEE ALSO +.Xr mfiutil 1 , .Xr amr 4 , .Xr pci 4 .Sh HISTORY 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" From 67c601d5f6eb2b25e2cef312253bdb4ab84d5359 Mon Sep 17 00:00:00 2001 From: Stanislav Sedov Date: Sat, 15 Aug 2009 14:39:33 +0000 Subject: [PATCH 056/453] - Avoid overflowing the swap size counters in human-readable mode by introducing the new CONVERT_BLOCKS macro which operates on sizes already converted to number of blocks. With this macro it is not longer needed to perform needless multiplication by blocksize just to divide on it later in CONVERT macro. Approved by: re (kib) MFC after: 1 week --- usr.sbin/pstat/pstat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 { From 2dc8b759bd119cc62767462659dfc2f5675344d4 Mon Sep 17 00:00:00 2001 From: Stanislav Sedov Date: Sat, 15 Aug 2009 15:15:20 +0000 Subject: [PATCH 057/453] - Proprely intialize UART parameters at probe stage, so uart(4) will initialize the FIFO memory correctly on attach. Before that this values was intialized in only in at91_usart_bus_attach which is called after the uart(4) memory allocation happens. Approved by: re (kib) MFC after: 1 week --- sys/arm/at91/uart_dev_at91usart.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 From 5ad0a62fe09319301dd33785c7e8d4f764de7c93 Mon Sep 17 00:00:00 2001 From: Dima Panov Date: Sat, 15 Aug 2009 15:40:30 +0000 Subject: [PATCH 058/453] Add my birthday Approved by: re (rwatson) miwi (mentor) --- usr.bin/calendar/calendars/calendar.freebsd | 1 + 1 file changed, 1 insertion(+) 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 From bc5980cb6c636a35446e744f2918e398a63710fd Mon Sep 17 00:00:00 2001 From: Giorgos Keramidas Date: Sat, 15 Aug 2009 17:57:21 +0000 Subject: [PATCH 059/453] iostat: add a bit of space between tty in/out columns The columns for tty input and output may bump against each other if the tty output needs more than 5 columns. Add a bit of space that pushes everything 1 column to the right, but also avoids the problem. Approved by: re (rwatson) --- usr.sbin/iostat/iostat.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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(); From 68a5590836584f6079c2b6d9e84ca4a4fe9caec6 Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Sat, 15 Aug 2009 18:37:06 +0000 Subject: [PATCH 060/453] Port recent IPI enhachements to en: * Introduce the ipi_nmi_handler() function for the Xen infrastructure * Fixup adeguately the ipi sender functions Approved by: re (kib) --- sys/i386/xen/mp_machdep.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/sys/i386/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c index bae07d4f608..92533662b26 100644 --- a/sys/i386/xen/mp_machdep.c +++ b/sys/i386/xen/mp_machdep.c @@ -118,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; @@ -1109,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--; @@ -1140,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. From 810ec53688ee0081762fb7b0db685a76217dc952 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Sat, 15 Aug 2009 21:10:52 +0000 Subject: [PATCH 061/453] * Fix a bug where PR-SCTP settings are ignore when using implicit association setup. * Fix a bug where message with illegal stream ids are not deleted. * Fix a crash when reporting back unsent messages from the send_queue. * Fix a bug related to INIT retransmission when the socket is already closed. * Fix a bug where associations were stalled when partial delivery API was enabled. * Fix a bug where the receive buffer size was smaller than the partial_delivery_point. Approved by: re, rrs (mentor) MFC after: One day. --- sys/netinet/sctp_indata.c | 33 ++++++++----- sys/netinet/sctp_input.c | 35 +++++++++---- sys/netinet/sctp_output.c | 100 ++++++++++++++++++-------------------- sys/netinet/sctp_pcb.c | 7 ++- sys/netinet/sctp_timer.c | 6 +-- sys/netinet/sctputil.c | 90 +++++++++++++++++++++++++++------- sys/netinet/sctputil.h | 4 -- 7 files changed, 176 insertions(+), 99 deletions(-) diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 7abdd710a47..52d53e1b975 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) >> SCTP_PARTIAL_DELIVERY_SHIFT, + 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 @@ -2824,7 +2829,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) { @@ -2860,8 +2865,13 @@ doit_again: * be here or 1/4 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) >> SCTP_PARTIAL_DELIVERY_SHIFT, + 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; @@ -5192,7 +5202,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 +6299,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) && @@ -7786,7 +7797,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_output.c b/sys/netinet/sctp_output.c index 21b8f8f89c0..5cde4d0dd69 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); 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..53d84b794d3 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 */ @@ -5346,6 +5368,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 From d931ea0961d8d76c16c5dda42b2609b362948417 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Sat, 15 Aug 2009 22:26:26 +0000 Subject: [PATCH 062/453] Remove unused if_rawoutput() macro; it has been unused since at least FreeBSD 2. Approved by: re (kib) --- sys/net/if_var.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 428645fa206..aa83161cce3 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -235,7 +235,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 From a38fdf294650bdfc673c39fab49ae14f2c33feea Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Sat, 15 Aug 2009 23:07:43 +0000 Subject: [PATCH 063/453] Rather than fix questionable ifnet list locking in the implementation of the kern.polling.enable sysctl, remove the sysctl. It has been deprecated since FreeBSD 6 in favour of per-ifnet polling flags. Reviewed by: luigi Approved by: re (kib) --- share/man/man4/polling.4 | 19 ++++++++-------- sys/kern/kern_poll.c | 49 ---------------------------------------- 2 files changed, 10 insertions(+), 58 deletions(-) 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/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) { From 97e84697ae827993c2b07719c46b7b4da8622331 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sun, 16 Aug 2009 01:43:08 +0000 Subject: [PATCH 064/453] Decouple ACPI CPU Ids from FreeBSD's cpuid. The ACPI Ids can be sparse, which causes a kernel assert. Approved by: re (kensmith) --- sys/ia64/ia64/genassym.c | 1 - sys/ia64/ia64/machdep.c | 6 +++++- sys/ia64/ia64/mp_machdep.c | 32 ++++++++++++++------------------ 3 files changed, 19 insertions(+), 20 deletions(-) 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/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++; } } From 538e86713d153598a9069d6c77b98d51d4c740cb Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sun, 16 Aug 2009 01:48:46 +0000 Subject: [PATCH 065/453] Fix misalignment in nvpair_native_embedded() caused by the compiler replacing the bzero(). See also revision 195627, which fixed the misalignment in nvpair_native_embedded_array(). Approved by: re (kensmith) --- sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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))); From ab1a777e91108fe75346dfb805029bcad5817d11 Mon Sep 17 00:00:00 2001 From: Rink Springer Date: Sun, 16 Aug 2009 10:11:33 +0000 Subject: [PATCH 066/453] Prevent sysinstall from needlessly waiting for confirmation when using an USB device in non-interactive mode. If there are no USB devices, sysinstall gives an error messages, and if there is >1, it'll ask which one is to be used. This change allows a non-interactive install from USB media to succeed without any user interaction if there is exactly one USB disk device in the system it can use. Submitted by: Daniel O'Connor < doconnorat gsoft dot com dot au > Reviewed by: randi Approved by: re (rwatson) --- usr.sbin/sysinstall/media.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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); } From 532b195250330c00fd8ac4a076b492b70ef01f98 Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Sun, 16 Aug 2009 14:13:55 +0000 Subject: [PATCH 067/453] Change the usb workers from kernel processes to threads, this is mostly a cosmetic change to reduce cruft in the proc table. Also change the idle wait message to `-` like how taskqueues are. Reviewed by: julian Approved by: re (kib) --- sys/dev/usb/usb_process.c | 12 +++++++----- sys/dev/usb/usb_process.h | 4 ++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/sys/dev/usb/usb_process.c b/sys/dev/usb/usb_process.c index eb79f166508..5b98a819a8e 100644 --- a/sys/dev/usb/usb_process.c +++ b/sys/dev/usb/usb_process.c @@ -63,10 +63,12 @@ #endif #if (__FreeBSD_version >= 800000) +static struct proc *usbproc; #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__) @@ -207,8 +209,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)) { diff --git a/sys/dev/usb/usb_process.h b/sys/dev/usb/usb_process.h index c717dc1522b..71432c3bf70 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; From f6b3749db3712007127df95937ee6aa9a8f03b92 Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Sun, 16 Aug 2009 19:55:53 +0000 Subject: [PATCH 068/453] Fix small style regression introduced by the MPSAFE newbus code. Approved by: re (rwatson) --- sys/kern/subr_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index 67f09182d5f..52cd766296c 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -4131,7 +4131,7 @@ driver_module_handler(module_t mod, int what, void *arg) return (ENOMEM); } - switch (what) { + switch (what) { case MOD_LOAD: if (dmd->dmd_chainevh) error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); From cee5f0ca2d90c9fe8bf9c911fb7d4aa472c77d2a Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sun, 16 Aug 2009 21:27:35 +0000 Subject: [PATCH 069/453] Emit a proper error message instead of dumping core when 1) GEOM_PART does not exist in the kernel, and 2) the GEOM in question does not exist. Additionally abort in case of programming errors that result in neither the class nor geom not being present in the gctl request. Submitted by: "Andrey V. Elsukov" Approved by: re (kib) --- sbin/geom/class/part/geom_part.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) 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); From 3c6bf4efb9532f9569d00bc092fa87e1ad72c3d3 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Mon, 17 Aug 2009 06:05:55 +0000 Subject: [PATCH 070/453] Move mfiutil.1 to mfiutil.8 for consistency. Remove superfulous README. Approved by: re --- usr.sbin/mfiutil/Makefile | 1 + usr.sbin/mfiutil/README | 104 ---------------------- usr.sbin/mfiutil/{mfiutil.1 => mfiutil.8} | 0 3 files changed, 1 insertion(+), 104 deletions(-) delete mode 100644 usr.sbin/mfiutil/README rename usr.sbin/mfiutil/{mfiutil.1 => mfiutil.8} (100%) diff --git a/usr.sbin/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile index 173048719d0..03ded032958 100644 --- a/usr.sbin/mfiutil/Makefile +++ b/usr.sbin/mfiutil/Makefile @@ -3,6 +3,7 @@ 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 diff --git a/usr.sbin/mfiutil/README b/usr.sbin/mfiutil/README deleted file mode 100644 index 15e16bb0cdd..00000000000 --- a/usr.sbin/mfiutil/README +++ /dev/null @@ -1,104 +0,0 @@ -# $FreeBSD$ - -This package includes a mfiutil command for administering mfi(4) controllers -on FreeBSD. - -Version 1.0.13 - * Cleaned up warnings in preparation for integration with FreeBSD - -Version 1.0.12 - * Add 'drive clear' command to wipe drives with all 0x00 characters - -Version 1.0.11 - * Display serial number for drives - * Display location info for drives with 'show config' - -Version 1.0.10 - * Display min and max stripe size supported by adapters. - * Added support for examining the controller event log. - -Version 1.0.9 - * Display stripe size for volumes. - * Added support for setting the stripe size for new volumes. - * Fix a regression in 1.0.8 that broke creation of RAID-5 and RAID-50 - arrays. - -Version 1.0.8 - * Added support for RAID-60 arrays. - * Added 'flash' command to support firmware flashing. - -Version 1.0.7 - * Renamed 'clear config' to 'clear, 'create volume' to 'create', - 'delete volume' to 'delete', 'create spare' to 'add', and - 'delete spare' to 'remove'. The old names still work. - * Added support for RAID-6 arrays. - -Version 1.0.6 - * Added 'show patrol', 'patrol', 'start patrol', and 'stop patrol' - commands to manage patrol reads. - -Version 1.0.5 - * Added 'create volume' and 'delete volume' commands to manage volumes. - * Added 'clear config' command to clear entire configuration. - * Added more detailed error reporting based on firmware status codes. - * Renamed 'progress' command to 'drive progress'. - * Added 'volume progress' command to display progress of volume-level - activites such as background inits. - * Fixed 'create spare' to properly add global spares. - -Version 1.0.4 - * Added 'create spare' and 'delete spare' commands to manage hot spares. - * Added 'good' command to mark unconfigured bad drives as good. - * Display more information about hot spares in 'show config' - * Allow physical drives to be specified via Exx:Syy similar to megacli - * Display onboard memory size in 'show adapter' - -Version 1.0.3 - * Added 'cache' command to manage cache settings for volumes. - * Added 'name' command to name volumes. - * Added manpage. - -Version 1.0.2 - * Added 'show adapter' and 'show battery' commands. - * Added RAID level of volumes to 'show config' and 'show volumes'. - * Added drive model info to 'show config' and 'show drives'. - * Added package firmware version to 'show firmware'. - * Added read and write cache status to 'show volumes'. - * Map volume IDs to mfidX device names on newer kernels. - -Version 1.0.1 - * Added 'show firmware' command - -Version 1.0.0 - * Initial release - -usage: mfiutil [-u unit] ... - -Commands include: - version - show adapter - display controller information - show battery - display battery information - show config - display RAID configuration - show drives - list physical drives - show firmware - list firmware images - show volumes - list logical volumes - show patrol - display patrol read status - fail - fail a physical drive - good - mark a bad physical drive as good - rebuild - mark failed drive ready for rebuild - drive progress - display status of active operations - start rebuild - abort rebuild - locate - toggle drive LED - cache [command [setting]] - name - volume progress - display status of active operations - clear - clear volume configuration - create [-v] [,[,...]] [[,[,...]] - delete - add [volume] - add a hot spare - remove - remove a hot spare - patrol [interval [start]] - start patrol - start a patrol read - stop patrol - stop a patrol read - flash diff --git a/usr.sbin/mfiutil/mfiutil.1 b/usr.sbin/mfiutil/mfiutil.8 similarity index 100% rename from usr.sbin/mfiutil/mfiutil.1 rename to usr.sbin/mfiutil/mfiutil.8 From d78c3fa1d3f1e0fffc1715daf809779089230903 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Mon, 17 Aug 2009 06:11:30 +0000 Subject: [PATCH 071/453] Update the man page for FreeBSD 8.0 Approved by: re --- usr.sbin/mfiutil/mfiutil.8 | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/usr.sbin/mfiutil/mfiutil.8 b/usr.sbin/mfiutil/mfiutil.8 index d7860ab06dd..e8aa643ee8c 100644 --- a/usr.sbin/mfiutil/mfiutil.8 +++ b/usr.sbin/mfiutil/mfiutil.8 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 17, 2008 +.Dd August 16, 2009 .Dt MFIUTIL 1 .Os .Sh NAME @@ -161,9 +161,6 @@ on the volume may be specified by the corresponding device, such as .Em mfid0 . -Note that this second method only works on OS versions -.Dv 6.2-YAHOO-20070510 -and later. .Pp Drives may be specified in two forms. First, @@ -562,13 +559,8 @@ patrol read starting in 5 minutes: .Pp .Sh SEE ALSO .Xr mfi 4 -.Sh BUGS -On 64-bit OS versions -.Dv 6.2-YAHOO-20070514 -and earlier, -the -.Xr mfi 4 -driver does not properly report firmware errors to 32-bit versions of -.Nm . -As a result, -some commands may fail even though they do not report any errors. +.Sh HISTORY +The +.Nm +utility first appeared in +.Fx 8.0 . From b1f3db024c0d06581c16697a94e16e5269e57e7f Mon Sep 17 00:00:00 2001 From: Scott Long Date: Mon, 17 Aug 2009 06:15:08 +0000 Subject: [PATCH 072/453] Update the man page for manual section 8 Approved by: re --- usr.sbin/mfiutil/mfiutil.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/mfiutil/mfiutil.8 b/usr.sbin/mfiutil/mfiutil.8 index e8aa643ee8c..e6026d653d4 100644 --- a/usr.sbin/mfiutil/mfiutil.8 +++ b/usr.sbin/mfiutil/mfiutil.8 @@ -28,7 +28,7 @@ .\" $FreeBSD$ .\" .Dd August 16, 2009 -.Dt MFIUTIL 1 +.Dt MFIUTIL 8 .Os .Sh NAME .Nm mfiutil From aa1214d9a2e1e7dfaf9f8b9cbbe5cf473f41c74f Mon Sep 17 00:00:00 2001 From: Scott Long Date: Mon, 17 Aug 2009 06:15:44 +0000 Subject: [PATCH 073/453] Update the mptutil man page for FreeBSD 8.0 Approved by: re --- usr.sbin/mptutil/mptutil.8 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/usr.sbin/mptutil/mptutil.8 b/usr.sbin/mptutil/mptutil.8 index fcc34e8a162..7acaf3e90d3 100644 --- a/usr.sbin/mptutil/mptutil.8 +++ b/usr.sbin/mptutil/mptutil.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 22, 2008 +.Dd August 16, 2009 .Dt MPTUTIL 8 .Os .Sh NAME @@ -349,8 +349,6 @@ as a global hot spare: .Sh SEE ALSO .Xr mpt 4 .Sh BUGS -Deleting volumes usually provokes a kernel crash in OS versions older than -.Dv 6.3-YAHOO-20080722 . .Pp The handling of spare drives appears to be unreliable. The @@ -381,3 +379,8 @@ 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 . From 48423f5d8f99bce81b7d0b1d3a0199a94e294767 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 07:38:47 +0000 Subject: [PATCH 074/453] Be more precise how to get fsids - 'mount -v' doesn't show fsids unless is run by root. Approved by: re (kib) --- sbin/umount/umount.8 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 From 830940567b49bb0c08dfaed40418999e76616909 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 08:03:02 +0000 Subject: [PATCH 075/453] Remove files that are no longer used. Discussed with: kmacy Approved by: re (kib) --- cddl/lib/libnvpair/Makefile | 1 + sys/cddl/compat/opensolaris/rpc/xdr.h | 112 ---- .../uts/common/rpc/opensolaris_xdr.c | 621 ----------------- .../uts/common/rpc/opensolaris_xdr_array.c | 114 ---- .../uts/common/rpc/opensolaris_xdr_mem.c | 209 ------ .../contrib/opensolaris/uts/common/rpc/xdr.h | 632 ------------------ 6 files changed, 1 insertion(+), 1688 deletions(-) delete mode 100644 sys/cddl/compat/opensolaris/rpc/xdr.h delete mode 100644 sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr.c delete mode 100644 sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr_array.c delete mode 100644 sys/cddl/contrib/opensolaris/uts/common/rpc/opensolaris_xdr_mem.c delete mode 100644 sys/cddl/contrib/opensolaris/uts/common/rpc/xdr.h 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/sys/cddl/compat/opensolaris/rpc/xdr.h b/sys/cddl/compat/opensolaris/rpc/xdr.h deleted file mode 100644 index 5802f3f12ba..00000000000 --- a/sys/cddl/compat/opensolaris/rpc/xdr.h +++ /dev/null @@ -1,112 +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 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. - */ - -#ifndef _OPENSOLARIS_RPC_XDR_H_ -#define _OPENSOLARIS_RPC_XDR_H_ - -#include_next - -#ifndef _KERNEL -#include_next - -/* - * 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. - * - * 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. - */ -#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); - - } - return (FALSE); -} -#endif /* !_KERNEL */ - -#endif /* !_OPENSOLARIS_RPC_XDR_H_ */ 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 */ From fddc9540162902eed391bd3c26678b8e726440bb Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 08:36:41 +0000 Subject: [PATCH 076/453] - Fix a race where /dev/zfs control device is created before ZFS is fully initialized. Also destroy /dev/zfs before doing other deinitializations. - Initialization through taskq is no longer needed and there is a race where one of the zpool/zfs command loads zfs.ko and tries to do some work immediately, but /dev/zfs is not there yet. Reported by: pav Approved by: re (kib) --- .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) 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..ded407e37f7 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 @@ -3056,44 +3056,35 @@ zfsdev_fini(void) destroy_dev(zfsdev); } -static struct task zfs_start_task; static struct root_hold_token *zfs_root_token; - 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 +3092,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); From 6a3b289388c2f1b07b3d07f9ca8518c99129fbe2 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 08:42:34 +0000 Subject: [PATCH 077/453] 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. Approved by: re (kib) --- sys/kern/subr_taskqueue.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c index bd4f34d9b9b..e49c8024ecf 100644 --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -401,6 +401,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); } From 159ef108e1160b43c4cc4a9a0cbae38fae18c8a8 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 09:01:20 +0000 Subject: [PATCH 078/453] Remove OpenSolaris taskq port (it performs very poorly in our kernel) and replace it with wrappers around our taskqueue(9). To make it possible implement taskqueue_member() function which returns 1 if the given thread was created by the given taskqueue. Approved by: re (kib) --- share/man/man9/taskqueue.9 | 16 +- .../opensolaris/kern/opensolaris_taskq.c | 135 +++ sys/cddl/compat/opensolaris/sys/taskq_impl.h | 137 --- .../uts/common/fs/zfs/sys/zfs_context.h | 1 + .../contrib/opensolaris/uts/common/os/taskq.c | 1041 ----------------- .../opensolaris/uts/common}/sys/taskq.h | 24 +- sys/kern/subr_taskqueue.c | 20 + sys/modules/zfs/Makefile | 2 +- sys/sys/taskqueue.h | 2 + 9 files changed, 188 insertions(+), 1190 deletions(-) create mode 100644 sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c delete mode 100644 sys/cddl/compat/opensolaris/sys/taskq_impl.h delete mode 100644 sys/cddl/contrib/opensolaris/uts/common/os/taskq.c rename sys/cddl/{compat/opensolaris => contrib/opensolaris/uts/common}/sys/taskq.h (83%) diff --git a/share/man/man9/taskqueue.9 b/share/man/man9/taskqueue.9 index 241b20f4869..589c3c644fd 100644 --- a/share/man/man9/taskqueue.9 +++ b/share/man/man9/taskqueue.9 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 13, 2008 +.Dd August 17, 2009 .Dt TASKQUEUE 9 .Os .Sh NAME @@ -71,6 +71,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" @@ -182,6 +184,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 +is 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/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/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/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/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/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/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c index e49c8024ecf..bec3b566ea3 100644 --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -472,3 +472,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/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/sys/taskqueue.h b/sys/sys/taskqueue.h index 4065a58b3ed..244e3e20de2 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 @@ -60,6 +61,7 @@ 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 From f820bc079f5c632f6e19ce360e64c7f37aceb857 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 09:13:22 +0000 Subject: [PATCH 079/453] Fix panic in zfs recv code. The last vnode (mountpoint's vnode) can have 0 usecount. Reported by: Thomas Backman Approved by: re (kib) --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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..16c6683b7af 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 @@ -917,7 +917,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); From d83cfc37a4a000d20eeeb03fdb2392790434b6ea Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 09:21:39 +0000 Subject: [PATCH 080/453] - We need to recycle vnode instead of freeing znode. Submitted by: avg - Add missing vnode interlock unlock. - Remove redundant znode locking. Approved by: re (kib) --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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..ac75cc29679 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 @@ -3709,12 +3709,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; } From 0330a5dc1050b93ea00ae5552f021d7182016c99 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 09:25:37 +0000 Subject: [PATCH 081/453] If z_buf is NULL, we should free znode immediately. Noticed by: avg Approved by: re (kib) --- .../opensolaris/uts/common/fs/zfs/zfs_vnops.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) 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 ac75cc29679..84b365edc07 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 @@ -4350,7 +4350,6 @@ zfs_freebsd_reclaim(ap) { vnode_t *vp = ap->a_vp; znode_t *zp = VTOZ(vp); - zfsvfs_t *zfsvfs; ASSERT(zp != NULL); @@ -4360,13 +4359,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) { @@ -4382,8 +4386,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; From e35eb914f49f65b72e2b88046d2800849277d632 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 09:28:15 +0000 Subject: [PATCH 082/453] - Reduce z_teardown_lock lock scope a bit. - The error variable is int, not bool. - Convert spaces to tabs where needed. Approved by: re (kib) --- .../opensolaris/uts/common/fs/zfs/zfs_vnops.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 84b365edc07..b2a3a16193b 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 @@ -4529,9 +4529,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); } @@ -4597,9 +4597,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); @@ -4712,7 +4712,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, @@ -4729,13 +4729,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); } @@ -4825,10 +4825,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 From c321f4c43d93d376330dacedfb25bc8dd1d87ba3 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 09:34:00 +0000 Subject: [PATCH 083/453] Fix receive when dataset has no / in its name. Submitted by: James R. Van Artsdalen Approved by: re (kib) --- .../opensolaris/lib/libzfs/common/libzfs_sendrecv.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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) { From 8461b0f0434003f4f12eafdc6d43848683795f85 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 09:48:34 +0000 Subject: [PATCH 084/453] Manage asynchronous vnode release just like Solaris. Discussed with: kmacy Approved by: re (kib) --- sys/cddl/compat/opensolaris/sys/vnode.h | 1 - .../contrib/opensolaris/uts/common/fs/vnode.c | 134 ++---------------- .../opensolaris/uts/common/fs/zfs/dmu.c | 3 - .../opensolaris/uts/common/fs/zfs/dsl_pool.c | 10 ++ .../uts/common/fs/zfs/sys/dsl_pool.h | 3 + .../opensolaris/uts/common/fs/zfs/zfs_vnops.c | 9 +- .../opensolaris/uts/common/sys/vnode.h | 22 ++- 7 files changed, 50 insertions(+), 132 deletions(-) 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/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/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/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/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/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index b2a3a16193b..de7c2930eba 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); } 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. */ From 8e9fd65fbfb3c0a568fc496617117e6a6006ef68 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 10:00:18 +0000 Subject: [PATCH 085/453] getcwd() (when __getcwd() fails) works by stating current directory, going up (..), calling readdir and looking for previous directory inode. In case of .zfs/ directory this doesn't work, because .zfs/ is hidden by default, so it won't be visible in readdir output. Fix this by implementing VPTOCNP for snapshot directories, so __getcwd() doesn't fail and getcwd() doesn't have to use readdir method. This fixes /bin/pwd from within .zfs/snapshot//. Suggested by: kib Approved by: re (rwatson) --- .../uts/common/fs/zfs/zfs_ctldir.c | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) 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..cf99d68e8bb 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 @@ -1195,6 +1195,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 +1248,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 From 9c1a8ce494ad5036026929211d940e5c2d365c75 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 17 Aug 2009 10:20:22 +0000 Subject: [PATCH 086/453] Correct typo in the previous commit. Noticed by: pluknet Approved by: re (kib, implicit) --- share/man/man9/taskqueue.9 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/man/man9/taskqueue.9 b/share/man/man9/taskqueue.9 index 589c3c644fd..553010b8042 100644 --- a/share/man/man9/taskqueue.9 +++ b/share/man/man9/taskqueue.9 @@ -188,7 +188,7 @@ The .Fn taskqueue_member function returns .No 1 -is the given thread +if the given thread .Fa td is part of the given taskqeueue .Fa queue From fbe007da74cdadcc3619882f6859b17a7374f12e Mon Sep 17 00:00:00 2001 From: Rui Paulo Date: Mon, 17 Aug 2009 12:57:57 +0000 Subject: [PATCH 087/453] Fix a typo in ifdef mesh support. This would make mesh unworkable if TDMA support was compiled out. Approved by: re (kib) --- sys/net80211/ieee80211_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From faccac2d454505a00dda60eda6d692234096059a Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 17 Aug 2009 13:27:55 +0000 Subject: [PATCH 088/453] Correct a critical accounting error in pmap_demote_pde(). Specifically, when pmap_demote_pde() allocates a page table page to implement a user-space demotion, it must increment the pmap's resident page count. Not doing so, can lead to an underflow during address space termination that causes pmap_remove() to exit prematurely, before it has destroyed all of the mappings within the specified range. The ultimate effect or symptom of this error is an assertion failure in vm_page_free_toq() because the page being freed is still mapped. This error is only possible when superpage promotion is enabled. Thus, it only affects FreeBSD versions greater than 7.2. Tested by: pho, alc Reviewed by: alc Approved by: re (rwatson) MFC after: 1 week --- sys/amd64/amd64/pmap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 622ed629b01..b9eee49c97c 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -2261,6 +2261,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); From e8c91ce393aebd8193382fe6291597a775e0852b Mon Sep 17 00:00:00 2001 From: John Hay Date: Mon, 17 Aug 2009 15:19:03 +0000 Subject: [PATCH 090/453] Fix parse() so that the partition to boot (load /boot/loader) from can be set. The syntax as printed in main() is used: 0:ad(0p3)/boot/loader Reviewed by: jhb Approved by: re (kib) --- sys/boot/i386/gptboot/gptboot.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) 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++; From 60f04e38ca9c098ededd601ee7e6b3023273bcdf Mon Sep 17 00:00:00 2001 From: Rick Macklem Date: Mon, 17 Aug 2009 16:12:28 +0000 Subject: [PATCH 092/453] Apply the same patch as r196205 for nfs_upgrade_lock() and nfs_downgrade_lock() to the experimental nfs client. Approved by: re (kensmith), kib (mentor) --- sys/fs/nfsclient/nfs_clsubs.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) 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); } } From 8530137252c7085a59184d3587c76170879930e9 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Mon, 17 Aug 2009 16:16:46 +0000 Subject: [PATCH 093/453] The start of the EFI GPT partition in the PMBR can always be represented by CHS addressing. Don't define these fields as 0xff, but rather define them correctly. This prevents boot problems on PCs where GPT is being used. PR: 115406 Submitted by: Kent Hauser Approved by: re (kib) --- sys/geom/part/g_part_gpt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 */ From 353998acc3ece9273dd2d4f686a783867f717bdf Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Mon, 17 Aug 2009 16:17:21 +0000 Subject: [PATCH 094/453] * Change the scope of the ASSERT_ATOMIC_LOAD() from a generic check to a pointer-fetching specific operation check. Consequently, rename the operation ASSERT_ATOMIC_LOAD_PTR(). * Fix the implementation of ASSERT_ATOMIC_LOAD_PTR() by checking directly alignment on the word boundry, for all the given specific architectures. That's a bit too strict for some common case, but it assures safety. * Add a comment explaining the scope of the macro * Add a new stub in the lockmgr specific implementation Tested by: marcel (initial version), marius Reviewed by: rwatson, jhb (comment specific review) Approved by: re (kib) --- sys/kern/kern_lock.c | 3 +++ sys/kern/kern_mutex.c | 5 +++-- sys/kern/kern_rwlock.c | 5 +++-- sys/kern/kern_sx.c | 5 +++-- sys/sys/systm.h | 13 ++++++++++--- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index 0affad5f19b..29ae4accfa7 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) diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index f625098f248..85ca646370d 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -783,8 +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(m->mtx_lock, ("%s: mtx_lock not aligned for %s: %p", - __func__, name, &m->mtx_lock)); + 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_rwlock.c b/sys/kern/kern_rwlock.c index e2342506a0e..be05b39de0a 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -174,8 +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(rw->rw_lock, ("%s: rw_lock not aligned for %s: %p", - __func__, name, &rw->rw_lock)); + 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_sx.c b/sys/kern/kern_sx.c index 15c1c9bdf16..4a78444c09c 100644 --- a/sys/kern/kern_sx.c +++ b/sys/kern/kern_sx.c @@ -205,8 +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(sx->sx_lock, ("%s: sx_lock not aligned for %s: %p", - __func__, description, &sx->sx_lock)); + 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) diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 2e8b9adb458..96222da9152 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -89,9 +89,16 @@ extern int maxusers; /* system tune hint */ #define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] #endif -#define ASSERT_ATOMIC_LOAD(var,msg) \ - KASSERT(sizeof(var) <= sizeof(uintptr_t) && \ - ALIGN(&(var)) == (uintptr_t)&(var), msg) +/* + * 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 From 6577b1593de7f9846584db67286bda9a626f78aa Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 17 Aug 2009 17:09:14 +0000 Subject: [PATCH 095/453] Document the newly added SVNCMDARGS, SVNROOT, and SVNBRANCH variables. Approved by: re (kib) --- share/man/man7/release.7 | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/share/man/man7/release.7 b/share/man/man7/release.7 index a026db51d3e..d2174c50671 100644 --- a/share/man/man7/release.7 +++ b/share/man/man7/release.7 @@ -390,6 +390,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 From d53e359b9ababb9e920a032c95f9a3fc30b4afe3 Mon Sep 17 00:00:00 2001 From: Kip Macy Date: Mon, 17 Aug 2009 19:09:28 +0000 Subject: [PATCH 096/453] fix netboot issue by disabling flowtable lookups until initialization has been run Reviewed by: rwatson@ Approved by: re@ --- sys/net/flowtable.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c index 4078ae9138e..efdde72a278 100644 --- a/sys/net/flowtable.c +++ b/sys/net/flowtable.c @@ -203,6 +203,7 @@ 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_hits VNET(flowtable_hits) @@ -217,6 +218,7 @@ 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, enable, CTLFLAG_RW, @@ -345,7 +347,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; @@ -799,6 +801,7 @@ flowtable_init(const void *unused __unused) 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, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, From 386d94e8227f1379cdf2bc3487381efb5c9db146 Mon Sep 17 00:00:00 2001 From: Edwin Groothuis Date: Mon, 17 Aug 2009 23:50:15 +0000 Subject: [PATCH 097/453] Vendor import of tzdata2009l: - Egypt will go to Wintertime on 21 August 2009 - Heads up for a possible DST in Samoa Obtained from: ftp://elsie.nci.nih.gov/pub/ --- africa | 23 +++++++++++++++++++++-- australasia | 18 +++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/africa b/africa index 6e268c94781..ad89bb743c1 100644 --- a/africa +++ b/africa @@ -1,5 +1,5 @@ #

    -# @(#)africa	8.22
    +# @(#)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
    diff --git a/australasia b/australasia
    index efcfec74d15..2fc370f8bbc 100644
    --- a/australasia
    +++ b/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
    
    From 33ea30fed7516e17d712d96e2d961331bfc94c9c Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Tue, 18 Aug 2009 08:46:54 +0000
    Subject: [PATCH 098/453] Fix iSCSI initiator and vpo driver operation, broken
     by CAM changes.
    
    Reviewed by:	scottl, Danny Braniss
    Approved by:	re (rwatson)
    ---
     sys/cam/cam_ccb.h                 | 1 +
     sys/cam/cam_xpt.c                 | 2 ++
     sys/dev/iscsi/initiator/isc_cam.c | 2 ++
     sys/dev/ppbus/vpo.c               | 2 ++
     4 files changed, 7 insertions(+)
    
    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..1c2f61430a6 100644
    --- a/sys/cam/cam_xpt.c
    +++ b/sys/cam/cam_xpt.c
    @@ -3803,6 +3803,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:
    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/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);
    
    From 5daa555d8d94ac00405f52c7b2bcb9d63d119e65 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Tue, 18 Aug 2009 09:27:17 +0000
    Subject: [PATCH 099/453] Fix copy/paste bug, that requests data read during
     ATA device probe sequence for ATA_SETFEATURES/ATA_SF_SETXFER command which by
     definition transfers no data. Most of controllers are irrelevant to this bug,
     but some nVidia's doesn't.
    
    Tested on:	current@
    Approved by:	re (kib)
    ---
     sys/cam/ata/ata_xpt.c | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c
    index 0116b5b7459..0be44fc2b77 100644
    --- a/sys/cam/ata/ata_xpt.c
    +++ b/sys/cam/ata/ata_xpt.c
    @@ -370,10 +370,10 @@ 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_max_mode(ident_buf, ATA_UDMA6, ATA_UDMA6));
    
    From 594ca9ba6861648b9f31ddf4d1a250bda666baa8 Mon Sep 17 00:00:00 2001
    From: Tom Rhodes 
    Date: Tue, 18 Aug 2009 12:24:27 +0000
    Subject: [PATCH 100/453] Document MAKE_DVD and xref svn in ports.
    
    Approved by:	re@ (kib)
    ---
     share/man/man7/release.7 | 9 +++++++--
     1 file changed, 7 insertions(+), 2 deletions(-)
    
    diff --git a/share/man/man7/release.7 b/share/man/man7/release.7
    index d2174c50671..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.
    @@ -503,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 ,
    @@ -540,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
    
    From e477e4fe8eefd7a033e1ce392555e2bb905fc803 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Tue, 18 Aug 2009 13:55:48 +0000
    Subject: [PATCH 101/453] Remove unused taskqueue_find() function.
    
    Reviewed by:	dfr
    Approved by:	re (kib)
    ---
     share/man/man9/taskqueue.9 | 12 ++---------
     sys/kern/subr_taskqueue.c  | 43 --------------------------------------
     sys/sys/taskqueue.h        |  2 --
     3 files changed, 2 insertions(+), 55 deletions(-)
    
    diff --git a/share/man/man9/taskqueue.9 b/share/man/man9/taskqueue.9
    index 553010b8042..5a6f9200dbe 100644
    --- a/share/man/man9/taskqueue.9
    +++ b/share/man/man9/taskqueue.9
    @@ -28,7 +28,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd August 17, 2009
    +.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
    @@ -115,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.
    diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c
    index bec3b566ea3..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)
     {
    diff --git a/sys/sys/taskqueue.h b/sys/sys/taskqueue.h
    index 244e3e20de2..bf2e4ee31d0 100644
    --- a/sys/sys/taskqueue.h
    +++ b/sys/sys/taskqueue.h
    @@ -48,7 +48,6 @@ struct thread;
      */
     typedef void (*taskqueue_enqueue_fn)(void *context);
     
    -struct proc;
     struct taskqueue *taskqueue_create(const char *name, int mflags,
     				    taskqueue_enqueue_fn enqueue,
     				    void *context);
    @@ -56,7 +55,6 @@ 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);
    
    From 627dfd6df9892815d6dc1144d53fd522e42f4bfa Mon Sep 17 00:00:00 2001
    From: Michael Tuexen 
    Date: Tue, 18 Aug 2009 19:58:49 +0000
    Subject: [PATCH 102/453] Fix a crash when using one-to-one stlye socket in
     non-blocking mode and there is no listening server. PR: 137795 Approved by:
     re, rrs (mentor) MFC after:immediately.
    
    ---
     sys/netinet/sctp_output.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
    index 5cde4d0dd69..1e768fc5bbe 100644
    --- a/sys/netinet/sctp_output.c
    +++ b/sys/netinet/sctp_output.c
    @@ -12464,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 */
    
    From 44d90753923ae031d3d2ea25d3c91500ca41a3f2 Mon Sep 17 00:00:00 2001
    From: Pyun YongHyeon 
    Date: Tue, 18 Aug 2009 20:20:15 +0000
    Subject: [PATCH 103/453] Backout r193289. r193289 restored page select bits to
     previous value instead of blindly resetting it to 0. However, it seems page
     select bits of some 88E1116 PHY is initialized to invalid one such that
     restoring page select bits after programming broke MII register access. The
     correct solution would be reset page select bits to 0 in PHY attach stage but
     it would require more testing. Since we're in BETA stage such a change would
     be dangerous so just back it out. This change should fix nfe(4) breakage on
     NVIDIA MCP55.
    
    Reported by:	Ryan Rogers < webmaster <> doghouserepair dot com >
    		Sam Fourman Jr. < sfourman <> gmail dot com >
    Tested by:	Ryan Rogers < webmaster <> doghouserepair dot com >
    		Sam Fourman Jr. < sfourman <> gmail dot com >
    Approved by:	re (kib)
    ---
     sys/dev/mii/e1000phy.c | 4 +---
     1 file changed, 1 insertion(+), 3 deletions(-)
    
    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);
     		}
     	}
     
    
    From 3ee42584f9bfcec0c0364a11bf3e916b219763e5 Mon Sep 17 00:00:00 2001
    From: Kip Macy 
    Date: Tue, 18 Aug 2009 20:28:58 +0000
    Subject: [PATCH 104/453]  - change the interface to flowtable_lookup so that
     we don't rely on    the mbuf for obtaining the fib index  - check that a
     cached flow corresponds to the same fib index as the    packet for which we
     are doing the lookup  - at interface detach time flush any flows referencing
     stale rtentrys    associated with the interface that is going away (fixes
     reported    panics)  - reduce the time between cleans in case the cleaner is
     running at    the time the eventhandler is called and the wakeup is missed
     less    time will elapse before the eventhandler returns  - separate per-vnet
     initialization from global initialization    (pointed out by jeli@)
    
    Reviewed by:	sam@
    Approved by:	re@
    ---
     sys/net/flowtable.c     | 235 +++++++++++++++++++++++++++++++++-------
     sys/net/flowtable.h     |   2 +-
     sys/netinet/ip_output.c |   2 +-
     3 files changed, 196 insertions(+), 43 deletions(-)
    
    diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
    index efdde72a278..e9747277978 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,
    @@ -288,10 +296,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
     
    @@ -425,7 +433,7 @@ static bitstr_t *
     flowtable_mask(struct flowtable *ft)
     {
     	bitstr_t *mask;
    -	
    +
     	if (ft->ft_flags & FL_PCPU)
     		mask = ft->ft_masks[curcpu];
     	else
    @@ -501,7 +509,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;
    @@ -564,6 +572,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);
    @@ -591,13 +600,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;
     
    @@ -640,6 +649,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++;
    @@ -668,10 +678,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 {
    @@ -692,7 +700,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) {
    @@ -791,35 +799,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);
    -	V_flowtable_ready = 1;
    -}
    -
    -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
    @@ -973,14 +952,32 @@ flowtable_cleaner(void)
     		}
     		VNET_LIST_RUNLOCK();
     
    +		flowclean_cycles++;
     		/*
     		 * The 20 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,
    @@ -988,3 +985,159 @@ 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);
    +}
    +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);
    +	V_flowtable_ready = 1;
    +}
    +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
    +
    +#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/netinet/ip_output.c b/sys/netinet/ip_output.c
    index 33ba8383043..2ce94b5c561 100644
    --- a/sys/netinet/ip_output.c
    +++ b/sys/netinet/ip_output.c
    @@ -157,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
     	}
    
    From 7f21e273a80d0b88207d7c253594707fb33fe429 Mon Sep 17 00:00:00 2001
    From: Stanislav Sedov 
    Date: Tue, 18 Aug 2009 21:07:39 +0000
    Subject: [PATCH 105/453] - Do not try to reevaluate current RX production
     index on each   loop iteration as it can be updated by the card while we  
     process the RX ring forcing us to process RX descriptors   for which DMA
     synchronisation operation has not been   performed.  This fixes the bug when
     bge(4) drops packets   under high load.
    
    Discussed with:	yongari, marius
    Approved by:	re (kib)
    MFC after:	1 week
    ---
     sys/dev/bge/if_bge.c | 15 ++++++++-------
     1 file changed, 8 insertions(+), 7 deletions(-)
    
    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);
    
    From b5a6cecbcd90eac1f2bfb17c4e92aa8faa7cdfbd Mon Sep 17 00:00:00 2001
    From: Max Laier 
    Date: Wed, 19 Aug 2009 00:10:10 +0000
    Subject: [PATCH 106/453] If we cannot immediately get the pf_consistency_lock
     in the purge thread, restart the scan after acquiring the lock the hard way. 
     Otherwise we might end up with a dead reference.
    
    Reported by:		pfsense
    Reviewed by:		eri
    Initial patch by:	eri
    Tested by:		pfsense
    Approved by:		re (kib)
    ---
     sys/contrib/pf/net/pf.c    | 89 ++++++++++++++++++++++++++++----------
     sys/contrib/pf/net/pfvar.h |  5 +++
     2 files changed, 70 insertions(+), 24 deletions(-)
    
    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/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 *,
    
    From bd578dcc97c0dcebc9f57c0ec242bcb9ba3d7a06 Mon Sep 17 00:00:00 2001
    From: Edwin Groothuis 
    Date: Wed, 19 Aug 2009 03:52:15 +0000
    Subject: [PATCH 107/453] - Make note of the update of tzdata from 2008h to
     2009j - Make note of the update of tzcode from 2004a to 2009h   Add an extra
     alert that people who update via source or via   freebsd-update will have to
     run the tzsetup(8) utility.
    
    Approved by:	re (Kostik)
    ---
     release/doc/en_US.ISO8859-1/relnotes/article.sgml | 14 ++++++++++++--
     1 file changed, 12 insertions(+), 2 deletions(-)
    
    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.
    
    From 2f99457b0c7a503003c1db5d9606c60969ad52a9 Mon Sep 17 00:00:00 2001
    From: Michael Tuexen 
    Date: Wed, 19 Aug 2009 12:02:28 +0000
    Subject: [PATCH 108/453] Fix a bug in the handling of unreliable messages
     which results in stalled associations.
    
    Approved by: re, rrs (mentor)
    MFC after: immediately
    ---
     sys/netinet/sctputil.c | 14 +++++++++-----
     1 file changed, 9 insertions(+), 5 deletions(-)
    
    diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
    index 53d84b794d3..c7bdfb54b5c 100644
    --- a/sys/netinet/sctputil.c
    +++ b/sys/netinet/sctputil.c
    @@ -4667,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--;
    @@ -4715,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;
     			}
    
    From 6c813c1ccc8651b84b4803be1a33714c99961d76 Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Wed, 19 Aug 2009 14:30:46 +0000
    Subject: [PATCH 109/453] Small changes to the warning message generated by
     pty(4):
    
    - Only print the warning once, instead of filling up the screen.
    - Use the word "legacy" for the pty_warningcnt description, to prevent
      confusion.
    - Use log() instead of printf().
    
    Discussed with:	rwatson, jhb
    Approved by:	re (kib)
    ---
     sys/kern/tty_pty.c | 7 ++++---
     1 file changed, 4 insertions(+), 3 deletions(-)
    
    diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
    index 3bb5b476523..169229d15ec 100644
    --- a/sys/kern/tty_pty.c
    +++ b/sys/kern/tty_pty.c
    @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     
    @@ -47,10 +48,10 @@ __FBSDID("$FreeBSD$");
      * si_drv1 inside the cdev to mark whether the PTY is in use.
      */
     
    -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 +75,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");
     	}
    
    From 35d01728c65d765dec0bdfc48eeaf255abf44371 Mon Sep 17 00:00:00 2001
    From: Rafal Jaworowski 
    Date: Wed, 19 Aug 2009 14:39:08 +0000
    Subject: [PATCH 110/453] Fix USB cache sync operations for platforms with
     non-coherent DMA.
    
    - usb_pc_cpu_invalidate() is called between [consecutive] reads from a device,
      so a sequence of BUS_DMASYNC_POSTREAD and _PREREAD should be used. Note we
      cannot use or'ed shorthand ( _POSTREAD | _PREREAD) for BUS_DMASYNC flags, as
      the low level bus dma sync operation is implementation dependent and we
      cannot assume the required order of operations to be guaranteed.
    
    - usb_pc_cpu_flush() is called before writing to a device, so
      BUS_DMASYNC_PREWRITE should be used.
    
    Submitted by:	Grzegorz Bernacki
    Reviewed by:	HPS, arm@, usb@ ML
    Tested by:	HPS, Mike Tancsa
    Approved by:	re (kib)
    Obtained from:	Semihalf
    ---
     sys/dev/usb/usb_busdma.c | 7 +++----
     1 file changed, 3 insertions(+), 4 deletions(-)
    
    diff --git a/sys/dev/usb/usb_busdma.c b/sys/dev/usb/usb_busdma.c
    index e5d6ed7951e..3769102c510 100644
    --- a/sys/dev/usb/usb_busdma.c
    +++ b/sys/dev/usb/usb_busdma.c
    @@ -679,8 +679,8 @@ 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);
    +	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_POSTREAD);
    +	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREREAD);
     }
     
     /*------------------------------------------------------------------------*
    @@ -693,8 +693,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);
     }
     
     /*------------------------------------------------------------------------*
    
    From fcaeaff4b6aad1829edba34184950a3b3a9a403d Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Wed, 19 Aug 2009 15:17:13 +0000
    Subject: [PATCH 111/453] Explicitly line up the CPU state labels with the
     calculated starting column that takes into account the width of the largest
     CPU ID.  On systems with > 10 CPUs the labels for the first 10 CPUs were not
     lined up properly otherwise.
    
    Approved by:	re (kib)
    MFC after:	1 week
    ---
     contrib/top/display.c | 2 ++
     1 file changed, 2 insertions(+)
    
    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')
    
    From eb0ea23e837bc3e3993a7f84efdb868cbb49f93a Mon Sep 17 00:00:00 2001
    From: Marcel Moolenaar 
    Date: Wed, 19 Aug 2009 16:29:20 +0000
    Subject: [PATCH 112/453] Remove the dependency on the kernel -- in particular
     the gctl request to the GEOM_BSD class -- to translate the absolute offsets
     in the label to relative ones. This makes bslabel(8) work correctly with
     GEOM_PART and also when the BSD label is nested under arbitrary partitioning
     schemes.
    
    Inspired by:	Eygene Ryabinkin 
    Approved by:	re (kib)
    ---
     sbin/bsdlabel/bsdlabel.c | 41 ++++++++++++++++++++++------------------
     1 file changed, 23 insertions(+), 18 deletions(-)
    
    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);
     }
     
    
    From 1886a6912db5d770309f29cc63601197c5d9522d Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Wed, 19 Aug 2009 17:59:41 +0000
    Subject: [PATCH 113/453] Temporarily enhance em(4) and igb(4) hack to take
     account for IFF_NOARP. Without this changeset there will be no way to prevent
     these NICs from sending ARP, which is harmful in server farms that is
     configured as "Direct Server Return" behind a load balancer.
    
    A better fix would remove the whole hack completely but it would be
    later than 8.0-RELEASE.
    
    Reviewed by:	jfv, yongari
    Approved by:	re (kib)
    ---
     sys/dev/e1000/if_em.c  | 3 ++-
     sys/dev/e1000/if_igb.c | 3 ++-
     2 files changed, 4 insertions(+), 2 deletions(-)
    
    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);
    
    From 6d37c3ecd96b66696840f2e62e80cdc264ee9614 Mon Sep 17 00:00:00 2001
    From: Kip Macy 
    Date: Wed, 19 Aug 2009 20:13:09 +0000
    Subject: [PATCH 114/453] This change fixes a comment and addresses a complaint
     by kib@ by moving a frequently executed flowtable syslog statement from being
     conditional on bootverbose to conditional on a per-vnet flowtable sysctl.
    
    Approved by:	re@
    ---
     sys/net/flowtable.c | 8 ++++++--
     1 file changed, 6 insertions(+), 2 deletions(-)
    
    diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
    index e9747277978..f6cd77839bc 100644
    --- a/sys/net/flowtable.c
    +++ b/sys/net/flowtable.c
    @@ -199,6 +199,7 @@ static uint32_t		flowclean_cycles;
      * - 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);
    @@ -214,6 +215,7 @@ 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)
    @@ -229,6 +231,8 @@ static VNET_DEFINE(int, flowtable_ready) = 0;
     #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,
    @@ -902,7 +906,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);
     }
     
    @@ -954,7 +958,7 @@ flowtable_cleaner(void)
     
     		flowclean_cycles++;
     		/*
    -		 * The 20 second interval between cleaning checks
    +		 * The 10 second interval between cleaning checks
     		 * is arbitrary
     		 */
     		mtx_lock(&flowclean_lock);
    
    From 12f27c4e646c4ec763938195296f475c1b569861 Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Wed, 19 Aug 2009 20:39:33 +0000
    Subject: [PATCH 115/453] Make the MacBookPro3,1 hardware boot again.
    
    Tested by:	Patrick Lamaiziere 
    Approved by:	re (kib)
    ---
     sys/amd64/amd64/machdep.c | 1 +
     sys/i386/i386/machdep.c   | 1 +
     2 files changed, 2 insertions(+)
    
    diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
    index 8aee97524f5..2c54be28fdf 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 "
    diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
    index 1b24af39ce2..cba1637746e 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 "
    
    From 23d827ef055170d3c43b4db46f9959f10a4217ed Mon Sep 17 00:00:00 2001
    From: "Simon L. B. Nielsen" 
    Date: Wed, 19 Aug 2009 20:47:31 +0000
    Subject: [PATCH 116/453] Add support for backing up the old kernel when
     installing a new kernel using freebsd-update.  This applies to using
     freebsd-update in "upgrade mode" and normal freebsd-update on a security
     branch.
    
    The backup kernel will be written to /boot/kernel.old, if the directory
    does not exist, or the directory was created by freebsd-update in a
    previous backup.  Otherwise freebsd-update will generate a new directory
    name for use by the backup.  By default symbol files are not backed up
    to save diskspace and avoid filling up the root partition.
    
    This feature is fully configurable in the freebsd-update config file,
    but defaults to enabled.
    
    MFC after:	1 week (stable/7)
    Reviewed by:	cperciva
    Approved by:	re (kib)
    ---
     etc/freebsd-update.conf                   |  11 ++
     share/man/man5/freebsd-update.conf.5      |  52 ++++++-
     usr.sbin/freebsd-update/freebsd-update.sh | 162 +++++++++++++++++++++-
     3 files changed, 222 insertions(+), 3 deletions(-)
    
    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/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/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
     
    
    From 35ae9291c2621d66ac66ed4a4996761946ac3e2d Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Thu, 20 Aug 2009 00:05:29 +0000
    Subject: [PATCH 117/453] Our libc doesn't implement control method for XDR
     (only kernel does) and it will always return failure. Fix this by bringing
     userland implementation of xdrmem_control() back. This allow 'zpool import'
     to work again.
    
    Reported by:	Thomas Backman 
    Reviewed by:	kmacy
    Approved by:	re (kib)
    ---
     sys/cddl/compat/opensolaris/rpc/xdr.h | 70 +++++++++++++++++++++++++++
     1 file changed, 70 insertions(+)
     create mode 100644 sys/cddl/compat/opensolaris/rpc/xdr.h
    
    diff --git a/sys/cddl/compat/opensolaris/rpc/xdr.h b/sys/cddl/compat/opensolaris/rpc/xdr.h
    new file mode 100644
    index 00000000000..277e0c338f0
    --- /dev/null
    +++ b/sys/cddl/compat/opensolaris/rpc/xdr.h
    @@ -0,0 +1,70 @@
    +/*
    + * 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.
    + *
    + * 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.
    + *
    + * 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.
    + *
    + * 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.
    + *
    + * 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.
    + *
    + * Sun Microsystems, Inc.
    + * 2550 Garcia Avenue
    + * Mountain View, California  94043
    + */
    +
    +#ifndef	_OPENSOLARIS_RPC_XDR_H_
    +#define	_OPENSOLARIS_RPC_XDR_H_
    +
    +#include_next 
    +
    +#ifndef _KERNEL
    +
    +#include 
    +
    +/*
    + * Taken from sys/xdr/xdr_mem.c.
    + *
    + * 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.
    + */
    +static __inline bool_t
    +xdrmem_control(XDR *xdrs, int request, void *info)
    +{
    +	xdr_bytesrec *xptr;
    +
    +	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);
    +	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_ */
    
    From 52e12426d18affcdae36089493f2b01ab704d216 Mon Sep 17 00:00:00 2001
    From: Will Andrews 
    Date: Thu, 20 Aug 2009 02:33:12 +0000
    Subject: [PATCH 118/453] Fix CARP memory leaks on carp_if's malloc'd using
     M_CARP.  This occurs when CARP tries to free them using M_IFADDR after the
     last address for a virtual host is removed and when detaching from the parent
     interface.
    
    Reviewed by:	mlaier
    Approved by:	re (kib), ken (mentor)
    ---
     sys/netinet/ip_carp.c | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    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);
     	}
    
    From 497e910cd321dbdc45c010417bb7079365234fcf Mon Sep 17 00:00:00 2001
    From: Andriy Gapon 
    Date: Thu, 20 Aug 2009 10:57:14 +0000
    Subject: [PATCH 119/453] fstat: fix fsid comparison when executed on systems
     with 64-bit long
    
    This affects only fstat on zfs and devfs, only on 64-bit systems
    and only when fsid is greater than 2^31 - 1.
    When fstat examines a file via stat(2) it takes uint32_t st_dev
    and assigns to (signed) (64-bit) long fsid, this results in
    a positive value.
    When fstat examines opened files it takes int32_t f_fsid.val[0]
    and assigns to (signed) (64-bit) long fsid, this results in
    a negative value.
    So, while initially st_dev and f_fsid.val[0] have the same bit
    values they get promoted to different 64-bit values because
    of the signed-vs-unsigned difference.
    
    A fix is to use "more natural" positive numbers by introducing
    intermediate unsigned cast for f_fsid.val[0].
    
    Reviewed by:	jhb, lulf
    Approved by:	re (kib)
    MFC after:	1 week (to stable/7)
    ---
     usr.bin/fstat/fstat.c | 2 +-
     usr.bin/fstat/zfs.c   | 2 +-
     2 files changed, 2 insertions(+), 2 deletions(-)
    
    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
    
    From a56fe095f0d5fb20fc70b784acb0cd2d367d3e79 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Thu, 20 Aug 2009 19:17:53 +0000
    Subject: [PATCH 120/453] Temporarily revert the new-bus locking for 8.0
     release.  It will be reintroduced after HEAD is reopened for commits by re@.
    
    Approved by:	re (kib), attilio
    ---
     sys/dev/aac/aac.c                       |  8 +--
     sys/dev/acpica/acpi.c                   | 14 +++-
     sys/dev/acpica/acpi_battery.c           | 15 -----
     sys/dev/acpica/acpi_cpu.c               |  2 -
     sys/dev/acpica/acpi_dock.c              |  8 +--
     sys/dev/acpica/acpi_thermal.c           |  3 -
     sys/dev/adb/adb_bus.c                   |  2 -
     sys/dev/amdtemp/amdtemp.c               |  2 -
     sys/dev/amr/amr.c                       | 23 +------
     sys/dev/ata/ata-all.c                   | 34 +++++-----
     sys/dev/atkbdc/psm.c                    |  4 --
     sys/dev/bktr/bktr_os.c                  | 11 +---
     sys/dev/drm/drm_drv.c                   |  8 ---
     sys/dev/ips/ips_pci.c                   |  2 -
     sys/dev/mfi/mfi.c                       | 20 ++----
     sys/dev/mlx/mlx.c                       |  2 -
     sys/dev/mmc/mmc.c                       |  2 -
     sys/dev/pccbb/pccbb.c                   | 11 +++-
     sys/dev/pst/pst-iop.c                   |  2 -
     sys/dev/rp/rp.c                         |  4 --
     sys/dev/sound/pci/hda/hdac.c            |  2 -
     sys/dev/twe/twe.c                       |  6 --
     sys/dev/usb/controller/usb_controller.c | 30 ++++++---
     sys/dev/usb/input/ukbd.c                | 13 ++--
     sys/dev/usb/net/usb_ethernet.c          | 11 ++--
     sys/dev/usb/usb_compat_linux.c          | 27 ++++++--
     sys/dev/usb/usb_dev.c                   |  6 --
     sys/dev/usb/usb_handle_request.c        | 12 ++--
     sys/dev/usb/usb_hub.c                   | 19 ++----
     sys/dev/usb/wlan/if_upgt.c              |  4 +-
     sys/dev/xen/blkback/blkback.c           |  4 +-
     sys/dev/xen/netback/netback.c           |  4 +-
     sys/i386/acpica/acpi_machdep.c          |  6 --
     sys/i386/bios/smapi.c                   |  2 -
     sys/i386/bios/smbios.c                  |  2 -
     sys/i386/bios/vpd.c                     |  2 -
     sys/kern/subr_bus.c                     | 87 ++-----------------------
     sys/pc98/cbus/fdc.c                     |  6 --
     sys/sys/bus.h                           |  8 ---
     sys/xen/xenbus/xenbus_probe.c           |  4 --
     40 files changed, 130 insertions(+), 302 deletions(-)
    
    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..63f95d3eb2c 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);
     
    @@ -2528,7 +2534,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 +2611,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/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/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/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/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/drm/drm_drv.c b/sys/dev/drm/drm_drv.c
    index e12f8cdfa92..561afd5e8fb 100644
    --- a/sys/dev/drm/drm_drv.c
    +++ b/sys/dev/drm/drm_drv.c
    @@ -614,13 +614,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 +632,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 +708,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/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/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/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/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/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/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/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
    index bf99d54ea1f..9f4264d98ec 100644
    --- a/sys/dev/sound/pci/hda/hdac.c
    +++ b/sys/dev/sound/pci/hda/hdac.c
    @@ -7435,7 +7435,6 @@ hdac_attach2(void *arg)
     		    quirks_on, quirks_off);
     	);
     
    -	newbus_xlock();
     	hdac_lock(sc);
     
     	/* Remove ourselves from the config hooks */
    @@ -7675,7 +7674,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/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/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
    index f6776f01a4c..7a019dcaa7a 100644
    --- a/sys/dev/usb/controller/usb_controller.c
    +++ b/sys/dev/usb/controller/usb_controller.c
    @@ -143,7 +143,9 @@ usb_attach(device_t dev)
     	}
     
     	if (usb_post_init_called) {
    +		mtx_lock(&Giant);
     		usb_attach_sub(dev, bus);
    +		mtx_unlock(&Giant);
     		usb_needs_explore(bus, 1);
     	}
     	return (0);			/* return success */
    @@ -226,13 +228,20 @@ usb_bus_explore(struct usb_proc_msg *pm)
     		}
     		USB_BUS_UNLOCK(bus);
     
    +		mtx_lock(&Giant);
    +
     		/*
     		 * First update the USB power state!
     		 */
     		usb_bus_powerd(bus);
    -
    -		 /* Explore the Root USB HUB. */
    +		/*
    +		 * Explore the Root USB HUB. This call can sleep,
    +		 * exiting Giant, which is actually Giant.
    +		 */
     		(udev->hub->explore) (udev);
    +
    +		mtx_unlock(&Giant);
    +
     		USB_BUS_LOCK(bus);
     	}
     	if (bus->bus_roothold != NULL) {
    @@ -260,7 +269,7 @@ usb_bus_detach(struct usb_proc_msg *pm)
     	device_set_softc(dev, NULL);
     	USB_BUS_UNLOCK(bus);
     
    -	newbus_xlock();
    +	mtx_lock(&Giant);
     
     	/* detach children first */
     	bus_generic_detach(dev);
    @@ -272,7 +281,7 @@ usb_bus_detach(struct usb_proc_msg *pm)
     	usb_free_device(udev,
     	    USB_UNCFG_FLAG_FREE_EP0);
     
    -	newbus_xunlock();
    +	mtx_unlock(&Giant);
     	USB_BUS_LOCK(bus);
     	/* clear bdev variable last */
     	bus->bdev = NULL;
    @@ -341,7 +350,7 @@ usb_bus_attach(struct usb_proc_msg *pm)
     	}
     
     	USB_BUS_UNLOCK(bus);
    -	newbus_xlock();
    +	mtx_lock(&Giant);		/* XXX not required by USB */
     
     	/* default power_mask value */
     	bus->hw_power_state =
    @@ -374,7 +383,7 @@ usb_bus_attach(struct usb_proc_msg *pm)
     		err = USB_ERR_NOMEM;
     	}
     
    -	newbus_xunlock();
    +	mtx_unlock(&Giant);
     	USB_BUS_LOCK(bus);
     
     	if (err) {
    @@ -463,7 +472,7 @@ usb_post_init(void *arg)
     	int max;
     	int n;
     
    -	newbus_xlock();
    +	mtx_lock(&Giant);
     
     	usb_devclass_ptr = devclass_find("usbus");
     
    @@ -474,8 +483,11 @@ usb_post_init(void *arg)
     			dev = devclass_get_device(dc, n);
     			if (dev && device_is_attached(dev)) {
     				bus = device_get_ivars(dev);
    -				if (bus)
    +				if (bus) {
    +					mtx_lock(&Giant);
     					usb_attach_sub(dev, bus);
    +					mtx_unlock(&Giant);
    +				}
     			}
     		}
     	} else {
    @@ -487,7 +499,7 @@ usb_post_init(void *arg)
     
     	usb_needs_explore_all();
     
    -	newbus_xunlock();
    +	mtx_unlock(&Giant);
     }
     
     SYSINIT(usb_post_init, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, usb_post_init, NULL);
    diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
    index 2170b370016..0d09ad43783 100644
    --- a/sys/dev/usb/input/ukbd.c
    +++ b/sys/dev/usb/input/ukbd.c
    @@ -745,7 +745,7 @@ ukbd_attach(device_t dev)
     	uint16_t n;
     	uint16_t hid_len;
     
    -	mtx_lock(&Giant);
    +	mtx_assert(&Giant, MA_OWNED);
     
     	kbd_init_struct(kbd, UKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0);
     
    @@ -854,6 +854,9 @@ ukbd_attach(device_t dev)
     	if (bootverbose) {
     		genkbd_diag(kbd, bootverbose);
     	}
    +	/* lock keyboard mutex */
    +
    +	mtx_lock(&Giant);
     
     	/* start the keyboard */
     
    @@ -876,7 +879,7 @@ ukbd_detach(device_t dev)
     	struct ukbd_softc *sc = device_get_softc(dev);
     	int error;
     
    -	mtx_lock(&Giant);
    +	mtx_assert(&Giant, MA_OWNED);
     
     	DPRINTF("\n");
     
    @@ -913,8 +916,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 +927,9 @@ ukbd_resume(device_t dev)
     {
     	struct ukbd_softc *sc = device_get_softc(dev);
     
    -	mtx_lock(&Giant);
    +	mtx_assert(&Giant, MA_OWNED);
    +
     	ukbd_clear_state(&sc->sc_kbd);
    -	mtx_unlock(&Giant);
     
     	return (0);
     }
    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/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..cba8919255c 100644
    --- a/sys/dev/usb/usb_dev.c
    +++ b/sys/dev/usb/usb_dev.c
    @@ -1040,14 +1040,9 @@ 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();
     		return (ENXIO);
     	}
     	fflags = cpd->fflags;
    @@ -1081,7 +1076,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_handle_request.c b/sys/dev/usb/usb_handle_request.c
    index 2bc3eefd210..a720919b7d8 100644
    --- a/sys/dev/usb/usb_handle_request.c
    +++ b/sys/dev/usb/usb_handle_request.c
    @@ -152,7 +152,7 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
     	 * attach:
     	 */
     	USB_XFER_UNLOCK(xfer);
    -	newbus_xlock();
    +	mtx_lock(&Giant);		/* XXX */
     	sx_xlock(udev->default_sx + 1);
     
     	if (conf_no == USB_UNCONFIG_NO) {
    @@ -176,8 +176,8 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
     		goto done;
     	}
     done:
    +	mtx_unlock(&Giant);		/* XXX */
     	sx_unlock(udev->default_sx + 1);
    -	newbus_xunlock();
     	USB_XFER_LOCK(xfer);
     	return (err);
     }
    @@ -236,7 +236,7 @@ usb_handle_iface_request(struct usb_xfer *xfer,
     	 * attach:
     	 */
     	USB_XFER_UNLOCK(xfer);
    -	newbus_xlock();
    +	mtx_lock(&Giant);		/* XXX */
     	sx_xlock(udev->default_sx + 1);
     
     	error = ENXIO;
    @@ -353,20 +353,20 @@ tr_repeat:
     		goto tr_stalled;
     	}
     tr_valid:
    +	mtx_unlock(&Giant);
     	sx_unlock(udev->default_sx + 1);
    -	newbus_xunlock();
     	USB_XFER_LOCK(xfer);
     	return (0);
     
     tr_short:
    +	mtx_unlock(&Giant);
     	sx_unlock(udev->default_sx + 1);
    -	newbus_xunlock();
     	USB_XFER_LOCK(xfer);
     	return (USB_ERR_SHORT_XFER);
     
     tr_stalled:
    +	mtx_unlock(&Giant);
     	sx_unlock(udev->default_sx + 1);
    -	newbus_xunlock();
     	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..0defc97c30c 100644
    --- a/sys/dev/usb/usb_hub.c
    +++ b/sys/dev/usb/usb_hub.c
    @@ -234,10 +234,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 +318,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 +428,9 @@ 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) {
    @@ -987,6 +980,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 +992,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 +1006,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 +1037,7 @@ uhub_child_pnpinfo_string(device_t parent, device_t child,
     		goto done;
     	}
     done:
    +	mtx_unlock(&Giant);
     
     	return (0);
     }
    @@ -1778,13 +1775,10 @@ 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);
    -
     	/* notify all sub-devices about resume */
     	err = usb_suspend_resume(udev, 0);
     	sx_unlock(udev->default_sx + 1);
    -	newbus_xunlock();
     
     	/* check if peer has wakeup capability */
     	if (usb_peer_can_wakeup(udev)) {
    @@ -1850,13 +1844,10 @@ repeat:
     		}
     	}
     
    -	newbus_xlock();
     	sx_xlock(udev->default_sx + 1);
    -
     	/* notify all sub-devices about suspend */
     	err = usb_suspend_resume(udev, 1);
     	sx_unlock(udev->default_sx + 1);
    -	newbus_xunlock();
     
     	if (usb_peer_can_wakeup(udev)) {
     		/* allow device to do remote wakeup */
    diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c
    index 8714645450e..ff3220b716f 100644
    --- a/sys/dev/usb/wlan/if_upgt.c
    +++ b/sys/dev/usb/wlan/if_upgt.c
    @@ -465,7 +465,7 @@ upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
     
     	switch (cmd) {
     	case SIOCSIFFLAGS:
    -		newbus_xlock();
    +		mtx_lock(&Giant);
     		if (ifp->if_flags & IFF_UP) {
     			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
     				if ((ifp->if_flags ^ sc->sc_if_flags) &
    @@ -482,7 +482,7 @@ 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();
    +		mtx_unlock(&Giant);
     		break;
     	case SIOCGIFMEDIA:
     		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
    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/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/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/kern/subr_bus.c b/sys/kern/subr_bus.c
    index 52cd766296c..2964b8c1a22 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
      */
    @@ -413,6 +364,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,
    @@ -1109,7 +1061,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 +1759,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 +1857,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 +2508,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 +2542,7 @@ device_probe_and_attach(device_t dev)
     {
     	int error;
     
    -	NBL_ASSERT(SA_XLOCKED);
    +	GIANT_REQUIRED;
     
     	error = device_probe(dev);
     	if (error == -1)
    @@ -2626,8 +2576,6 @@ device_attach(device_t dev)
     {
     	int error;
     
    -	NBL_ASSERT(SA_XLOCKED);
    -
     	device_sysctl_init(dev);
     	if (!device_is_quiet(dev))
     		device_print_child(dev->parent, dev);
    @@ -2669,7 +2617,7 @@ device_detach(device_t dev)
     {
     	int error;
     
    -	NBL_ASSERT(SA_XLOCKED);
    +	GIANT_REQUIRED;
     
     	PDEBUG(("%s", DEVICENAME(dev)));
     	if (dev->state == DS_BUSY)
    @@ -2713,8 +2661,6 @@ int
     device_quiesce(device_t dev)
     {
     
    -	NBL_ASSERT(SA_XLOCKED);
    -
     	PDEBUG(("%s", DEVICENAME(dev)));
     	if (dev->state == DS_BUSY)
     		return (EBUSY);
    @@ -2735,7 +2681,6 @@ device_quiesce(device_t dev)
     int
     device_shutdown(device_t dev)
     {
    -
     	if (dev->state < DS_ATTACHED)
     		return (0);
     	return (DEVICE_SHUTDOWN(dev));
    @@ -3151,8 +3096,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 +3116,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 +3996,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 +4055,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) {
     	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 +4115,6 @@ driver_module_handler(module_t mod, int what, void *arg)
     		error = EOPNOTSUPP;
     		break;
     	}
    -	NBL_XUNLOCK();
     
     	return (error);
     }
    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/sys/bus.h b/sys/sys/bus.h
    index 7ed06f4fed9..2362041dad2 100644
    --- a/sys/sys/bus.h
    +++ b/sys/sys/bus.h
    @@ -478,14 +478,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/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);
    
    From 0cef25aeb2d96e3a54c439a1f9b550ceaea4f792 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Thu, 20 Aug 2009 19:23:58 +0000
    Subject: [PATCH 121/453] Change the 'resid' parameter to sglist_consume_uio()
     from an int to a size_t to match the recent type change of the uio_resid
     member of struct uio.
    
    Approved by:	re (kib)
    ---
     share/man/man9/sglist.9 | 2 +-
     sys/kern/subr_sglist.c  | 2 +-
     sys/sys/sglist.h        | 2 +-
     3 files changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/share/man/man9/sglist.9 b/share/man/man9/sglist.9
    index 8c1c046ad76..a265498148f 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
    diff --git a/sys/kern/subr_sglist.c b/sys/kern/subr_sglist.c
    index 7f551d99cd8..474f6767294 100644
    --- a/sys/kern/subr_sglist.c
    +++ b/sys/kern/subr_sglist.c
    @@ -315,7 +315,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;
    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);
    
    From ad3764ac1d2b50252e23678101213e60fa7bb5f5 Mon Sep 17 00:00:00 2001
    From: Marko Zec 
    Date: Thu, 20 Aug 2009 22:39:20 +0000
    Subject: [PATCH 122/453] vimage(8) is a legacy CLI interface for managing
     jails associated with network stack instances, which is provided for
     compatibility with older applications.  This change brings it back to life in
     a followup to the initial conversion of vimage to use the new jail(4)
     userland-kernel API:
    
    - when creating vimages via "vimage -c", by default turn on a few
    options expected by legacy applications, such as allow operations on
    raw sockets, FS mounts etc, and allow jail-related parameters to be
    optionally configured.
    
    - introduce the "-m" modifier which allows for configuring jail
    parameters of existing vimages / vnet-jails.
    
    - make "vimage name command ..." actually work.
    
    - when reassigning ifnets to vnets using "vimage -i", attempt to rename
    the ifnet as "ethXXX" on arrival in the target vnet.  Several legacy
    applications are known to depend heavily on such behavior.
    
    - vimage -l lists only jails associated with vnets.  The output is
    sorted using vimage / jail names as keys.
    
    - vimage -l by default searches only the current level in the jail
    hierarchy.  Recursive listing can be requested via -r switch.
    
    - vimage -l by default prints only jail names on each line, making
    such output suitable for pipelining to other commands.  More verbose
    output can be obtained via -v switch, and even more jail specific
    information will be displayed if -j switch is turned on.
    
    - there's no need to build vimage as statically linked, so update the
    Makefile accordingly.
    
    - update the vimage.8 man page.
    
    Approved by:	re (rwatson), julian (mentor)
    MFC after:	immediately
    ---
     tools/tools/vimage/Makefile |   1 -
     tools/tools/vimage/vimage.8 | 155 +++++++------
     tools/tools/vimage/vimage.c | 420 ++++++++++++++++++++++++++----------
     3 files changed, 400 insertions(+), 176 deletions(-)
    
    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..b54f9d6224c 100644
    --- a/tools/tools/vimage/vimage.c
    +++ b/tools/tools/vimage/vimage.c
    @@ -28,142 +28,294 @@
      */
     
     #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 ((jid = 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 (jid < 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 +324,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);
     }
    
    From b4e7e7a06598ca94ab6c1f687335a11d1792653d Mon Sep 17 00:00:00 2001
    From: Peter Wemm 
    Date: Thu, 20 Aug 2009 22:53:28 +0000
    Subject: [PATCH 123/453] Fix signed comparison bug when ticks goes negative
     after 24 days of uptime.  This causes the tcp time_wait state code to fail to
     expire sockets in timewait state.
    
    Approved by:	re (kensmith)
    ---
     sys/netinet/tcp_timewait.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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);
    
    From 66406b8f2522d479b5b53e1af6e466775f37a4b4 Mon Sep 17 00:00:00 2001
    From: Jung-uk Kim 
    Date: Thu, 20 Aug 2009 22:58:05 +0000
    Subject: [PATCH 124/453] Check whether the SMBIOS reports reasonable amount of
     memory.  If it is less than "avail memory", fall back to Maxmem to avoid user
     confusion. We use SMBIOS information to display "real memory" since r190599
     but some broken SMBIOS implementation reported only half of actual memory.
    
    Tested by:	bz
    Approved by:	re (kib)
    ---
     sys/amd64/amd64/machdep.c | 22 ++++++++++++----------
     sys/i386/i386/machdep.c   | 22 ++++++++++++----------
     2 files changed, 24 insertions(+), 20 deletions(-)
    
    diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
    index 2c54be28fdf..0bfd7ada653 100644
    --- a/sys/amd64/amd64/machdep.c
    +++ b/sys/amd64/amd64/machdep.c
    @@ -236,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/i386/i386/machdep.c b/sys/i386/i386/machdep.c
    index cba1637746e..9c1ea0b143b 100644
    --- a/sys/i386/i386/machdep.c
    +++ b/sys/i386/i386/machdep.c
    @@ -280,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.
     	 */
    
    From eb4d96a26846b601a31164d8e8f88bcd9658fdfb Mon Sep 17 00:00:00 2001
    From: Ken Smith 
    Date: Fri, 21 Aug 2009 01:00:15 +0000
    Subject: [PATCH 125/453] Fix a boot hang for hptrr(4) caused by changes
     introduced in r195534. It is necessary to make sure cpi->transport is set for
     xpt_scan_bus() to work properly.
    
    Submitted by: Bernhard Schmidt (scb+freebsd-current  techwires
                   net)
    Reviewed by:  scottl
    Approved by:  re (kib)
    ---
     sys/dev/hptrr/hptrr_osm_bsd.c | 4 ++++
     1 file changed, 4 insertions(+)
    
    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;
     	}
    
    From eb5a1e8f38a4cf29a77ac42812356460d5e8cf78 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Fri, 21 Aug 2009 02:59:07 +0000
    Subject: [PATCH 126/453] This patch fixes two bugs in sglist(9) and improves
     robustness of the API via better semantics if a request to append an address
     range to an existing list fails. - When cloning an sglist, properly set the
     length in the new sglist instead of   leaving the new list empty. - Properly
     compute the amount of data added to an sglist via   _sglist_append_buf(). 
     This allows sglist_consume_uio() to properly update   uio_resid. - When a
     request to append an address range to a scatter/gather list fails,   restore
     the sglist to the state it had at the start of the function call   instead of
     resetting it to an empty list.
    
    Requested by:	np (3)
    Approved by:	re (kib)
    ---
     share/man/man9/sglist.9 |  4 ++
     sys/kern/subr_sglist.c  | 90 +++++++++++++++++++++++++++++++++--------
     2 files changed, 78 insertions(+), 16 deletions(-)
    
    diff --git a/share/man/man9/sglist.9 b/share/man/man9/sglist.9
    index a265498148f..e43a04b4d04 100644
    --- a/share/man/man9/sglist.9
    +++ b/share/man/man9/sglist.9
    @@ -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/sys/kern/subr_sglist.c b/sys/kern/subr_sglist.c
    index 474f6767294..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;
     		}
     	}
    @@ -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);
    
    From cd81cd3fd1f57ef36b84e59181b1a29fb77b7936 Mon Sep 17 00:00:00 2001
    From: Julian Elischer 
    Date: Fri, 21 Aug 2009 09:22:32 +0000
    Subject: [PATCH 127/453] Don't allow access to the internals until it has all
     been set up. Specifically, not until the per-vnet parts have been set up.
    
    Submitted by:	kmacy@
    Reviewed by:	julian@, zec@
    Approved by:	re(rwatson)
    MFC after:	immediately
    ---
     sys/net/flowtable.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
    index f6cd77839bc..98127edd5b2 100644
    --- a/sys/net/flowtable.c
    +++ b/sys/net/flowtable.c
    @@ -999,6 +999,7 @@ flowtable_init_vnet(const void *unused __unused)
     	    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);
    @@ -1011,7 +1012,6 @@ flowtable_init(const void *unused __unused)
     	mtx_init(&flowclean_lock, "flowclean lock", NULL, MTX_DEF);
     	EVENTHANDLER_REGISTER(ifnet_departure_event, flowtable_flush, NULL,
     	    EVENTHANDLER_PRI_ANY);
    -	V_flowtable_ready = 1;
     }
     SYSINIT(flowtable_init, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
         flowtable_init, NULL);
    @@ -1022,6 +1022,7 @@ static void
     flowtable_uninit(const void *unused __unused)
     {
     
    +	V_flowtable_ready = 0;
     	uma_zdestroy(V_flow_ipv4_zone);
     	uma_zdestroy(V_flow_ipv6_zone);
     }
    
    From 2b978628436aae61e9bce492dc375e0e47a2152e Mon Sep 17 00:00:00 2001
    From: Marko Zec 
    Date: Fri, 21 Aug 2009 11:13:56 +0000
    Subject: [PATCH 128/453] Bugfix: all requests for creating vnets via vimage -c
     were always reported as failures, even if the actual library / system call
     would succeed, because error message would be reported if the return value
     from jail_setv() call was >= 0, and if not, then if that same value was < 0,
     i.e. always.  The correct behavior is to abort (only) if jail_setv() returns
     < 0.
    
    Approved by:	re (rwatson), julian (mentor)
    ---
     tools/tools/vimage/vimage.c | 6 ++----
     1 file changed, 2 insertions(+), 4 deletions(-)
    
    diff --git a/tools/tools/vimage/vimage.c b/tools/tools/vimage/vimage.c
    index b54f9d6224c..e6655999c50 100644
    --- a/tools/tools/vimage/vimage.c
    +++ b/tools/tools/vimage/vimage.c
    @@ -252,7 +252,7 @@ main(int argc, char **argv)
     		exit(0);
     
     	case VI_CREATE:
    -		if ((jid = jail_setv(JAIL_CREATE,
    +		if (jail_setv(JAIL_CREATE,
     		    "name", argv[0],
     		    "vnet", NULL,
     		    "host", NULL,
    @@ -260,9 +260,7 @@ main(int argc, char **argv)
     		    "allow.raw_sockets", "true",
     		    "allow.socket_af", "true",
     		    "allow.mount", "true",
    -		    NULL)) >= 0)
    -				break;
    -		if (jid < 0)
    +		    NULL) < 0)
     			break;
     		if (argc == 1)
     			exit(0);
    
    From c4b21cbe4a686587f01e66490bb9a658a5d4c5cf Mon Sep 17 00:00:00 2001
    From: Julian Elischer 
    Date: Fri, 21 Aug 2009 11:20:10 +0000
    Subject: [PATCH 129/453] Fix ipfw's initialization functions to get the
     correct order of evaluation to allow vnet and non vnet operation. Move some
     functions from ip_fw_pfil.c to ip_fw2.c and mode to mostly using the SYSINIT
     and VNET_SYSINIT handlers instead of the modevent handler. Correct some
     spelling errors in comments in the affected code. Note this bug fixes a crash
     in NON VIMAGE kernels when ipfw is unloaded.
    
    This patch is a minimal patch for 8.0
    I have a much larger patch that actually fixes the underlying problems
    that will be applied after 8.0
    
    Reviewed by:	zec@, rwatson@, bz@(earlier version)
    Approved by:	re (rwatson)
    MFC after:	Immediatly
    ---
     sys/netinet/ip_fw.h           |   6 +-
     sys/netinet/ipfw/ip_fw2.c     | 126 +++++++++++++++++++++++++++++-----
     sys/netinet/ipfw/ip_fw_pfil.c |  60 +++-------------
     3 files changed, 123 insertions(+), 69 deletions(-)
    
    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/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
    index 31065daa308..a17a64792e8 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
    @@ -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,6 +4637,20 @@ 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).
    @@ -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);
    
    From cf48cc9f696a2da600ee5fd422bb0b6a8d21ebba Mon Sep 17 00:00:00 2001
    From: Ken Smith 
    Date: Sat, 22 Aug 2009 23:44:37 +0000
    Subject: [PATCH 130/453] Make head 9.0-CURRENT in preparation for lifting code
     freeze.
    
    Approved by:	re (implicit)
    ---
     UPDATING                          | 4 ++--
     gnu/usr.bin/groff/tmac/mdoc.local | 3 ++-
     release/Makefile                  | 8 ++++----
     sys/conf/newvers.sh               | 4 ++--
     sys/sys/param.h                   | 2 +-
     usr.sbin/pkg_install/add/main.c   | 4 +++-
     6 files changed, 14 insertions(+), 11 deletions(-)
    
    diff --git a/UPDATING b/UPDATING
    index 8c31a898e50..893744a2652 100644
    --- a/UPDATING
    +++ b/UPDATING
    @@ -8,8 +8,8 @@ Items affecting the ports and packages system can be found in
     /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
    +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
    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/release/Makefile b/release/Makefile
    index fd3cb929d3c..26038c4c58f 100644
    --- a/release/Makefile
    +++ b/release/Makefile
    @@ -24,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
    @@ -72,7 +72,7 @@ BUILDNAME?=${BASE}-${DATE}-SNAP
     #
     # Subversion branch to build for src.  If this is not set then it is
     # automatically computed from RELEASETAG.
    -#SVNBRANCH=stable/7
    +#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
    diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
    index f56d20ebbf4..d88ce381d63 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
    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/usr.sbin/pkg_install/add/main.c b/usr.sbin/pkg_install/add/main.c
    index b2d511ebc7b..461c36752f2 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" },
    +	{ 800000, 899000, "/packages-8-stable" },
    +	{ 900000, 999000, "/packages-9-current" },
     	{ 0, 9999999, "/packages-current" },
     	{ 0, 0, NULL }
     };
    
    From c61ff194899e032b2cb041f86e6e7f20af015fcc Mon Sep 17 00:00:00 2001
    From: Doug Barton 
    Date: Sun, 23 Aug 2009 05:42:50 +0000
    Subject: [PATCH 131/453] Add a script to create the /var/db/mergemaster.mtree
     file for new releases so that when users subsequently update their source
     trees they can make use of mergemaster's -U option.
    
    ---
     release/scripts/mm-mtree.sh | 155 ++++++++++++++++++++++++++++++++++++
     1 file changed, 155 insertions(+)
     create mode 100755 release/scripts/mm-mtree.sh
    
    diff --git a/release/scripts/mm-mtree.sh b/release/scripts/mm-mtree.sh
    new file mode 100755
    index 00000000000..d132a34a0e7
    --- /dev/null
    +++ b/release/scripts/mm-mtree.sh
    @@ -0,0 +1,155 @@
    +#!/bin/sh
    +
    +# mergemaster mtree database generator
    +
    +# This script is intended to be used as part of the release building
    +# process to generate the /var/db/mergemaster.mtree file relevant to
    +# the source tree used to create the release so that users can make
    +# use of mergemaster's -U option to update their files after csup'ing
    +# to -stable.
    +
    +# Copyright 2009 Douglas Barton
    +# dougb@FreeBSD.org
    +
    +# $FreeBSD$
    +
    +PATH=/bin:/usr/bin:/usr/sbin
    +
    +display_usage () {
    +  VERSION_NUMBER=`grep "[$]FreeBSD:" $0 | cut -d ' ' -f 4`
    +  echo "${0##*/} version ${VERSION_NUMBER}"
    +  echo "Usage: ${0##*/} [-m /path] [-t /path] [-A arch] [-F ] [-D /path]"
    +  echo "Options:"
    +  echo "  -m /path/directory  Specify location of source to do the make in"
    +  echo "  -t /path/directory  Specify temp root directory"
    +  echo "  -A architecture  Alternative architecture name to pass to make"
    +  echo "  -F  Specify what to put on the make command line"
    +  echo '  -D /path/directory  Specify the destination directory to install files to'
    +  echo ''
    +}
    +
    +# Set the default path for the temporary root environment
    +#
    +TEMPROOT='/var/tmp/temproot'
    +
    +# Assign the location of the mtree database
    +#
    +MTREEDB=${MTREEDB:-/var/db}
    +MTREEFILE="${MTREEDB}/mergemaster.mtree"
    +
    +# Check the command line options
    +#
    +while getopts "m:t:A:F:D:h" COMMAND_LINE_ARGUMENT ; do
    +  case "${COMMAND_LINE_ARGUMENT}" in
    +  m)
    +    SOURCEDIR=${OPTARG}
    +    ;;
    +  t)
    +    TEMPROOT=${OPTARG}
    +    ;;
    +  A)
    +    ARCHSTRING='TARGET_ARCH='${OPTARG}
    +    ;;
    +  F)
    +    MM_MAKE_ARGS="${OPTARG}"
    +    ;;
    +  D)
    +    DESTDIR=${OPTARG}
    +    ;;
    +  h)
    +    display_usage
    +    exit 0
    +    ;;
    +  *)
    +    echo ''
    +    display_usage
    +    exit 1
    +    ;;
    +  esac
    +done
    +
    +# Assign the source directory
    +#
    +SOURCEDIR=${SOURCEDIR:-/usr/src}
    +if [ ! -f ${SOURCEDIR}/Makefile.inc1 -a \
    +   -f ${SOURCEDIR}/../Makefile.inc1 ]; then
    +  echo " *** The source directory you specified (${SOURCEDIR})"
    +  echo "     will be reset to ${SOURCEDIR}/.."
    +  echo ''
    +  sleep 3
    +  SOURCEDIR=${SOURCEDIR}/..
    +fi
    +
    +# Setup make to use system files from SOURCEDIR
    +MM_MAKE="make ${ARCHSTRING} ${MM_MAKE_ARGS} -m ${SOURCEDIR}/share/mk"
    +
    +delete_temproot () {
    +  rm -rf "${TEMPROOT}" 2>/dev/null
    +  chflags -R 0 "${TEMPROOT}" 2>/dev/null
    +  rm -rf "${TEMPROOT}" || exit 1
    +}
    +
    +[ -d "${TEMPROOT}" ] && delete_temproot
    +
    +echo "*** Creating the temporary root environment in ${TEMPROOT}"
    +
    +if mkdir -p "${TEMPROOT}"; then
    +  echo " *** ${TEMPROOT} ready for use"
    +fi
    +
    +if [ ! -d "${TEMPROOT}" ]; then
    +  echo ''
    +  echo "  *** FATAL ERROR: Cannot create ${TEMPROOT}"
    +  echo ''
    +  exit 1
    +fi
    +
    +echo " *** Creating and populating directory structure in ${TEMPROOT}"
    +echo ''
    +
    +{ cd ${SOURCEDIR} || { echo "*** Cannot cd to ${SOURCEDIR}" ; exit 1;}
    +  case "${DESTDIR}" in
    +  '') ;;
    +  *)
    +    ${MM_MAKE} DESTDIR=${DESTDIR} distrib-dirs
    +    ;;
    +  esac
    +  od=${TEMPROOT}/usr/obj
    +  ${MM_MAKE} DESTDIR=${TEMPROOT} distrib-dirs &&
    +  MAKEOBJDIRPREFIX=$od ${MM_MAKE} _obj SUBDIR_OVERRIDE=etc &&
    +  MAKEOBJDIRPREFIX=$od ${MM_MAKE} everything SUBDIR_OVERRIDE=etc &&
    +  MAKEOBJDIRPREFIX=$od ${MM_MAKE} DESTDIR=${TEMPROOT} distribution;} ||
    +  { echo '';
    +    echo "  *** FATAL ERROR: Cannot 'cd' to ${SOURCEDIR} and install files to";
    +    echo "      the temproot environment";
    +    echo '';
    +    exit 1;}
    +
    +# We really don't want to have to deal with files like login.conf.db, pwd.db,
    +# or spwd.db.  Instead, we want to compare the text versions, and run *_mkdb.
    +# Prompt the user to do so below, as needed.
    +#
    +rm -f ${TEMPROOT}/etc/*.db ${TEMPROOT}/etc/passwd
    +
    +# We only need to compare things like freebsd.cf once
    +find ${TEMPROOT}/usr/obj -type f -delete 2>/dev/null
    +
    +# Delete stuff we do not need to keep the mtree database small,
    +# and to make the actual comparison faster.
    +find ${TEMPROOT}/usr -type l -delete 2>/dev/null
    +find ${TEMPROOT} -type f -size 0 -delete 2>/dev/null
    +find -d ${TEMPROOT} -type d -empty -delete 2>/dev/null
    +
    +# Build the mtree database in a temporary location.
    +MTREENEW=`mktemp -t mergemaster.mtree`
    +mtree -ci -p ${TEMPROOT} -k size,md5digest > ${MTREENEW} 2>/dev/null
    +
    +if [ -s "${MTREENEW}" ]; then
    +  echo "*** Saving mtree database for future upgrades"
    +  test -e "${DESTDIR}${MTREEFILE}" && unlink ${DESTDIR}${MTREEFILE}
    +  mv ${MTREENEW} ${DESTDIR}${MTREEFILE}
    +fi
    +
    +delete_temproot
    +
    +exit 0
    
    From d05203a19f5484746d625c9a1c0c6d9e0dab8158 Mon Sep 17 00:00:00 2001
    From: Doug Barton 
    Date: Sun, 23 Aug 2009 05:45:38 +0000
    Subject: [PATCH 132/453] The svnversion string is only relevant when
     newvers.sh is called during the kernel build process, the other places that
     call the script do not make use of that information. So restrict execution of
     the svnversion-related code to the kernel build context.
    
    ---
     sys/conf/newvers.sh | 36 ++++++++++++++++--------------------
     1 file changed, 16 insertions(+), 20 deletions(-)
    
    diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
    index d88ce381d63..49e99fd3d6f 100644
    --- a/sys/conf/newvers.sh
    +++ b/sys/conf/newvers.sh
    @@ -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
    
    From 86567e4164cbc4f4a5e647e1221722657e549132 Mon Sep 17 00:00:00 2001
    From: Doug Barton 
    Date: Sun, 23 Aug 2009 05:47:19 +0000
    Subject: [PATCH 133/453] Move is_wired_interface() from rc.d/wpa_supplicant
     into network.subr, simplify it a bit, and make use of that method to
     determine if an interface is a candidate for IPv6 rtsol rather than listing
     all of the possible wireless interfaces that should _not_ get rtsol'ed.
    
    This change is only relevant for 8.0+ unless the "wlan mandatory" code
    gets ported back to RELENG_7.
    ---
     etc/network.subr        | 22 +++++++++++++++++++---
     etc/rc.d/wpa_supplicant | 12 ------------
     2 files changed, 19 insertions(+), 15 deletions(-)
    
    diff --git a/etc/network.subr b/etc/network.subr
    index 22bfc7dc8b9..c14985473e9 100644
    --- a/etc/network.subr
    +++ b/etc/network.subr
    @@ -816,6 +816,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 +869,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_available=yes ;;
    +			*)	rtsol_available=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/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
    
    From f20a61ffe6cb9633ff53ee16d8a0d682abeb338a Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 05:47:33 +0000
    Subject: [PATCH 134/453] Fix typos.
    
    Reported by:	Harald Servat 
    ---
     lib/libpmc/pmc.3       | 2 +-
     lib/libpmc/pmc.atom.3  | 4 ++--
     lib/libpmc/pmc.core2.3 | 2 +-
     3 files changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/lib/libpmc/pmc.3 b/lib/libpmc/pmc.3
    index af96fc09caf..e1ebde0ddaa 100644
    --- a/lib/libpmc/pmc.3
    +++ b/lib/libpmc/pmc.3
    @@ -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
    diff --git a/lib/libpmc/pmc.atom.3 b/lib/libpmc/pmc.atom.3
    index 934d22201f1..f39102286f6 100644
    --- a/lib/libpmc/pmc.atom.3
    +++ b/lib/libpmc/pmc.atom.3
    @@ -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
    @@ -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.
    diff --git a/lib/libpmc/pmc.core2.3 b/lib/libpmc/pmc.core2.3
    index 6d86c304276..5c1f56fa13f 100644
    --- a/lib/libpmc/pmc.core2.3
    +++ b/lib/libpmc/pmc.core2.3
    @@ -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
    
    From b53a052da82dd0c8d2a0ad5ee9807c4ab88f7b44 Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 05:49:12 +0000
    Subject: [PATCH 135/453] Fix a typo.
    
    Reported by:	John McCullough 
    ---
     lib/libpmc/pmc.3 | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lib/libpmc/pmc.3 b/lib/libpmc/pmc.3
    index e1ebde0ddaa..2a1ce52c6ac 100644
    --- a/lib/libpmc/pmc.3
    +++ b/lib/libpmc/pmc.3
    @@ -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
    
    From 3198bdba61e97bf16761dd2efe9b10581493d29a Mon Sep 17 00:00:00 2001
    From: Doug Barton 
    Date: Sun, 23 Aug 2009 05:56:54 +0000
    Subject: [PATCH 136/453] Fix the typo mentioned in the PR, and one additional.
     Fix caps while I'm here.
    
    PR:		conf/138087
    Submitted by:	Chris Petrik 
    ---
     etc/rc.d/ipsec | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    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
    
    From 5dcb8c704e9952afa16c6cd8537704ce2047b31d Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 06:19:02 +0000
    Subject: [PATCH 137/453] Correct grammar.
    
    ---
     lib/libpmc/pmc.3 | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/lib/libpmc/pmc.3 b/lib/libpmc/pmc.3
    index 2a1ce52c6ac..1307c011fd9 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.
    @@ -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 until, but
     excluding, the value returned by function
     .Fn pmc_ncpu .
     On platforms supporting sparsely numbered CPUs not all the numbers in
    
    From abb0a58ed9eb00f51f804a7102d8de1fafbd2272 Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 06:22:31 +0000
    Subject: [PATCH 138/453] Correct typos.
    
    ---
     lib/libpmc/pmc_read.3 | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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
    
    From a3579a8757c724d3af38f1e0f17a0d0f0a1f2fed Mon Sep 17 00:00:00 2001
    From: Ken Smith 
    Date: Sun, 23 Aug 2009 06:30:14 +0000
    Subject: [PATCH 139/453] Update name of INDEX file as part of 8.0 -> 9.0
     transition.
    
    ---
     etc/defaults/periodic.conf | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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
    
    From 7dfdb5c88254a863e3a87ce8b0d311c5dc879509 Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 07:24:39 +0000
    Subject: [PATCH 140/453] Fix typos.
    
    ---
     lib/libpmc/pmc.core2.3 | 18 +++++++++---------
     1 file changed, 9 insertions(+), 9 deletions(-)
    
    diff --git a/lib/libpmc/pmc.core2.3 b/lib/libpmc/pmc.core2.3
    index 5c1f56fa13f..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
    @@ -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
    
    From a2cd12e7a0c0bde2fd4e2510c29a6d9b68779367 Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 07:29:34 +0000
    Subject: [PATCH 141/453] Fix typos, use American English spellings.
    
    ---
     lib/libpmc/pmc.k7.3 |  4 ++--
     lib/libpmc/pmc.k8.3 |  4 ++--
     lib/libpmc/pmc.p4.3 | 30 +++++++++++++++---------------
     lib/libpmc/pmc.p6.3 |  6 +++---
     4 files changed, 22 insertions(+), 22 deletions(-)
    
    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.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
    
    From 445f22cfe7d56ca1eedbb22489e97f18ec47d9fe Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 07:30:12 +0000
    Subject: [PATCH 142/453] Fix a typo.
    
    ---
     lib/libpmc/pmc_capabilities.3 | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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
    
    From cbd3e3c8adb69782bbe971b7e5c781932993017e Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 07:31:10 +0000
    Subject: [PATCH 143/453] Fix typos.
    
    ---
     lib/libpmc/pmc.p5.3 | 14 +++++++-------
     1 file changed, 7 insertions(+), 7 deletions(-)
    
    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
    
    From ef582158680b23678fe3acd5d4473324677a1bc4 Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 07:32:30 +0000
    Subject: [PATCH 144/453] Use US spellings, fix typos.
    
    ---
     lib/libpmc/pmc.atom.3 | 16 ++++++++--------
     lib/libpmc/pmc.core.3 | 18 +++++++++---------
     lib/libpmc/pmc.iaf.3  |  2 +-
     3 files changed, 18 insertions(+), 18 deletions(-)
    
    diff --git a/lib/libpmc/pmc.atom.3 b/lib/libpmc/pmc.atom.3
    index f39102286f6..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
    @@ -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
    @@ -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.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:
    
    From 58cf5c84e0571eca794fc57018b93ff9a09379ab Mon Sep 17 00:00:00 2001
    From: Julian Elischer 
    Date: Sun, 23 Aug 2009 07:48:11 +0000
    Subject: [PATCH 145/453] Add claraifications to the kproc and kthread manpages
     and link the kthread_create(9) man page to the kproc(9) page as it had
     migrated and people looking for it may need a hand to find its new name.
    
    MFC after:	1 week
    ---
     share/man/man9/Makefile  |  1 +
     share/man/man9/kproc.9   | 22 ++++++++++++++++++++++
     share/man/man9/kthread.9 | 21 +++++++++++++++++++++
     3 files changed, 44 insertions(+)
    
    diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
    index 3148d5eed1c..86b5838c112 100644
    --- a/share/man/man9/Makefile
    +++ b/share/man/man9/Makefile
    @@ -713,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/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
    
    From 8f26c03fe64c21c8e35ebcb8eff474a0c4b29312 Mon Sep 17 00:00:00 2001
    From: Julian Elischer 
    Date: Sun, 23 Aug 2009 07:59:28 +0000
    Subject: [PATCH 146/453] Fix typo in comment that has been bugging me for
     days.
    
    MFC after:	1 week
    ---
     sys/netinet/ipfw/ip_fw2.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
    index a17a64792e8..d9ffc675289 100644
    --- a/sys/netinet/ipfw/ip_fw2.c
    +++ b/sys/netinet/ipfw/ip_fw2.c
    @@ -4653,7 +4653,7 @@ ipfw_init(void)
     #endif
     	/*
     	 * Other things that are only done the first time.
    -	 * (now that we a re cuaranteed of success).
    +	 * (now that we a re guaranteed of success).
     	 */
     	ip_fw_ctl_ptr = ipfw_ctl;
     	ip_fw_chk_ptr = ipfw_chk;
    
    From 5c67885a2660e6403402851f912dd01331cb45d4 Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Sun, 23 Aug 2009 08:04:40 +0000
    Subject: [PATCH 147/453] Add ttydisc_rint_simple().
    
    I noticed several drivers in our tree don't actually care about parity
    and framing, such as pts(4), snp(4) (and my partially finished console
    driver). Instead of duplicating a lot of code, I think we'd better add a
    utility function for those drivers to quickly process a buffer of input.
    
    Also change pts(4) and snp(4) to use this function.
    ---
     sys/dev/snp/snp.c      | 11 +++--------
     sys/kern/tty_pts.c     | 25 ++++++-------------------
     sys/kern/tty_ttydisc.c | 16 ++++++++++++++++
     sys/sys/ttydisc.h      |  1 +
     4 files changed, 26 insertions(+), 27 deletions(-)
    
    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/kern/tty_pts.c b/sys/kern/tty_pts.c
    index d5045c17b4d..c77cf2a1d82 100644
    --- a/sys/kern/tty_pts.c
    +++ b/sys/kern/tty_pts.c
    @@ -215,25 +215,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. */
    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/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);
    
    From d3cef1d91e71ecb542b1933ea731329468e84d5d Mon Sep 17 00:00:00 2001
    From: Julian Elischer 
    Date: Sun, 23 Aug 2009 08:49:32 +0000
    Subject: [PATCH 148/453] Fix another typo right next to the previous one, that
     amazingly, I did not see before.
    
    MFC after:	 1 week
    ---
     sys/netinet/ipfw/ip_fw2.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
    index d9ffc675289..e35669dc3a2 100644
    --- a/sys/netinet/ipfw/ip_fw2.c
    +++ b/sys/netinet/ipfw/ip_fw2.c
    @@ -4653,7 +4653,7 @@ ipfw_init(void)
     #endif
     	/*
     	 * Other things that are only done the first time.
    -	 * (now that we a re guaranteed of success).
    +	 * (now that we are guaranteed of success).
     	 */
     	ip_fw_ctl_ptr = ipfw_ctl;
     	ip_fw_chk_ptr = ipfw_chk;
    
    From 88579aa572d7472e2a7199cc7466438f69e73244 Mon Sep 17 00:00:00 2001
    From: Rui Paulo 
    Date: Sun, 23 Aug 2009 09:55:06 +0000
    Subject: [PATCH 149/453] Constify prime numbers.
    
    ---
     sys/kern/kern_subr.c | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    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]))
     
     /*
    
    From 3471c35ded56ab98da54291b8c99a79853879f6f Mon Sep 17 00:00:00 2001
    From: Rui Paulo 
    Date: Sun, 23 Aug 2009 09:58:06 +0000
    Subject: [PATCH 150/453] Make dev.asmc.N.light.control writable by everyone.
    
    Submitted by:	Patrick Lamaiziere 
    MFC after:	1 week
    ---
     sys/dev/asmc/asmc.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    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");
     	}
    
    From 1869987e4273cf9ded59dbedb6e7099386c05a5d Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 23 Aug 2009 11:22:46 +0000
    Subject: [PATCH 151/453] - Give minclsyspri and maxclsyspri real values
     (consulted with kmacy). - Honour 'pri' argument for thread_create().
    
    ---
     sys/cddl/compat/opensolaris/sys/mutex.h |  2 +-
     sys/cddl/compat/opensolaris/sys/proc.h  | 18 +++++++++++++++---
     2 files changed, 16 insertions(+), 4 deletions(-)
    
    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..dfacebc45e2 100644
    --- a/sys/cddl/compat/opensolaris/sys/proc.h
    +++ b/sys/cddl/compat/opensolaris/sys/proc.h
    @@ -34,13 +34,16 @@
     #include_next 
     #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
     
    @@ -58,6 +61,7 @@ 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)
     {
    +	kthread_t *td;
     	proc_t *p;
     	int error;
     
    @@ -70,7 +74,15 @@ thread_create(caddr_t stk, size_t stksize, void (*proc)(void *), void *arg,
     
     	error = kproc_create(proc, arg, &p, 0, stksize / PAGE_SIZE,
     	    "solthread %p", proc);
    -	return (error == 0 ? FIRST_THREAD_IN_PROC(p) : NULL);
    +	if (error != 0)
    +		td = NULL;
    +	else {
    +		td = FIRST_THREAD_IN_PROC(p);
    +		thread_lock(td);
    +		sched_prio(td, pri);
    +		thread_unlock(td);
    +	}
    +	return (td);
     }
     
     #define	thread_exit()	kproc_exit(0)
    
    From 4ec2b0e7ced7855a21f6cc05d7f40bde52bfee8c Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 23 Aug 2009 11:27:08 +0000
    Subject: [PATCH 152/453] Set priority of vdev_geom threads and zvol threads to
     PRIBIO.
    
    ---
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c | 4 ++++
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c      | 4 ++++
     2 files changed, 8 insertions(+)
    
    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..2e7904c37f1 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);
    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..8cb5125a8c9 100644
    --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
    +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
    @@ -402,6 +402,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);
    
    From 5d5535163a1ceb0ba12a3bc3623e6312836ba8b1 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 23 Aug 2009 11:33:46 +0000
    Subject: [PATCH 153/453] - Hide ZFS kernel threads under zfskern process. -
     Use better (shorter) threads names: 	'zvol:worker zvol/tank/vol00' -> 'zvol
     tank/vol00' 	'vdev:worker da0' -> 'vdev da0'
    
    ---
     sys/cddl/compat/opensolaris/sys/proc.h          | 17 ++++++++---------
     .../opensolaris/uts/common/fs/zfs/vdev_geom.c   |  6 +++---
     .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c   |  1 +
     .../opensolaris/uts/common/fs/zfs/zvol.c        |  5 +++--
     .../contrib/opensolaris/uts/common/sys/callb.h  |  2 --
     5 files changed, 15 insertions(+), 16 deletions(-)
    
    diff --git a/sys/cddl/compat/opensolaris/sys/proc.h b/sys/cddl/compat/opensolaris/sys/proc.h
    index dfacebc45e2..52ef867d49e 100644
    --- a/sys/cddl/compat/opensolaris/sys/proc.h
    +++ b/sys/cddl/compat/opensolaris/sys/proc.h
    @@ -57,12 +57,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)
     {
    -	kthread_t *td;
    -	proc_t *p;
    +	kthread_t *td = NULL;
     	int error;
     
     	/*
    @@ -71,13 +72,11 @@ 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);
    -	if (error != 0)
    -		td = NULL;
    -	else {
    -		td = FIRST_THREAD_IN_PROC(p);
    +	error = kproc_kthread_add(proc, arg, &zfsproc, &td, 0,
    +	    stksize / PAGE_SIZE, "zfskern", "solthread %p", proc);
    +	if (error == 0) {
     		thread_lock(td);
     		sched_prio(td, pri);
     		thread_unlock(td);
    @@ -85,7 +84,7 @@ thread_create(caddr_t stk, size_t stksize, void (*proc)(void *), void *arg,
     	return (td);
     }
     
    -#define	thread_exit()	kproc_exit(0)
    +#define	thread_exit()	kthread_exit()
     
     #endif	/* _KERNEL */
     
    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 2e7904c37f1..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
    @@ -207,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);
    @@ -534,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_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
    index ded407e37f7..69b126ed7f5 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
    @@ -3057,6 +3057,7 @@ zfsdev_fini(void)
     }
     
     static struct root_hold_token *zfs_root_token;
    +struct proc *zfsproc;
     
     uint_t zfs_fsyncer_key;
     extern uint_t rrw_tsd_key;
    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 8cb5125a8c9..a43cfdcab00 100644
    --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
    +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
    @@ -415,7 +415,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);
    @@ -828,7 +828,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:
    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),		\
    
    From 69eb6d71d0c17236b77a4a3e2eff4078edf2b25e Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Sun, 23 Aug 2009 12:23:24 +0000
    Subject: [PATCH 154/453] Add support for diffs generated by Perforce.
    
    It basically picks the filenames from the "====" line and strips off the
    # revision number.
    ---
     gnu/usr.bin/patch/pch.c | 24 ++++++++++++++++++++++++
     1 file changed, 24 insertions(+)
    
    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 &&
    
    From f2159cc7908d09fcb3e11c23a28760dc96ccfe8e Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Sun, 23 Aug 2009 12:44:15 +0000
    Subject: [PATCH 155/453] Fix the conformance of poll(2) for sockets after
     r195423 by returning POLLHUP instead of POLLIN for several cases. Now, the
     tools/regression/poll results for FreeBSD are closer to that of the Solaris
     and Linux.
    
    Also, improve the POSIX conformance by explicitely clearing POLLOUT
    when POLLHUP is reported in pollscan(), making the fix global.
    
    Submitted by:	bde
    Reviewed by:	rwatson
    MFC after:	1 week
    ---
     sys/kern/sys_generic.c |  7 +++++++
     sys/kern/uipc_socket.c | 12 +++++-------
     2 files changed, 12 insertions(+), 7 deletions(-)
    
    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/uipc_socket.c b/sys/kern/uipc_socket.c
    index 2f4dd92736a..c60b8d1abce 100644
    --- a/sys/kern/uipc_socket.c
    +++ b/sys/kern/uipc_socket.c
    @@ -2898,13 +2898,11 @@ sopoll_generic(struct socket *so, int events, struct ucred *active_cred,
     		if (so->so_oobmark || (so->so_rcv.sb_state & SBS_RCVATMARK))
     			revents |= events & (POLLPRI | POLLRDBAND);
     
    -	if ((events & POLLINIGNEOF) == 0) {
    -		if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
    -			revents |= events & (POLLIN | POLLRDNORM);
    -			if (so->so_snd.sb_state & SBS_CANTSENDMORE)
    -				revents |= POLLHUP;
    -		}
    -	}
    +	if ((events & POLLINIGNEOF) == 0)
    +		if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
    +			revents |= POLLHUP;
    +	if (so->so_snd.sb_state & SBS_CANTSENDMORE)
    +		revents |= POLLHUP;
     
     	if (revents == 0) {
     		if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
    
    From b7421a6928c470446c8bd74218149745b1c1db16 Mon Sep 17 00:00:00 2001
    From: "Simon L. B. Nielsen" 
    Date: Sun, 23 Aug 2009 13:58:25 +0000
    Subject: [PATCH 156/453] Import DTLS fix from upstream OpenSSL 0.9.8 branch:
    
    Fix memory consumption bug with "future epoch" DTLS records.
    
    Note that this will not get FreeBSD Security Advisory as DTLS is
    experimental in OpenSSL.
    
    Security:	CVE-2009-1377
    Obtained from:	OpenSSL CVS
    		http://cvs.openssl.org/chngview?cn=18187
    ---
     crypto/pqueue/pqueue.c | 14 ++++++++++++++
     crypto/pqueue/pqueue.h |  1 +
     ssl/d1_pkt.c           |  4 ++++
     3 files changed, 19 insertions(+)
    
    diff --git a/crypto/pqueue/pqueue.c b/crypto/pqueue/pqueue.c
    index 5cc18527f8d..6c89f06fb10 100644
    --- a/crypto/pqueue/pqueue.c
    +++ b/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/pqueue/pqueue.h b/crypto/pqueue/pqueue.h
    index 02386d130e9..16c4072681c 100644
    --- a/crypto/pqueue/pqueue.h
    +++ b/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/ssl/d1_pkt.c b/ssl/d1_pkt.c
    index eb56cf987ba..4ae9be54ae6 100644
    --- a/ssl/d1_pkt.c
    +++ b/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)
    
    From f8f8fb827d260bb6161b82bb67de04c0a4c9868c Mon Sep 17 00:00:00 2001
    From: "Simon L. B. Nielsen" 
    Date: Sun, 23 Aug 2009 14:12:01 +0000
    Subject: [PATCH 157/453] Import DTLS fix from upstream OpenSSL 0.9.8 branch:
    
    Fix fragment handling memory leak.
    
    Note that this will not get FreeBSD Security Advisory as DTLS is
    experimental in OpenSSL.
    
    Security:	CVE-2009-1378
    Obtained from:	OpenSSL CVS
    		http://cvs.openssl.org/filediff?f=openssl/ssl/d1_both.c&v1=1.4.2.13&v2=1.4.2.15
    ---
     ssl/d1_both.c | 11 ++++++++++-
     1 file changed, 10 insertions(+), 1 deletion(-)
    
    diff --git a/ssl/d1_both.c b/ssl/d1_both.c
    index 15a201a25cf..0c863179bc8 100644
    --- a/ssl/d1_both.c
    +++ b/ssl/d1_both.c
    @@ -561,7 +561,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];
     
    
    From 58c74b7534a4526075de41fd4b24bc769866523a Mon Sep 17 00:00:00 2001
    From: "Simon L. B. Nielsen" 
    Date: Sun, 23 Aug 2009 14:15:28 +0000
    Subject: [PATCH 158/453] Import DTLS fix from upstream OpenSSL 0.9.8 branch:
    
    Do not access freed data structure.
    
    Note that this will not get FreeBSD Security Advisory as DTLS is
    experimental in OpenSSL.
    
    Security:	CVE-2009-1379
    Obtained from:	OpenSSL CVS
    		http://cvs.openssl.org/chngview?cn=18156
    ---
     ssl/d1_both.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/ssl/d1_both.c b/ssl/d1_both.c
    index 0c863179bc8..967d8c542dd 100644
    --- a/ssl/d1_both.c
    +++ b/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);
    
    From f21c255c2a937db7c430d949ac1bc0aa398bd822 Mon Sep 17 00:00:00 2001
    From: Robert Noland 
    Date: Sun, 23 Aug 2009 14:27:46 +0000
    Subject: [PATCH 159/453] Clean up the locking in drm_alloc_resource()
    
    MFC after:	2 weeks
    ---
     sys/dev/drm/drm_bufs.c | 22 +++++++++++++++-------
     1 file changed, 15 insertions(+), 7 deletions(-)
    
    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;
     }
     
    
    From 2418baa339922b3f79007c2f66e2fb614e15dfe0 Mon Sep 17 00:00:00 2001
    From: Robert Noland 
    Date: Sun, 23 Aug 2009 14:31:20 +0000
    Subject: [PATCH 160/453] Clean up the handling of device minors
    
    Submitted by:	Ed
    MFC after:	2 weeks
    ---
     sys/dev/drm/drmP.h       | 1 -
     sys/dev/drm/drm_drv.c    | 8 +++-----
     sys/dev/drm/drm_fops.c   | 4 +---
     sys/dev/drm/drm_sysctl.c | 7 ++++---
     4 files changed, 8 insertions(+), 12 deletions(-)
    
    diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h
    index e630f861d57..9c5f4a470c6 100644
    --- a/sys/dev/drm/drmP.h
    +++ b/sys/dev/drm/drmP.h
    @@ -416,7 +416,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_drv.c b/sys/dev/drm/drm_drv.c
    index 561afd5e8fb..1fb8342d567 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);
    @@ -210,11 +207,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 +604,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);
     
    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_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,
    
    From fe173b46fd865ac240e9b4a9b86b7fe1fe5264d8 Mon Sep 17 00:00:00 2001
    From: Robert Noland 
    Date: Sun, 23 Aug 2009 14:33:12 +0000
    Subject: [PATCH 161/453] Add a read only sysctl tracking the hw.drm.msi
     tunable.
    
    MFC after:	2 weeks
    ---
     sys/dev/drm/drmP.h    | 2 ++
     sys/dev/drm/drm_drv.c | 3 +++
     2 files changed, 5 insertions(+)
    
    diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h
    index 9c5f4a470c6..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 */
    diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c
    index 1fb8342d567..c690c34dfa3 100644
    --- a/sys/dev/drm/drm_drv.c
    +++ b/sys/dev/drm/drm_drv.c
    @@ -133,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	*/ \
    
    From f0c2a617dfb432d01bc5a716eb18dae12e6b45e3 Mon Sep 17 00:00:00 2001
    From: "Simon L. B. Nielsen" 
    Date: Sun, 23 Aug 2009 14:39:15 +0000
    Subject: [PATCH 162/453] Import DTLS fix from upstream OpenSSL 0.9.8 branch:
    
    Fix DTLS fragment bug - out-of-sequence message handling which could
    result in NULL pointer dereference in
    dtls1_process_out_of_seq_message().
    
    Note that this will not get FreeBSD Security Advisory as DTLS is
    experimental in OpenSSL.
    
    Security:	CVE-2009-1387
    Obtained from:	OpenSSL CVS
    		http://cvs.openssl.org/chngview?cn=17958
    ---
     ssl/d1_both.c | 33 +++++++++++++++++----------------
     1 file changed, 17 insertions(+), 16 deletions(-)
    
    diff --git a/ssl/d1_both.c b/ssl/d1_both.c
    index 967d8c542dd..01771921061 100644
    --- a/ssl/d1_both.c
    +++ b/ssl/d1_both.c
    @@ -585,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:
    
    From dd1259dafb74ce9bd3ffe2aee9136f0a2348355d Mon Sep 17 00:00:00 2001
    From: Joseph Koshy 
    Date: Sun, 23 Aug 2009 14:48:25 +0000
    Subject: [PATCH 163/453] Use a more appropriate choice of words.
    
    Submitted by:	danfe
    ---
     lib/libpmc/pmc.3 | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lib/libpmc/pmc.3 b/lib/libpmc/pmc.3
    index 1307c011fd9..f48fe7985e9 100644
    --- a/lib/libpmc/pmc.3
    +++ b/lib/libpmc/pmc.3
    @@ -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 until, 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
    
    From f588a0bda542052e2bac3a8dc550968846b5331b Mon Sep 17 00:00:00 2001
    From: Robert Noland 
    Date: Sun, 23 Aug 2009 14:55:57 +0000
    Subject: [PATCH 164/453] Add kernel support for Radeon R6/7xx 3D.
    
    You will still need Mesa from git and possibly an updated DDX driver,
    but this is working fairly well now.
    
    MFC after:	2 weeks
    ---
     sys/conf/files                  |    2 +
     sys/dev/drm/r600_blit.c         | 1986 +++++++++++++++++++++++++++++++
     sys/dev/drm/r600_cp.c           |  135 +++
     sys/dev/drm/radeon_cp.c         |    8 +-
     sys/dev/drm/radeon_cs.c         |  856 +++++++++++++
     sys/dev/drm/radeon_drm.h        |   22 +
     sys/dev/drm/radeon_drv.h        |  114 +-
     sys/dev/drm/radeon_state.c      |   23 +-
     sys/modules/drm/radeon/Makefile |    4 +-
     9 files changed, 3129 insertions(+), 21 deletions(-)
     create mode 100644 sys/dev/drm/r600_blit.c
     create mode 100644 sys/dev/drm/radeon_cs.c
    
    diff --git a/sys/conf/files b/sys/conf/files
    index 0769151a1c5..69997985027 100644
    --- a/sys/conf/files
    +++ b/sys/conf/files
    @@ -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
    diff --git a/sys/dev/drm/r600_blit.c b/sys/dev/drm/r600_blit.c
    new file mode 100644
    index 00000000000..4848579675f
    --- /dev/null
    +++ b/sys/dev/drm/r600_blit.c
    @@ -0,0 +1,1986 @@
    +/*-
    + * Copyright 2009 Advanced Micro Devices, Inc.
    + *
    + * Permission is hereby granted, free of charge, to any person obtaining a
    + * copy of this software and associated documentation files (the "Software"),
    + * to deal in the Software without restriction, including without limitation
    + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    + * and/or sell copies of the Software, and to permit persons to whom the
    + * Software is furnished to do so, subject to the following conditions:
    + *
    + * The above copyright notice and this permission notice (including the next
    + * paragraph) shall be included in all copies or substantial portions of the
    + * Software.
    + *
    + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
    + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
    + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    + * DEALINGS IN THE SOFTWARE.
    + *
    + * Authors:
    + *     Alex Deucher 
    + */
    +
    +#include 
    +__FBSDID("$FreeBSD$");
    +
    +#include "dev/drm/drmP.h"
    +#include "dev/drm/drm.h"
    +#include "dev/drm/radeon_drm.h"
    +#include "dev/drm/radeon_drv.h"
    +
    +static u32 r6xx_default_state[] =
    +{
    +	0xc0002400,
    +	0x00000000,
    +	0xc0012800,
    +	0x80000000,
    +	0x80000000,
    +	0xc0004600,
    +	0x00000016,
    +	0xc0016800,
    +	0x00000010,
    +	0x00028000,
    +	0xc0016800,
    +	0x00000010,
    +	0x00008000,
    +	0xc0016800,
    +	0x00000542,
    +	0x07000003,
    +	0xc0016800,
    +	0x000005c5,
    +	0x00000000,
    +	0xc0016800,
    +	0x00000363,
    +	0x00000000,
    +	0xc0016800,
    +	0x0000060c,
    +	0x82000000,
    +	0xc0016800,
    +	0x0000060e,
    +	0x01020204,
    +	0xc0016f00,
    +	0x00000000,
    +	0x00000000,
    +	0xc0016f00,
    +	0x00000001,
    +	0x00000000,
    +	0xc0096900,
    +	0x0000022a,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000004,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000000a,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000000b,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000010c,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000010d,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000200,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000343,
    +	0x00000060,
    +	0xc0016900,
    +	0x00000344,
    +	0x00000040,
    +	0xc0016900,
    +	0x00000351,
    +	0x0000aa00,
    +	0xc0016900,
    +	0x00000104,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000010e,
    +	0x00000000,
    +	0xc0046900,
    +	0x00000105,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0xc0036900,
    +	0x00000109,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0xc0046900,
    +	0x0000030c,
    +	0x01000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0xc0046900,
    +	0x00000048,
    +	0x3f800000,
    +	0x00000000,
    +	0x3f800000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x0000008e,
    +	0x0000000f,
    +	0xc0016900,
    +	0x00000080,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000083,
    +	0x0000ffff,
    +	0xc0016900,
    +	0x00000084,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000085,
    +	0x20002000,
    +	0xc0016900,
    +	0x00000086,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000087,
    +	0x20002000,
    +	0xc0016900,
    +	0x00000088,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000089,
    +	0x20002000,
    +	0xc0016900,
    +	0x0000008a,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000008b,
    +	0x20002000,
    +	0xc0016900,
    +	0x0000008c,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000094,
    +	0x80000000,
    +	0xc0016900,
    +	0x00000095,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000b4,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x00000096,
    +	0x80000000,
    +	0xc0016900,
    +	0x00000097,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000b6,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x00000098,
    +	0x80000000,
    +	0xc0016900,
    +	0x00000099,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000b8,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x0000009a,
    +	0x80000000,
    +	0xc0016900,
    +	0x0000009b,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000ba,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x0000009c,
    +	0x80000000,
    +	0xc0016900,
    +	0x0000009d,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000bc,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x0000009e,
    +	0x80000000,
    +	0xc0016900,
    +	0x0000009f,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000be,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a0,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a1,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c0,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a2,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a3,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c2,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a4,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a5,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c4,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a6,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a7,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c6,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a8,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a9,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c8,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000aa,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000ab,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000ca,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000ac,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000ad,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000cc,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000ae,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000af,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000ce,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000b0,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000b1,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000d0,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000b2,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000b3,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000d2,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x00000293,
    +	0x00004010,
    +	0xc0016900,
    +	0x00000300,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000301,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000312,
    +	0xffffffff,
    +	0xc0016900,
    +	0x00000307,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000308,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000283,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000292,
    +	0x00000000,
    +	0xc0066900,
    +	0x0000010f,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000206,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000207,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000208,
    +	0x00000000,
    +	0xc0046900,
    +	0x00000303,
    +	0x3f800000,
    +	0x3f800000,
    +	0x3f800000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x00000205,
    +	0x00000004,
    +	0xc0016900,
    +	0x00000280,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000281,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000037e,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000382,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000380,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000383,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000381,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000282,
    +	0x00000008,
    +	0xc0016900,
    +	0x00000302,
    +	0x0000002d,
    +	0xc0016900,
    +	0x0000037f,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b2,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b6,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b7,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b8,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b9,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000225,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000229,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000237,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000100,
    +	0x00000800,
    +	0xc0016900,
    +	0x00000101,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000102,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002a8,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002a9,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000103,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000284,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000290,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000285,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000286,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000287,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000288,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000289,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028a,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028b,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028c,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028d,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028e,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028f,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002a1,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002a5,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002ac,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002ad,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002ae,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002c8,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000206,
    +	0x00000100,
    +	0xc0016900,
    +	0x00000204,
    +	0x00010000,
    +	0xc0036e00,
    +	0x00000000,
    +	0x00000012,
    +	0x00000000,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000008f,
    +	0x0000000f,
    +	0xc0016900,
    +	0x000001e8,
    +	0x00000001,
    +	0xc0016900,
    +	0x00000202,
    +	0x00cc0000,
    +	0xc0016900,
    +	0x00000205,
    +	0x00000244,
    +	0xc0016900,
    +	0x00000203,
    +	0x00000210,
    +	0xc0016900,
    +	0x000001b1,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000185,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b3,
    +	0x00000001,
    +	0xc0016900,
    +	0x000001b4,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000191,
    +	0x00000b00,
    +	0xc0016900,
    +	0x000001b5,
    +	0x00000000,
    +};
    +
    +static u32 r7xx_default_state[] =
    +{
    +	0xc0012800,
    +	0x80000000,
    +	0x80000000,
    +	0xc0004600,
    +	0x00000016,
    +	0xc0016800,
    +	0x00000010,
    +	0x00028000,
    +	0xc0016800,
    +	0x00000010,
    +	0x00008000,
    +	0xc0016800,
    +	0x00000542,
    +	0x07000002,
    +	0xc0016800,
    +	0x000005c5,
    +	0x00000000,
    +	0xc0016800,
    +	0x00000363,
    +	0x00004000,
    +	0xc0016800,
    +	0x0000060c,
    +	0x00000000,
    +	0xc0016800,
    +	0x0000060e,
    +	0x00420204,
    +	0xc0016f00,
    +	0x00000000,
    +	0x00000000,
    +	0xc0016f00,
    +	0x00000001,
    +	0x00000000,
    +	0xc0096900,
    +	0x0000022a,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000004,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000000a,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000000b,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000010c,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000010d,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000200,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000343,
    +	0x00000060,
    +	0xc0016900,
    +	0x00000344,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000351,
    +	0x0000aa00,
    +	0xc0016900,
    +	0x00000104,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000010e,
    +	0x00000000,
    +	0xc0046900,
    +	0x00000105,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0xc0046900,
    +	0x0000030c,
    +	0x01000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000008e,
    +	0x0000000f,
    +	0xc0016900,
    +	0x00000080,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000083,
    +	0x0000ffff,
    +	0xc0016900,
    +	0x00000084,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000085,
    +	0x20002000,
    +	0xc0016900,
    +	0x00000086,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000087,
    +	0x20002000,
    +	0xc0016900,
    +	0x00000088,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000089,
    +	0x20002000,
    +	0xc0016900,
    +	0x0000008a,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000008b,
    +	0x20002000,
    +	0xc0016900,
    +	0x0000008c,
    +	0xaaaaaaaa,
    +	0xc0016900,
    +	0x00000094,
    +	0x80000000,
    +	0xc0016900,
    +	0x00000095,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000b4,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x00000096,
    +	0x80000000,
    +	0xc0016900,
    +	0x00000097,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000b6,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x00000098,
    +	0x80000000,
    +	0xc0016900,
    +	0x00000099,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000b8,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x0000009a,
    +	0x80000000,
    +	0xc0016900,
    +	0x0000009b,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000ba,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x0000009c,
    +	0x80000000,
    +	0xc0016900,
    +	0x0000009d,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000bc,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x0000009e,
    +	0x80000000,
    +	0xc0016900,
    +	0x0000009f,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000be,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a0,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a1,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c0,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a2,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a3,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c2,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a4,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a5,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c4,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a6,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a7,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c6,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000a8,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000a9,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000c8,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000aa,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000ab,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000ca,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000ac,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000ad,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000cc,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000ae,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000af,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000ce,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000b0,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000b1,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000d0,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x000000b2,
    +	0x80000000,
    +	0xc0016900,
    +	0x000000b3,
    +	0x20002000,
    +	0xc0026900,
    +	0x000000d2,
    +	0x00000000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x00000293,
    +	0x00514000,
    +	0xc0016900,
    +	0x00000300,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000301,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000312,
    +	0xffffffff,
    +	0xc0016900,
    +	0x00000307,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000308,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000283,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000292,
    +	0x00000000,
    +	0xc0066900,
    +	0x0000010f,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000206,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000207,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000208,
    +	0x00000000,
    +	0xc0046900,
    +	0x00000303,
    +	0x3f800000,
    +	0x3f800000,
    +	0x3f800000,
    +	0x3f800000,
    +	0xc0016900,
    +	0x00000205,
    +	0x00000004,
    +	0xc0016900,
    +	0x00000280,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000281,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000037e,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000382,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000380,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000383,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000381,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000282,
    +	0x00000008,
    +	0xc0016900,
    +	0x00000302,
    +	0x0000002d,
    +	0xc0016900,
    +	0x0000037f,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b2,
    +	0x00000001,
    +	0xc0016900,
    +	0x000001b6,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b7,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b8,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b9,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000225,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000229,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000237,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000100,
    +	0x00000800,
    +	0xc0016900,
    +	0x00000101,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000102,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002a8,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002a9,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000103,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000284,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000290,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000285,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000286,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000287,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000288,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000289,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028a,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028b,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028c,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028d,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028e,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000028f,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002a1,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002a5,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002ac,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002ad,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002ae,
    +	0x00000000,
    +	0xc0016900,
    +	0x000002c8,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000206,
    +	0x00000100,
    +	0xc0016900,
    +	0x00000204,
    +	0x00010000,
    +	0xc0036e00,
    +	0x00000000,
    +	0x00000012,
    +	0x00000000,
    +	0x00000000,
    +	0xc0016900,
    +	0x0000008f,
    +	0x0000000f,
    +	0xc0016900,
    +	0x000001e8,
    +	0x00000001,
    +	0xc0016900,
    +	0x00000202,
    +	0x00cc0000,
    +	0xc0016900,
    +	0x00000205,
    +	0x00000244,
    +	0xc0016900,
    +	0x00000203,
    +	0x00000210,
    +	0xc0016900,
    +	0x000001b1,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000185,
    +	0x00000000,
    +	0xc0016900,
    +	0x000001b3,
    +	0x00000001,
    +	0xc0016900,
    +	0x000001b4,
    +	0x00000000,
    +	0xc0016900,
    +	0x00000191,
    +	0x00000b00,
    +	0xc0016900,
    +	0x000001b5,
    +	0x00000000,
    +};
    +
    +/* same for r6xx/r7xx */
    +static u32 r6xx_vs[] =
    +{
    +	0x00000004,
    +	0x81000000,
    +	0x0000203c,
    +	0x94000b08,
    +	0x00004000,
    +	0x14200b1a,
    +	0x00000000,
    +	0x00000000,
    +	0x3c000000,
    +	0x68cd1000,
    +	0x00080000,
    +	0x00000000,
    +};
    +
    +static u32 r6xx_ps[] =
    +{
    +	0x00000002,
    +	0x80800000,
    +	0x00000000,
    +	0x94200688,
    +	0x00000010,
    +	0x000d1000,
    +	0xb0800000,
    +	0x00000000,
    +};
    +
    +#define DI_PT_RECTLIST 0x11
    +#define DI_INDEX_SIZE_16_BIT 0x0
    +#define DI_SRC_SEL_AUTO_INDEX 0x2
    +
    +#define FMT_8 1
    +#define FMT_5_6_5 8
    +#define FMT_8_8_8_8 0x1a
    +#define COLOR_8 1
    +#define COLOR_5_6_5 8
    +#define COLOR_8_8_8_8 0x1a
    +
    +#define R600_CB0_DEST_BASE_ENA (1 << 6)
    +#define R600_TC_ACTION_ENA (1 << 23)
    +#define R600_VC_ACTION_ENA (1 << 24)
    +#define R600_CB_ACTION_ENA (1 << 25)
    +#define R600_DB_ACTION_ENA (1 << 26)
    +#define R600_SH_ACTION_ENA (1 << 27)
    +#define R600_SMX_ACTION_ENA (1 << 28)
    +
    +#define R600_CB_COLOR0_SIZE 0x28060
    +#define R600_CB_COLOR0_VIEW 0x28080
    +#define R600_CB_COLOR0_INFO 0x280a0
    +#define R600_CB_COLOR0_TILE 0x280c0
    +#define R600_CB_COLOR0_FRAG 0x280e0
    +#define R600_CB_COLOR0_MASK 0x28100
    +
    +#define R600_SQ_PGM_START_VS                                   0x28858
    +#define R600_SQ_PGM_RESOURCES_VS 0x28868
    +#define R600_SQ_PGM_CF_OFFSET_VS 0x288d0
    +#define R600_SQ_PGM_START_PS                                   0x28840
    +#define R600_SQ_PGM_RESOURCES_PS 0x28850
    +#define R600_SQ_PGM_EXPORTS_PS 0x28854
    +#define R600_SQ_PGM_CF_OFFSET_PS 0x288cc
    +
    +#define R600_VGT_PRIMITIVE_TYPE 0x8958
    +
    +#define R600_PA_SC_SCREEN_SCISSOR_TL 0x28030
    +#define R600_PA_SC_GENERIC_SCISSOR_TL 0x28240
    +#define R600_PA_SC_WINDOW_SCISSOR_TL 0x28204
    +
    +#define R600_SQ_TEX_VTX_INVALID_TEXTURE                        0x0
    +#define R600_SQ_TEX_VTX_INVALID_BUFFER                         0x1
    +#define R600_SQ_TEX_VTX_VALID_TEXTURE                          0x2
    +#define R600_SQ_TEX_VTX_VALID_BUFFER                           0x3
    +
    +/* packet 3 type offsets */
    +#define R600_SET_CONFIG_REG_OFFSET                             0x00008000
    +#define R600_SET_CONFIG_REG_END                                0x0000ac00
    +#define R600_SET_CONTEXT_REG_OFFSET                            0x00028000
    +#define R600_SET_CONTEXT_REG_END                               0x00029000
    +#define R600_SET_ALU_CONST_OFFSET                              0x00030000
    +#define R600_SET_ALU_CONST_END                                 0x00032000
    +#define R600_SET_RESOURCE_OFFSET                               0x00038000
    +#define R600_SET_RESOURCE_END                                  0x0003c000
    +#define R600_SET_SAMPLER_OFFSET                                0x0003c000
    +#define R600_SET_SAMPLER_END                                   0x0003cff0
    +#define R600_SET_CTL_CONST_OFFSET                              0x0003cff0
    +#define R600_SET_CTL_CONST_END                                 0x0003e200
    +#define R600_SET_LOOP_CONST_OFFSET                             0x0003e200
    +#define R600_SET_LOOP_CONST_END                                0x0003e380
    +#define R600_SET_BOOL_CONST_OFFSET                             0x0003e380
    +#define R600_SET_BOOL_CONST_END                                0x00040000
    +
    +/* Packet 3 types */
    +#define R600_IT_INDIRECT_BUFFER_END               0x00001700
    +#define R600_IT_SET_PREDICATION                   0x00002000
    +#define R600_IT_REG_RMW                           0x00002100
    +#define R600_IT_COND_EXEC                         0x00002200
    +#define R600_IT_PRED_EXEC                         0x00002300
    +#define R600_IT_START_3D_CMDBUF                   0x00002400
    +#define R600_IT_DRAW_INDEX_2                      0x00002700
    +#define R600_IT_CONTEXT_CONTROL                   0x00002800
    +#define R600_IT_DRAW_INDEX_IMMD_BE                0x00002900
    +#define R600_IT_INDEX_TYPE                        0x00002A00
    +#define R600_IT_DRAW_INDEX                        0x00002B00
    +#define R600_IT_DRAW_INDEX_AUTO                   0x00002D00
    +#define R600_IT_DRAW_INDEX_IMMD                   0x00002E00
    +#define R600_IT_NUM_INSTANCES                     0x00002F00
    +#define R600_IT_STRMOUT_BUFFER_UPDATE             0x00003400
    +#define R600_IT_INDIRECT_BUFFER_MP                0x00003800
    +#define R600_IT_MEM_SEMAPHORE                     0x00003900
    +#define R600_IT_MPEG_INDEX                        0x00003A00
    +#define R600_IT_WAIT_REG_MEM                      0x00003C00
    +#define R600_IT_MEM_WRITE                         0x00003D00
    +#define R600_IT_INDIRECT_BUFFER                   0x00003200
    +#define R600_IT_CP_INTERRUPT                      0x00004000
    +#define R600_IT_SURFACE_SYNC                      0x00004300
    +#define R600_IT_ME_INITIALIZE                     0x00004400
    +#define R600_IT_COND_WRITE                        0x00004500
    +#define R600_IT_EVENT_WRITE                       0x00004600
    +#define R600_IT_EVENT_WRITE_EOP                   0x00004700
    +#define R600_IT_ONE_REG_WRITE                     0x00005700
    +#define R600_IT_SET_CONFIG_REG                    0x00006800
    +#define R600_IT_SET_CONTEXT_REG                   0x00006900
    +#define R600_IT_SET_ALU_CONST                     0x00006A00
    +#define R600_IT_SET_BOOL_CONST                    0x00006B00
    +#define R600_IT_SET_LOOP_CONST                    0x00006C00
    +#define R600_IT_SET_RESOURCE                      0x00006D00
    +#define R600_IT_SET_SAMPLER                       0x00006E00
    +#define R600_IT_SET_CTL_CONST                     0x00006F00
    +#define R600_IT_SURFACE_BASE_UPDATE               0x00007300
    +
    +static inline void
    +set_render_target(drm_radeon_private_t *dev_priv, int format, int w, int h, u64 gpu_addr)
    +{
    +	u32 cb_color_info;
    +	int pitch, slice;
    +	RING_LOCALS;
    +	DRM_DEBUG("\n");
    +
    +	h = (h + 7) & ~7;
    +	if (h < 8)
    +		h = 8;
    +
    +	cb_color_info = ((format << 2) | (1 << 27));
    +	pitch = (w / 8) - 1;
    +	slice = ((w * h) / 64) - 1;
    +
    +	if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600) &&
    +	    ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770)) {
    +		BEGIN_RING(21 + 2);
    +		OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +		OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +		OUT_RING(gpu_addr >> 8);
    +		OUT_RING(CP_PACKET3(R600_IT_SURFACE_BASE_UPDATE, 0));
    +		OUT_RING(2 << 0);
    +	} else {
    +		BEGIN_RING(21);
    +		OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +		OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +		OUT_RING(gpu_addr >> 8);
    +	}
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_CB_COLOR0_SIZE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING((pitch << 0) | (slice << 10));
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_CB_COLOR0_VIEW - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(0);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_CB_COLOR0_INFO - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(cb_color_info);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_CB_COLOR0_TILE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(0);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_CB_COLOR0_FRAG - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(0);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_CB_COLOR0_MASK - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(0);
    +
    +	ADVANCE_RING();
    +}
    +
    +static inline void
    +cp_set_surface_sync(drm_radeon_private_t *dev_priv,
    +		    u32 sync_type, u32 size, u64 mc_addr)
    +{
    +	u32 cp_coher_size;
    +	RING_LOCALS;
    +	DRM_DEBUG("\n");
    +
    +	if (size == 0xffffffff)
    +		cp_coher_size = 0xffffffff;
    +	else
    +		cp_coher_size = ((size + 255) >> 8);
    +
    +	BEGIN_RING(5);
    +	OUT_RING(CP_PACKET3(R600_IT_SURFACE_SYNC, 3));
    +	OUT_RING(sync_type);
    +	OUT_RING(cp_coher_size);
    +	OUT_RING((mc_addr >> 8));
    +	OUT_RING(10); /* poll interval */
    +	ADVANCE_RING();
    +}
    +
    +static inline void
    +set_shaders(struct drm_device *dev)
    +{
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +	u64 gpu_addr;
    +	int shader_size, i;
    +	u32 *vs, *ps;
    +	uint32_t sq_pgm_resources;
    +	RING_LOCALS;
    +	DRM_DEBUG("\n");
    +
    +	/* load shaders */
    +	vs = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset);
    +	ps = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset + 256);
    +
    +	shader_size = sizeof(r6xx_vs) / 4;
    +	for (i= 0; i < shader_size; i++)
    +		vs[i] = r6xx_vs[i];
    +	shader_size = sizeof(r6xx_ps) / 4;
    +	for (i= 0; i < shader_size; i++)
    +		ps[i] = r6xx_ps[i];
    +
    +	dev_priv->blit_vb->used = 512;
    +
    +	gpu_addr = dev_priv->gart_buffers_offset + dev_priv->blit_vb->offset;
    +
    +	/* setup shader regs */
    +	sq_pgm_resources = (1 << 0);
    +
    +	BEGIN_RING(9 + 12);
    +	/* VS */
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_SQ_PGM_START_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(gpu_addr >> 8);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_SQ_PGM_RESOURCES_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(sq_pgm_resources);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_SQ_PGM_CF_OFFSET_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(0);
    +
    +	/* PS */
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_SQ_PGM_START_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING((gpu_addr + 256) >> 8);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_SQ_PGM_RESOURCES_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(sq_pgm_resources | (1 << 28));
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_SQ_PGM_EXPORTS_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(2);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
    +        OUT_RING((R600_SQ_PGM_CF_OFFSET_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING(0);
    +	ADVANCE_RING();
    +
    +	cp_set_surface_sync(dev_priv,
    +			    R600_SH_ACTION_ENA, 512, gpu_addr);
    +}
    +
    +static inline void
    +set_vtx_resource(drm_radeon_private_t *dev_priv, u64 gpu_addr)
    +{
    +	uint32_t sq_vtx_constant_word2;
    +	RING_LOCALS;
    +	DRM_DEBUG("\n");
    +
    +	sq_vtx_constant_word2 = (((gpu_addr >> 32) & 0xff) | (16 << 8));
    +
    +	BEGIN_RING(9);
    +	OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7));
    +	OUT_RING(0x460);
    +	OUT_RING(gpu_addr & 0xffffffff);
    +	OUT_RING(48 - 1);
    +	OUT_RING(sq_vtx_constant_word2);
    +	OUT_RING(1 << 0);
    +	OUT_RING(0);
    +	OUT_RING(0);
    +	OUT_RING(R600_SQ_TEX_VTX_VALID_BUFFER << 30);
    +	ADVANCE_RING();
    +
    +	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_RS880) ||*/
    +	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710))
    +		cp_set_surface_sync(dev_priv,
    +				    R600_TC_ACTION_ENA, 48, gpu_addr);
    +	else
    +		cp_set_surface_sync(dev_priv,
    +				    R600_VC_ACTION_ENA, 48, gpu_addr);
    +}
    +
    +static inline void
    +set_tex_resource(drm_radeon_private_t *dev_priv,
    +		 int format, int w, int h, int pitch, u64 gpu_addr)
    +{
    +	uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
    +	RING_LOCALS;
    +	DRM_DEBUG("\n");
    +
    +	if (h < 1)
    +		h = 1;
    +
    +	sq_tex_resource_word0 = (1 << 0);
    +	sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) |
    +				  ((w - 1) << 19));
    +
    +	sq_tex_resource_word1 = (format << 26);
    +	sq_tex_resource_word1 |= ((h - 1) << 0);
    +
    +	sq_tex_resource_word4 = ((1 << 14) |
    +				 (0 << 16) |
    +				 (1 << 19) |
    +				 (2 << 22) |
    +				 (3 << 25));
    +
    +	BEGIN_RING(9);
    +	OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7));
    +	OUT_RING(0);
    +	OUT_RING(sq_tex_resource_word0);
    +	OUT_RING(sq_tex_resource_word1);
    +	OUT_RING(gpu_addr >> 8);
    +	OUT_RING(gpu_addr >> 8);
    +	OUT_RING(sq_tex_resource_word4);
    +	OUT_RING(0);
    +	OUT_RING(R600_SQ_TEX_VTX_VALID_TEXTURE << 30);
    +	ADVANCE_RING();
    +
    +}
    +
    +static inline void
    +set_scissors(drm_radeon_private_t *dev_priv, int x1, int y1, int x2, int y2)
    +{
    +	RING_LOCALS;
    +	DRM_DEBUG("\n");
    +
    +	BEGIN_RING(12);
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2));
    +        OUT_RING((R600_PA_SC_SCREEN_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING((x1 << 0) | (y1 << 16));
    +	OUT_RING((x2 << 0) | (y2 << 16));
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2));
    +        OUT_RING((R600_PA_SC_GENERIC_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31));
    +	OUT_RING((x2 << 0) | (y2 << 16));
    +
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2));
    +        OUT_RING((R600_PA_SC_WINDOW_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2);
    +	OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31));
    +	OUT_RING((x2 << 0) | (y2 << 16));
    +	ADVANCE_RING();
    +}
    +
    +static inline void
    +draw_auto(drm_radeon_private_t *dev_priv)
    +{
    +	RING_LOCALS;
    +	DRM_DEBUG("\n");
    +
    +	BEGIN_RING(10);
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
    +        OUT_RING((R600_VGT_PRIMITIVE_TYPE - R600_SET_CONFIG_REG_OFFSET) >> 2);
    +	OUT_RING(DI_PT_RECTLIST);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_INDEX_TYPE, 0));
    +	OUT_RING(DI_INDEX_SIZE_16_BIT);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_NUM_INSTANCES, 0));
    +	OUT_RING(1);
    +
    +	OUT_RING(CP_PACKET3(R600_IT_DRAW_INDEX_AUTO, 1));
    +	OUT_RING(3);
    +	OUT_RING(DI_SRC_SEL_AUTO_INDEX);
    +
    +	ADVANCE_RING();
    +	COMMIT_RING();
    +}
    +
    +static inline void
    +set_default_state(drm_radeon_private_t *dev_priv)
    +{
    +	int default_state_dw, i;
    +	u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2;
    +	u32 sq_thread_resource_mgmt, sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2;
    +	int num_ps_gprs, num_vs_gprs, num_temp_gprs, num_gs_gprs, num_es_gprs;
    +	int num_ps_threads, num_vs_threads, num_gs_threads, num_es_threads;
    +	int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries;
    +	RING_LOCALS;
    +
    +	switch ((dev_priv->flags & RADEON_FAMILY_MASK)) {
    +	case CHIP_R600:
    +		num_ps_gprs = 192;
    +		num_vs_gprs = 56;
    +		num_temp_gprs = 4;
    +		num_gs_gprs = 0;
    +		num_es_gprs = 0;
    +		num_ps_threads = 136;
    +		num_vs_threads = 48;
    +		num_gs_threads = 4;
    +		num_es_threads = 4;
    +		num_ps_stack_entries = 128;
    +		num_vs_stack_entries = 128;
    +		num_gs_stack_entries = 0;
    +		num_es_stack_entries = 0;
    +		break;
    +	case CHIP_RV630:
    +	case CHIP_RV635:
    +		num_ps_gprs = 84;
    +		num_vs_gprs = 36;
    +		num_temp_gprs = 4;
    +		num_gs_gprs = 0;
    +		num_es_gprs = 0;
    +		num_ps_threads = 144;
    +		num_vs_threads = 40;
    +		num_gs_threads = 4;
    +		num_es_threads = 4;
    +		num_ps_stack_entries = 40;
    +		num_vs_stack_entries = 40;
    +		num_gs_stack_entries = 32;
    +		num_es_stack_entries = 16;
    +		break;
    +	case CHIP_RV610:
    +	case CHIP_RV620:
    +	case CHIP_RS780:
    +	/*case CHIP_RS880:*/
    +	default:
    +		num_ps_gprs = 84;
    +		num_vs_gprs = 36;
    +		num_temp_gprs = 4;
    +		num_gs_gprs = 0;
    +		num_es_gprs = 0;
    +		num_ps_threads = 136;
    +		num_vs_threads = 48;
    +		num_gs_threads = 4;
    +		num_es_threads = 4;
    +		num_ps_stack_entries = 40;
    +		num_vs_stack_entries = 40;
    +		num_gs_stack_entries = 32;
    +		num_es_stack_entries = 16;
    +		break;
    +	case CHIP_RV670:
    +		num_ps_gprs = 144;
    +		num_vs_gprs = 40;
    +		num_temp_gprs = 4;
    +		num_gs_gprs = 0;
    +		num_es_gprs = 0;
    +		num_ps_threads = 136;
    +		num_vs_threads = 48;
    +		num_gs_threads = 4;
    +		num_es_threads = 4;
    +		num_ps_stack_entries = 40;
    +		num_vs_stack_entries = 40;
    +		num_gs_stack_entries = 32;
    +		num_es_stack_entries = 16;
    +		break;
    +	case CHIP_RV770:
    +		num_ps_gprs = 192;
    +		num_vs_gprs = 56;
    +		num_temp_gprs = 4;
    +		num_gs_gprs = 0;
    +		num_es_gprs = 0;
    +		num_ps_threads = 188;
    +		num_vs_threads = 60;
    +		num_gs_threads = 0;
    +		num_es_threads = 0;
    +		num_ps_stack_entries = 256;
    +		num_vs_stack_entries = 256;
    +		num_gs_stack_entries = 0;
    +		num_es_stack_entries = 0;
    +		break;
    +	case CHIP_RV730:
    +	case CHIP_RV740:
    +		num_ps_gprs = 84;
    +		num_vs_gprs = 36;
    +		num_temp_gprs = 4;
    +		num_gs_gprs = 0;
    +		num_es_gprs = 0;
    +		num_ps_threads = 188;
    +		num_vs_threads = 60;
    +		num_gs_threads = 0;
    +		num_es_threads = 0;
    +		num_ps_stack_entries = 128;
    +		num_vs_stack_entries = 128;
    +		num_gs_stack_entries = 0;
    +		num_es_stack_entries = 0;
    +		break;
    +	case CHIP_RV710:
    +		num_ps_gprs = 192;
    +		num_vs_gprs = 56;
    +		num_temp_gprs = 4;
    +		num_gs_gprs = 0;
    +		num_es_gprs = 0;
    +		num_ps_threads = 144;
    +		num_vs_threads = 48;
    +		num_gs_threads = 0;
    +		num_es_threads = 0;
    +		num_ps_stack_entries = 128;
    +		num_vs_stack_entries = 128;
    +		num_gs_stack_entries = 0;
    +		num_es_stack_entries = 0;
    +		break;
    +	}
    +
    +	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_RS880) ||*/
    +	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710))
    +		sq_config = 0;
    +	else
    +		sq_config = R600_VC_ENABLE;
    +
    +	sq_config |= (R600_DX9_CONSTS |
    +		      R600_ALU_INST_PREFER_VECTOR |
    +		      R600_PS_PRIO(0) |
    +		      R600_VS_PRIO(1) |
    +		      R600_GS_PRIO(2) |
    +		      R600_ES_PRIO(3));
    +
    +	sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(num_ps_gprs) |
    +				  R600_NUM_VS_GPRS(num_vs_gprs) |
    +				  R600_NUM_CLAUSE_TEMP_GPRS(num_temp_gprs));
    +	sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(num_gs_gprs) |
    +				  R600_NUM_ES_GPRS(num_es_gprs));
    +	sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(num_ps_threads) |
    +				   R600_NUM_VS_THREADS(num_vs_threads) |
    +				   R600_NUM_GS_THREADS(num_gs_threads) |
    +				   R600_NUM_ES_THREADS(num_es_threads));
    +	sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(num_ps_stack_entries) |
    +				    R600_NUM_VS_STACK_ENTRIES(num_vs_stack_entries));
    +	sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(num_gs_stack_entries) |
    +				    R600_NUM_ES_STACK_ENTRIES(num_es_stack_entries));
    +
    +	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) {
    +		default_state_dw = sizeof(r7xx_default_state) / 4;
    +		BEGIN_RING(default_state_dw + 10);
    +		for (i = 0; i < default_state_dw; i++)
    +			OUT_RING(r7xx_default_state[i]);
    +	} else {
    +		default_state_dw = sizeof(r6xx_default_state) / 4;
    +		BEGIN_RING(default_state_dw + 10);
    +		for (i = 0; i < default_state_dw; i++)
    +			OUT_RING(r6xx_default_state[i]);
    +	}
    +	OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
    +	OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT);
    +	/* SQ config */
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 6));
    +        OUT_RING((R600_SQ_CONFIG - R600_SET_CONFIG_REG_OFFSET) >> 2);
    +	OUT_RING(sq_config);
    +	OUT_RING(sq_gpr_resource_mgmt_1);
    +	OUT_RING(sq_gpr_resource_mgmt_2);
    +	OUT_RING(sq_thread_resource_mgmt);
    +	OUT_RING(sq_stack_resource_mgmt_1);
    +	OUT_RING(sq_stack_resource_mgmt_2);
    +	ADVANCE_RING();
    +}
    +
    +static inline uint32_t i2f(uint32_t input)
    +{
    +	u32 result, i, exponent, fraction;
    +
    +	if ((input & 0x3fff) == 0)
    +		result = 0; /* 0 is a special case */
    +	else {
    +		exponent = 140; /* exponent biased by 127; */
    +		fraction = (input & 0x3fff) << 10; /* cheat and only
    +						      handle numbers below 2^^15 */
    +		for (i = 0; i < 14; i++) {
    +			if (fraction & 0x800000)
    +				break;
    +			else {
    +				fraction = fraction << 1; /* keep
    +							     shifting left until top bit = 1 */
    +				exponent = exponent -1;
    +			}
    +		}
    +		result = exponent << 23 | (fraction & 0x7fffff); /* mask
    +								    off top bit; assumed 1 */
    +	}
    +	return result;
    +}
    +
    +int
    +r600_prepare_blit_copy(struct drm_device *dev)
    +{
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +	DRM_DEBUG("\n");
    +
    +	dev_priv->blit_vb = radeon_freelist_get(dev);
    +	if (!dev_priv->blit_vb) {
    +		DRM_ERROR("Unable to allocate vertex buffer for blit\n");
    +		return -EAGAIN;
    +	}
    +
    +	set_default_state(dev_priv);
    +	set_shaders(dev);
    +
    +	return 0;
    +}
    +
    +void
    +r600_done_blit_copy(struct drm_device *dev)
    +{
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +	RING_LOCALS;
    +	DRM_DEBUG("\n");
    +
    +	BEGIN_RING(5);
    +	OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
    +	OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT);
    +	/* wait for 3D idle clean */
    +	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
    +	OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2);
    +	OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN);
    +
    +	ADVANCE_RING();
    +	COMMIT_RING();
    +
    +	dev_priv->blit_vb->used = 0;
    +	radeon_cp_discard_buffer(dev, dev_priv->blit_vb);
    +}
    +
    +void
    +r600_blit_copy(struct drm_device *dev,
    +	       uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
    +	       int size_bytes)
    +{
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +	int max_bytes;
    +	u64 vb_addr;
    +	u32 *vb;
    +
    +	vb = (u32 *) ((char *)dev->agp_buffer_map->handle +
    +		      dev_priv->blit_vb->offset + dev_priv->blit_vb->used);
    +
    +	if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
    +		max_bytes = 8192;
    +
    +		while (size_bytes) {
    +			int cur_size = size_bytes;
    +			int src_x = src_gpu_addr & 255;
    +			int dst_x = dst_gpu_addr & 255;
    +			int h = 1;
    +			src_gpu_addr = src_gpu_addr & ~255;
    +			dst_gpu_addr = dst_gpu_addr & ~255;
    +
    +			if (!src_x && !dst_x) {
    +				h = (cur_size / max_bytes);
    +				if (h == 0)
    +					h = 1;
    +				else
    +					cur_size = max_bytes;
    +			} else {
    +				if (cur_size > max_bytes)
    +					cur_size = max_bytes;
    +				if (cur_size > (max_bytes - dst_x))
    +					cur_size = (max_bytes - dst_x);
    +				if (cur_size > (max_bytes - src_x))
    +					cur_size = (max_bytes - src_x);
    +			}
    +
    +			if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
    +				dev_priv->blit_vb->used = 0;
    +				radeon_cp_discard_buffer(dev, dev_priv->blit_vb);
    +				dev_priv->blit_vb = radeon_freelist_get(dev);
    +				if (!dev_priv->blit_vb)
    +					return;
    +				set_shaders(dev);
    +				vb = (u32 *) ((char *)dev->agp_buffer_map->handle +
    +					      dev_priv->blit_vb->offset + dev_priv->blit_vb->used);
    +			}
    +
    +			vb[0] = i2f(dst_x);
    +			vb[1] = 0;
    +			vb[2] = i2f(src_x);
    +			vb[3] = 0;
    +
    +			vb[4] = i2f(dst_x);
    +			vb[5] = i2f(h);
    +			vb[6] = i2f(src_x);
    +			vb[7] = i2f(h);
    +
    +			vb[8] = i2f(dst_x + cur_size);
    +			vb[9] = i2f(h);
    +			vb[10] = i2f(src_x + cur_size);
    +			vb[11] = i2f(h);
    +
    +			/* src */
    +			set_tex_resource(dev_priv, FMT_8,
    +					 src_x + cur_size, h, src_x + cur_size,
    +					 src_gpu_addr);
    +
    +			cp_set_surface_sync(dev_priv,
    +					    R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
    +
    +			/* dst */
    +			set_render_target(dev_priv, COLOR_8,
    +					  dst_x + cur_size, h,
    +					  dst_gpu_addr);
    +
    +			/* scissors */
    +			set_scissors(dev_priv, dst_x, 0, dst_x + cur_size, h);
    +
    +			/* Vertex buffer setup */
    +			vb_addr = dev_priv->gart_buffers_offset +
    +                                dev_priv->blit_vb->offset +
    +				dev_priv->blit_vb->used;
    +			set_vtx_resource(dev_priv, vb_addr);
    +
    +			/* draw */
    +			draw_auto(dev_priv);
    +
    +			cp_set_surface_sync(dev_priv,
    +					    R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
    +					    cur_size * h, dst_gpu_addr);
    +
    +			vb += 12;
    +			dev_priv->blit_vb->used += 12 * 4;
    +
    +			src_gpu_addr += cur_size;
    +			dst_gpu_addr += cur_size;
    +			size_bytes -= cur_size * h;
    +		}
    +	} else {
    +		max_bytes = 8192 * 4;
    +
    +		while (size_bytes) {
    +			int cur_size = size_bytes;
    +			int src_x = (src_gpu_addr & 255);
    +			int dst_x = (dst_gpu_addr & 255);
    +			int h = 1;
    +			src_gpu_addr = src_gpu_addr & ~255;
    +			dst_gpu_addr = dst_gpu_addr & ~255;
    +
    +			if (!src_x && !dst_x) {
    +				h = (cur_size / max_bytes);
    +				if (h == 0)
    +					h = 1;
    +				else
    +					cur_size = max_bytes;
    +			} else {
    +				if (cur_size > max_bytes)
    +				    cur_size = max_bytes;
    +				if (cur_size > (max_bytes - dst_x))
    +					cur_size = (max_bytes - dst_x);
    +				if (cur_size > (max_bytes - src_x))
    +					cur_size = (max_bytes - src_x);
    +			}
    +
    +			if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
    +				dev_priv->blit_vb->used = 0;
    +				radeon_cp_discard_buffer(dev, dev_priv->blit_vb);
    +				dev_priv->blit_vb = radeon_freelist_get(dev);
    +				if (!dev_priv->blit_vb)
    +					return;
    +				set_shaders(dev);
    +				vb = (u32 *) ((char *)dev->agp_buffer_map->handle +
    +					      dev_priv->blit_vb->offset + dev_priv->blit_vb->used);
    +			}
    +
    +			vb[0] = i2f(dst_x / 4);
    +			vb[1] = 0;
    +			vb[2] = i2f(src_x / 4);
    +			vb[3] = 0;
    +
    +			vb[4] = i2f(dst_x / 4);
    +			vb[5] = i2f(h);
    +			vb[6] = i2f(src_x / 4);
    +			vb[7] = i2f(h);
    +
    +			vb[8] = i2f((dst_x + cur_size) / 4);
    +			vb[9] = i2f(h);
    +			vb[10] = i2f((src_x + cur_size) / 4);
    +			vb[11] = i2f(h);
    +
    +			/* src */
    +			set_tex_resource(dev_priv, FMT_8_8_8_8,
    +					 (src_x + cur_size) / 4,
    +					 h, (src_x + cur_size) / 4,
    +					 src_gpu_addr);
    +
    +			cp_set_surface_sync(dev_priv,
    +					    R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
    +
    +			/* dst */
    +			set_render_target(dev_priv, COLOR_8_8_8_8,
    +					  dst_x + cur_size, h,
    +					  dst_gpu_addr);
    +
    +			/* scissors */
    +			set_scissors(dev_priv, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
    +
    +			/* Vertex buffer setup */
    +			vb_addr = dev_priv->gart_buffers_offset +
    +                                dev_priv->blit_vb->offset +
    +				dev_priv->blit_vb->used;
    +			set_vtx_resource(dev_priv, vb_addr);
    +
    +			/* draw */
    +			draw_auto(dev_priv);
    +
    +			cp_set_surface_sync(dev_priv,
    +					    R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
    +					    cur_size * h, dst_gpu_addr);
    +
    +			vb += 12;
    +			dev_priv->blit_vb->used += 12 * 4;
    +
    +			src_gpu_addr += cur_size;
    +			dst_gpu_addr += cur_size;
    +			size_bytes -= cur_size * h;
    +		}
    +	}
    +}
    +
    +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)
    +{
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +	int cb_format, tex_format;
    +	u64 vb_addr;
    +	u32 *vb;
    +
    +	vb = (u32 *) ((char *)dev->agp_buffer_map->handle +
    +		      dev_priv->blit_vb->offset + dev_priv->blit_vb->used);
    +
    +	if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
    +		dev_priv->blit_vb->used = 0;
    +		radeon_cp_discard_buffer(dev, dev_priv->blit_vb);
    +		dev_priv->blit_vb = radeon_freelist_get(dev);
    +		if (!dev_priv->blit_vb)
    +			return;
    +		set_shaders(dev);
    +		vb = (u32 *) ((char *)dev->agp_buffer_map->handle +
    +			      dev_priv->blit_vb->offset + dev_priv->blit_vb->used);
    +	}
    +
    +	if (cpp == 4) {
    +		cb_format = COLOR_8_8_8_8;
    +		tex_format = FMT_8_8_8_8;
    +	} else if (cpp == 2) {
    +		cb_format = COLOR_5_6_5;
    +		tex_format = FMT_5_6_5;
    +	} else {
    +		cb_format = COLOR_8;
    +		tex_format = FMT_8;
    +	}
    +
    +	vb[0] = i2f(dx);
    +	vb[1] = i2f(dy);
    +	vb[2] = i2f(sx);
    +	vb[3] = i2f(sy);
    +
    +	vb[4] = i2f(dx);
    +	vb[5] = i2f(dy + h);
    +	vb[6] = i2f(sx);
    +	vb[7] = i2f(sy + h);
    +
    +	vb[8] = i2f(dx + w);
    +	vb[9] = i2f(dy + h);
    +	vb[10] = i2f(sx + w);
    +	vb[11] = i2f(sy + h);
    +
    +	/* src */
    +	set_tex_resource(dev_priv, tex_format,
    +			 src_pitch / cpp,
    +			 sy + h, src_pitch / cpp,
    +			 src_gpu_addr);
    +
    +	cp_set_surface_sync(dev_priv,
    +			    R600_TC_ACTION_ENA, (src_pitch * (sy + h)), src_gpu_addr);
    +
    +	/* dst */
    +	set_render_target(dev_priv, cb_format,
    +			  dst_pitch / cpp, dy + h,
    +			  dst_gpu_addr);
    +
    +	/* scissors */
    +	set_scissors(dev_priv, dx, dy, dx + w, dy + h);
    +
    +	/* Vertex buffer setup */
    +	vb_addr = dev_priv->gart_buffers_offset +
    +		dev_priv->blit_vb->offset +
    +		dev_priv->blit_vb->used;
    +	set_vtx_resource(dev_priv, vb_addr);
    +
    +	/* draw */
    +	draw_auto(dev_priv);
    +
    +	cp_set_surface_sync(dev_priv,
    +			    R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
    +			    dst_pitch * (dy + h), dst_gpu_addr);
    +
    +	dev_priv->blit_vb->used += 12 * 4;
    +}
    diff --git a/sys/dev/drm/r600_cp.c b/sys/dev/drm/r600_cp.c
    index 8c33eb6f483..2a4a6bd873c 100644
    --- a/sys/dev/drm/r600_cp.c
    +++ b/sys/dev/drm/r600_cp.c
    @@ -1843,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,
    @@ -2100,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;
     }
     
    @@ -2232,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..3a4aa983377 100644
    --- a/sys/dev/drm/radeon_cp.c
    +++ b/sys/dev/drm/radeon_cp.c
    @@ -2060,6 +2060,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 +2114,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 +2130,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_cs.c b/sys/dev/drm/radeon_cs.c
    new file mode 100644
    index 00000000000..4fc6e7ea22a
    --- /dev/null
    +++ b/sys/dev/drm/radeon_cs.c
    @@ -0,0 +1,856 @@
    +/*-
    + * Copyright 2008 Jerome Glisse.
    + * All Rights Reserved.
    + *
    + * Permission is hereby granted, free of charge, to any person obtaining a
    + * copy of this software and associated documentation files (the "Software"),
    + * to deal in the Software without restriction, including without limitation
    + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    + * and/or sell copies of the Software, and to permit persons to whom the
    + * Software is furnished to do so, subject to the following conditions:
    + *
    + * The above copyright notice and this permission notice (including the next
    + * paragraph) shall be included in all copies or substantial portions of the
    + * Software.
    + *
    + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
    + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
    + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    + * DEALINGS IN THE SOFTWARE.
    + *
    + * Authors:
    + *    Jerome Glisse 
    + */
    +
    +#include 
    +__FBSDID("$FreeBSD$");
    +#include "dev/drm/drmP.h"
    +#include "dev/drm/radeon_drm.h"
    +#include "dev/drm/radeon_drv.h"
    +
    +/* regs */
    +#define AVIVO_D1MODE_VLINE_START_END                           0x6538
    +#define AVIVO_D2MODE_VLINE_START_END                           0x6d38
    +#define R600_CP_COHER_BASE                                     0x85f8
    +#define R600_DB_DEPTH_BASE                                     0x2800c
    +#define R600_CB_COLOR0_BASE                                    0x28040
    +#define R600_CB_COLOR1_BASE                                    0x28044
    +#define R600_CB_COLOR2_BASE                                    0x28048
    +#define R600_CB_COLOR3_BASE                                    0x2804c
    +#define R600_CB_COLOR4_BASE                                    0x28050
    +#define R600_CB_COLOR5_BASE                                    0x28054
    +#define R600_CB_COLOR6_BASE                                    0x28058
    +#define R600_CB_COLOR7_BASE                                    0x2805c
    +#define R600_SQ_PGM_START_FS                                   0x28894
    +#define R600_SQ_PGM_START_ES                                   0x28880
    +#define R600_SQ_PGM_START_VS                                   0x28858
    +#define R600_SQ_PGM_START_GS                                   0x2886c
    +#define R600_SQ_PGM_START_PS                                   0x28840
    +#define R600_VGT_DMA_BASE                                      0x287e8
    +#define R600_VGT_DMA_BASE_HI                                   0x287e4
    +#define R600_VGT_STRMOUT_BASE_OFFSET_0                         0x28b10
    +#define R600_VGT_STRMOUT_BASE_OFFSET_1                         0x28b14
    +#define R600_VGT_STRMOUT_BASE_OFFSET_2                         0x28b18
    +#define R600_VGT_STRMOUT_BASE_OFFSET_3                         0x28b1c
    +#define R600_VGT_STRMOUT_BASE_OFFSET_HI_0                      0x28b44
    +#define R600_VGT_STRMOUT_BASE_OFFSET_HI_1                      0x28b48
    +#define R600_VGT_STRMOUT_BASE_OFFSET_HI_2                      0x28b4c
    +#define R600_VGT_STRMOUT_BASE_OFFSET_HI_3                      0x28b50
    +#define R600_VGT_STRMOUT_BUFFER_BASE_0                         0x28ad8
    +#define R600_VGT_STRMOUT_BUFFER_BASE_1                         0x28ae8
    +#define R600_VGT_STRMOUT_BUFFER_BASE_2                         0x28af8
    +#define R600_VGT_STRMOUT_BUFFER_BASE_3                         0x28b08
    +#define R600_VGT_STRMOUT_BUFFER_OFFSET_0                       0x28adc
    +#define R600_VGT_STRMOUT_BUFFER_OFFSET_1                       0x28aec
    +#define R600_VGT_STRMOUT_BUFFER_OFFSET_2                       0x28afc
    +#define R600_VGT_STRMOUT_BUFFER_OFFSET_3                       0x28b0c
    +
    +/* resource type */
    +#define R600_SQ_TEX_VTX_INVALID_TEXTURE                        0x0
    +#define R600_SQ_TEX_VTX_INVALID_BUFFER                         0x1
    +#define R600_SQ_TEX_VTX_VALID_TEXTURE                          0x2
    +#define R600_SQ_TEX_VTX_VALID_BUFFER                           0x3
    +
    +/* packet 3 type offsets */
    +#define R600_SET_CONFIG_REG_OFFSET                             0x00008000
    +#define R600_SET_CONFIG_REG_END                                0x0000ac00
    +#define R600_SET_CONTEXT_REG_OFFSET                            0x00028000
    +#define R600_SET_CONTEXT_REG_END                               0x00029000
    +#define R600_SET_ALU_CONST_OFFSET                              0x00030000
    +#define R600_SET_ALU_CONST_END                                 0x00032000
    +#define R600_SET_RESOURCE_OFFSET                               0x00038000
    +#define R600_SET_RESOURCE_END                                  0x0003c000
    +#define R600_SET_SAMPLER_OFFSET                                0x0003c000
    +#define R600_SET_SAMPLER_END                                   0x0003cff0
    +#define R600_SET_CTL_CONST_OFFSET                              0x0003cff0
    +#define R600_SET_CTL_CONST_END                                 0x0003e200
    +#define R600_SET_LOOP_CONST_OFFSET                             0x0003e200
    +#define R600_SET_LOOP_CONST_END                                0x0003e380
    +#define R600_SET_BOOL_CONST_OFFSET                             0x0003e380
    +#define R600_SET_BOOL_CONST_END                                0x00040000
    +
    +/* Packet 3 types */
    +#define R600_IT_INDIRECT_BUFFER_END               0x00001700
    +#define R600_IT_SET_PREDICATION                   0x00002000
    +#define R600_IT_REG_RMW                           0x00002100
    +#define R600_IT_COND_EXEC                         0x00002200
    +#define R600_IT_PRED_EXEC                         0x00002300
    +#define R600_IT_START_3D_CMDBUF                   0x00002400
    +#define R600_IT_DRAW_INDEX_2                      0x00002700
    +#define R600_IT_CONTEXT_CONTROL                   0x00002800
    +#define R600_IT_DRAW_INDEX_IMMD_BE                0x00002900
    +#define R600_IT_INDEX_TYPE                        0x00002A00
    +#define R600_IT_DRAW_INDEX                        0x00002B00
    +#define R600_IT_DRAW_INDEX_AUTO                   0x00002D00
    +#define R600_IT_DRAW_INDEX_IMMD                   0x00002E00
    +#define R600_IT_NUM_INSTANCES                     0x00002F00
    +#define R600_IT_STRMOUT_BUFFER_UPDATE             0x00003400
    +#define R600_IT_INDIRECT_BUFFER_MP                0x00003800
    +#define R600_IT_MEM_SEMAPHORE                     0x00003900
    +#define R600_IT_MPEG_INDEX                        0x00003A00
    +#define R600_IT_WAIT_REG_MEM                      0x00003C00
    +#define R600_IT_MEM_WRITE                         0x00003D00
    +#define R600_IT_INDIRECT_BUFFER                   0x00003200
    +#define R600_IT_CP_INTERRUPT                      0x00004000
    +#define R600_IT_SURFACE_SYNC                      0x00004300
    +#define R600_IT_ME_INITIALIZE                     0x00004400
    +#define R600_IT_COND_WRITE                        0x00004500
    +#define R600_IT_EVENT_WRITE                       0x00004600
    +#define R600_IT_EVENT_WRITE_EOP                   0x00004700
    +#define R600_IT_ONE_REG_WRITE                     0x00005700
    +#define R600_IT_SET_CONFIG_REG                    0x00006800
    +#define R600_IT_SET_CONTEXT_REG                   0x00006900
    +#define R600_IT_SET_ALU_CONST                     0x00006A00
    +#define R600_IT_SET_BOOL_CONST                    0x00006B00
    +#define R600_IT_SET_LOOP_CONST                    0x00006C00
    +#define R600_IT_SET_RESOURCE                      0x00006D00
    +#define R600_IT_SET_SAMPLER                       0x00006E00
    +#define R600_IT_SET_CTL_CONST                     0x00006F00
    +#define R600_IT_SURFACE_BASE_UPDATE               0x00007300
    +
    +int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
    +{
    +	struct drm_radeon_cs_parser parser;
    +	struct drm_radeon_private *dev_priv = dev->dev_private;
    +	struct drm_radeon_cs *cs = data;
    +	uint32_t cs_id;
    +	struct drm_radeon_cs_chunk __user **chunk_ptr = NULL;
    +	uint64_t *chunk_array;
    +	uint64_t *chunk_array_ptr;
    +	long size;
    +	int r, i;
    +
    +	mtx_lock(&dev_priv->cs.cs_mutex);
    +	/* set command stream id to 0 which is fake id */
    +	cs_id = 0;
    +	cs->cs_id = cs_id;
    +
    +	if (dev_priv == NULL) {
    +		DRM_ERROR("called with no initialization\n");
    +		mtx_unlock(&dev_priv->cs.cs_mutex);
    +		return -EINVAL;
    +	}
    +	if (!cs->num_chunks) {
    +		mtx_unlock(&dev_priv->cs.cs_mutex);
    +		return 0;
    +	}
    +
    +
    +	chunk_array = drm_calloc(cs->num_chunks, sizeof(uint64_t), DRM_MEM_DRIVER);
    +	if (!chunk_array) {
    +		mtx_unlock(&dev_priv->cs.cs_mutex);
    +		return -ENOMEM;
    +	}
    +
    +	chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks);
    +
    +	if (DRM_COPY_FROM_USER(chunk_array, chunk_array_ptr, sizeof(uint64_t)*cs->num_chunks)) {
    +		r = -EFAULT;
    +		goto out;
    +	}
    +
    +	parser.dev = dev;
    +	parser.file_priv = fpriv;
    +	parser.reloc_index = -1;
    +	parser.ib_index = -1;
    +	parser.num_chunks = cs->num_chunks;
    +	/* copy out the chunk headers */
    +	parser.chunks = drm_calloc(parser.num_chunks, sizeof(struct drm_radeon_kernel_chunk), DRM_MEM_DRIVER);
    +	if (!parser.chunks) {
    +		r = -ENOMEM;
    +		goto out;
    +	}
    +
    +	for (i = 0; i < parser.num_chunks; i++) {
    +		struct drm_radeon_cs_chunk user_chunk;
    +
    +		chunk_ptr = (void __user *)(unsigned long)chunk_array[i];
    +
    +		if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr, sizeof(struct drm_radeon_cs_chunk))){
    +			r = -EFAULT;
    +			goto out;
    +		}
    +		parser.chunks[i].chunk_id = user_chunk.chunk_id;
    +
    +		if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS)
    +			parser.reloc_index = i;
    +
    +		if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_IB)
    +			parser.ib_index = i;
    +
    +		if (parser.chunks[i].chunk_id == RADEON_CHUNK_ID_OLD) {
    +			parser.ib_index = i;
    +			parser.reloc_index = -1;
    +		}
    +
    +		parser.chunks[i].length_dw = user_chunk.length_dw;
    +		parser.chunks[i].chunk_data = (uint32_t *)(unsigned long)user_chunk.chunk_data;
    +
    +		parser.chunks[i].kdata = NULL;
    +		size = parser.chunks[i].length_dw * sizeof(uint32_t);
    +
    +		switch(parser.chunks[i].chunk_id) {
    +		case RADEON_CHUNK_ID_IB:
    +		case RADEON_CHUNK_ID_OLD:
    +			if (size == 0) {
    +				r = -EINVAL;
    +				goto out;
    +			}
    +		case RADEON_CHUNK_ID_RELOCS:
    +			if (size) {
    +				parser.chunks[i].kdata = drm_alloc(size, DRM_MEM_DRIVER);
    +				if (!parser.chunks[i].kdata) {
    +					r = -ENOMEM;
    +					goto out;
    +				}
    +
    +				if (DRM_COPY_FROM_USER(parser.chunks[i].kdata, parser.chunks[i].chunk_data, size)) {
    +					r = -EFAULT;
    +					goto out;
    +				}
    +			} else
    +				parser.chunks[i].kdata = NULL;
    +			break;
    +		default:
    +			break;
    +		}
    +		DRM_DEBUG("chunk %d %d %d %p\n", i, parser.chunks[i].chunk_id, parser.chunks[i].length_dw,
    +			  parser.chunks[i].chunk_data);
    +	}
    +
    +	if (parser.chunks[parser.ib_index].length_dw > (16 * 1024)) {
    +		DRM_ERROR("cs->dwords too big: %d\n", parser.chunks[parser.ib_index].length_dw);
    +		r = -EINVAL;
    +		goto out;
    +	}
    +
    +	/* get ib */
    +	r = dev_priv->cs.ib_get(&parser);
    +	if (r) {
    +		DRM_ERROR("ib_get failed\n");
    +		goto out;
    +	}
    +
    +	/* now parse command stream */
    +	r = dev_priv->cs.parse(&parser);
    +	if (r) {
    +		goto out;
    +	}
    +
    +out:
    +	dev_priv->cs.ib_free(&parser, r);
    +
    +	/* emit cs id sequence */
    +	dev_priv->cs.id_emit(&parser, &cs_id);
    +
    +	cs->cs_id = cs_id;
    +
    +	mtx_unlock(&dev_priv->cs.cs_mutex);
    +
    +	for (i = 0; i < parser.num_chunks; i++) {
    +		if (parser.chunks[i].kdata)
    +			drm_free(parser.chunks[i].kdata, parser.chunks[i].length_dw * sizeof(uint32_t), DRM_MEM_DRIVER);
    +	}
    +
    +	drm_free(parser.chunks, sizeof(struct drm_radeon_kernel_chunk)*parser.num_chunks, DRM_MEM_DRIVER);
    +	drm_free(chunk_array, sizeof(uint64_t)*parser.num_chunks, DRM_MEM_DRIVER);
    +
    +	return r;
    +}
    +
    +/* for non-mm */
    +static int r600_nomm_relocate(struct drm_radeon_cs_parser *parser, uint32_t *reloc, uint64_t *offset)
    +{
    +	struct drm_device *dev = parser->dev;
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +	struct drm_radeon_kernel_chunk *reloc_chunk = &parser->chunks[parser->reloc_index];
    +	uint32_t offset_dw = reloc[1];
    +
    +	//DRM_INFO("reloc: 0x%08x 0x%08x\n", reloc[0], reloc[1]);
    +	//DRM_INFO("length: %d\n", reloc_chunk->length_dw);
    +
    +	if (!reloc_chunk->kdata)
    +		return -EINVAL;
    +
    +	if (offset_dw > reloc_chunk->length_dw) {
    +		DRM_ERROR("Offset larger than chunk 0x%x %d\n", offset_dw, reloc_chunk->length_dw);
    +		return -EINVAL;
    +	}
    +
    +	/* 40 bit addr */
    +	*offset = reloc_chunk->kdata[offset_dw + 3];
    +	*offset <<= 32;
    +	*offset |= reloc_chunk->kdata[offset_dw + 0];
    +
    +	//DRM_INFO("offset 0x%lx\n", *offset);
    +
    +	if (!radeon_check_offset(dev_priv, *offset)) {
    +		DRM_ERROR("bad offset! 0x%lx\n", (unsigned long)*offset);
    +		return -EINVAL;
    +	}
    +
    +	return 0;
    +}
    +
    +static inline int r600_cs_packet0(struct drm_radeon_cs_parser *parser, uint32_t *offset_dw_p)
    +{
    +	uint32_t hdr, num_dw, reg;
    +	int count_dw = 1;
    +	int ret = 0;
    +	uint32_t offset_dw = *offset_dw_p;
    +	int incr = 2;
    +
    +	hdr = parser->chunks[parser->ib_index].kdata[offset_dw];
    +	num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2;
    +	reg = (hdr & 0xffff) << 2;
    +
    +	while (count_dw < num_dw) {
    +		switch (reg) {
    +		case AVIVO_D1MODE_VLINE_START_END:
    +		case AVIVO_D2MODE_VLINE_START_END:
    +			break;
    +		default:
    +			ret = -EINVAL;
    +			DRM_ERROR("bad packet 0 reg: 0x%08x\n", reg);
    +			break;
    +		}
    +		if (ret)
    +			break;
    +		count_dw++;
    +		reg += 4;
    +	}
    +	*offset_dw_p += incr;
    +	return ret;
    +}
    +
    +static inline int r600_cs_packet3(struct drm_radeon_cs_parser *parser, uint32_t *offset_dw_p)
    +{
    +	struct drm_device *dev = parser->dev;
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +	uint32_t hdr, num_dw, start_reg, end_reg, reg;
    +	uint32_t *reloc;
    +	uint64_t offset;
    +	int ret = 0;
    +	uint32_t offset_dw = *offset_dw_p;
    +	int incr = 2;
    +	int i;
    +	struct drm_radeon_kernel_chunk *ib_chunk;
    +
    +	ib_chunk = &parser->chunks[parser->ib_index];
    +
    +	hdr = ib_chunk->kdata[offset_dw];
    +	num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2;
    +
    +	/* just the ones we use for now, add more later */
    +	switch (hdr & 0xff00) {
    +	case R600_IT_START_3D_CMDBUF:
    +		//DRM_INFO("R600_IT_START_3D_CMDBUF\n");
    +		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
    +			ret = -EINVAL;
    +		if (num_dw != 2)
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad START_3D\n");
    +		break;
    +	case R600_IT_CONTEXT_CONTROL:
    +		//DRM_INFO("R600_IT_CONTEXT_CONTROL\n");
    +		if (num_dw != 3)
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad CONTEXT_CONTROL\n");
    +		break;
    +	case R600_IT_INDEX_TYPE:
    +	case R600_IT_NUM_INSTANCES:
    +		//DRM_INFO("R600_IT_INDEX_TYPE/R600_IT_NUM_INSTANCES\n");
    +		if (num_dw != 2)
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES\n");
    +		break;
    +	case R600_IT_DRAW_INDEX:
    +		//DRM_INFO("R600_IT_DRAW_INDEX\n");
    +		if (num_dw != 5) {
    +			ret = -EINVAL;
    +			DRM_ERROR("bad DRAW_INDEX\n");
    +			break;
    +		}
    +		reloc = ib_chunk->kdata + offset_dw + num_dw;
    +		ret = dev_priv->cs.relocate(parser, reloc, &offset);
    +		if (ret) {
    +			DRM_ERROR("bad DRAW_INDEX\n");
    +			break;
    +		}
    +		ib_chunk->kdata[offset_dw + 1] = (offset & 0xffffffff);
    +		ib_chunk->kdata[offset_dw + 2] = (upper_32_bits(offset) & 0xff);
    +		break;
    +	case R600_IT_DRAW_INDEX_AUTO:
    +		//DRM_INFO("R600_IT_DRAW_INDEX_AUTO\n");
    +		if (num_dw != 3)
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad DRAW_INDEX_AUTO\n");
    +		break;
    +	case R600_IT_DRAW_INDEX_IMMD_BE:
    +	case R600_IT_DRAW_INDEX_IMMD:
    +		//DRM_INFO("R600_IT_DRAW_INDEX_IMMD\n");
    +		if (num_dw < 4)
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad DRAW_INDEX_IMMD\n");
    +		break;
    +	case R600_IT_WAIT_REG_MEM:
    +		//DRM_INFO("R600_IT_WAIT_REG_MEM\n");
    +		if (num_dw != 7)
    +			ret = -EINVAL;
    +		/* bit 4 is reg (0) or mem (1) */
    +		if (ib_chunk->kdata[offset_dw + 1] & 0x10) {
    +			reloc = ib_chunk->kdata + offset_dw + num_dw;
    +			ret = dev_priv->cs.relocate(parser, reloc, &offset);
    +			if (ret) {
    +				DRM_ERROR("bad WAIT_REG_MEM\n");
    +				break;
    +			}
    +			ib_chunk->kdata[offset_dw + 2] = (offset & 0xffffffff);
    +			ib_chunk->kdata[offset_dw + 3] = (upper_32_bits(offset) & 0xff);
    +		}
    +		if (ret)
    +			DRM_ERROR("bad WAIT_REG_MEM\n");
    +		break;
    +	case R600_IT_SURFACE_SYNC:
    +		//DRM_INFO("R600_IT_SURFACE_SYNC\n");
    +		if (num_dw != 5)
    +			ret = -EINVAL;
    +		/* 0xffffffff/0x0 is flush all cache flag */
    +		else if ((ib_chunk->kdata[offset_dw + 2] == 0xffffffff) &&
    +			 (ib_chunk->kdata[offset_dw + 3] == 0))
    +			ret = 0;
    +		else {
    +			reloc = ib_chunk->kdata + offset_dw + num_dw;
    +			ret = dev_priv->cs.relocate(parser, reloc, &offset);
    +			if (ret) {
    +				DRM_ERROR("bad SURFACE_SYNC\n");
    +				break;
    +			}
    +			ib_chunk->kdata[offset_dw + 3] += ((offset >> 8) & 0xffffffff);
    +		}
    +		break;
    +	case R600_IT_EVENT_WRITE:
    +		//DRM_INFO("R600_IT_EVENT_WRITE\n");
    +		if ((num_dw != 4) && (num_dw != 2))
    +			ret = -EINVAL;
    +		if (num_dw > 2) {
    +			reloc = ib_chunk->kdata + offset_dw + num_dw;
    +			ret = dev_priv->cs.relocate(parser, reloc, &offset);
    +			if (ret) {
    +				DRM_ERROR("bad EVENT_WRITE\n");
    +				break;
    +			}
    +			ib_chunk->kdata[offset_dw + 2] += (offset & 0xffffffff);
    +			ib_chunk->kdata[offset_dw + 3] |= (upper_32_bits(offset) & 0xff);
    +		}
    +		if (ret)
    +			DRM_ERROR("bad EVENT_WRITE\n");
    +		break;
    +	case R600_IT_EVENT_WRITE_EOP:
    +		//DRM_INFO("R600_IT_EVENT_WRITE_EOP\n");
    +		if (num_dw != 6) {
    +			ret = -EINVAL;
    +			DRM_ERROR("bad EVENT_WRITE_EOP\n");
    +			break;
    +		}
    +		reloc = ib_chunk->kdata + offset_dw + num_dw;
    +		ret = dev_priv->cs.relocate(parser, reloc, &offset);
    +		if (ret) {
    +			DRM_ERROR("bad EVENT_WRITE_EOP\n");
    +			break;
    +		}
    +		ib_chunk->kdata[offset_dw + 2] += (offset & 0xffffffff);
    +		ib_chunk->kdata[offset_dw + 3] |= (upper_32_bits(offset) & 0xff);
    +		break;
    +	case R600_IT_SET_CONFIG_REG:
    +		//DRM_INFO("R600_IT_SET_CONFIG_REG\n");
    +		start_reg = (ib_chunk->kdata[offset_dw + 1] << 2) + R600_SET_CONFIG_REG_OFFSET;
    +		end_reg = 4 * (num_dw - 2) + start_reg - 4;
    +		if ((start_reg < R600_SET_CONFIG_REG_OFFSET) ||
    +		    (start_reg >= R600_SET_CONFIG_REG_END) ||
    +		    (end_reg >= R600_SET_CONFIG_REG_END))
    +			ret = -EINVAL;
    +		else {
    +			for (i = 0; i < (num_dw - 2); i++) {
    +				reg = start_reg + (4 * i);
    +				switch (reg) {
    +				case R600_CP_COHER_BASE:
    +					/* use R600_IT_SURFACE_SYNC */
    +					ret = -EINVAL;
    +					break;
    +				default:
    +					break;
    +				}
    +				if (ret)
    +					break;
    +			}
    +		}
    +		if (ret)
    +			DRM_ERROR("bad SET_CONFIG_REG\n");
    +		break;
    +	case R600_IT_SET_CONTEXT_REG:
    +		//DRM_INFO("R600_IT_SET_CONTEXT_REG\n");
    +		start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
    +		start_reg += R600_SET_CONTEXT_REG_OFFSET;
    +		end_reg = 4 * (num_dw - 2) + start_reg - 4;
    +		if ((start_reg < R600_SET_CONTEXT_REG_OFFSET) ||
    +		    (start_reg >= R600_SET_CONTEXT_REG_END) ||
    +		    (end_reg >= R600_SET_CONTEXT_REG_END))
    +			ret = -EINVAL;
    +		else {
    +			for (i = 0; i < (num_dw - 2); i++) {
    +				reg = start_reg + (4 * i);
    +				switch (reg) {
    +				case R600_DB_DEPTH_BASE:
    +				case R600_CB_COLOR0_BASE:
    +				case R600_CB_COLOR1_BASE:
    +				case R600_CB_COLOR2_BASE:
    +				case R600_CB_COLOR3_BASE:
    +				case R600_CB_COLOR4_BASE:
    +				case R600_CB_COLOR5_BASE:
    +				case R600_CB_COLOR6_BASE:
    +				case R600_CB_COLOR7_BASE:
    +				case R600_SQ_PGM_START_FS:
    +				case R600_SQ_PGM_START_ES:
    +				case R600_SQ_PGM_START_VS:
    +				case R600_SQ_PGM_START_GS:
    +				case R600_SQ_PGM_START_PS:
    +					//DRM_INFO("reg: 0x%08x\n", reg);
    +					reloc = ib_chunk->kdata + offset_dw + num_dw + (i * 2);
    +					ret = dev_priv->cs.relocate(parser, reloc, &offset);
    +					if (ret) {
    +						DRM_ERROR("bad SET_CONTEXT_REG\n");
    +						break;
    +					}
    +					ib_chunk->kdata[offset_dw + 2 + i] +=
    +						((offset >> 8) & 0xffffffff);
    +					break;
    +				case R600_VGT_DMA_BASE:
    +				case R600_VGT_DMA_BASE_HI:
    +					/* These should be handled by DRAW_INDEX packet 3 */
    +				case R600_VGT_STRMOUT_BASE_OFFSET_0:
    +				case R600_VGT_STRMOUT_BASE_OFFSET_1:
    +				case R600_VGT_STRMOUT_BASE_OFFSET_2:
    +				case R600_VGT_STRMOUT_BASE_OFFSET_3:
    +				case R600_VGT_STRMOUT_BASE_OFFSET_HI_0:
    +				case R600_VGT_STRMOUT_BASE_OFFSET_HI_1:
    +				case R600_VGT_STRMOUT_BASE_OFFSET_HI_2:
    +				case R600_VGT_STRMOUT_BASE_OFFSET_HI_3:
    +				case R600_VGT_STRMOUT_BUFFER_BASE_0:
    +				case R600_VGT_STRMOUT_BUFFER_BASE_1:
    +				case R600_VGT_STRMOUT_BUFFER_BASE_2:
    +				case R600_VGT_STRMOUT_BUFFER_BASE_3:
    +				case R600_VGT_STRMOUT_BUFFER_OFFSET_0:
    +				case R600_VGT_STRMOUT_BUFFER_OFFSET_1:
    +				case R600_VGT_STRMOUT_BUFFER_OFFSET_2:
    +				case R600_VGT_STRMOUT_BUFFER_OFFSET_3:
    +					/* These should be handled by STRMOUT_BUFFER packet 3 */
    +					DRM_ERROR("bad context reg: 0x%08x\n", reg);
    +					ret = -EINVAL;
    +					break;
    +				default:
    +					break;
    +				}
    +				if (ret)
    +					break;
    +			}
    +		}
    +		if (ret)
    +			DRM_ERROR("bad SET_CONTEXT_REG\n");
    +		break;
    +	case R600_IT_SET_RESOURCE:
    +		//DRM_INFO("R600_IT_SET_RESOURCE\n");
    +		if ((num_dw - 2) % 7)
    +			ret = -EINVAL;
    +		start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
    +		start_reg += R600_SET_RESOURCE_OFFSET;
    +		end_reg = 4 * (num_dw - 2) + start_reg - 4;
    +		if ((start_reg < R600_SET_RESOURCE_OFFSET) ||
    +		    (start_reg >= R600_SET_RESOURCE_END) ||
    +		    (end_reg >= R600_SET_RESOURCE_END))
    +			ret = -EINVAL;
    +		else {
    +			for (i = 0; i < ((num_dw - 2) / 7); i++) {
    +				switch ((ib_chunk->kdata[offset_dw + (i * 7) + 6 + 2] & 0xc0000000) >> 30) {
    +				case R600_SQ_TEX_VTX_INVALID_TEXTURE:
    +				case R600_SQ_TEX_VTX_INVALID_BUFFER:
    +				default:
    +					ret = -EINVAL;
    +					break;
    +				case R600_SQ_TEX_VTX_VALID_TEXTURE:
    +					/* tex base */
    +					reloc = ib_chunk->kdata + offset_dw + num_dw + (i * 4);
    +					ret = dev_priv->cs.relocate(parser, reloc, &offset);
    +					if (ret)
    +						break;
    +					ib_chunk->kdata[offset_dw + (i * 7) + 2 + 2] +=
    +						((offset >> 8) & 0xffffffff);
    +					/* tex mip base */
    +					reloc = ib_chunk->kdata + offset_dw + num_dw + (i * 4) + 2;
    +					ret = dev_priv->cs.relocate(parser, reloc, &offset);
    +					if (ret)
    +						break;
    +					ib_chunk->kdata[offset_dw + (i * 7) + 3 + 2] +=
    +						((offset >> 8) & 0xffffffff);
    +					break;
    +				case R600_SQ_TEX_VTX_VALID_BUFFER:
    +					/* vtx base */
    +					reloc = ib_chunk->kdata + offset_dw + num_dw + (i * 2);
    +					ret = dev_priv->cs.relocate(parser, reloc, &offset);
    +					if (ret)
    +						break;
    +					ib_chunk->kdata[offset_dw + (i * 7) + 0 + 2] += (offset & 0xffffffff);
    +					ib_chunk->kdata[offset_dw + (i * 7) + 2 + 2] |= (upper_32_bits(offset) & 0xff);
    +					break;
    +				}
    +				if (ret)
    +					break;
    +			}
    +		}
    +		if (ret)
    +			DRM_ERROR("bad SET_RESOURCE\n");
    +		break;
    +	case R600_IT_SET_ALU_CONST:
    +		//DRM_INFO("R600_IT_SET_ALU_CONST\n");
    +		start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
    +		start_reg += R600_SET_ALU_CONST_OFFSET;
    +		end_reg = 4 * (num_dw - 2) + start_reg - 4;
    +		if ((start_reg < R600_SET_ALU_CONST_OFFSET) ||
    +		    (start_reg >= R600_SET_ALU_CONST_END) ||
    +		    (end_reg >= R600_SET_ALU_CONST_END))
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad SET_ALU_CONST\n");
    +		break;
    +	case R600_IT_SET_BOOL_CONST:
    +		//DRM_INFO("R600_IT_SET_BOOL_CONST\n");
    +		start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
    +		start_reg += R600_SET_BOOL_CONST_OFFSET;
    +		end_reg = 4 * (num_dw - 2) + start_reg - 4;
    +		if ((start_reg < R600_SET_BOOL_CONST_OFFSET) ||
    +		    (start_reg >= R600_SET_BOOL_CONST_END) ||
    +		    (end_reg >= R600_SET_BOOL_CONST_END))
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad SET_BOOL_CONST\n");
    +		break;
    +	case R600_IT_SET_LOOP_CONST:
    +		//DRM_INFO("R600_IT_SET_LOOP_CONST\n");
    +		start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
    +		start_reg += R600_SET_LOOP_CONST_OFFSET;
    +		end_reg = 4 * (num_dw - 2) + start_reg - 4;
    +		if ((start_reg < R600_SET_LOOP_CONST_OFFSET) ||
    +		    (start_reg >= R600_SET_LOOP_CONST_END) ||
    +		    (end_reg >= R600_SET_LOOP_CONST_END))
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad SET_LOOP_CONST\n");
    +		break;
    +	case R600_IT_SET_CTL_CONST:
    +		//DRM_INFO("R600_IT_SET_CTL_CONST\n");
    +		start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
    +		start_reg += R600_SET_CTL_CONST_OFFSET;
    +		end_reg = 4 * (num_dw - 2) + start_reg - 4;
    +		if ((start_reg < R600_SET_CTL_CONST_OFFSET) ||
    +		    (start_reg >= R600_SET_CTL_CONST_END) ||
    +		    (end_reg >= R600_SET_CTL_CONST_END))
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad SET_CTL_CONST\n");
    +		break;
    +	case R600_IT_SET_SAMPLER:
    +		//DRM_INFO("R600_IT_SET_SAMPLER\n");
    +		if ((num_dw - 2) % 3)
    +			ret = -EINVAL;
    +		start_reg = ib_chunk->kdata[offset_dw + 1] << 2;
    +		start_reg += R600_SET_SAMPLER_OFFSET;
    +		end_reg = 4 * (num_dw - 2) + start_reg - 4;
    +		if ((start_reg < R600_SET_SAMPLER_OFFSET) ||
    +		    (start_reg >= R600_SET_SAMPLER_END) ||
    +		    (end_reg >= R600_SET_SAMPLER_END))
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad SET_SAMPLER\n");
    +		break;
    +	case R600_IT_SURFACE_BASE_UPDATE:
    +		//DRM_INFO("R600_IT_SURFACE_BASE_UPDATE\n");
    +		if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) ||
    +		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600))
    +			ret = -EINVAL;
    +		if (num_dw != 2)
    +			ret = -EINVAL;
    +		if (ret)
    +			DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
    +		break;
    +	case RADEON_CP_NOP:
    +		//DRM_INFO("NOP: %d\n", ib_chunk->kdata[offset_dw + 1]);
    +		break;
    +	default:
    +		DRM_ERROR("invalid packet 3 0x%08x\n", 0xff00);
    +		ret = -EINVAL;
    +		break;
    +	}
    +
    +	*offset_dw_p += incr;
    +	return ret;
    +}
    +
    +static int r600_cs_parse(struct drm_radeon_cs_parser *parser)
    +{
    +	volatile int rb;
    +	struct drm_radeon_kernel_chunk *ib_chunk;
    +	/* scan the packet for various things */
    +	int count_dw = 0, size_dw;
    +	int ret = 0;
    +
    +	ib_chunk = &parser->chunks[parser->ib_index];
    +	size_dw = ib_chunk->length_dw;
    +
    +	while (count_dw < size_dw && ret == 0) {
    +		int hdr = ib_chunk->kdata[count_dw];
    +		int num_dw = (hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16;
    +
    +		switch (hdr & RADEON_CP_PACKET_MASK) {
    +		case RADEON_CP_PACKET0:
    +			ret = r600_cs_packet0(parser, &count_dw);
    +			break;
    +		case RADEON_CP_PACKET1:
    +			ret = -EINVAL;
    +			break;
    +		case RADEON_CP_PACKET2:
    +			DRM_DEBUG("Packet 2\n");
    +			num_dw += 1;
    +			break;
    +		case RADEON_CP_PACKET3:
    +			ret = r600_cs_packet3(parser, &count_dw);
    +			break;
    +		}
    +
    +		count_dw += num_dw;
    +	}
    +
    +	if (ret)
    +		return ret;
    +
    +
    +	/* copy the packet into the IB */
    +	memcpy(parser->ib, ib_chunk->kdata, ib_chunk->length_dw * sizeof(uint32_t));
    +
    +	/* read back last byte to flush WC buffers */
    +	rb = readl(((vm_offset_t)parser->ib + (ib_chunk->length_dw-1) * sizeof(uint32_t)));
    +
    +	return 0;
    +}
    +
    +static uint32_t radeon_cs_id_get(struct drm_radeon_private *radeon)
    +{
    +	/* FIXME: protect with a spinlock */
    +	/* FIXME: check if wrap affect last reported wrap & sequence */
    +	radeon->cs.id_scnt = (radeon->cs.id_scnt + 1) & 0x00FFFFFF;
    +	if (!radeon->cs.id_scnt) {
    +		/* increment wrap counter */
    +		radeon->cs.id_wcnt += 0x01000000;
    +		/* valid sequence counter start at 1 */
    +		radeon->cs.id_scnt = 1;
    +	}
    +	return (radeon->cs.id_scnt | radeon->cs.id_wcnt);
    +}
    +
    +static void r600_cs_id_emit(struct drm_radeon_cs_parser *parser, uint32_t *id)
    +{
    +	drm_radeon_private_t *dev_priv = parser->dev->dev_private;
    +	RING_LOCALS;
    +
    +	//dev_priv->irq_emitted = radeon_update_breadcrumb(parser->dev);
    +
    +	*id = radeon_cs_id_get(dev_priv);
    +
    +	/* SCRATCH 2 */
    +	BEGIN_RING(3);
    +	R600_CLEAR_AGE(*id);
    +	ADVANCE_RING();
    +	COMMIT_RING();
    +}
    +
    +static uint32_t r600_cs_id_last_get(struct drm_device *dev)
    +{
    +	//drm_radeon_private_t *dev_priv = dev->dev_private;
    +
    +	//return GET_R600_SCRATCH(dev_priv, 2);
    +	return 0;
    +}
    +
    +static int r600_ib_get(struct drm_radeon_cs_parser *parser)
    +{
    +	struct drm_device *dev = parser->dev;
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +	struct drm_buf *buf;
    +
    +	buf = radeon_freelist_get(dev);
    +	if (!buf) {
    +		dev_priv->cs_buf = NULL;
    +		return -EBUSY;
    +	}
    +	buf->file_priv = parser->file_priv;
    +	dev_priv->cs_buf = buf;
    +	parser->ib = (void *)((vm_offset_t)dev->agp_buffer_map->handle +
    +	    buf->offset);
    +
    +	return 0;
    +}
    +
    +static void r600_ib_free(struct drm_radeon_cs_parser *parser, int error)
    +{
    +	struct drm_device *dev = parser->dev;
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +	struct drm_buf *buf = dev_priv->cs_buf;
    +
    +	if (buf) {
    +		if (!error)
    +			r600_cp_dispatch_indirect(dev, buf, 0,
    +						  parser->chunks[parser->ib_index].length_dw * sizeof(uint32_t));
    +		radeon_cp_discard_buffer(dev, buf);
    +		COMMIT_RING();
    +	}
    +}
    +
    +int r600_cs_init(struct drm_device *dev)
    +{
    +	drm_radeon_private_t *dev_priv = dev->dev_private;
    +
    +	dev_priv->cs.ib_get = r600_ib_get;
    +	dev_priv->cs.ib_free = r600_ib_free;
    +	dev_priv->cs.id_emit = r600_cs_id_emit;
    +	dev_priv->cs.id_last_get = r600_cs_id_last_get;
    +	dev_priv->cs.parse = r600_cs_parse;
    +	dev_priv->cs.relocate = r600_nomm_relocate;
    +	return 0;
    +}
    diff --git a/sys/dev/drm/radeon_drm.h b/sys/dev/drm/radeon_drm.h
    index 70d3aaa6fc5..2e64e29092d 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 {
    @@ -755,4 +758,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 5914b13b5dd..983733a652c 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:
      *
    @@ -236,6 +236,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)
     
    @@ -349,6 +389,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;
     
    @@ -379,10 +425,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));
    @@ -476,6 +522,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
      */
    @@ -1827,26 +1900,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)
     
    @@ -1961,14 +2046,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..7c312211dd6 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;
     }
    @@ -3156,6 +3162,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 +3230,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/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 
    
    From e1ec1f53b14961386e489b4fcb90bd9a9a3e65d6 Mon Sep 17 00:00:00 2001
    From: Robert Noland 
    Date: Sun, 23 Aug 2009 15:02:58 +0000
    Subject: [PATCH 165/453] Add GET_PARAM support for Z pipes.
    
    This is needed for occulsion queries on rv530 chips.
    
    MFC after:	2 weeks
    ---
     sys/dev/drm/radeon_cp.c    | 9 +++++++++
     sys/dev/drm/radeon_drm.h   | 2 ++
     sys/dev/drm/radeon_drv.h   | 6 +++++-
     sys/dev/drm/radeon_state.c | 3 +++
     4 files changed, 19 insertions(+), 1 deletion(-)
    
    diff --git a/sys/dev/drm/radeon_cp.c b/sys/dev/drm/radeon_cp.c
    index 3a4aa983377..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);
    diff --git a/sys/dev/drm/radeon_drm.h b/sys/dev/drm/radeon_drm.h
    index 2e64e29092d..11f2fcb8d8a 100644
    --- a/sys/dev/drm/radeon_drm.h
    +++ b/sys/dev/drm/radeon_drm.h
    @@ -688,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;
    diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h
    index 983733a652c..a1cd48bc20d 100644
    --- a/sys/dev/drm/radeon_drv.h
    +++ b/sys/dev/drm/radeon_drv.h
    @@ -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
     
     /*
    @@ -368,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;
     
    @@ -758,6 +761,7 @@ extern int r600_cs_init(struct drm_device *dev);
     
     /* 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)
    diff --git a/sys/dev/drm/radeon_state.c b/sys/dev/drm/radeon_state.c
    index 7c312211dd6..e032b8f811e 100644
    --- a/sys/dev/drm/radeon_state.c
    +++ b/sys/dev/drm/radeon_state.c
    @@ -3078,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;
    
    From 41fe1fab16c63db5ac1ead49036d2359314ac616 Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Sun, 23 Aug 2009 16:04:10 +0000
    Subject: [PATCH 166/453] Enable _DIRENT_HAVE_D_TYPE so wpa_cli scans
     directories properly for it's unix domain socket.  Before this change wpa_cli
     would take the first file in the directory that was not "." or "..".
    
    Submitted by:	Brandon Gooch 
    MFC after:	3 days
    ---
     usr.sbin/wpa/wpa_cli/Makefile | 2 ++
     1 file changed, 2 insertions(+)
    
    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
    
    From d429d7201e8f70b30b132ee07b2aef42bc46c608 Mon Sep 17 00:00:00 2001
    From: Hajimu UMEMOTO 
    Date: Sun, 23 Aug 2009 17:00:16 +0000
    Subject: [PATCH 167/453] - Add AS lookup functionality to traceroute6(8) as
     well. - Support for IPv6 transport for AS lookup. - Introduce $RA_SERVER to
     set whois server. - Support for 4 byte ASN. - ANSIfy function declaration in
     as.c.
    
    Tested by:	IHANet folks.
    ---
     contrib/traceroute/as.c            | 86 +++++++++++++-----------------
     contrib/traceroute/as.h            |  6 +--
     contrib/traceroute/traceroute.c    | 10 ++--
     usr.sbin/traceroute6/Makefile      |  5 ++
     usr.sbin/traceroute6/traceroute6.8 | 11 +++-
     usr.sbin/traceroute6/traceroute6.c | 29 +++++++++-
     6 files changed, 87 insertions(+), 60 deletions(-)
    
    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/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)
    
    From 43ec3cc665558fc6e3f22dd6ea184ea302bf8a10 Mon Sep 17 00:00:00 2001
    From: Ivan Voras 
    Date: Sun, 23 Aug 2009 18:15:13 +0000
    Subject: [PATCH 168/453] Remove (c) line.
    
    Requested by:	pjd
    Approved by:	gnn (mentor)
    MFC after:	1 month
    ---
     sbin/geom/class/label/glabel.8 | 1 -
     1 file changed, 1 deletion(-)
    
    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
    
    From 01318abc57a6012fc71129351d6e1a2ce3e2feb4 Mon Sep 17 00:00:00 2001
    From: Antoine Brodin 
    Date: Sun, 23 Aug 2009 18:28:58 +0000
    Subject: [PATCH 169/453] ObsoleteFiles.inc:   kthread_create(9) was
     resurrected as a mlink to kproc(9)
    
    ---
     ObsoleteFiles.inc | 2 --
     1 file changed, 2 deletions(-)
    
    diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
    index 9bed51f280b..e963f655351 100644
    --- a/ObsoleteFiles.inc
    +++ b/ObsoleteFiles.inc
    @@ -803,8 +803,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
    
    From 6913541fe4e3e70fc838fe1a722712bbe187ed1c Mon Sep 17 00:00:00 2001
    From: Doug Barton 
    Date: Sun, 23 Aug 2009 19:52:47 +0000
    Subject: [PATCH 170/453] Prior to the dire warning about values of
     network_interfaces other than AUTO the biggest mistake users made was leaving
     lo0 off the list. Since lo0 is effectively mandatory, check for it and add it
     to the list if it's not there.
    
    ---
     etc/network.subr | 7 +++++++
     1 file changed, 7 insertions(+)
    
    diff --git a/etc/network.subr b/etc/network.subr
    index c14985473e9..f3a85603bf5 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 '*)	;;	# This is fine, do nothing
    +		*)	_tmplist="lo0 ${_tmplist}" ;;
    +		esac
     		;;
     	esac
     
    
    From 562c5c5bf0e2132becca80623bda5038e069406e Mon Sep 17 00:00:00 2001
    From: Olivier Houchard 
    Date: Sun, 23 Aug 2009 19:54:36 +0000
    Subject: [PATCH 171/453] No need to remove the same flag multiple times.
    
    ---
     sys/arm/xscale/ixp425/ixdp425_pci.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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
    
    From bfdaa523828e5a7e690ec5d7e9b5353bef992d2f Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Sun, 23 Aug 2009 20:26:09 +0000
    Subject: [PATCH 172/453] Allow pty(4) to be loaded as a kld.
    
    Unfortunately, the wrappers that are present in pts(4) don't have the
    mechanics to allow pty(4) to be unloaded safely, so I'm forcing this kld
    to return EBUSY. This also means we have to enable some extra code in
    pts(4) unconditionally.
    
    Proposed by:	rwatson
    ---
     sys/conf/files                        |  2 +-
     sys/conf/options                      |  1 -
     sys/{kern/tty_pty.c => dev/pty/pty.c} | 22 ++++++++++++++++++----
     sys/kern/tty_pts.c                    |  4 ----
     sys/modules/pty/Makefile              |  8 ++++++++
     5 files changed, 27 insertions(+), 10 deletions(-)
     rename sys/{kern/tty_pty.c => dev/pty/pty.c} (90%)
     create mode 100644 sys/modules/pty/Makefile
    
    diff --git a/sys/conf/files b/sys/conf/files
    index 69997985027..b5baadee14b 100644
    --- a/sys/conf/files
    +++ b/sys/conf/files
    @@ -1297,6 +1297,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
    @@ -2059,7 +2060,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
    diff --git a/sys/conf/options b/sys/conf/options
    index ac2d87c0195..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
    diff --git a/sys/kern/tty_pty.c b/sys/dev/pty/pty.c
    similarity index 90%
    rename from sys/kern/tty_pty.c
    rename to sys/dev/pty/pty.c
    index 169229d15ec..d3dce9f1746 100644
    --- a/sys/kern/tty_pty.c
    +++ b/sys/dev/pty/pty.c
    @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -117,11 +118,24 @@ 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
    +pty_modevent(module_t mod, int type, void *data)
     {
     
    -	EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
    +        switch(type) {
    +        case MOD_LOAD: 
    +		EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
    +		break;
    +	case MOD_SHUTDOWN:
    +		break;
    +	case MOD_UNLOAD:
    +		/* XXX: No unloading support yet. */
    +		return (EBUSY);
    +	default:
    +		return (EOPNOTSUPP);
    +	}
    +
    +	return (0);
     }
     
    -SYSINIT(pty, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, pty_init, NULL);
    +DEV_MODULE(pty, pty_modevent, NULL);
    diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
    index c77cf2a1d82..b38070a3f12 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. */
     #define PTS_EXTERNAL
    -#endif /* DEV_PTY */
     /* Add bits to make Linux binaries work. */
     #define PTS_LINUX
     
    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 
    
    From 77dfcdc44559d4bca03d156d87c2e214c6172c04 Mon Sep 17 00:00:00 2001
    From: Robert Watson 
    Date: Sun, 23 Aug 2009 20:40:19 +0000
    Subject: [PATCH 173/453] Rework global locks for interface list and index
     management, correcting several critical bugs, including race conditions and
     lock order issues:
    
    Replace the single rwlock, ifnet_lock, with two locks, an rwlock and an
    sxlock.  Either can be held to stablize the lists and indexes, but both
    are required to write.  This allows the list to be held stable in both
    network interrupt contexts and sleepable user threads across sleeping
    memory allocations or device driver interactions.  As before, writes to
    the interface list must occur from sleepable contexts.
    
    Reviewed by:	bz, julian
    MFC after:	3 days
    ---
     sys/compat/linux/linux_ioctl.c    | 10 ++--
     sys/contrib/altq/altq/altq_subr.c |  8 +--
     sys/kern/kern_uuid.c              |  6 +-
     sys/net/bridgestp.c               |  4 +-
     sys/net/if.c                      | 94 +++++++++++++++++++------------
     sys/net/if_llatbl.c               |  8 +--
     sys/net/if_var.h                  | 42 +++++++++++---
     sys/net/if_vlan.c                 |  4 +-
     sys/netgraph/ng_gif.c             |  4 +-
     sys/netinet/in.c                  |  7 +--
     sys/netinet6/icmp6.c              | 12 ++--
     sys/netinet6/in6.c                | 11 +---
     sys/netinet6/in6_ifattach.c       |  6 +-
     sys/netinet6/nd6.c                |  4 +-
     sys/netipsec/xform_ipip.c         |  8 +--
     sys/nfsclient/bootp_subr.c        |  2 +-
     16 files changed, 133 insertions(+), 97 deletions(-)
    
    diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
    index 11dc6d5041b..03ac3340749 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);
     }
    @@ -2177,7 +2175,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;
     
    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/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/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/if.c b/sys/net/if.c
    index 5d108981cdd..fe497d69de2 100644
    --- a/sys/net/if.c
    +++ b/sys/net/if.c
    @@ -154,14 +154,26 @@ 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;
    +
     static	if_com_alloc_t *if_com_alloc[256];
     static	if_com_free_t *if_com_free[256];
     
    @@ -188,9 +200,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 +211,19 @@ 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);
     }
     
     static void
    -ifnet_setbyindex(u_short idx, struct ifnet *ifp)
    +ifnet_setbyindex_locked(u_short idx, struct ifnet *ifp)
     {
     
     	IFNET_WLOCK_ASSERT();
    @@ -219,16 +231,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);
     }
     
    @@ -361,9 +382,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,7 +402,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);
    +	ifnet_setbyindex_locked(ifp->if_index, NULL);
     	while (V_if_index > 0 && ifnet_byindex_locked(V_if_index) == NULL)
     		V_if_index--;
     	IFNET_WUNLOCK();
    @@ -855,11 +874,14 @@ 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);
    +	ifnet_setbyindex_locked(ifp->if_index, NULL);
     	while (V_if_index > 0 && ifnet_byindex_locked(V_if_index) == NULL)
     		V_if_index--;
     	IFNET_WUNLOCK();
    @@ -886,7 +908,7 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
     		V_if_index = ifp->if_index;
     	if (V_if_index >= V_if_indexlim)
     		if_grow();
    -	ifnet_setbyindex(ifp->if_index, ifp);
    +	ifnet_setbyindex_locked(ifp->if_index, ifp);
     	IFNET_WUNLOCK();
     
     	if_attach_internal(ifp, 1);
    @@ -1368,7 +1390,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 +1417,7 @@ ifa_ifwithaddr_internal(struct sockaddr *addr, int getref)
     	}
     	ifa = NULL;
     done:
    -	IFNET_RUNLOCK();
    +	IFNET_RUNLOCK_NOSLEEP();
     	return (ifa);
     }
     
    @@ -1423,7 +1445,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 +1464,7 @@ ifa_ifwithbroadaddr(struct sockaddr *addr)
     	}
     	ifa = NULL;
     done:
    -	IFNET_RUNLOCK();
    +	IFNET_RUNLOCK_NOSLEEP();
     	return (ifa);
     }
     
    @@ -1456,7 +1478,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 +1497,7 @@ ifa_ifwithdstaddr(struct sockaddr *addr)
     	}
     	ifa = NULL;
     done:
    -	IFNET_RUNLOCK();
    +	IFNET_RUNLOCK_NOSLEEP();
     	return (ifa);
     }
     
    @@ -1508,7 +1530,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 +1606,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 +1885,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 +1896,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 +1911,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 +1919,7 @@ ifunit_ref(const char *name)
     	}
     	if (ifp != NULL)
     		if_ref(ifp);
    -	IFNET_RUNLOCK();
    +	IFNET_RUNLOCK_NOSLEEP();
     	return (ifp);
     }
     
    @@ -1906,12 +1928,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 +2543,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 +2868,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 +2917,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 +2925,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_llatbl.c b/sys/net/if_llatbl.c
    index a1b574f9f37..a3617f50d65 100644
    --- a/sys/net/if_llatbl.c
    +++ b/sys/net/if_llatbl.c
    @@ -200,14 +200,14 @@ lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask)
     {
     	struct lltable *llt;
     
    -	IFNET_RLOCK();
    +	IFNET_RLOCK_NOSLEEP();
     	SLIST_FOREACH(llt, &lltables, llt_link) {
     		if (llt->llt_af != af)
     			continue;
     
     		llt->llt_prefix_free(llt, prefix, mask);
     	}
    -	IFNET_RUNLOCK();
    +	IFNET_RUNLOCK_NOSLEEP();
     }
     
     
    @@ -300,13 +300,13 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
     	}
     
     	/* XXX linked list may be too expensive */
    -	IFNET_RLOCK();
    +	IFNET_RLOCK_NOSLEEP();
     	SLIST_FOREACH(llt, &lltables, llt_link) {
     		if (llt->llt_af == dst->sa_family &&
     		    llt->llt_ifp == ifp)
     			break;
     	}
    -	IFNET_RUNLOCK();
    +	IFNET_RUNLOCK_NOSLEEP();
     	KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n"));
     
     	if (flags && LLE_CREATE)
    diff --git a/sys/net/if_var.h b/sys/net/if_var.h
    index aa83161cce3..0bfd9f19a8a 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 
     
    @@ -754,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
    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/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/in.c b/sys/netinet/in.c
    index 15d38b191b5..8c9984c1c62 100644
    --- a/sys/netinet/in.c
    +++ b/sys/netinet/in.c
    @@ -1407,12 +1407,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();
    +	IFNET_RLOCK_ASSERT();
     
     	error = 0;
     	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
    diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
    index 7fe63b603cf..6f13c692d0c 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);
     }
    diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
    index c4333ed60a6..7d9f7e7620a 100644
    --- a/sys/netinet6/in6.c
    +++ b/sys/netinet6/in6.c
    @@ -2234,7 +2234,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 */
    @@ -2244,7 +2244,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;
     }
    @@ -2495,12 +2495,7 @@ 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();
    +	IFNET_RLOCK_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/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/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)) {
    
    From 6852110b6488f38f8d6139d6265deb26f29d7a11 Mon Sep 17 00:00:00 2001
    From: Robert Watson 
    Date: Sun, 23 Aug 2009 21:00:21 +0000
    Subject: [PATCH 174/453] Rather than using IFNET_RLOCK() when iterating over
     (and modifying) the ifnet list during if_ef load, directly acquire the
     ifnet_sxlock exclusively.  That way when if_alloc() recurses the lock, it's a
     write recursion rather than a read->write recursion.
    
    This code structure is arguably a bug, so add a comment indicating that
    this is the case.  Post-8.0, we should fix this, but this commit
    resolves panic-on-load for if_ef.
    
    Discussed with:	bz, julian
    Reported by:	phk
    MFC after:	3 days
    ---
     sys/net/if_ef.c | 17 +++++++++++++++--
     1 file changed, 15 insertions(+), 2 deletions(-)
    
    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();
    
    From eb33e843b84fbb6d20613f9bec9fa0013d61d7e3 Mon Sep 17 00:00:00 2001
    From: Jilles Tjoelker 
    Date: Sun, 23 Aug 2009 21:09:46 +0000
    Subject: [PATCH 175/453] sh: Fix crash when undefining or redefining a
     currently executing function.
    
    Add a reference count to function definitions.
    Memory may leak if multiple SIGINTs arrive in interactive mode,
    this will be fixed later by changing SIGINT handling.
    
    PR:		bin/137640
    ---
     bin/sh/eval.c                             |  7 +++--
     bin/sh/exec.c                             |  8 +++---
     bin/sh/exec.h                             |  3 +-
     bin/sh/mknodes.c                          |  9 ++++--
     bin/sh/nodes.c.pat                        | 35 +++++++++++++++++------
     tools/regression/bin/sh/execution/func1.0 |  4 +++
     6 files changed, 48 insertions(+), 18 deletions(-)
     create mode 100644 tools/regression/bin/sh/execution/func1.0
    
    diff --git a/bin/sh/eval.c b/bin/sh/eval.c
    index 39e16602abf..8dfa7ddf406 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(&cmdentry.u.func->n, EV_TESTED);
     		else
    -			evaltree(cmdentry.u.func, 0);
    +			evaltree(&cmdentry.u.func->n, 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..639a23cf78f 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(&cmdp->param.func->n);
     			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..904f9f4092a 100644
    --- a/bin/sh/mknodes.c
    +++ b/bin/sh/mknodes.c
    @@ -248,8 +248,13 @@ 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("\tunsigned int refcount;\n", hfile);
    +	fputs("\tunion node n;\n", hfile);
    +	fputs("};\n\n\n", hfile);
    +	fputs("struct funcdef *copyfunc(union node *);\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..b6a855977d7 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.
      */
    @@ -65,17 +66,22 @@ STATIC char *nodesavestr(char *);
      * 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;
     }
     
     
    @@ -144,14 +150,25 @@ nodesavestr(char *s)
     }
     
     
    +void
    +reffunc(struct funcdef *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/tools/regression/bin/sh/execution/func1.0 b/tools/regression/bin/sh/execution/func1.0
    new file mode 100644
    index 00000000000..317b0058868
    --- /dev/null
    +++ b/tools/regression/bin/sh/execution/func1.0
    @@ -0,0 +1,4 @@
    +# $FreeBSD$
    +
    +MALLOC_OPTIONS=J sh -c 'g() { g() { :; }; :; }; g' &&
    +MALLOC_OPTIONS=J sh -c 'g() { unset -f g; :; }; g'
    
    From 7c4e421f767862aca206c9c1f01a040c19c9497d Mon Sep 17 00:00:00 2001
    From: Olivier Houchard 
    Date: Sun, 23 Aug 2009 23:37:53 +0000
    Subject: [PATCH 176/453] KDB needs , so move it under
     #ifdef KDB. While I'm there, remove dead code, we will never support acorn26.
    
    ---
     sys/arm/arm/undefined.c | 5 ++---
     1 file changed, 2 insertions(+), 3 deletions(-)
    
    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);
    
    From 521bb8f319bec9741d018b095afb61f585ae79f4 Mon Sep 17 00:00:00 2001
    From: Ken Smith 
    Date: Mon, 24 Aug 2009 03:04:13 +0000
    Subject: [PATCH 177/453] Oops.  Needed to adjust a little bit more of the line
     for packages-8-stable now that we're prepping for 8.0's release.
    
    Submitted by:	pluknet at gmail dot com
    Pointy hat:	kensmith
    ---
     usr.sbin/pkg_install/add/main.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/usr.sbin/pkg_install/add/main.c b/usr.sbin/pkg_install/add/main.c
    index 461c36752f2..eaed0c0c2eb 100644
    --- a/usr.sbin/pkg_install/add/main.c
    +++ b/usr.sbin/pkg_install/add/main.c
    @@ -89,7 +89,7 @@ struct {
     	{ 503100, 599000, "/packages-5-stable" },
     	{ 600100, 699000, "/packages-6-stable" },
     	{ 700100, 799000, "/packages-7-stable" },
    -	{ 800000, 899000, "/packages-8-stable" },
    +	{ 800500, 899000, "/packages-8-stable" },
     	{ 900000, 999000, "/packages-9-current" },
     	{ 0, 9999999, "/packages-current" },
     	{ 0, 0, NULL }
    
    From f24b6817d656b71dac543a2c1b604fa09f1f836c Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 04:57:48 +0000
    Subject: [PATCH 178/453] Remove redundant Giant reference. Giant will be
     dropped automatically when the mutex argument is NULL.
    
    Reported by: Various people
    Submitted by: hps
    ---
     sys/dev/sound/usb/uaudio.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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
    
    From 34b48722240a6d7b264d9ea60453210ff1dca248 Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 04:58:11 +0000
    Subject: [PATCH 179/453]         - allow disabling "root_mount_hold()" by     
        setting a sysctl/tunable at boot         - remove some redundant initial
     explore code
    
    Submitted by:	hps
    ---
     sys/dev/usb/controller/usb_controller.c | 104 +++++++-----------------
     1 file changed, 30 insertions(+), 74 deletions(-)
    
    diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
    index 7a019dcaa7a..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,12 +139,8 @@ usb_attach(device_t dev)
     		bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
     	}
     
    -	if (usb_post_init_called) {
    -		mtx_lock(&Giant);
    -		usb_attach_sub(dev, bus);
    -		mtx_unlock(&Giant);
    -		usb_needs_explore(bus, 1);
    -	}
    +	usb_attach_sub(dev, bus);
    +
     	return (0);			/* return success */
     }
     
    @@ -226,22 +219,24 @@ usb_bus_explore(struct usb_proc_msg *pm)
     			/* avoid zero, hence that is memory default */
     			bus->driver_added_refcount = 1;
     		}
    -		USB_BUS_UNLOCK(bus);
     
    -		mtx_lock(&Giant);
    +		/*
    +		 * 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);
     
     		/*
     		 * First update the USB power state!
     		 */
     		usb_bus_powerd(bus);
    -		/*
    -		 * Explore the Root USB HUB. This call can sleep,
    -		 * exiting Giant, which is actually Giant.
    -		 */
    +
    +		 /* Explore the Root USB HUB. */
     		(udev->hub->explore) (udev);
    -
    -		mtx_unlock(&Giant);
    -
     		USB_BUS_LOCK(bus);
     	}
     	if (bus->bus_roothold != NULL) {
    @@ -269,10 +264,10 @@ usb_bus_detach(struct usb_proc_msg *pm)
     	device_set_softc(dev, NULL);
     	USB_BUS_UNLOCK(bus);
     
    -	mtx_lock(&Giant);
    -
     	/* detach children first */
    +	mtx_lock(&Giant);
     	bus_generic_detach(dev);
    +	mtx_unlock(&Giant);
     
     	/*
     	 * Free USB Root device, but not any sub-devices, hence they
    @@ -281,7 +276,6 @@ usb_bus_detach(struct usb_proc_msg *pm)
     	usb_free_device(udev,
     	    USB_UNCFG_FLAG_FREE_EP0);
     
    -	mtx_unlock(&Giant);
     	USB_BUS_LOCK(bus);
     	/* clear bdev variable last */
     	bus->bdev = NULL;
    @@ -297,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);
    @@ -350,7 +350,6 @@ usb_bus_attach(struct usb_proc_msg *pm)
     	}
     
     	USB_BUS_UNLOCK(bus);
    -	mtx_lock(&Giant);		/* XXX not required by USB */
     
     	/* default power_mask value */
     	bus->hw_power_state =
    @@ -383,7 +382,6 @@ usb_bus_attach(struct usb_proc_msg *pm)
     		err = USB_ERR_NOMEM;
     	}
     
    -	mtx_unlock(&Giant);
     	USB_BUS_LOCK(bus);
     
     	if (err) {
    @@ -401,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;
    @@ -454,55 +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;
    -
    -	mtx_lock(&Giant);
    -
    -	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) {
    -					mtx_lock(&Giant);
    -					usb_attach_sub(dev, bus);
    -					mtx_unlock(&Giant);
    -				}
    -			}
    -		}
    -	} else {
    -		DPRINTFN(0, "no devclass\n");
    -	}
    -	usb_post_init_called = 1;
    -
    -	/* explore all USB busses in parallell */
    -
    -	usb_needs_explore_all();
    -
    -	mtx_unlock(&Giant);
    -}
    -
    -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);
     
     /*------------------------------------------------------------------------*
    
    From 247549d145f04f56fa68dbea62d3289cf5c49fbd Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 04:58:42 +0000
    Subject: [PATCH 180/453]         - patch for cordump slowdown. Avoid using
     DELAY(1000) when no         keys are pressed.         - Reported by: Various
     people
    
            - add sysctl to disable keyboard led control request
            - Reported by: Yoshihiro Ota
    
            - Save system CPU usage: Patch to stop keyboard timer when no
            keys are pressed.
    
    Submitted by:	hps
    MFC after:	3 days
    ---
     sys/dev/usb/input/ukbd.c | 83 ++++++++++++++++++++++++----------------
     1 file changed, 50 insertions(+), 33 deletions(-)
    
    diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
    index 0d09ad43783..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_assert(&Giant, MA_OWNED);
    -
     	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);
     
    @@ -862,9 +903,6 @@ ukbd_attach(device_t dev)
     
     	usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
     
    -	/* start the timer */
    -
    -	ukbd_timeout(sc);
     	mtx_unlock(&Giant);
     	return (0);			/* success */
     
    @@ -879,8 +917,6 @@ ukbd_detach(device_t dev)
     	struct ukbd_softc *sc = device_get_softc(dev);
     	int error;
     
    -	mtx_assert(&Giant, MA_OWNED);
    -
     	DPRINTF("\n");
     
     	if (sc->sc_flags & UKBD_FLAG_POLLING) {
    @@ -927,8 +963,6 @@ ukbd_resume(device_t dev)
     {
     	struct ukbd_softc *sc = device_get_softc(dev);
     
    -	mtx_assert(&Giant, MA_OWNED);
    -
     	ukbd_clear_state(&sc->sc_kbd);
     
     	return (0);
    @@ -945,7 +979,6 @@ ukbd_configure(int flags)
     static int
     ukbd__probe(int unit, void *arg, int flags)
     {
    -	mtx_assert(&Giant, MA_OWNED);
     	return (ENXIO);
     }
     
    @@ -953,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);
     }
     
    @@ -961,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);
     }
     
    @@ -969,7 +1000,6 @@ ukbd_test_if(keyboard_t *kbd)
     static int
     ukbd_term(keyboard_t *kbd)
     {
    -	mtx_assert(&Giant, MA_OWNED);
     	return (ENXIO);
     }
     
    @@ -977,7 +1007,6 @@ ukbd_term(keyboard_t *kbd)
     static int
     ukbd_intr(keyboard_t *kbd, void *arg)
     {
    -	mtx_assert(&Giant, MA_OWNED);
     	return (0);
     }
     
    @@ -985,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);
     }
     
    @@ -1004,7 +1032,6 @@ ukbd_enable(keyboard_t *kbd)
     		mtx_unlock(&Giant);
     		return (retval);
     	}
    -	mtx_assert(&Giant, MA_OWNED);
     	KBD_ACTIVATE(kbd);
     	return (0);
     }
    @@ -1021,7 +1048,6 @@ ukbd_disable(keyboard_t *kbd)
     		mtx_unlock(&Giant);
     		return (retval);
     	}
    -	mtx_assert(&Giant, MA_OWNED);
     	KBD_DEACTIVATE(kbd);
     	return (0);
     }
    @@ -1050,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]) {
    @@ -1086,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))) {
    @@ -1125,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]) {
    @@ -1190,7 +1213,6 @@ ukbd_read_char(keyboard_t *kbd, int wait)
     		if (!mtx_owned(&Giant))
     			return (NOKEY);
     	}
    -	mtx_assert(&Giant, MA_OWNED);
     
     next_code:
     
    @@ -1393,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 */
    @@ -1527,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 */
    @@ -1547,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;
     }
     
    @@ -1555,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);
     }
     
    @@ -1572,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;
    
    From 03a7d05c2d43aa2d7d759daa44f5fba6fc82777d Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 04:59:09 +0000
    Subject: [PATCH 181/453]         - FIFO's are always opened separately in read
     and write         direction even if the actual device is opened for read and 
            write. Fix fflags check so that the UFM and URIO drivers work.
     Reported by: Krassimir Slavchev
    
    Submitted by:	hps
    ---
     sys/dev/usb/misc/ufm.c     | 15 ++++-----------
     sys/dev/usb/storage/urio.c |  3 ---
     2 files changed, 4 insertions(+), 14 deletions(-)
    
    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/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);
    
    From 069f9a8bd6eb82eea60ecf0d74e82b451c0cfdea Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 05:00:07 +0000
    Subject: [PATCH 182/453] We used 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.
    
    Submitted by:	John Hood via hps
    ---
     sys/dev/usb/net/if_aue.c | 13 ++++++++-----
     1 file changed, 8 insertions(+), 5 deletions(-)
    
    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. */
    
    From 9739167c6456503a2dbae4ae0fd0a27e1317346a Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 05:00:33 +0000
    Subject: [PATCH 183/453]          - fix CDC ethernet matching order so that
     the match flags get correct.
    
    Reported by: Juergen Lock
    
    Submitted by:	hps
    ---
     sys/dev/usb/net/if_cdce.c | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    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
    
    From ec1201a2c9427690a2928a4f5090263cf6699358 Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 05:01:06 +0000
    Subject: [PATCH 184/453]          - Fix false positive uipaq probe
    
    Reported by: Alexander Motin 
    
    Submitted by:	hps
    ---
     sys/dev/usb/serial/uipaq.c | 4 ++++
     sys/dev/usb/usb.h          | 2 ++
     2 files changed, 6 insertions(+)
    
    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/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
    
    From 40675d1a705d9ea52e5fa3a81f85c0b75865efe4 Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 05:01:40 +0000
    Subject: [PATCH 185/453]          - fix uvisor support, mostly correct buffer
     sizes used.          - correct device info flag for SONY Cli NR70V
    
    Reported by: Marc Fonvieille
    Submitted by:	hps
    ---
     sys/dev/usb/serial/uvisor.c | 46 ++++++++++++++++++++++++++++---------
     1 file changed, 35 insertions(+), 11 deletions(-)
    
    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;
     	}
     }
     
    
    From 77c33ae7cc52a0591fb6b01197c3154d67bbc539 Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 05:02:36 +0000
    Subject: [PATCH 186/453] Add mass storage quirks.
    
    PR:             usb/137138,usb/137226,usb/137789,usb/135372
    
    Submitted by:	hps
    ---
     sys/dev/usb/storage/umass.c | 16 ++++++++++++++++
     sys/dev/usb/usbdevs         | 14 ++++++++++++++
     2 files changed, 30 insertions(+)
    
    diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
    index 2e412d98ca3..f09d1bab5c2 100644
    --- a/sys/dev/usb/storage/umass.c
    +++ b/sys/dev/usb/storage/umass.c
    @@ -412,6 +412,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 +737,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 +901,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 +977,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}
     };
     
    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
    
    From f2db024fe608bdbc61cc0edcdae81af7cbb36738 Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 05:03:30 +0000
    Subject: [PATCH 187/453] Add a reminder comment to optimize bus_dmamap_sync
     calls.
    
    Submitted by:	hps
    ---
     sys/dev/usb/usb_busdma.c | 6 ++++++
     1 file changed, 6 insertions(+)
    
    diff --git a/sys/dev/usb/usb_busdma.c b/sys/dev/usb/usb_busdma.c
    index 3769102c510..177b94faceb 100644
    --- a/sys/dev/usb/usb_busdma.c
    +++ b/sys/dev/usb/usb_busdma.c
    @@ -679,6 +679,12 @@ usb_pc_cpu_invalidate(struct usb_page_cache *pc)
     		/* nothing has been loaded into this page cache! */
     		return;
     	}
    +
    +	/*
    +	 * 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);
     }
    
    From a5508450dc81ea658a61993fb46b517d8a0086ee Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 05:03:59 +0000
    Subject: [PATCH 188/453] Remove redundant locking.
    
    Submitted by:	hps
    ---
     sys/dev/usb/wlan/if_upgt.c | 2 --
     1 file changed, 2 deletions(-)
    
    diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c
    index ff3220b716f..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:
    -		mtx_lock(&Giant);
     		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);
    -		mtx_unlock(&Giant);
     		break;
     	case SIOCGIFMEDIA:
     		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
    
    From cb18f7d12b575ae66814e2c3ec40d67c042c1495 Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Mon, 24 Aug 2009 05:05:38 +0000
    Subject: [PATCH 189/453]          - Patch to allow USB controller to resume
     operation after          being polled.
    
             - Remove the need for Giant from the USB HUB driver.
    
             - Leave device unconfigured instead of disabling the USB port
               when Huawei Autoinstall disk detection triggers. This should
               fix problems that the Huawei device is not detected after
               Autoinstall eject is issued.
             - Reported by: Nikolay Antsiferov
    
             - Fix memory use after free race for USB character devices.
             - Reported by: Lucius Windschuh
    
             - Factor out the enumeration lock into three functions to make the
             coming newbus lock conversion more easy.
              - usbd_enum_lock
              - usbd_enum_unlock
              - usbd_enum_is_locked
    
    Submitted by:	hps
    ---
     sys/dev/usb/usb_dev.c            | 19 ++++----
     sys/dev/usb/usb_device.c         | 80 +++++++++++++++++++++++---------
     sys/dev/usb/usb_device.h         |  3 ++
     sys/dev/usb/usb_handle_request.c | 30 ++++++------
     sys/dev/usb/usb_hub.c            | 29 ++++++++----
     sys/dev/usb/usb_process.c        | 26 +++++++++++
     sys/dev/usb/usb_process.h        |  1 +
     sys/dev/usb/usb_transfer.c       |  4 --
     8 files changed, 130 insertions(+), 62 deletions(-)
    
    diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
    index cba8919255c..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) {
    @@ -1042,9 +1039,9 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
     	 * reference if we need it!
     	 */
     	err = usb_ref_device(cpd, &refs, 0 /* no uref */ );
    -	if (err) {
    +	if (err)
     		return (ENXIO);
    -	}
    +
     	fflags = cpd->fflags;
     
     	f = NULL;			/* set default value */
    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 a720919b7d8..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);
    -	mtx_lock(&Giant);		/* XXX */
    -	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:
    -	mtx_unlock(&Giant);		/* XXX */
    -	sx_unlock(udev->default_sx + 1);
    +	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);
    -	mtx_lock(&Giant);		/* XXX */
    -	sx_xlock(udev->default_sx + 1);
    +
    +	usbd_enum_lock(udev);
     
     	error = ENXIO;
     
    @@ -353,20 +352,17 @@ tr_repeat:
     		goto tr_stalled;
     	}
     tr_valid:
    -	mtx_unlock(&Giant);
    -	sx_unlock(udev->default_sx + 1);
    +	usbd_enum_unlock(udev);
     	USB_XFER_LOCK(xfer);
     	return (0);
     
     tr_short:
    -	mtx_unlock(&Giant);
    -	sx_unlock(udev->default_sx + 1);
    +	usbd_enum_unlock(udev);
     	USB_XFER_LOCK(xfer);
     	return (USB_ERR_SHORT_XFER);
     
     tr_stalled:
    -	mtx_unlock(&Giant);
    -	sx_unlock(udev->default_sx + 1);
    +	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 0defc97c30c..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;
    @@ -428,7 +429,6 @@ repeat:
     		mode = USB_MODE_HOST;
     
     	/* need to create a new child */
    -
     	child = usb_alloc_device(sc->sc_dev, udev->bus, udev,
     	    udev->depth + 1, portno - 1, portno, speed, mode);
     	if (child == NULL) {
    @@ -691,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));
     
    @@ -774,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, "
    @@ -850,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 */
    @@ -868,6 +870,9 @@ error:
     		free(udev->hub, M_USBDEV);
     		udev->hub = NULL;
     	}
    +
    +	mtx_destroy(&sc->sc_mtx);
    +
     	return (ENXIO);
     }
     
    @@ -908,6 +913,9 @@ uhub_detach(device_t dev)
     
     	free(hub, M_USBDEV);
     	sc->sc_udev->hub = NULL;
    +
    +	mtx_destroy(&sc->sc_mtx);
    +
     	return (0);
     }
     
    @@ -1775,10 +1783,13 @@ usb_dev_resume_peer(struct usb_device *udev)
     		/* always update hardware power! */
     		(bus->methods->set_hw_power) (bus);
     	}
    -	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);
    +
    +	usbd_enum_unlock(udev);
     
     	/* check if peer has wakeup capability */
     	if (usb_peer_can_wakeup(udev)) {
    @@ -1844,10 +1855,12 @@ repeat:
     		}
     	}
     
    -	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);
    +
    +	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 5b98a819a8e..08108853d55 100644
    --- a/sys/dev/usb/usb_process.c
    +++ b/sys/dev/usb/usb_process.c
    @@ -448,3 +448,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 71432c3bf70..b4159af1bbd 100644
    --- a/sys/dev/usb/usb_process.h
    +++ b/sys/dev/usb/usb_process.h
    @@ -75,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 */
    
    From 416b15e41ebc562bd3e89f4713567632adc308f1 Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Mon, 24 Aug 2009 08:27:42 +0000
    Subject: [PATCH 190/453] Cleanups to the Xen console driver:
    
    - Use CONSOLE_DRIVER() instead of the deprecated CONS_DRIVER() declaration.
    
    - This means we cannot use cn_checkc anymore, which is supposed to do
      the same as cn_getc nowadays. Remove the cn_getc implementation (that
      was never being called) and rename cn_checkc to cn_getc.
    
    - Don't run-time patch cn_putc, but add the logic to xc_cnputc().
    
    This means I could do some cleanups to our console code...
    
    Tested by:	nobody on hackers@
    ---
     sys/dev/xen/console/console.c | 68 ++++++++++++++---------------------
     1 file changed, 27 insertions(+), 41 deletions(-)
    
    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) {
    
    From daf4075a300a73824b741fa35d1e5fcf919b21a8 Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Mon, 24 Aug 2009 09:17:01 +0000
    Subject: [PATCH 191/453] Unhardcode 0x100 inside kbdcontrol.
    
    In preparation for Unicode support for the keyboard layer, we'd better
    get rid of all the hardcoded 0x100/0xff constants in kbdcontrol.
    Instead, add a flag called SPECIAL stored in the top bit of the integer.
    
    Adding Unicode support is very simple now; just change u_char map[] to
    u_int map[] in keyent_t, change the bounds checking in kbdcontrol to
    0x1FFFFF and modify the ioctls to allow loading these new keymaps.
    ---
     usr.sbin/kbdcontrol/kbdcontrol.c | 144 ++++++++++++++++---------------
     1 file changed, 73 insertions(+), 71 deletions(-)
    
    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]);
     		}
    
    From d57425ab65fee206551168d05c5bb81fb9e0ba95 Mon Sep 17 00:00:00 2001
    From: Marko Zec 
    Date: Mon, 24 Aug 2009 10:03:41 +0000
    Subject: [PATCH 192/453] When registering a protocol to an existing protocol
     domain via pf_proto_register(), iterate over all existing vnets to call
     protosw_init() and thus the appropriate .pr_init() handler in the context of
     each vnet. NB in the future we probably want to separate pr_init() handlers
     into two, i.e. per-vnet and global, functions.
    
    This change has no impact on nooptions VIMAGE builds.
    
    Approved by:	re (rwatson), julian (mentor)
    MFC after:	3 days
    ---
     sys/kern/uipc_domain.c | 9 ++++++++-
     1 file changed, 8 insertions(+), 1 deletion(-)
    
    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);
     }
    
    From 2b73aacaf9ab339d6aaaf256f17f298dc54c423e Mon Sep 17 00:00:00 2001
    From: Marko Zec 
    Date: Mon, 24 Aug 2009 10:06:02 +0000
    Subject: [PATCH 193/453] Introduce a div_destroy() function which takes over
     per-vnet cleanup tasks from the existing modevent / MOD_UNLOAD handler, and
     register div_destroy() in protosw as per-vnet .pr_destroy() handler for
     options VIMAGE builds.  In nooptions VIMAGE builds, div_destroy() will be
     invoked from the modevent handler, resulting in effectively identical
     operation as it was prior this change.  div_destroy() also tears down
     hashtables used by ipdivert, which were previously left behind on ipdivert
     kldunloads.
    
    For options VIMAGE builds only, temporarily disable kldunloading of ipdivert,
    because without introducing additional locking logic it is impossible to
    atomically check whether all ipdivert instances in all vnets are idle, and
    proceed with cleanup without opening a race window for a vnet to open an
    ipdivert socket while ipdivert tear-down is in progress.
    
    While here, staticize div_init(), because it is not used outside of
    ip_divert.c.
    
    In cooperation with:	julian
    Approved by:	re (rwatson), julian (mentor)
    MFC after:	3 days
    ---
     sys/netinet/ip_divert.c | 35 ++++++++++++++++++++++++++++++-----
     sys/netinet/ip_divert.h |  1 -
     2 files changed, 30 insertions(+), 6 deletions(-)
    
    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_ */
    
    From 0348c661d18262546ed177e4f7fd250976823944 Mon Sep 17 00:00:00 2001
    From: Marko Zec 
    Date: Mon, 24 Aug 2009 10:09:30 +0000
    Subject: [PATCH 194/453] Fix NFS panics with options VIMAGE kernels by
     apropriately setting curvnet context inside the RPC code.
    
    Temporarily set td's cred to mount's cred before calling socreate() via
    __rpc_nconf2socket().
    
    Submitted by:	rmacklem (in part)
    Reviewed by:	rmacklem, rwatson
    Discussed with:	dfr, bz
    Approved by:	re (rwatson), julian (mentor)
    MFC after:	3 days
    ---
     sys/fs/nfsclient/nfs_clvnops.c |  4 ++--
     sys/nfsclient/nfs_vnops.c      |  3 +++
     sys/rpc/clnt_dg.c              |  5 +++++
     sys/rpc/clnt_rc.c              |  5 +++--
     sys/rpc/clnt_vc.c              |  9 ++++++++-
     sys/rpc/rpc_generic.c          | 10 +++++++++-
     sys/rpc/svc_dg.c               |  6 ++++++
     sys/rpc/svc_generic.c          |  7 +++++++
     sys/rpc/svc_vc.c               | 21 ++++++++++++++++++---
     9 files changed, 61 insertions(+), 9 deletions(-)
    
    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/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/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) {
     			/*
    
    From 52db6805eae0c705cc29b3ca8614be18e24dae16 Mon Sep 17 00:00:00 2001
    From: Marko Zec 
    Date: Mon, 24 Aug 2009 10:14:09 +0000
    Subject: [PATCH 195/453] When moving ifnets from one vnet to another, and the
     ifnet has ifaddresses of AF_LINK type which thus have an embedded if_index
     "backpointer", we must update that if_index backpointer to reflect the new
     if_index that our ifnet just got assigned.
    
    This change affects only options VIMAGE builds.
    
    Submitted by:	bz
    Reviewed by:	bz
    Approved by:	re (rwatson), julian (mentor)
    ---
     sys/net/if.c | 15 +++++++++++++++
     1 file changed, 15 insertions(+)
    
    diff --git a/sys/net/if.c b/sys/net/if.c
    index fe497d69de2..a1155cd2acc 100644
    --- a/sys/net/if.c
    +++ b/sys/net/if.c
    @@ -589,6 +589,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);
    
    From 0cb8b6a9b746fba6bbf707e4d438cb48c9e7e545 Mon Sep 17 00:00:00 2001
    From: Marko Zec 
    Date: Mon, 24 Aug 2009 10:16:19 +0000
    Subject: [PATCH 196/453] When "jail -c vnet" request fails, the current code
     actually creates and leaves behind an orphaned vnet.  This change ensures
     that such vnets get released.
    
    This change affects only options VIMAGE builds.
    
    Submitted by:	jamie
    Discussed with:	bz
    Approved by:	re (rwatson), julian (mentor)
    MFC after:	3 days
    ---
     sys/kern/kern_jail.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
    index 8f185833e8a..892d2111bed 100644
    --- a/sys/kern/kern_jail.c
    +++ b/sys/kern/kern_jail.c
    @@ -2456,7 +2456,7 @@ prison_deref(struct prison *pr, int flags)
     		sx_downgrade(&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) {
    
    From 2992abe0471f46e91ad033e6aed5c2da439deac2 Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Mon, 24 Aug 2009 10:53:30 +0000
    Subject: [PATCH 197/453] Allow multiple console devices per driver without
     insane code duplication.
    
    Say, a driver wants to have multiple console devices to pick from, you
    would normally write down something like this:
    
    	CONSOLE_DRIVER(dev1);
    	CONSOLE_DRIVER(dev2);
    
    Unfortunately, this means that you have to declare 10 cn routines,
    instead of 5. It also isn't possible to initialize cn_arg on beforehand.
    
    I noticed this restriction when I was implementing some of the console
    bits for my vt(4) driver in my newcons branch. I have a single set of cn
    routines (termcn_*) which are shared by all vt(4) console devices.
    
    In order to solve this, I'm adding a separate consdev_ops structure,
    which contains all the function pointers. This structure is referenced
    through consdev's cn_ops field.
    
    While there, I'm removing CONS_DRIVER() and cn_checkc, which have been
    deprecated for years. They weren't used throughout the source, until the
    Xen console driver showed up. CONSOLE_DRIVER() has been changed to do
    the right thing. It now declares both the consdev and consdev_ops
    structure and ties them together. In other words: this change doesn't
    change the KPI for drivers that used the regular way of declaring
    console devices.
    
    If drivers want to use multiple console devices, they can do this as
    follows:
    
    	static const struct consdev_ops mydriver_cnops = {
    		.cn_probe	= mydriver_cnprobe,
    		...
    	};
    	static struct mydriver_softc cons0_softc = {
    		...
    	};
    	CONSOLE_DEVICE(cons0, mydriver_cnops, &cons0_softc);
    	static struct mydriver_softc cons1_softc = {
    		...
    	};
    	CONSOLE_DEVICE(cons1, mydriver_cnops, &cons1_softc);
    
    Obtained from:	//depot/user/ed/newcons/...
    ---
     sys/kern/kern_cons.c | 23 ++++++++++-------------
     sys/sys/cons.h       | 25 ++++++++++++++-----------
     2 files changed, 24 insertions(+), 24 deletions(-)
    
    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/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);
    
    From 0fa753b3fb9e37bcf56a68c54e99565a0b4ead5c Mon Sep 17 00:00:00 2001
    From: Randall Stewart 
    Date: Mon, 24 Aug 2009 11:13:32 +0000
    Subject: [PATCH 198/453] This fixes two bugs in the NR-Sack code:  1) When
     calculating the table offset for sliding the sack     array, the two byte
     values must be "ored" together in order     for us to do the correct sliding
     of the arrays.  2) We were NOT properly doing CC and other changes to things
     only     NR-Sacked. The solution here is to make a separate function that    
     will actually do both CC/updates and free things if its NR sack'd.     This
     actually shrinks out common code from three places (much better).
    
    MFC after:	3 days
    ---
     sys/netinet/sctp_indata.c | 715 ++++++++++++++------------------------
     1 file changed, 255 insertions(+), 460 deletions(-)
    
    diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
    index 52d53e1b975..7d242694e3f 100644
    --- a/sys/netinet/sctp_indata.c
    +++ b/sys/netinet/sctp_indata.c
    @@ -2525,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;
     
    @@ -2555,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
    @@ -2582,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;
     		}
    @@ -3182,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,
    @@ -3194,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;
    @@ -3263,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);
    @@ -6855,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;
    @@ -6932,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);
    @@ -7164,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++) {
     
    @@ -7207,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;
    
    From 00ee13a0afaef63b132bbfcf9e15b30d3bafcf8f Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Mon, 24 Aug 2009 11:16:44 +0000
    Subject: [PATCH 199/453] Our implementation of granpt(3) could be valid in the
     future.
    
    When I wrote the pseudo-terminal driver for the MPSAFE TTY code, Robert
    Watson and I agreed the best way to implement this, would be to let
    posix_openpt() create a pseudo-terminal with proper permissions in place
    and let grantpt() and unlockpt() be no-ops.
    
    This isn't valid behaviour when looking at the spec. Because I thought
    it was an elegant solution, I filed a bug report at the Austin Group
    about this. In their last teleconference, they agreed on this subject.
    This means that future revisions of POSIX may allow grantpt() and
    unlockpt() to be no-ops if an open() on /dev/ptmx (if the implementation
    has such a device) and posix_openpt() already do the right thing.
    
    I'd rather put this in the manpage, because simply mentioning we don't
    comply to any standard makes it look worse than it is. Right now we
    don't, but at least we took care of it.
    
    Approved by:	re (kib)
    MFC after:	3 days
    ---
     lib/libc/stdlib/ptsname.3 | 26 +++++++++++---------------
     1 file changed, 11 insertions(+), 15 deletions(-)
    
    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.
    
    From 24ae5c4a7369e61b835f4313770029d0b25ece34 Mon Sep 17 00:00:00 2001
    From: Michael Tuexen 
    Date: Mon, 24 Aug 2009 11:46:40 +0000
    Subject: [PATCH 200/453] This fixes a bug where the value set by
     SCTP_PARTIAL_DELIVERY_POINT was not honored, if the socket buffer size was
     not 4 times that large.
    
    Approved by: rrs (mentor)
    MFC after: 3 days.
    ---
     sys/netinet/sctp_indata.c | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
    index 7d242694e3f..9174522237b 100644
    --- a/sys/netinet/sctp_indata.c
    +++ b/sys/netinet/sctp_indata.c
    @@ -921,7 +921,7 @@ doit_again:
     			 * but should we?
     			 */
     			if (stcb->sctp_socket) {
    -				pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
    +				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;
    @@ -2867,11 +2867,11 @@ 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 (stcb->sctp_socket) {
    -			pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
    +			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;
    
    From 8e937462f45aa338f11c9113fcde27aba40704ca Mon Sep 17 00:00:00 2001
    From: Robert Watson 
    Date: Mon, 24 Aug 2009 12:52:05 +0000
    Subject: [PATCH 201/453] Make if_grow static -- it's not used outside of if.c,
     and with the internals destined to change, it's better if it remains that
     way.
    
    MFC after:	3 days
    ---
     sys/net/if.c     | 3 ++-
     sys/net/if_var.h | 1 -
     2 files changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/sys/net/if.c b/sys/net/if.c
    index a1155cd2acc..6433168895d 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);
    @@ -297,7 +298,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;
    diff --git a/sys/net/if_var.h b/sys/net/if_var.h
    index 0bfd9f19a8a..3ab620816a4 100644
    --- a/sys/net/if_var.h
    +++ b/sys/net/if_var.h
    @@ -826,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 *);
    
    From 20cb1f56a90158c46eb215dcf1e02cfb45803520 Mon Sep 17 00:00:00 2001
    From: Alexander Leidinger 
    Date: Mon, 24 Aug 2009 13:10:55 +0000
    Subject: [PATCH 202/453] - Update config to doxygen 1.5.2 (I use this with
     1.5.9). - Add linprocfs and linsysfs to the linuxulator dox. - Take the
     generated includes from the .m files from a subdirectory   instead of putting
     everything into $(.OBJDIR). This imporves the   human readbility of the
     source directory contents a lot, if you do not   create a separate OBJDIR. -
     Assume UTF-8 encoding for every input file. - Strip the source and dest path
     from the output, we are not interested   in the absolute location on the
     machine where the docs are created,   relative the the root of the FreeBSD
     source is what interests us. - Exclude .svn directories. - Switch to
     alphabetic index. - Use one line per INCLUDE_PATH member in the common
     dox-config. - Bump the __FreeBSD__ version to 9.		[MFC: to 8] -
     Switch from hardcoded .m files to an run-time generated one. Takes   a little
     bit more time to get started with actual work, but at least   is more
     future-proof. If you generate dox for all subsystems, the   time to find all
     .m files in the source is magnitutes lower than   producing the docs. - Make
     the *DEST_PATH overidable from the environment. This allows to   produce the
     output directly in the docroot of a webserver. - Fix the path when telling
     the user where he can find the API docs.
    
    MFC after:	1 month (after 8.0)
    ---
     tools/kerneldoc/subsys/Dependencies        | 16 ++---
     tools/kerneldoc/subsys/Doxyfile-cam        |  2 +-
     tools/kerneldoc/subsys/Doxyfile-crypto     |  2 +-
     tools/kerneldoc/subsys/Doxyfile-dev_pci    |  2 +-
     tools/kerneldoc/subsys/Doxyfile-dev_sound  |  2 +-
     tools/kerneldoc/subsys/Doxyfile-dev_usb    |  2 +-
     tools/kerneldoc/subsys/Doxyfile-geom       |  2 +-
     tools/kerneldoc/subsys/Doxyfile-kern       |  2 +-
     tools/kerneldoc/subsys/Doxyfile-libkern    |  2 +-
     tools/kerneldoc/subsys/Doxyfile-linux      |  4 +-
     tools/kerneldoc/subsys/Doxyfile-net80211   |  2 +-
     tools/kerneldoc/subsys/Doxyfile-netgraph   |  2 +-
     tools/kerneldoc/subsys/Doxyfile-netinet    |  2 +-
     tools/kerneldoc/subsys/Doxyfile-netinet6   |  2 +-
     tools/kerneldoc/subsys/Doxyfile-netipsec   |  2 +-
     tools/kerneldoc/subsys/Doxyfile-opencrypto |  2 +-
     tools/kerneldoc/subsys/Doxyfile-vm         |  2 +-
     tools/kerneldoc/subsys/Makefile            | 68 +++++-----------------
     tools/kerneldoc/subsys/common-Doxyfile     | 38 +++++++-----
     19 files changed, 63 insertions(+), 93 deletions(-)
    
    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
    
    From 89ffc202d6864ca8a0388020b1e1e6443a16dd9a Mon Sep 17 00:00:00 2001
    From: "Bjoern A. Zeeb" 
    Date: Mon, 24 Aug 2009 16:19:47 +0000
    Subject: [PATCH 203/453] Fix handling of .note.ABI-tag section for GNU systems
     [1]. Handle GNU/Linux according to LSB Core Specification 4.0, Chapter 11.
     Object Format, 11.8. ABI note tag.
    
    Also check the first word of desc, not only name, according to
    glibc abi-tags specification to distinguish between Linux and
    kFreeBSD.
    
    Add explicit handling for Debian GNU/kFreeBSD, which runs
    on our kernels as well [2].
    
    In {amd64,i386}/trap.c, when checking osrel of the current process,
    also check the ABI to not change the signal behaviour for Linux
    binary processes, now that we save an osrel version for all three
    from the lists above in struct proc [2].
    
    These changes make it possible to run FreeBSD, Debian GNU/kFreeBSD
    and Linux binaries on the same machine again for at least i386 and
    amd64, and no longer break kFreeBSD which was detected as GNU(/Linux).
    
    PR:		kern/135468
    Submitted by:	dchagin [1] (initial patch)
    Suggested by:	kib [2]
    Tested by:	Petr Salinger (Petr.Salinger seznam.cz) for kFreeBSD
    Reviewed by:	kib
    MFC after:	3 days
    ---
     sys/amd64/amd64/elf_machdep.c      | 17 +++++++++
     sys/amd64/amd64/trap.c             |  4 +-
     sys/amd64/linux32/linux32_sysvec.c | 35 ++++++++++++++---
     sys/compat/ia32/ia32_sysvec.c      | 15 ++++++++
     sys/i386/i386/elf_machdep.c        | 16 ++++++++
     sys/i386/i386/trap.c               |  4 +-
     sys/i386/linux/linux_sysvec.c      | 35 ++++++++++++++---
     sys/kern/imgact_elf.c              | 60 +++++++++++++++++++++++++++---
     sys/sys/imgact_elf.h               |  6 ++-
     9 files changed, 173 insertions(+), 19 deletions(-)
    
    diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
    index c5e19cff797..ea48b252feb 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
    +};
    +
    +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/trap.c b/sys/amd64/amd64/trap.c
    index 323e8d1677a..65f761eaa4a 100644
    --- a/sys/amd64/amd64/trap.c
    +++ b/sys/amd64/amd64/trap.c
    @@ -409,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/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/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
    index af8168e909d..5c2c571f113 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
    +};
    +
    +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/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
    index b68a73ec3e6..a4ff9e2160b 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
    +};
    +
    +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/trap.c b/sys/i386/i386/trap.c
    index 354d791c6f4..f7064f04a53 100644
    --- a/sys/i386/i386/trap.c
    +++ b/sys/i386/i386/trap.c
    @@ -423,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/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/kern/imgact_elf.c b/sys/kern/imgact_elf.c
    index e2c0a12cb54..68035239136 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)
     {
    @@ -1371,11 +1421,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/sys/imgact_elf.h b/sys/sys/imgact_elf.h
    index 60979d96f12..3eecf85000b 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 {
    @@ -91,6 +94,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_ */
    
    From c5e246d4463dd3088504b292b0296abe4e9525d5 Mon Sep 17 00:00:00 2001
    From: Brian Somers 
    Date: Mon, 24 Aug 2009 17:18:17 +0000
    Subject: [PATCH 204/453] When realloc()ing device memory for transfer to
     another ppp process, don't continue to use the realloc()d pointer - it might
     have changed!
    
    Remove some stray diagnostics while I'm here.
    
    MFC after:	3 days
    ---
     usr.sbin/ppp/ether.c    | 7 ++++---
     usr.sbin/ppp/netgraph.c | 8 ++++----
     usr.sbin/ppp/tty.c      | 9 +++++----
     3 files changed, 13 insertions(+), 11 deletions(-)
    
    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/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/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;
    
    From 887ff31f063dd61f130fcf38896c9e03752603a0 Mon Sep 17 00:00:00 2001
    From: Brian Somers 
    Date: Mon, 24 Aug 2009 17:19:45 +0000
    Subject: [PATCH 205/453] When ``ppp -direct'' is invoked by a program that
     uses pipe(2) to create stdin and stdout, don't blindly try to use stdin as a
     bi-directional channel.  Instead, detect the pipe and set up a special exec
     handler that indirects write() calls through stdout.
    
    This fixes the problem where ``set device "!ssh -e none host ppp
    -direct label"'' no longer works with an openssh-5.2 server side as
    that version of openssh ignores the USE_PIPES config setting and
    *always* uses pipes (rather than socketpair) for stdin/stdout channels.
    
    MFC after:	3 days
    ---
     usr.sbin/ppp/exec.c     | 420 ++++++++++++++++++++++++++++------------
     usr.sbin/ppp/exec.h     |   2 +-
     usr.sbin/ppp/main.c     |   6 +-
     usr.sbin/ppp/physical.c |   1 +
     4 files changed, 304 insertions(+), 125 deletions(-)
    
    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/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);
    
    From 143cbd17804c2c06fbabcd5c905ba3f78515c843 Mon Sep 17 00:00:00 2001
    From: Ken Smith 
    Date: Mon, 24 Aug 2009 18:43:22 +0000
    Subject: [PATCH 206/453] Update example for RELENG_8.
    
    ---
     share/examples/cvsup/stable-supfile | 9 +++++----
     1 file changed, 5 insertions(+), 4 deletions(-)
    
    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
    
    From 5fa06abe8977025bfbbcee9e419425a5221d773e Mon Sep 17 00:00:00 2001
    From: Pyun YongHyeon 
    Date: Mon, 24 Aug 2009 18:58:13 +0000
    Subject: [PATCH 207/453] Add RTL8168DP/RTL8111DP device id. While I'm here
     append "8111D" to the description of RTL8168D as RL_HWREV_8168D can be either
     RTL8168D or RTL8111D.
    
    PR:	kern/137672
    MFC after:	3 days
    ---
     sys/dev/re/if_re.c | 8 +++++---
     sys/pci/if_rlreg.h | 1 +
     2 files changed, 6 insertions(+), 3 deletions(-)
    
    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/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
    
    From e4d5e248217b571ebd776dedc33378d45a57ca87 Mon Sep 17 00:00:00 2001
    From: Pyun YongHyeon 
    Date: Mon, 24 Aug 2009 20:37:15 +0000
    Subject: [PATCH 208/453] Don't try to power down PHY when alc(4) failed to map
     the device. This fixes system crash when mapping alc(4) device failed in
     device attach.
    
    Reported by:	Jim < stapleton.41 <> gmail DOT com >
    MFC after:	3 days
    ---
     sys/dev/alc/if_alc.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    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);
    
    From d166ef528634f40143b8edd3653883b2c967f248 Mon Sep 17 00:00:00 2001
    From: Jack F Vogel 
    Date: Mon, 24 Aug 2009 20:41:51 +0000
    Subject: [PATCH 209/453] A couple of changes:  first, make header split on by
     default and remove from its dependency on LRO, my tests have shown that its
     always beneficial, even when doing bridging. Second, fix up a few problems in
     the statistics code, the adapter dependencies had gotten lost so some code
     that should only run on 82599 was always running, this resulted in bogus flow
     control numbers on 82598.
    
    ---
     sys/dev/ixgbe/ixgbe.c | 68 +++++++++++++++++++++++++++++++------------
     1 file changed, 50 insertions(+), 18 deletions(-)
    
    diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
    index bd95bdf0a9f..23b185722b2 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 "
    @@ -1459,8 +1467,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 +1890,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 +1903,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 +3549,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 +3571,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 +4474,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.gorc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
    +		adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
    +	}
     
     	/*
     	 * Workaround: mprc hardware is incorrectly counting
    @@ -4494,9 +4529,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 +4564,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;
     }
     
    
    From 3de029efaf8769c6da76bb58ee0ba2a53f61751a Mon Sep 17 00:00:00 2001
    From: Jack F Vogel 
    Date: Mon, 24 Aug 2009 21:04:51 +0000
    Subject: [PATCH 210/453] When bridging LRO is causing a problem, the believe
     that it would work as long as all interfaces have TSO seems to be false,
     until the matter gets sorted out just disable LRO completely.
    
    ---
     sys/net/if_bridge.c | 13 ++++++-------
     1 file changed, 6 insertions(+), 7 deletions(-)
    
    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);
     	}
     
    
    From 2fcd493c4b73047481421ffda231a4478bf68569 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Mon, 24 Aug 2009 21:51:46 +0000
    Subject: [PATCH 211/453] Tweak the way that the ACPI and ISA bus drivers match
     hint devices to BIOS-enumerated devices: - Assume a device is a match if the
     memory and I/O ports match even if the   IRQ or DRQ is wrong or missing. 
     Some BIOSes don't include an IRQ for   the atrtc device for example. - Add a
     hack to better match floppy controller devices.  Many BIOSes do not   include
     the starting port of the floppy controller listed in the hints   (0x3f0) in
     the resources for the device.  So far, however, all the BIOS   variations
     encountered do include the 'port + 2' resource (0x3f2), so   adjust the
     matching for "fdc" devices to look for 'port + 2'.
    
    Reviewed by:	imp
    MFC after:	3 days
    ---
     sys/dev/acpica/acpi.c | 20 ++++++++++++++++++--
     sys/isa/isahint.c     | 27 +++++++++++++++++++++++----
     2 files changed, 41 insertions(+), 6 deletions(-)
    
    diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
    index 63f95d3eb2c..a2e58833d25 100644
    --- a/sys/dev/acpica/acpi.c
    +++ b/sys/dev/acpica/acpi.c
    @@ -1014,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
    @@ -1033,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++;
    @@ -1046,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;
    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;
    
    From 7b0eef0b32db946b866471aa4c88b5de1dd65c31 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Mon, 24 Aug 2009 21:55:43 +0000
    Subject: [PATCH 212/453] Fix a few issues with the lib32 dist so that it
     includes ldd32. - Use a better find invocation to purge empty directories
     from all the dist   trees during a release build.  The previous version did
     not purge   directories whose contents were all empty directories. -
     Explicitly blacklist a few files from the lib32 dist instead of using a  
     whitelist.  A better longterm solution is to fix the few offenders to not  
     install data files during a lib32 install.
    
    MFC after:	3 days
    ---
     release/Makefile              | 2 +-
     release/scripts/lib32-make.sh | 2 +-
     2 files changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/release/Makefile b/release/Makefile
    index 26038c4c58f..18b1dc906d2 100644
    --- a/release/Makefile
    +++ b/release/Makefile
    @@ -696,7 +696,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}
     
     #
    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
    
    From 1dc6903b78d9b46b92d117cc3dada1332dd953ac Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Mon, 24 Aug 2009 21:56:41 +0000
    Subject: [PATCH 213/453] Invoke the recently added mm-mtree.sh release script
     to store a pre-built mergemaster mtree database in the 'base' dist.
    
    MFC after:	3 days
    ---
     release/Makefile | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/release/Makefile b/release/Makefile
    index 18b1dc906d2..b8cea264388 100644
    --- a/release/Makefile
    +++ b/release/Makefile
    @@ -646,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).
    
    From b7084131de5c1ecc33b638664d36c8939704014c Mon Sep 17 00:00:00 2001
    From: Doug Barton 
    Date: Mon, 24 Aug 2009 22:05:08 +0000
    Subject: [PATCH 214/453] Improve the case test to detect the presence of lo0
     in the list of network_interfaces.
    
    Submitted by:	Christoph Mallon 
    ---
     etc/network.subr | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/etc/network.subr b/etc/network.subr
    index f3a85603bf5..01f836e9cf6 100644
    --- a/etc/network.subr
    +++ b/etc/network.subr
    @@ -731,7 +731,7 @@ list_net_interfaces()
     		# lo0 is effectively mandatory, so help prevent foot-shooting
     		#
     		case "$_tmplist" in
    -		lo0*|*lo0|*' lo0 '*)	;;	# This is fine, do nothing
    +		lo0|'lo0 '*|*' lo0'|*' lo0 '*) ;; # This is fine, do nothing
     		*)	_tmplist="lo0 ${_tmplist}" ;;
     		esac
     		;;
    
    From c5bebef869537d1929695afd7c988bdb055c72ce Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Mon, 24 Aug 2009 22:35:53 +0000
    Subject: [PATCH 215/453] Fix VESA modes and allow 8bit depth modes.
    
    PR:		i386/124902
    Submitted by:	paradox 
    MFC after:	2 months
    ---
     sys/dev/syscons/scvgarndr.c | 20 ++++++++++++++++-
     sys/dev/syscons/scvidctl.c  |  4 ++++
     sys/i386/isa/vesa.c         | 45 ++++++++++++++++++++-----------------
     3 files changed, 47 insertions(+), 22 deletions(-)
    
    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/i386/isa/vesa.c b/sys/i386/isa/vesa.c
    index 736daffbabe..8c0188a3603 100644
    --- a/sys/i386/isa/vesa.c
    +++ b/sys/i386/isa/vesa.c
    @@ -1074,6 +1074,11 @@ vesa_set_mode(video_adapter_t *adp, int mode)
     		(info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
     	vesa_adp->va_crtc_addr =
     		(vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
    +
    +	vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
    +	vesa_adp->va_window_size = info.vi_window_size;
    +	vesa_adp->va_window_gran = info.vi_window_gran;
    +
     	if (info.vi_flags & V_INFO_LINEAR) {
     #if VESA_DEBUG > 1
     		printf("VESA: setting up LFB\n");
    @@ -1083,33 +1088,31 @@ vesa_set_mode(video_adapter_t *adp, int mode)
     					vesa_adp_info->v_memsize*64*1024);
     		vesa_adp->va_buffer_size = info.vi_buffer_size;
     		vesa_adp->va_window = vesa_adp->va_buffer;
    -		vesa_adp->va_window_size = info.vi_buffer_size/info.vi_planes;
    -		vesa_adp->va_window_gran = info.vi_buffer_size/info.vi_planes;
     	} else {
     		vesa_adp->va_buffer = 0;
    -		vesa_adp->va_buffer_size = info.vi_buffer_size;
    -		vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
    -		vesa_adp->va_window_size = info.vi_window_size;
    -		vesa_adp->va_window_gran = info.vi_window_gran;
    +		vesa_adp->va_buffer_size = 0;
     	}
    +#if VESA_DEBUG > 1
    +	printf("VESA: buffer %x, buffer_size %d, window %x, window_size %d\n",
    +			vesa_adp->va_buffer,
    +			vesa_adp->va_buffer_size,
    +			vesa_adp->va_window,
    +			vesa_adp->va_window_size);
    +#endif
     	vesa_adp->va_window_orig = 0;
     	len = vesa_bios_get_line_length();
    -	if (len > 0) {
    -		vesa_adp->va_line_width = len;
    -	} else if (info.vi_flags & V_INFO_GRAPHICS) {
    -		switch (info.vi_depth/info.vi_planes) {
    -		case 1:
    -			vesa_adp->va_line_width = info.vi_width/8;
    -			break;
    -		case 2:
    -			vesa_adp->va_line_width = info.vi_width/4;
    -			break;
    +	if (info.vi_flags & V_INFO_GRAPHICS) {
    +		switch (info.vi_depth) {
     		case 4:
    -			vesa_adp->va_line_width = info.vi_width/2;
    +			vesa_adp->va_line_width = info.vi_width;
     			break;
     		case 8:
    -		default: /* shouldn't happen */
    -			vesa_adp->va_line_width = info.vi_width;
    +		case 15:
    +		case 16:
    +		case 24:
    +		case 32:
    +		default:
    +			vesa_adp->va_line_width = info.vi_width * (info.vi_depth / 8);
     			break;
     		case 15:
     		case 16:
    @@ -1126,8 +1129,8 @@ vesa_set_mode(video_adapter_t *adp, int mode)
     	vesa_adp->va_disp_start.x = 0;
     	vesa_adp->va_disp_start.y = 0;
     #if VESA_DEBUG > 0
    -	printf("vesa_set_mode(): vi_width:%d, len:%d, line_width:%d\n",
    -	       info.vi_width, len, vesa_adp->va_line_width);
    +	printf("vesa_set_mode(): vi_width:%d, len:%d, line_width:%d vi_mem_model:%d\n",
    +	       info.vi_width, len, vesa_adp->va_line_width, info.vi_mem_model);
     #endif
     	bcopy(&info, &vesa_adp->va_info, sizeof(vesa_adp->va_info));
     
    
    From 4f0d3f44e096ac34dfcb8f24994199ad5a560822 Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Mon, 24 Aug 2009 23:44:07 +0000
    Subject: [PATCH 216/453] Consider flag == 0 as the same of flag == R_NEXT. 
     This change will restore a historical behavior that has been changed by
     revision 190491, and has seen to break exim.
    
    ---
     lib/libc/db/hash/hash.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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;
    
    From f904c88659fd7ead602e726a4f65e13a30e3842b Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Tue, 25 Aug 2009 01:04:15 +0000
    Subject: [PATCH 217/453] Add a missing .El.
    
    Founded by:	make manlint
    ---
     share/man/man5/tmpfs.5 | 1 +
     1 file changed, 1 insertion(+)
    
    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
    
    From 80469c1b255d32b4780539b39a2a898aadc2c498 Mon Sep 17 00:00:00 2001
    From: Philippe Charnier 
    Date: Tue, 25 Aug 2009 04:09:09 +0000
    Subject: [PATCH 218/453] ANSIfy functions declarations, adjust prototypes.
     Rename local variable to not conflict with err().
    
    ---
     sbin/route/route.c | 133 ++++++++++++++++++++-------------------------
     1 file changed, 58 insertions(+), 75 deletions(-)
    
    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;
    
    From 0d239eefe535f0a1ce3429d1360fcfd752f1ae0f Mon Sep 17 00:00:00 2001
    From: Ulf Lilleengen 
    Date: Tue, 25 Aug 2009 06:21:45 +0000
    Subject: [PATCH 219/453] - Add a SIGINFO handler for savecore.
    
    ---
     sbin/savecore/savecore.c | 18 +++++++++++++++++-
     1 file changed, 17 insertions(+), 1 deletion(-)
    
    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;
    +}
    
    From 58a745889f940e206a00be747447dedc66beebfe Mon Sep 17 00:00:00 2001
    From: Warner Losh 
    Date: Tue, 25 Aug 2009 06:25:59 +0000
    Subject: [PATCH 220/453] Rather than havnig enabled/disabled, implement a max
     queue depth. While usually not an issue, this firewalls bugs in the code that
     may run us out of memory.
    
    Fix a memory exhaustion in the case where devctl was disabled, but the
    link was bouncing.  The check to queue was in the wrong place.
    
    Implement a new sysctl hw.bus.devctl_queue to control the depth.  Make
    compatibility hacks for hw.bus.devctl_disable to ease transition.
    
    Reviewed by:	emaste@
    Approved by:	re@ (kib)
    MFC after:	asap
    ---
     sys/kern/subr_bus.c | 75 +++++++++++++++++++++++++++++++++++++--------
     1 file changed, 62 insertions(+), 13 deletions(-)
    
    diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
    index 2964b8c1a22..f202631ce88 100644
    --- a/sys/kern/subr_bus.c
    +++ b/sys/kern/subr_bus.c
    @@ -350,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;
    @@ -385,6 +392,7 @@ static struct dev_softc
     {
     	int	inuse;
     	int	nonblock;
    +	int	queued;
     	struct mtx mtx;
     	struct cv cv;
     	struct selinfo sel;
    @@ -423,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);
     }
     
    @@ -458,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);
    @@ -531,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);
    @@ -614,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)
    @@ -731,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);
    @@ -744,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);
    @@ -886,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;
    
    From 2c4f649f5032b83c48e8c454c3c4eb9425a923dd Mon Sep 17 00:00:00 2001
    From: Brian Somers 
    Date: Tue, 25 Aug 2009 07:52:09 +0000
    Subject: [PATCH 221/453] Document that ppp handles pipe(2) descriptors
     specially in -direct mode.
    
    MFC after:	3 days
    ---
     usr.sbin/ppp/ppp.8.m4 | 15 ++++++++++++++-
     1 file changed, 14 insertions(+), 1 deletion(-)
    
    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 ,
    
    From a7817ce466c80dc5e861ae128d7c35c86729046c Mon Sep 17 00:00:00 2001
    From: Rafal Jaworowski 
    Date: Tue, 25 Aug 2009 09:30:03 +0000
    Subject: [PATCH 222/453] Eliminate platform_pmap_init() to simplify Marvell
     bootstrap code.
    
    ---
     sys/arm/mv/discovery/db78xxx.c  | 15 +--------------
     sys/arm/mv/kirkwood/db88f6xxx.c | 15 +--------------
     sys/arm/mv/mv_machdep.c         |  7 +++++--
     sys/arm/mv/mvvar.h              |  6 +++++-
     sys/arm/mv/orion/db88f5xxx.c    | 14 +-------------
     5 files changed, 13 insertions(+), 44 deletions(-)
    
    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/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/mvvar.h b/sys/arm/mv/mvvar.h
    index 061f3633d89..9274dcfdbea 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,7 +129,6 @@ 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);
    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)
     {
    
    From 5694b144c0a6119391beb3b1d3ffbf2f52cce42c Mon Sep 17 00:00:00 2001
    From: Rafal Jaworowski 
    Date: Tue, 25 Aug 2009 09:35:50 +0000
    Subject: [PATCH 223/453] Properly handle initial state of power mgmt.
    
    Modules on Marvell SOC can be selectively PM-disabled, and we must not access
    disabled devices' registers (attempt to initialize them) unconditionally, as
    this leads to the system hang. This patch introduces graceful handling of the
    PM state during devices init.
    
    Submitted by:	Michal Hajduk
    Obtained from:	Semihalf
    ---
     sys/arm/mv/common.c | 119 ++++++++++++++++++++++++++++++++++++++++++++
     sys/arm/mv/mvreg.h  |  16 +++++-
     sys/arm/mv/mvvar.h  |   1 +
     3 files changed, 134 insertions(+), 2 deletions(-)
    
    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/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 9274dcfdbea..7d7de32f7c8 100644
    --- a/sys/arm/mv/mvvar.h
    +++ b/sys/arm/mv/mvvar.h
    @@ -135,6 +135,7 @@ 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);
    
    From c0d853f6b994e929806b1c15e8098117229e933f Mon Sep 17 00:00:00 2001
    From: Rafal Jaworowski 
    Date: Tue, 25 Aug 2009 09:39:11 +0000
    Subject: [PATCH 224/453] Exclude common Kirkwood settings so they can be
     shared among various platforms based on this SOC. This is a preliminary step
     for SheevaPlug support.
    
    Submitted by:	Michal Hajduk
    Obtained from:	Semihalf
    ---
     sys/arm/mv/kirkwood/files.db88f6xxx |  3 +--
     sys/arm/mv/kirkwood/files.kirkwood  |  4 ++++
     sys/arm/mv/kirkwood/std.db88f6xxx   |  7 +------
     sys/arm/mv/kirkwood/std.kirkwood    | 15 +++++++++++++++
     4 files changed, 21 insertions(+), 8 deletions(-)
     create mode 100644 sys/arm/mv/kirkwood/files.kirkwood
     create mode 100644 sys/arm/mv/kirkwood/std.kirkwood
    
    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/files.kirkwood b/sys/arm/mv/kirkwood/files.kirkwood
    new file mode 100644
    index 00000000000..afcea155578
    --- /dev/null
    +++ b/sys/arm/mv/kirkwood/files.kirkwood
    @@ -0,0 +1,4 @@
    +# $FreeBSD$
    +
    +arm/mv/rtc.c			standard
    +arm/mv/kirkwood/kirkwood.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/kirkwood/std.kirkwood b/sys/arm/mv/kirkwood/std.kirkwood
    new file mode 100644
    index 00000000000..6b74920b5f9
    --- /dev/null
    +++ b/sys/arm/mv/kirkwood/std.kirkwood
    @@ -0,0 +1,15 @@
    +# $FreeBSD$
    +
    +# kernel gets loaded at 0x00900000 by the loader, but runs at virtual address
    +# 0xc0900000.  RAM starts at 0.  We put the pagetable at a reasonable place
    +# in memory, but may need to bounce it higher if there's a problem with this.
    +# We could paper over this by loading the kernel at 0xc0000000 virtual, but
    +# that leads to other complications, so we'll just reclaim the lower region of
    +# ram after we're loaded.  Put the page tables for startup at 1MB.
    +makeoptions	KERNPHYSADDR=0x00900000
    +makeoptions	KERNVIRTADDR=0xc0900000
    +
    +options		KERNPHYSADDR=0x00900000
    +options		KERNVIRTADDR=0xc0900000
    +options		PHYSADDR=0x00000000
    +options		STARTUP_PAGETABLE_ADDR=0x00100000
    
    From 18159f6a492148603a5338751a65286ef724dec2 Mon Sep 17 00:00:00 2001
    From: Rafal Jaworowski 
    Date: Tue, 25 Aug 2009 09:47:12 +0000
    Subject: [PATCH 225/453] Introduce MII_ADDR_BASE option on ARM, which allows
     to override the default per platform requirements.
    
    Notes:
    - Only used by mge(4) at the moment.
    
    - This is very simplified approach and should be replaced by some long-term
      solution for managing the board/platform configuration (among others the
      MAC-PHY binding info).
    
    Submitted by:	Michal Hajduk
    Obtained from:	Semihalf
    ---
     sys/conf/options.arm |  1 +
     sys/dev/mge/if_mge.c | 11 +++++++----
     2 files changed, 8 insertions(+), 4 deletions(-)
    
    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/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 &
    
    From dc56e98f0d95e809a1044d38f86dd9e734857fe0 Mon Sep 17 00:00:00 2001
    From: Robert Watson 
    Date: Tue, 25 Aug 2009 09:52:38 +0000
    Subject: [PATCH 226/453] Use locks specific to the lltable code, rather than
     borrow the ifnet list/index locks, to protect link layer address tables. 
     This avoids lock order issues during interface teardown, but maintains the
     bug that sysctl copy routines may be called while a non-sleepable lock is
     held.
    
    Reviewed by:	bz, kmacy
    MFC after:	3 days
    ---
     sys/net/if_llatbl.c | 29 +++++++++++++++--------------
     sys/net/if_llatbl.h |  7 +++++++
     sys/netinet/in.c    |  2 +-
     sys/netinet6/in6.c  |  2 +-
     4 files changed, 24 insertions(+), 16 deletions(-)
    
    diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
    index a3617f50d65..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_NOSLEEP();
    +	LLTABLE_RLOCK();
     	SLIST_FOREACH(llt, &lltables, llt_link) {
     		if (llt->llt_af != af)
     			continue;
     
     		llt->llt_prefix_free(llt, prefix, mask);
     	}
    -	IFNET_RUNLOCK_NOSLEEP();
    +	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_NOSLEEP();
    +	LLTABLE_RLOCK();
     	SLIST_FOREACH(llt, &lltables, llt_link) {
     		if (llt->llt_af == dst->sa_family &&
     		    llt->llt_ifp == ifp)
     			break;
     	}
    -	IFNET_RUNLOCK_NOSLEEP();
    +	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/netinet/in.c b/sys/netinet/in.c
    index 8c9984c1c62..203f9e6be25 100644
    --- a/sys/netinet/in.c
    +++ b/sys/netinet/in.c
    @@ -1407,7 +1407,7 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
     	} arpc;
     	int error, i;
     
    -	IFNET_RLOCK_ASSERT();
    +	LLTABLE_LOCK_ASSERT();
     
     	error = 0;
     	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
    diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
    index 7d9f7e7620a..b0b25854027 100644
    --- a/sys/netinet6/in6.c
    +++ b/sys/netinet6/in6.c
    @@ -2495,7 +2495,7 @@ in6_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
     	} ndpc;
     	int i, error;
     
    -	IFNET_RLOCK_ASSERT();
    +	LLTABLE_LOCK_ASSERT();
     
     	error = 0;
     	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
    
    From 7ec5aa41ca385c868587599d13f6a235151129c2 Mon Sep 17 00:00:00 2001
    From: Rafal Jaworowski 
    Date: Tue, 25 Aug 2009 10:09:25 +0000
    Subject: [PATCH 227/453] Introduce SheevaPlug support.
    
      - The device is based on Marvell 88F6281 system on chip.
      - More info about the platform at http://www.plugcomputer.org
    
      - To build the FreeBSD kernel:
        make buildkernel TARGET_ARCH=arm KERNCONF=SHEEVAPLUG
    
      - Installation notes at: http://wiki.freebsd.org/FreeBSDMarvell
    
    Submitted by:	Michal Hajduk
    Obtained from:	Semihalf
    ---
     sys/arm/conf/SHEEVAPLUG              |  70 ++++++++++++
     sys/arm/mv/kirkwood/files.sheevaplug |   4 +
     sys/arm/mv/kirkwood/sheevaplug.c     | 152 +++++++++++++++++++++++++++
     sys/arm/mv/kirkwood/std.sheevaplug   |   8 ++
     4 files changed, 234 insertions(+)
     create mode 100644 sys/arm/conf/SHEEVAPLUG
     create mode 100644 sys/arm/mv/kirkwood/files.sheevaplug
     create mode 100644 sys/arm/mv/kirkwood/sheevaplug.c
     create mode 100644 sys/arm/mv/kirkwood/std.sheevaplug
    
    diff --git a/sys/arm/conf/SHEEVAPLUG b/sys/arm/conf/SHEEVAPLUG
    new file mode 100644
    index 00000000000..d11b34d57b3
    --- /dev/null
    +++ b/sys/arm/conf/SHEEVAPLUG
    @@ -0,0 +1,70 @@
    +#
    +# Custom kernel for Marvell SheevaPlug devices.
    +#
    +# $FreeBSD$
    +#
    +
    +ident		SHEEVAPLUG
    +include		"../mv/kirkwood/std.sheevaplug"
    +
    +options 	SOC_MV_KIRKWOOD
    +makeoptions	MODULES_OVERRIDE=""
    +
    +#makeoptions	DEBUG=-g		#Build kernel with gdb(1) debug symbols
    +makeoptions	WERROR="-Werror"
    +
    +options 	SCHED_4BSD		#4BSD scheduler
    +options 	INET			#InterNETworking
    +options 	INET6			#IPv6 communications protocols
    +options 	FFS			#Berkeley Fast Filesystem
    +options 	NFSCLIENT		#Network Filesystem Client
    +options 	NFSLOCKD		#Network Lock Manager
    +options 	NFS_ROOT		#NFS usable as /, requires NFSCLIENT
    +options 	BOOTP
    +options 	BOOTP_NFSROOT
    +options 	BOOTP_NFSV3
    +options 	BOOTP_WIRED_TO=mge0
    +
    +# Root fs on USB device
    +#options 	ROOTDEVNAME=\"ufs:/dev/da0a\"
    +
    +options 	SYSVSHM			#SYSV-style shared memory
    +options 	SYSVMSG			#SYSV-style message queues
    +options 	SYSVSEM			#SYSV-style semaphores
    +options 	_KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
    +options 	MUTEX_NOINLINE
    +options 	RWLOCK_NOINLINE
    +options 	NO_FFS_SNAPSHOT
    +options 	NO_SWAPPING
    +
    +# Debugging
    +options 	ALT_BREAK_TO_DEBUGGER
    +options 	DDB
    +options 	KDB
    +
    +# Pseudo devices
    +device		random
    +device		pty
    +device		loop
    +
    +# Serial ports
    +device		uart
    +
    +# Networking
    +device		ether
    +device		mge			# Marvell Gigabit Ethernet controller
    +device		mii
    +device		e1000phy
    +device		bpf
    +options		HZ=1000
    +options		DEVICE_POLLING
    +device		vlan
    +
    +# USB
    +device		usb
    +device		ehci
    +device		umass
    +device		scbus
    +device		pass
    +device		da
    +
    diff --git a/sys/arm/mv/kirkwood/files.sheevaplug b/sys/arm/mv/kirkwood/files.sheevaplug
    new file mode 100644
    index 00000000000..f56c2abd9f5
    --- /dev/null
    +++ b/sys/arm/mv/kirkwood/files.sheevaplug
    @@ -0,0 +1,4 @@
    +# $FreeBSD$
    +
    +include "arm/mv/kirkwood/files.kirkwood"
    +arm/mv/kirkwood/sheevaplug.c	standard
    diff --git a/sys/arm/mv/kirkwood/sheevaplug.c b/sys/arm/mv/kirkwood/sheevaplug.c
    new file mode 100644
    index 00000000000..ae8b59201cf
    --- /dev/null
    +++ b/sys/arm/mv/kirkwood/sheevaplug.c
    @@ -0,0 +1,152 @@
    +/*-
    + * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
    + * Copyright (C) 2009 Semihalf
    + * All rights reserved.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + * 3. Neither the name of MARVELL nor the names of contributors
    + *    may be used to endorse or promote products derived from this software
    + *    without specific prior written permission.
    + *
    + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    + * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
    + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    + * SUCH DAMAGE.
    + */
    +
    +#include 
    +__FBSDID("$FreeBSD$");
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +
    +/*
    + * Virtual address space layout:
    + * -----------------------------
    + * 0x0000_0000 - 0x7FFF_FFFF	: User Process (2 GB)
    + * 0x8000_0000 - 0xBBFF_FFFF	: Unused (960 MB)
    + * 0xBC00_0000 - 0xBDFF_FFFF	: Device Bus: CS1 (32 MB)
    + * 0xBE00_0000 - 0xBECF_FFFF	: Unused (13 MB)
    + * 0xBED0_0000 - 0xBEDF_FFFF	: Device Bus: CS2 (1 MB)
    + * 0xBEE0_0000 - 0xBEEF_FFFF	: Device Bus: CS0 (1 MB)
    + * 0xBEF0_0000 - 0xBEFF_FFFF	: Device Bus: BOOT (1 MB)
    + * 0xBF00_0000 - 0xBFFF_FFFF	: Unused (16 MB)
    + * 0xC000_0000 - virtual_avail	: Kernel Reserved (text, data, page tables,
    + * 				: stack etc.)
    + * virtual-avail - 0xEFFF_FFFF	: KVA (virtual_avail is typically < 0xc0a0_0000)
    + * 0xF000_0000 - 0xF0FF_FFFF	: No-Cache allocation area (16 MB)
    + * 0xF100_0000 - 0xF10F_FFFF	: SoC Integrated devices registers range (1 MB)
    + * 0xF110_0000 - 0xF11F_FFFF	: CESA SRAM (1 MB)
    + * 0xF120_0000 - 0xFFFE_FFFF	: Unused (237 MB + 960 kB)
    + * 0xFFFF_0000 - 0xFFFF_0FFF	: 'High' vectors page (4 kB)
    + * 0xFFFF_1000 - 0xFFFF_1FFF	: ARM_TP_ADDRESS/RAS page (4 kB)
    + * 0xFFFF_2000 - 0xFFFF_FFFF	: Unused (56 kB)
    + */
    +
    +/* Static device mappings. */
    +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.
    +	 */
    +	{ /* SoC integrated peripherals registers range */
    +		MV_BASE,
    +		MV_PHYS_BASE,
    +		MV_SIZE,
    +		VM_PROT_READ | VM_PROT_WRITE,
    +		PTE_NOCACHE,
    +	},
    +	{ /* CESA SRAM */
    +		MV_CESA_SRAM_BASE,
    +		MV_CESA_SRAM_PHYS_BASE,
    +		MV_CESA_SRAM_SIZE,
    +		VM_PROT_READ | VM_PROT_WRITE,
    +		PTE_NOCACHE,
    +	},
    +	{ 0, 0, 0, 0, 0, }
    +};
    +
    +const struct gpio_config mv_gpio_config[] = {
    +	{ -1, -1, -1 }
    +};
    +
    +void
    +platform_mpp_init(void)
    +{
    +
    +	/*
    +	 * MPP configuration for Sheeva Plug
    +	 *
    +	 * MPP[0]:  NF_IO[2]
    +	 * MPP[1]:  NF_IO[3]
    +	 * MPP[2]:  NF_IO[4]
    +	 * MPP[3]:  NF_IO[5]
    +	 * MPP[4]:  NF_IO[6]
    +	 * MPP[5]:  NF_IO[7]
    +	 * MPP[6]:  SYSRST_OUTn
    +	 * MPP[8]:  UA0_RTS
    +	 * MPP[9]:  UA0_CTS
    +	 * MPP[10]: UA0_TXD
    +	 * MPP[11]: UA0_RXD
    +	 * MPP[12]: SD_CLK
    +	 * MPP[13]: SD_CMD
    +	 * MPP[14]: SD_D[0]
    +	 * MPP[15]: SD_D[1]
    +	 * MPP[16]: SD_D[2]
    +	 * MPP[17]: SD_D[3]
    +	 * MPP[18]: NF_IO[0]
    +	 * MPP[19]: NF_IO[1]
    +	 * MPP[29]: TSMP[9]
    +	 *
    +	 * Others:  GPIO
    +	 */
    +
    +	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL0, 0x01111111);
    +	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL1, 0x11113322);
    +	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL2, 0x00001111);
    +	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL3, 0x00100000);
    +	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL4, 0x00000000);
    +	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL5, 0x00000000);
    +	bus_space_write_4(obio_tag, MV_MPP_BASE, MPP_CONTROL6, 0x00000000);
    +}
    +
    +static void
    +platform_identify(void *dummy)
    +{
    +
    +	soc_identify();
    +
    +	/*
    +	 * XXX Board identification e.g. read out from FPGA or similar should
    +	 * go here
    +	 */
    +}
    +SYSINIT(platform_identify, SI_SUB_CPU, SI_ORDER_SECOND, platform_identify, NULL);
    diff --git a/sys/arm/mv/kirkwood/std.sheevaplug b/sys/arm/mv/kirkwood/std.sheevaplug
    new file mode 100644
    index 00000000000..a289914f327
    --- /dev/null
    +++ b/sys/arm/mv/kirkwood/std.sheevaplug
    @@ -0,0 +1,8 @@
    +# $FreeBSD$
    +
    +include	"../mv/std.mv"
    +include "../mv/kirkwood/std.kirkwood"
    +files	"../mv/kirkwood/files.sheevaplug"
    +
    +options		PHYSMEM_SIZE=0x20000000
    +options		MII_ADDR_BASE=0
    
    From 08cc4f35428c4b23482566efdcc1473ca854dec9 Mon Sep 17 00:00:00 2001
    From: Gleb Smirnoff 
    Date: Tue, 25 Aug 2009 14:08:33 +0000
    Subject: [PATCH 228/453] Fix build broken in r196524.
    
    ---
     sys/i386/isa/vesa.c | 8 --------
     1 file changed, 8 deletions(-)
    
    diff --git a/sys/i386/isa/vesa.c b/sys/i386/isa/vesa.c
    index 8c0188a3603..2cb19762e36 100644
    --- a/sys/i386/isa/vesa.c
    +++ b/sys/i386/isa/vesa.c
    @@ -1114,14 +1114,6 @@ vesa_set_mode(video_adapter_t *adp, int mode)
     		default:
     			vesa_adp->va_line_width = info.vi_width * (info.vi_depth / 8);
     			break;
    -		case 15:
    -		case 16:
    -			vesa_adp->va_line_width = info.vi_width*2;
    -			break;
    -		case 24:
    -		case 32:
    -			vesa_adp->va_line_width = info.vi_width*4;
    -			break;
     		}
     	} else {
     		vesa_adp->va_line_width = info.vi_width;
    
    From 51e8c0d6c654c9f139b0f884c33560aa208ee351 Mon Sep 17 00:00:00 2001
    From: Andrew Thompson 
    Date: Tue, 25 Aug 2009 16:59:55 +0000
    Subject: [PATCH 229/453] It is possible for all the kthreads to exit (hci
     modules unloaded) which in turn ends our usb process. This means the proc
     pointer becomes invalid and will panic if a new kthread is added. Count the
     number of threads and clear the proc pointer on the last one.
    
    Suggested by:	julian
    MFC after:	3 days
    ---
     sys/dev/usb/usb_process.c | 9 +++++++++
     1 file changed, 9 insertions(+)
    
    diff --git a/sys/dev/usb/usb_process.c b/sys/dev/usb/usb_process.c
    index 08108853d55..eb503fd18c4 100644
    --- a/sys/dev/usb/usb_process.c
    +++ b/sys/dev/usb/usb_process.c
    @@ -64,6 +64,7 @@
     
     #if (__FreeBSD_version >= 800000)
     static struct proc *usbproc;
    +static int usb_pcount;
     #define	USB_THREAD_CREATE(f, s, p, ...) \
     		kproc_kthread_add((f), (s), &usbproc, (p), RFHIGHPID, \
     		    0, "usb", __VA_ARGS__)
    @@ -183,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);
     }
    @@ -218,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:
    
    From 7064977fd9382c6462b51148aa372649490c92e0 Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Tue, 25 Aug 2009 19:07:26 +0000
    Subject: [PATCH 230/453] Add a new rc.d script, static_arp, which enables the
     administrator to statically bind IPv4 <-> MAC address at boot time.
    
    In order to use this, the administrator needs to configure the following
    rc.conf(5) variable:
    
     - static_arp_pairs: A list of names for static bind pairs, and,
     - a series of static_arp_(name): the arguments that is being passed to
       ``arp -S'' operation.
    
    Example:
      static_arp_pairs="gw"
      static_arp_gw="192.168.1.1 00:01:02:03:04:05"
    
    See the rc.conf(5) manual page for more details.
    
    Reviewed by:	-rc@
    MFC after:	2 weeks
    ---
     etc/defaults/rc.conf     |  1 +
     etc/rc.d/Makefile        |  2 +-
     etc/rc.d/static_arp      | 71 ++++++++++++++++++++++++++++++++++++++++
     share/man/man5/rc.conf.5 | 18 +++++++++-
     4 files changed, 90 insertions(+), 2 deletions(-)
     create mode 100644 etc/rc.d/static_arp
    
    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/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/static_arp b/etc/rc.d/static_arp
    new file mode 100644
    index 00000000000..937d66069d8
    --- /dev/null
    +++ b/etc/rc.d/static_arp
    @@ -0,0 +1,71 @@
    +#!/bin/sh
    +#
    +# Copyright (c) 2009  Xin LI 
    +# 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.
    +#
    +# Configure static ARP table
    +#
    +# $FreeBSD$
    +#
    +
    +# PROVIDE: static_arp
    +# REQUIRE: netif
    +# KEYWORD: nojail
    +
    +. /etc/rc.subr
    +
    +name="static_arp"
    +start_cmd="static_arp_start"
    +stop_cmd="static_arp_stop"
    +
    +static_arp_start()
    +{
    +	if [ -n "${static_arp_pairs}" ]; then
    +		echo -n 'Binding static ARP pair(s):'
    +		for e in ${static_arp_pairs}; do
    +			local arp_args
    +			echo -n " ${e}"
    +			eval arp_args=\$static_arp_${e}
    +			arp -S ${arp_args} >/dev/null 2>&1
    +		done
    +		echo '.'
    +	fi
    +}
    +
    +static_arp_stop()
    +{
    +	if [ -n "${static_arp_pairs}" ]; then
    +		echo -n 'Unbinding static ARP pair(s):'
    +		for e in ${static_arp_pairs}; do
    +			local arp_args
    +			echo -n " ${e}"
    +			eval arp_args=\$static_arp_${e}
    +			arp -d ${arp_args%%[ 	]*} > /dev/null 2>&1
    +		done
    +		echo '.'
    +	fi
    +}
    +
    +load_rc_config $name
    +run_rc_command "$1"
    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
    
    From c31650ade16a1f64307820485d56e1adedda3660 Mon Sep 17 00:00:00 2001
    From: Max Laier 
    Date: Tue, 25 Aug 2009 19:30:32 +0000
    Subject: [PATCH 231/453] Fix argument ordering to memcpy as well as the size
     of the copy in the (theoretical) case that pfi_buffer_cnt should be greater
     than ~_max.
    
    Submitted by:	pjd
    Reviewed by:	{krw,sthen,markus}@openbsd.org
    MFC after:	3 days
    ---
     sys/contrib/pf/net/pf_if.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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;
    
    From 28ef31c725425d0dd2c9096c1c5c7df46de74dda Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Tue, 25 Aug 2009 20:05:51 +0000
    Subject: [PATCH 232/453] Localize 'e'.
    
    Submitted by:	dougb
    ---
     etc/rc.d/static_arp | 6 ++++--
     1 file changed, 4 insertions(+), 2 deletions(-)
    
    diff --git a/etc/rc.d/static_arp b/etc/rc.d/static_arp
    index 937d66069d8..582518fe97e 100644
    --- a/etc/rc.d/static_arp
    +++ b/etc/rc.d/static_arp
    @@ -41,10 +41,11 @@ stop_cmd="static_arp_stop"
     
     static_arp_start()
     {
    +	local e arp_args
    +
     	if [ -n "${static_arp_pairs}" ]; then
     		echo -n 'Binding static ARP pair(s):'
     		for e in ${static_arp_pairs}; do
    -			local arp_args
     			echo -n " ${e}"
     			eval arp_args=\$static_arp_${e}
     			arp -S ${arp_args} >/dev/null 2>&1
    @@ -55,10 +56,11 @@ static_arp_start()
     
     static_arp_stop()
     {
    +	local e arp_args
    +
     	if [ -n "${static_arp_pairs}" ]; then
     		echo -n 'Unbinding static ARP pair(s):'
     		for e in ${static_arp_pairs}; do
    -			local arp_args
     			echo -n " ${e}"
     			eval arp_args=\$static_arp_${e}
     			arp -d ${arp_args%%[ 	]*} > /dev/null 2>&1
    
    From 61f6986b0753fa694682668161dc4b0eb777ae96 Mon Sep 17 00:00:00 2001
    From: Robert Watson 
    Date: Tue, 25 Aug 2009 20:21:16 +0000
    Subject: [PATCH 233/453] Break out allocation of new ifindex values from
     if_alloc() and if_vmove(), and centralize in a single function
     ifindex_alloc().  Assert the IFNET_WLOCK, and add missing IFNET_WLOCK in
     if_alloc().  This does not close all known races in this code.
    
    Reviewed by:	bz
    MFC after:	3 days
    ---
     sys/net/if.c | 76 +++++++++++++++++++++++++++++-----------------------
     1 file changed, 42 insertions(+), 34 deletions(-)
    
    diff --git a/sys/net/if.c b/sys/net/if.c
    index 6433168895d..f2f1c4f86af 100644
    --- a/sys/net/if.c
    +++ b/sys/net/if.c
    @@ -223,6 +223,37 @@ ifnet_byindex_ref(u_short idx)
     	return (ifp);
     }
     
    +/*
    + * Allocate an ifindex array entry; return 0 on success or an error on
    + * failure.
    + */
    +static int
    +ifindex_alloc(u_short *idxp)
    +{
    +	u_short idx;
    +
    +	IFNET_WLOCK_ASSERT();
    +
    +	/*
    +	 * Try to find an empty slot below if_index.  If we fail, take the
    +	 * next slot.
    +	 */
    +	for (idx = 1; idx <= V_if_index; idx++) {
    +		if (ifnet_byindex_locked(idx) == 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_locked(u_short idx, struct ifnet *ifp)
     {
    @@ -335,32 +366,19 @@ 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(&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_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) {
    @@ -882,6 +900,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
    @@ -907,23 +926,12 @@ if_vmove(struct ifnet *ifp, struct vnet *new_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(&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();
    +	}
    +	ifp->if_index = idx;
     	ifnet_setbyindex_locked(ifp->if_index, ifp);
     	IFNET_WUNLOCK();
     
    
    From e9d90c5143725166f1350d9edb9ebe3045cf3434 Mon Sep 17 00:00:00 2001
    From: Jilles Tjoelker 
    Date: Tue, 25 Aug 2009 20:33:37 +0000
    Subject: [PATCH 234/453] Add some tests for poll(2)/shutdown(2) interaction.
    
    ---
     tools/regression/poll/Makefile   |   5 +-
     tools/regression/poll/sockpoll.c | 202 +++++++++++++++++++++++++++++++
     2 files changed, 205 insertions(+), 2 deletions(-)
     create mode 100644 tools/regression/poll/sockpoll.c
    
    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/poll/sockpoll.c b/tools/regression/poll/sockpoll.c
    new file mode 100644
    index 00000000000..4bffd29dc6f
    --- /dev/null
    +++ b/tools/regression/poll/sockpoll.c
    @@ -0,0 +1,202 @@
    +/* $FreeBSD$ */
    +
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +static const char *
    +decode_events(int events)
    +{
    +	char *ncresult;
    +	const char *result;
    +
    +	switch (events) {
    +	case POLLIN:
    +		result = "POLLIN";
    +		break;
    +	case POLLOUT:
    +		result = "POLLOUT";
    +		break;
    +	case POLLIN | POLLOUT:
    +		result = "POLLIN | POLLOUT";
    +		break;
    +	case POLLHUP:
    +		result = "POLLHUP";
    +		break;
    +	case POLLIN | POLLHUP:
    +		result = "POLLIN | POLLHUP";
    +		break;
    +	case POLLOUT | POLLHUP:
    +		result = "POLLOUT | POLLHUP";
    +		break;
    +	case POLLIN | POLLOUT | POLLHUP:
    +		result = "POLLIN | POLLOUT | POLLHUP";
    +		break;
    +	default:
    +		asprintf(&ncresult, "%#x", events);
    +		result = ncresult;
    +		break;
    +	}
    +	return (result);
    +}
    +
    +static void
    +report(int num, const char *state, int expected, int got)
    +{
    +	if (expected == got)
    +		printf("ok %-2d    ", num);
    +	else
    +		printf("not ok %-2d", num);
    +	printf(" state %s: expected %s; got %s\n",
    +	    state, decode_events(expected), decode_events(got));
    +	fflush(stdout);
    +}
    +
    +static int
    +set_nonblocking(int sck)
    +{
    +	int flags;
    +
    +	flags = fcntl(sck, F_GETFL, 0);
    +	flags |= O_NONBLOCK;
    +
    +	if (fcntl(sck, F_SETFL, flags))
    +		return -1;
    +
    +	return 0;
    +}
    +
    +static char largeblock[1048576]; /* should be more than AF_UNIX sockbuf size */
    +static int fd[2];
    +static struct pollfd pfd0;
    +static struct pollfd pfd1;
    +
    +void
    +setup(void)
    +{
    +	if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0)
    +		err(1, "socketpair");
    +	if (set_nonblocking(fd[0]) == -1)
    +		err(1, "fcntl");
    +	if (set_nonblocking(fd[1]) == -1)
    +		err(1, "fcntl");
    +	pfd0.fd = fd[0];
    +	pfd0.events = POLLIN | POLLOUT;
    +	pfd1.fd = fd[1];
    +	pfd1.events = POLLIN | POLLOUT;
    +}
    +
    +int
    +main(void)
    +{
    +	int num;
    +
    +	num = 1;
    +	printf("1..18\n");
    +	fflush(stdout);
    +
    +	/* Large write with close */
    +	setup();
    +	if (poll(&pfd0, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "initial 0", POLLOUT, pfd0.revents);
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "initial 1", POLLOUT, pfd1.revents);
    +	if (write(fd[0], largeblock, sizeof(largeblock)) == -1)
    +		err(1, "write");
    +	if (poll(&pfd0, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "after large write", 0, pfd0.revents);
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "other side after large write", POLLIN | POLLOUT, pfd1.revents);
    +	close(fd[0]);
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "other side after close", POLLIN | POLLHUP, pfd1.revents);
    +	if (read(fd[1], largeblock, sizeof(largeblock)) == -1)
    +		err(1, "read");
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "other side after reading input", POLLHUP, pfd1.revents);
    +	close(fd[1]);
    +
    +	/* With shutdown(SHUT_WR) */
    +	setup();
    +	if (shutdown(fd[0], SHUT_WR) == -1)
    +		err(1, "shutdown");
    +	if (poll(&pfd0, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "after shutdown(SHUT_WR)", POLLOUT, pfd0.revents);
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
    +	switch (read(fd[1], largeblock, sizeof(largeblock))) {
    +		case 0:
    +			break;
    +		case -1:
    +			err(1, "read after other side shutdown");
    +			break;
    +		default:
    +			errx(1, "kernel made up data that was never written");
    +	}
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "other side after reading EOF", POLLIN | POLLOUT, pfd1.revents);
    +	if (write(fd[1], largeblock, sizeof(largeblock)) == -1)
    +		err(1, "write");
    +	if (poll(&pfd0, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "after data from other side", POLLIN | POLLOUT, pfd0.revents);
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "after writing", POLLIN, pfd1.revents);
    +	if (shutdown(fd[1], SHUT_WR) == -1)
    +		err(1, "shutdown second");
    +	if (poll(&pfd0, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "after second shutdown", POLLIN | POLLHUP, pfd0.revents);
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "after second shutdown", POLLHUP, pfd1.revents);
    +	close(fd[0]);
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "after close", POLLHUP, pfd1.revents);
    +	close(fd[1]);
    +
    +	/*
    +	 * With shutdown(SHUT_RD)
    +	 * Note that shutdown(SHUT_WR) is passed to the peer, but
    +	 * shutdown(SHUT_RD) is not.
    +	 */
    +	setup();
    +	if (shutdown(fd[0], SHUT_RD) == -1)
    +		err(1, "shutdown");
    +	if (poll(&pfd0, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "after shutdown(SHUT_RD)", POLLIN | POLLOUT, pfd0.revents);
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents);
    +	if (shutdown(fd[0], SHUT_WR) == -1)
    +		err(1, "shutdown");
    +	if (poll(&pfd0, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "after shutdown(SHUT_WR)", POLLHUP, pfd0.revents);
    +	if (poll(&pfd1, 1, 0) == -1)
    +		err(1, "poll");
    +	report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
    +	close(fd[0]);
    +	close(fd[1]);
    +
    +	return (0);
    +}
    
    From 986dffaf53ffcd066ddd187b7c424941428a2921 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Tue, 25 Aug 2009 20:35:57 +0000
    Subject: [PATCH 235/453] - Use the headers from ACPI-CA to define various
     constants and structures   for table layouts, etc. rather than homerolling
     our own structures and   constants in acpidump.h. - Verify the extended
     checksum on the RSDP. - Handle new ACPI 3.0 fields in MADT including X2APIC
     entries and   UIDs for local SAPICs. - Add handling for new ACPI 3.0 flags in
     the FADT.
    
    Reviewed by:	jkim
    MFC after:	1 month
    ---
     usr.sbin/acpi/acpidump/acpi.c      | 826 ++++++++++++++++-------------
     usr.sbin/acpi/acpidump/acpi_user.c |  48 +-
     usr.sbin/acpi/acpidump/acpidump.c  |   6 +-
     usr.sbin/acpi/acpidump/acpidump.h  | 375 ++-----------
     4 files changed, 519 insertions(+), 736 deletions(-)
    
    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;
    
    From 74d1c4927a3b7ce785e41e97e33a804f4f8c62ce Mon Sep 17 00:00:00 2001
    From: Jilles Tjoelker 
    Date: Tue, 25 Aug 2009 21:44:14 +0000
    Subject: [PATCH 236/453] Fix poll() on half-closed sockets, while retaining
     POLLHUP for fifos.
    
    This reverts part of r196460, so that sockets only return POLLHUP if both
    directions are closed/error. Fifos get POLLHUP by closing the unused
    direction immediately after creating the sockets.
    
    The tools/regression/poll/*poll.c tests now pass except for two other things:
    - if POLLHUP is returned, POLLIN is always returned as well instead of only
      when there is data left in the buffer to be read
    - fifo old/new reader distinction does not work the way POSIX specs it
    
    Reviewed by:	kib, bde
    ---
     sys/fs/fifofs/fifo_vnops.c |  3 +++
     sys/kern/uipc_socket.c     | 12 +++++++-----
     2 files changed, 10 insertions(+), 5 deletions(-)
    
    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/kern/uipc_socket.c b/sys/kern/uipc_socket.c
    index c60b8d1abce..2f4dd92736a 100644
    --- a/sys/kern/uipc_socket.c
    +++ b/sys/kern/uipc_socket.c
    @@ -2898,11 +2898,13 @@ sopoll_generic(struct socket *so, int events, struct ucred *active_cred,
     		if (so->so_oobmark || (so->so_rcv.sb_state & SBS_RCVATMARK))
     			revents |= events & (POLLPRI | POLLRDBAND);
     
    -	if ((events & POLLINIGNEOF) == 0)
    -		if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
    -			revents |= POLLHUP;
    -	if (so->so_snd.sb_state & SBS_CANTSENDMORE)
    -		revents |= POLLHUP;
    +	if ((events & POLLINIGNEOF) == 0) {
    +		if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
    +			revents |= events & (POLLIN | POLLRDNORM);
    +			if (so->so_snd.sb_state & SBS_CANTSENDMORE)
    +				revents |= POLLHUP;
    +		}
    +	}
     
     	if (revents == 0) {
     		if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
    
    From f9f231846a10c0ce03c2f132bf28f0465316b71b Mon Sep 17 00:00:00 2001
    From: Colin Percival 
    Date: Wed, 26 Aug 2009 03:30:06 +0000
    Subject: [PATCH 237/453] Don't try to mmap the contents of empty files.  This
     behaviour was harmless prior to r195693, since historical behaviour of
     mmap(2) was to silently ignore length-zero mmap requests; but mmap now
     returns EINVAL, which caused look(1) to emit an error message and fail.
    
    Among other things, this makes `freebsd-update fetch` on a newly installed
    8.0-BETA3 system print bogus warning messages.
    
    MFC after:	3 days
    ---
     usr.bin/look/look.c | 4 ++++
     1 file changed, 4 insertions(+)
    
    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;
    
    From ed2dabfc685ae29d37cb1c1d62682abf7866c362 Mon Sep 17 00:00:00 2001
    From: Robert Watson 
    Date: Wed, 26 Aug 2009 11:13:10 +0000
    Subject: [PATCH 238/453] Add IFNET_HOLD reserved pointer value for the ifindex
     ifnet array, which allows an index to be reserved for an ifnet without making
     the ifnet available for management operations.  Use this in if_alloc() while
     the ifnet lock is released between initial index allocation and completion of
     ifnet initialization.
    
    Add ifindex_free() to centralize the implementation of releasing an
    ifindex value.  Use in if_free() and if_vmove(), as well as when
    releasing a held index in if_alloc().
    
    Reviewed by:	bz
    MFC after:	3 days
    ---
     sys/net/if.c | 52 +++++++++++++++++++++++++++++++++++++++-------------
     1 file changed, 39 insertions(+), 13 deletions(-)
    
    diff --git a/sys/net/if.c b/sys/net/if.c
    index f2f1c4f86af..36c0d037b9a 100644
    --- a/sys/net/if.c
    +++ b/sys/net/if.c
    @@ -175,6 +175,13 @@ int	ifqmaxlen = IFQ_MAXLEN;
     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];
     
    @@ -193,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);
     }
     
    @@ -228,18 +237,18 @@ ifnet_byindex_ref(u_short idx)
      * failure.
      */
     static int
    -ifindex_alloc(u_short *idxp)
    +ifindex_alloc_locked(u_short *idxp)
     {
     	u_short idx;
     
     	IFNET_WLOCK_ASSERT();
     
     	/*
    -	 * Try to find an empty slot below if_index.  If we fail, take the
    +	 * 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 (ifnet_byindex_locked(idx) == NULL)
    +		if (V_ifindex_table[idx].ife_ifnet == NULL)
     			break;
     	}
     
    @@ -254,6 +263,27 @@ ifindex_alloc(u_short *idxp)
     	return (0);
     }
     
    +static void
    +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)
     {
    @@ -370,11 +400,12 @@ if_alloc(u_char type)
     
     	ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO);
     	IFNET_WLOCK();
    -	if (ifindex_alloc(&idx) != 0) {
    +	if (ifindex_alloc_locked(&idx) != 0) {
     		IFNET_WUNLOCK();
     		free(ifp, M_IFNET);
     		return (NULL);
     	}
    +	ifnet_setbyindex_locked(idx, IFNET_HOLD);
     	IFNET_WUNLOCK();
     	ifp->if_index = idx;
     	ifp->if_type = type;
    @@ -383,6 +414,7 @@ if_alloc(u_char type)
     		ifp->if_l2com = if_com_alloc[type](type, ifp);
     		if (ifp->if_l2com == NULL) {
     			free(ifp, M_IFNET);
    +			ifindex_free(idx);
     			return (NULL);
     		}
     	}
    @@ -421,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_locked(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)
    @@ -916,18 +946,14 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
     	 * or we'd lock on one vnet and unlock on another.
     	 */
     	IFNET_WLOCK();
    -	ifnet_setbyindex_locked(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);
     
    -	IFNET_WLOCK();
    -	if (ifindex_alloc(&idx) != 0) {
    +	if (ifindex_alloc_locked(&idx) != 0) {
     		IFNET_WUNLOCK();
     		panic("if_index overflow");
     	}
    
    From 4f4946d3379ff2225b9612de09c2bacb83db7b85 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Wed, 26 Aug 2009 14:32:37 +0000
    Subject: [PATCH 239/453] Honor the vfs.timestamp_precision sysctl settings for
     utimes(path, NULL) and similar calls.
    
    Obtained from:	Petr Salinger, Debian GNU/kFreeBSD, Debian bug #489894
    MFC after:	3 days
    ---
     sys/kern/vfs_syscalls.c | 3 +--
     1 file changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
    index f5705f9ca06..ed7f999ccef 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) {
    
    From 5486ffc898503a846ecaf3f5ef9f9269beb4540e Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Wed, 26 Aug 2009 21:10:47 +0000
    Subject: [PATCH 240/453] Add a temporary workaround which just lets init die
     instead of causing a panic if it is killed due to a unsolved stack overflow
     seen very late during shutdown on sparc64 when the gmirror worker process
     exists, which is a regression introduced in 8.0.
    
    Reviewed by:	kib
    MFC after:	3 days
    ---
     sys/kern/kern_exit.c | 7 ++++++-
     1 file changed, 6 insertions(+), 1 deletion(-)
    
    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!");
    
    From 622247c0fb7d924e8f046d4b88010624beb15e81 Mon Sep 17 00:00:00 2001
    From: Stanislav Sedov 
    Date: Wed, 26 Aug 2009 21:14:28 +0000
    Subject: [PATCH 241/453] - Add quirk for Sony DSC digital cameras.  This umass
     devices fail   to attach without these quirks applied.
    
    PR:		usb/137035
    URL:		http://lists.freebsd.org/pipermail/freebsd-current/2009-August/010852.html
    Reported by:	Henri Hennebert , Andrey V. Elsukov 
    MFC after:	1 week
    ---
     sys/cam/scsi/scsi_da.c | 8 ++++++++
     1 file changed, 8 insertions(+)
    
    diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
    index f5ec895909b..e331545032a 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
     	}
     };
     
    
    From 7bcee7f33679f16e41a43ff62c3d965fdbd6678c Mon Sep 17 00:00:00 2001
    From: Qing Li 
    Date: Wed, 26 Aug 2009 21:32:50 +0000
    Subject: [PATCH 242/453] When multiple interfaces exist in the system, with
     each interface having an IPv6 address assigned to it, and if an incoming
     packet received on one interface has a packet destination address that
     belongs to another interface, the routing table is consulted to determine how
     to reach this packet destination. Since the packet destination is an
     interface address, the route table will return a host route with the loopback
     interface as rt_ifp. The input code must recognize this fact, instead of
     using the loopback interface, the input code performs a search to find the
     right interface that owns the given IPv6 address.
    
    Reviewed by:	bz, gnn, kmacy
    MFC after:	immediately
    ---
     sys/netinet6/ip6_input.c | 27 +++++++++++++++++++++++++--
     1 file changed, 25 insertions(+), 2 deletions(-)
    
    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;
     		}
     	}
    
    From c16ce31b318f72d628d0bebc6a74e86294acb4be Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Thu, 27 Aug 2009 08:28:34 +0000
    Subject: [PATCH 243/453] Fix an obvious topology lock leak.
    
    MFC after:	3 days
    ---
     sys/geom/multipath/g_multipath.c | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c
    index ca442bdc6a4..ed7e71e09a2 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",
    
    From 07a93e6b3c3b8f68a76edbcc13ca7dd805459980 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Thu, 27 Aug 2009 08:40:51 +0000
    Subject: [PATCH 244/453] There's no need for checking result of M_WAITOK
     allocation.
    
    ---
     sys/geom/multipath/g_multipath.c | 4 ----
     1 file changed, 4 deletions(-)
    
    diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c
    index ed7e71e09a2..d24edb6f585 100644
    --- a/sys/geom/multipath/g_multipath.c
    +++ b/sys/geom/multipath/g_multipath.c
    @@ -295,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;
    
    From d4267a481bd0d2f83194fbe33b13a78b2032b905 Mon Sep 17 00:00:00 2001
    From: Marc Fonvieille 
    Date: Thu, 27 Aug 2009 13:18:59 +0000
    Subject: [PATCH 245/453] Update some comments to match the removal of the
     docset compilation during the release build.
    
    ---
     release/Makefile | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/release/Makefile b/release/Makefile
    index b8cea264388..e3a11715828 100644
    --- a/release/Makefile
    +++ b/release/Makefile
    @@ -1163,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} \
    
    From d1321a41a5a539b62f752dc73f6e40e6f8818185 Mon Sep 17 00:00:00 2001
    From: Doug Barton 
    Date: Thu, 27 Aug 2009 15:24:26 +0000
    Subject: [PATCH 246/453] In the loop through the list of interfaces in
     network6_interface_setup() rtsol_interface gets reset to "yes" each time
     through the loop, but rtsol_available does not. If a user has lo0 first in
     their list of interfaces rtsol_available will get set to "no" the first time
     through the loop and subsequent interfaces will not get rtsol'ed when they
     should.
    
    Therefore change the conditional for the is_wired() test to _interface.
    
    Noticed by:	Dimitry Andric 
    ---
     etc/network.subr | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/etc/network.subr b/etc/network.subr
    index 01f836e9cf6..e794faba2d7 100644
    --- a/etc/network.subr
    +++ b/etc/network.subr
    @@ -879,8 +879,8 @@ network6_interface_setup()
     		# Wireless NIC cards are virtualized through the wlan interface
     		if ! is_wired_interface ${i}; then
     			case "${i}" in
    -			wlan*)	rtsol_available=yes ;;
    -			*)	rtsol_available=no ;;
    +			wlan*)	rtsol_interface=yes ;;
    +			*)	rtsol_interface=no ;;
     			esac
     		fi
     
    
    From c4884ffa6faf71057c81ac78a42037d4e192415e Mon Sep 17 00:00:00 2001
    From: Jamie Gritton 
    Date: Thu, 27 Aug 2009 16:15:51 +0000
    Subject: [PATCH 247/453] Fix a LOR between allprison_lock and vnode locks by
     releasing allprison_lock before releasing a prison's root vnode.
    
    PR:		kern/138004
    Reviewed by:	kib
    Approved by:	bz (mentor)
    MFC after:	3 days
    ---
     sys/kern/kern_jail.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
    index 892d2111bed..47201d2b8df 100644
    --- a/sys/kern/kern_jail.c
    +++ b/sys/kern/kern_jail.c
    @@ -2453,7 +2453,7 @@ 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_vnet != ppr->pr_vnet)
    @@ -2479,7 +2479,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;
     	}
     }
     
    
    From 276904bf02a005a36e6daea638c09d5605e02a0e Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Thu, 27 Aug 2009 17:32:58 +0000
    Subject: [PATCH 248/453] recognie invalid register names
    
    ---
     tools/tools/ath/athpoke/athpoke.c | 11 ++++++++++-
     1 file changed, 10 insertions(+), 1 deletion(-)
    
    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));
    
    From 418db7a1b2086fd010813e2a42f56b6c74ed0b02 Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Thu, 27 Aug 2009 17:33:44 +0000
    Subject: [PATCH 249/453] enable mesh by default
    
    ---
     sys/arm/conf/CAMBRIA | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/sys/arm/conf/CAMBRIA b/sys/arm/conf/CAMBRIA
    index bd22118416a..4ff2f385a6b 100644
    --- a/sys/arm/conf/CAMBRIA
    +++ b/sys/arm/conf/CAMBRIA
    @@ -107,6 +107,7 @@ device		random		# Entropy device
     # Wireless NIC cards
     device		wlan		# 802.11 support
     options 	IEEE80211_DEBUG
    +options 	IEEE80211_SUPPORT_MESH
     options 	IEEE80211_SUPPORT_TDMA
     options 	IEEE80211_SUPPORT_MESH
     device		wlan_wep	# 802.11 WEP support
    
    From c1d8b5aaddfe4c14377830b469dc4ffa3891aed2 Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Thu, 27 Aug 2009 17:42:37 +0000
    Subject: [PATCH 250/453] change default regdomain for thailand
    
    Obtained from:	linux-wireless@kernel.org
    ---
     sys/dev/ath/ath_hal/ah_regdomain.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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 },
    
    From 4b9222b7eafc2d870acd54ced1bcc7eeda33c4c3 Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Thu, 27 Aug 2009 17:55:44 +0000
    Subject: [PATCH 251/453] revert r196600; didn't notice it'd been done already
    
    Submitted by:	jhay
    ---
     sys/arm/conf/CAMBRIA | 1 -
     1 file changed, 1 deletion(-)
    
    diff --git a/sys/arm/conf/CAMBRIA b/sys/arm/conf/CAMBRIA
    index 4ff2f385a6b..bd22118416a 100644
    --- a/sys/arm/conf/CAMBRIA
    +++ b/sys/arm/conf/CAMBRIA
    @@ -107,7 +107,6 @@ device		random		# Entropy device
     # Wireless NIC cards
     device		wlan		# 802.11 support
     options 	IEEE80211_DEBUG
    -options 	IEEE80211_SUPPORT_MESH
     options 	IEEE80211_SUPPORT_TDMA
     options 	IEEE80211_SUPPORT_MESH
     device		wlan_wep	# 802.11 WEP support
    
    From 840f51bb6d25bce472b0fc1887d37c778145a80d Mon Sep 17 00:00:00 2001
    From: Jilles Tjoelker 
    Date: Thu, 27 Aug 2009 22:23:23 +0000
    Subject: [PATCH 252/453] Add some tests for a fixed bug in an uncommitted
     patch. (Trying to get syntax errors for sh -c ':; do' and `:; do`.)
    
    ---
     tools/regression/bin/sh/builtins/eval3.0 | 9 +++++++++
     1 file changed, 9 insertions(+)
     create mode 100644 tools/regression/bin/sh/builtins/eval3.0
    
    diff --git a/tools/regression/bin/sh/builtins/eval3.0 b/tools/regression/bin/sh/builtins/eval3.0
    new file mode 100644
    index 00000000000..dfb8357c727
    --- /dev/null
    +++ b/tools/regression/bin/sh/builtins/eval3.0
    @@ -0,0 +1,9 @@
    +# $FreeBSD$
    +
    +eval 'false;' && exit 1
    +eval 'true;' || exit 1
    +eval 'false;
    +' && exit 1
    +eval 'true;
    +' || exit 1
    +exit 0
    
    From 0437a93339119fea6fa4a4db2a8b1c32fd791263 Mon Sep 17 00:00:00 2001
    From: Qing Li 
    Date: Fri, 28 Aug 2009 05:37:31 +0000
    Subject: [PATCH 253/453] Do not try to free the rt_lle entry of the cached
     route in ip_output() if the cached route was not initialized from the
     flow-table. The rt_lle entry is invalid unless it has been initialized
     through the flow-table.
    
    Reviewed by:	kmacy, rwatson
    MFC after:	immediately
    ---
     sys/netinet/ip_output.c | 4 +---
     1 file changed, 1 insertion(+), 3 deletions(-)
    
    diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
    index 2ce94b5c561..e222cdaaa1f 100644
    --- a/sys/netinet/ip_output.c
    +++ b/sys/netinet/ip_output.c
    @@ -202,10 +202,8 @@ again:
     	if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
     			  dst->sin_family != AF_INET ||
     			  dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
    -		if (!nortfree) {
    +		if (!nortfree)
     			RTFREE(ro->ro_rt);
    -			LLE_FREE(ro->ro_lle);
    -		}
     		ro->ro_rt = (struct rtentry *)NULL;
     		ro->ro_lle = (struct llentry *)NULL;
     	}
    
    From 9231d35f4d9c3a71ca7117cb305d04680a523907 Mon Sep 17 00:00:00 2001
    From: Qing Li 
    Date: Fri, 28 Aug 2009 07:01:09 +0000
    Subject: [PATCH 254/453] In ip_output(), the flow-table module must not try to
     cache L2/L3 information for interface of IFF_POINTOPOINT or IFF_LOOPBACK
     type. Since the L2 information (rt_lle) is invalid for these interface types,
     accidental caching attempt will trigger panic when the invalid rt_lle
     reference is accessed.
    
    When installing a new route, or when updating an existing route, the
    user supplied gateway address may be an interface address (this is
    particularly true for point-to-point interface related modules such
    as ppp, if_tun, if_gif). Currently the routing command handler always
    set the RTF_GATEWAY flag if the gateway address is given as part of the
    command paramters. Therefore the gateway address must be verified against
    interface addresses or else the route would be treated as an indirect
    route, thus making that route unusable.
    
    Reviewed by:	kmacy, julia, rwatson
    Verified by:	marcus
    MFC after:	3 days
    ---
     sys/net/flowtable.c |  6 ++++++
     sys/net/rtsock.c    | 35 ++++++++++++++++++++++++++++++++++-
     2 files changed, 40 insertions(+), 1 deletion(-)
    
    diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
    index 98127edd5b2..22cab54e47a 100644
    --- a/sys/net/flowtable.c
    +++ b/sys/net/flowtable.c
    @@ -692,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
    diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
    index 8fb889908f9..e48ab9041d0 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(&gw_ro, 0);
    +		/* 
    +		 * 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) {
    
    From 2b77dd0181b7bccfeaf252bb10da41c3d6530946 Mon Sep 17 00:00:00 2001
    From: Michael Tuexen 
    Date: Fri, 28 Aug 2009 08:41:59 +0000
    Subject: [PATCH 255/453] Fix a bug where vlan interfaces are not supported by
     SCTP.
    
    Approved by: rrs (mentor)
    MFC after: 3 days
    ---
     sys/netinet/sctp_bsd_addr.c | 1 +
     1 file changed, 1 insertion(+)
    
    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:
    
    From f105c8be8c15321bc8db4e4e47387f891108f3d3 Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Fri, 28 Aug 2009 10:23:40 +0000
    Subject: [PATCH 256/453] Hook up the pty(4) module to the build.
    
    ---
     sys/modules/Makefile | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/sys/modules/Makefile b/sys/modules/Makefile
    index 30d21963564..94d7d9ad413 100644
    --- a/sys/modules/Makefile
    +++ b/sys/modules/Makefile
    @@ -225,6 +225,7 @@ SUBDIR=	${_3dfx} \
     	procfs \
     	pseudofs \
     	${_pst} \
    +	pty  \
     	puc \
     	ral \
     	ralfw \
    
    From 2fa8c8d21e96f6f364ddb529d742c4d34ae56b66 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Fri, 28 Aug 2009 14:06:55 +0000
    Subject: [PATCH 257/453] Extend the device pager to support different memory
     attributes on different pages in an object. - Add a new variant of d_mmap()
     currently called d_mmap2() which accepts   an additional in/out parameter
     that is the memory attribute to use for   the requested page. - A driver
     either uses d_mmap() or d_mmap2() for all requests but not both.   The
     current implementation uses a flag in the cdevsw (D_MMAP2) to indicate   that
     the driver provides a d_mmap2() handler instead of d_mmap().  This   is done
     to make the change ABI compatible with existing drivers and   MFC'able to 7
     and 8.
    
    Submitted by:	alc
    MFC after:	1 month
    ---
     sys/kern/kern_conf.c  | 14 ++++++++++----
     sys/sys/conf.h        | 10 +++++++++-
     sys/sys/types.h       |  1 +
     sys/vm/device_pager.c | 20 +++++++++++++++-----
     sys/vm/vm.h           | 12 ++++++------
     5 files changed, 41 insertions(+), 16 deletions(-)
    
    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/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/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/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/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 .
    
    From a99fcfd4ca91f6fc8cd17f665933648559172adf Mon Sep 17 00:00:00 2001
    From: Marko Zec 
    Date: Fri, 28 Aug 2009 22:30:55 +0000
    Subject: [PATCH 258/453] Introduce a separate sx lock for protecting lists of
     vnet sysinit and sysuninit handlers.
    
    Previously, sx_vnet, which is a lock designated for protecting
    the vnet list, was (ab)used for protecting vnet sysinit / sysuninit
    handler lists as well.  Holding exclusively the sx_vnet lock while
    invoking sysinit and / or sysuninit handlers turned out to be
    problematic, since some of the handlers may attempt to wake up
    another thread and wait for it to walk over the vnet list, hence
    acquire a shared lock on sx_vnet, which in turn leads to a deadlock.
    Protecting vnet sysinit / sysuninit lists with a separate lock
    mitigates this issue, which was first observed with
    flowtable_flush() / flowtable_cleaner() in sys/net/flowtable.c.
    
    Reviewed by:	rwatson, jhb
    MFC after:	3 days
    ---
     sys/net/vnet.c | 46 ++++++++++++++++++++++++++--------------------
     1 file changed, 26 insertions(+), 20 deletions(-)
    
    diff --git a/sys/net/vnet.c b/sys/net/vnet.c
    index 17bcbc6fb51..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
    
    From e16947f83d758544093c5709d58be72bd4d25522 Mon Sep 17 00:00:00 2001
    From: Jilles Tjoelker 
    Date: Fri, 28 Aug 2009 22:41:25 +0000
    Subject: [PATCH 259/453] sh: Fix crash with empty functions (f() { })
     introduced in r196483
    
    Empty pairs of braces are represented by a NULL node pointer, just like
    empty lines at the top level.
    
    Support for empty pairs of braces may be removed later. They make the code
    more complex, have inconsistent behaviour (may or may not change $?), are
    not specified by POSIX and are not allowed by some other shells like bash,
    dash and ksh93.
    
    Reported by:	kan
    ---
     bin/sh/eval.c                             |  4 ++--
     bin/sh/exec.c                             |  2 +-
     bin/sh/mknodes.c                          |  6 ++----
     bin/sh/nodes.c.pat                        | 13 ++++++++++++-
     tools/regression/bin/sh/execution/func2.0 | 11 +++++++++++
     5 files changed, 28 insertions(+), 8 deletions(-)
     create mode 100644 tools/regression/bin/sh/execution/func2.0
    
    diff --git a/bin/sh/eval.c b/bin/sh/eval.c
    index 8dfa7ddf406..7978b84f051 100644
    --- a/bin/sh/eval.c
    +++ b/bin/sh/eval.c
    @@ -807,9 +807,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
     		funcnest++;
     		exitstatus = oexitstatus;
     		if (flags & EV_TESTED)
    -			evaltree(&cmdentry.u.func->n, EV_TESTED);
    +			evaltree(getfuncnode(cmdentry.u.func), EV_TESTED);
     		else
    -			evaltree(&cmdentry.u.func->n, 0);
    +			evaltree(getfuncnode(cmdentry.u.func), 0);
     		funcnest--;
     		INTOFF;
     		unreffunc(cmdentry.u.func);
    diff --git a/bin/sh/exec.c b/bin/sh/exec.c
    index 639a23cf78f..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->n);
    +			name = commandtext(getfuncnode(cmdp->param.func));
     			out1c(' ');
     			out1str(name);
     			ckfree(name);
    diff --git a/bin/sh/mknodes.c b/bin/sh/mknodes.c
    index 904f9f4092a..1a177f89531 100644
    --- a/bin/sh/mknodes.c
    +++ b/bin/sh/mknodes.c
    @@ -248,11 +248,9 @@ output(char *file)
     	fputs("\tstruct nodelist *next;\n", hfile);
     	fputs("\tunion node *n;\n", hfile);
     	fputs("};\n\n\n", hfile);
    -	fputs("struct funcdef {\n", hfile);
    -	fputs("\tunsigned int refcount;\n", hfile);
    -	fputs("\tunion node n;\n", hfile);
    -	fputs("};\n\n\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);
     
    diff --git a/bin/sh/nodes.c.pat b/bin/sh/nodes.c.pat
    index b6a855977d7..1f5adbbae4a 100644
    --- a/bin/sh/nodes.c.pat
    +++ b/bin/sh/nodes.c.pat
    @@ -61,6 +61,10 @@ 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.
    @@ -85,6 +89,12 @@ copyfunc(union node *n)
     }
     
     
    +union node *
    +getfuncnode(struct funcdef *fn)
    +{
    +	return fn == NULL ? NULL : &fn->n;
    +}
    +
     
     STATIC void
     calcsize(union node *n)
    @@ -153,7 +163,8 @@ nodesavestr(char *s)
     void
     reffunc(struct funcdef *fn)
     {
    -	fn->refcount++;
    +	if (fn)
    +		fn->refcount++;
     }
     
     
    diff --git a/tools/regression/bin/sh/execution/func2.0 b/tools/regression/bin/sh/execution/func2.0
    new file mode 100644
    index 00000000000..affa802a5e2
    --- /dev/null
    +++ b/tools/regression/bin/sh/execution/func2.0
    @@ -0,0 +1,11 @@
    +# $FreeBSD$
    +
    +f() { }
    +f
    +hash -v f >/dev/null
    +f() { { }; }
    +f
    +hash -v f >/dev/null
    +f() { { } }
    +f
    +hash -v f >/dev/null
    
    From a26f987f5def5b239c708c45af9b461043e2de47 Mon Sep 17 00:00:00 2001
    From: Marko Zec 
    Date: Fri, 28 Aug 2009 22:51:07 +0000
    Subject: [PATCH 260/453] Fix a few panics in linuxulator + VIMAGE due to
     curvnet not being set.
    
    This change affects only options VIMAGE builds.
    
    Reviewed by:	julian
    MFC after:	3 days
    ---
     sys/compat/linprocfs/linprocfs.c | 2 ++
     sys/compat/linux/linux_ioctl.c   | 9 ++++++++-
     2 files changed, 10 insertions(+), 1 deletion(-)
    
    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 03ac3340749..8acc5929258 100644
    --- a/sys/compat/linux/linux_ioctl.c
    +++ b/sys/compat/linux/linux_ioctl.c
    @@ -2104,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) {
     		/*
    @@ -2117,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);
    @@ -2146,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;
    @@ -2157,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 */
    @@ -2223,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);
     }
    
    From 3132ad0d1dc5ce4b67a3c88dd1fe4c7b572c6c24 Mon Sep 17 00:00:00 2001
    From: Warner Losh 
    Date: Sat, 29 Aug 2009 01:34:42 +0000
    Subject: [PATCH 261/453] Connect bwi up to the build.  While there are some
     problems with this driver still, it generally works well for most people most
     of the time.  It is still too green for GENERIC, however.
    
    Submitted by:	many (latest being kwm@)
    MFC after:	2 days (before RC1 if possible)
    ---
     sys/conf/NOTES       | 2 ++
     sys/modules/Makefile | 1 +
     2 files changed, 3 insertions(+)
    
    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/modules/Makefile b/sys/modules/Makefile
    index 94d7d9ad413..51408b3b6bb 100644
    --- a/sys/modules/Makefile
    +++ b/sys/modules/Makefile
    @@ -40,6 +40,7 @@ SUBDIR=	${_3dfx} \
     	${_bktr} \
     	${_bm} \
     	bridgestp \
    +	bwi \
     	cam \
     	${_canbepm} \
     	${_canbus} \
    
    From 58e279db020b474a0d8d2b91c056cd02c9445e84 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Sat, 29 Aug 2009 02:17:40 +0000
    Subject: [PATCH 262/453] Mark the fake pages constructed by the OBJT_SG pager
     valid.  This was accidentally lost at one point during the PAT development. 
     Without this fix vm_pager_get_pages() was zeroing each of the pages.
    
    Submitted by:	czander @ NVidia
    MFC after:	3 days
    ---
     sys/vm/sg_pager.c | 1 +
     1 file changed, 1 insertion(+)
    
    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);
     }
    
    From e0fdd85ff701d47c8464509d73d405bfc4b19d55 Mon Sep 17 00:00:00 2001
    From: Tim Kientzle 
    Date: Sat, 29 Aug 2009 03:17:24 +0000
    Subject: [PATCH 263/453] Style: Remove trailing whitespace.
    
    ---
     lib/libc/posix1e/acl_support.c | 22 +++++++++++-----------
     1 file changed, 11 insertions(+), 11 deletions(-)
    
    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);
    
    From c3cf0b476fa28f2fddbfbbbb371011cc90d17d61 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Sat, 29 Aug 2009 13:28:02 +0000
    Subject: [PATCH 264/453] Remove the altkstacks, instead instantiate threads
     with kernel stack allocated with the right size from the start. For the
     thread that has kernel stack cached, verify that requested stack size is
     equial to the actual, and reallocate the stack if sizes differ [1].
    
    This fixes the bug introduced by r173361 that was committed several days
    after r173004 and consisted of kthread_add(9) ignoring the non-default
    kernel stack size.
    
    Also, r173361 removed the caching of the kernel stacks for a non-first
    thread in the process. Introduce separate kernel stack cache that keeps
    some limited amount of preallocated kernel stacks to lower the latency
    of thread allocation. Add vm_lowmem handler to prune the cache on
    low memory condition. This way, system with reasonable amount of the
    threads get lower latency of thread creation, while still not exhausting
    significant portion of KVA for unused kstacks.
    
    Submitted by:	peter [1]
    Discussed with:	jhb, julian, peter
    Reviewed by:	jhb
    Tested by:	pho
    MFC after:	1 week
    ---
     sys/arm/arm/vm_machdep.c |   3 -
     sys/kern/kern_fork.c     |  25 ++++---
     sys/kern/kern_kthread.c  |   5 +-
     sys/kern/kern_proc.c     |  10 ---
     sys/kern/kern_thr.c      |   2 +-
     sys/kern/kern_thread.c   |  17 +++--
     sys/sys/proc.h           |   6 +-
     sys/vm/vm_extern.h       |   2 -
     sys/vm/vm_glue.c         | 140 +++++++++++++++++++++++++++------------
     9 files changed, 128 insertions(+), 82 deletions(-)
    
    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/kern/kern_fork.c b/sys/kern/kern_fork.c
    index 4e2eaa98f3a..b5a40828a48 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(td);
    +			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_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_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_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/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/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..234cde90523 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;
    +	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 = ks_ce;
    +		kstack_cache = ks_ce;
    +		mtx_unlock(&kstack_cache_mtx);
    +		return;
    +	}
    +	vm_thread_stack_dispose(ksobj, ks, pages);
    +	td->td_kstack = 0;
    +	td->td_kstack_pages = 0;
    +}
    +
    +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,
    
    From cbc3c1f6877980eccaf9ab72a55a2a31d2143ab2 Mon Sep 17 00:00:00 2001
    From: Robert Noland 
    Date: Sat, 29 Aug 2009 16:01:21 +0000
    Subject: [PATCH 265/453] Swap the start/end virtual addresses in
     pmap_invalidate_cache_range().
    
    This fixes the functionality on non SelfSnoop hardware.
    
    Found by:	rnoland
    Submitted by:	alc
    Reviewed by:	kib
    MFC after:	3 days
    ---
     sys/amd64/amd64/pmap.c | 4 ++--
     sys/i386/i386/pmap.c   | 4 ++--
     2 files changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
    index b9eee49c97c..f0da536a012 100644
    --- a/sys/amd64/amd64/pmap.c
    +++ b/sys/amd64/amd64/pmap.c
    @@ -943,8 +943,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 {
     
    diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
    index c6f1d5fe2a4..405cbd30cfe 100644
    --- a/sys/i386/i386/pmap.c
    +++ b/sys/i386/i386/pmap.c
    @@ -967,8 +967,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 {
     
    
    From b6b2d1bf884d50ff4a3e2220f25e68e8583b2cf4 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Sat, 29 Aug 2009 18:01:02 +0000
    Subject: [PATCH 266/453] Dispose the kernel stack of the proper thread.
    
    Submitted by:	alc
    MFC after:	1 week
    ---
     sys/kern/kern_fork.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
    index b5a40828a48..03d8cbc6bc1 100644
    --- a/sys/kern/kern_fork.c
    +++ b/sys/kern/kern_fork.c
    @@ -292,7 +292,7 @@ norfproc_fail:
     	} else {
     		if (td2->td_kstack == 0 || td2->td_kstack_pages != pages) {
     			if (td2->td_kstack != 0)
    -				vm_thread_dispose(td);
    +				vm_thread_dispose(td2);
     			if (!thread_alloc_stack(td2, pages)) {
     				error = ENOMEM;
     				goto fail1;
    
    From f25fa6abb23bb6b0e27be2f98aef014eeb3207c3 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Sat, 29 Aug 2009 21:53:08 +0000
    Subject: [PATCH 267/453] Reverse r196640 and r196644 for now.
    
    ---
     sys/arm/arm/vm_machdep.c |   3 +
     sys/kern/kern_fork.c     |  25 +++----
     sys/kern/kern_kthread.c  |   5 +-
     sys/kern/kern_proc.c     |  10 +++
     sys/kern/kern_thr.c      |   2 +-
     sys/kern/kern_thread.c   |  17 ++---
     sys/sys/proc.h           |   6 +-
     sys/vm/vm_extern.h       |   2 +
     sys/vm/vm_glue.c         | 138 ++++++++++++---------------------------
     9 files changed, 81 insertions(+), 127 deletions(-)
    
    diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
    index 6bd57999d3a..1a907cc7577 100644
    --- a/sys/arm/arm/vm_machdep.c
    +++ b/sys/arm/arm/vm_machdep.c
    @@ -119,6 +119,9 @@ 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/kern/kern_fork.c b/sys/kern/kern_fork.c
    index 03d8cbc6bc1..4e2eaa98f3a 100644
    --- a/sys/kern/kern_fork.c
    +++ b/sys/kern/kern_fork.c
    @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
     
     #include "opt_kdtrace.h"
     #include "opt_ktrace.h"
    -#include "opt_kstack_pages.h"
     
     #include 
     #include 
    @@ -277,29 +276,25 @@ norfproc_fail:
     
     	mem_charged = 0;
     	vm2 = NULL;
    -	if (pages == 0)
    -		pages = KSTACK_PAGES;
     	/* Allocate new proc. */
     	newproc = uma_zalloc(proc_zone, M_WAITOK);
    -	td2 = FIRST_THREAD_IN_PROC(newproc);
    -	if (td2 == NULL) {
    -		td2 = thread_alloc(pages);
    +	if (TAILQ_EMPTY(&newproc->p_threads)) {
    +		td2 = thread_alloc();
     		if (td2 == NULL) {
     			error = ENOMEM;
     			goto fail1;
     		}
     		proc_linkup(newproc, td2);
    -	} 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;
    -			}
    +	} 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;
     		}
     	}
    -
     	if ((flags & RFMEM) == 0) {
     		vm2 = vmspace_fork(p1->p_vmspace, &mem_charged);
     		if (vm2 == NULL) {
    diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
    index 3c5248ebbb6..10928321681 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(pages);
    +	newtd = thread_alloc();
     	if (newtd == NULL)
     		return (ENOMEM);
     
    @@ -282,6 +282,9 @@ 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_proc.c b/sys/kern/kern_proc.c
    index e012a3ed4c0..cdbc01207ea 100644
    --- a/sys/kern/kern_proc.c
    +++ b/sys/kern/kern_proc.c
    @@ -203,6 +203,14 @@ 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)
    @@ -759,6 +767,8 @@ 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_thr.c b/sys/kern/kern_thr.c
    index 630069b5940..c478c63bd9b 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(0);
    +	newtd = thread_alloc();
     	if (newtd == NULL)
     		return (ENOMEM);
     
    diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
    index 4f3b32cdd0a..d47bd8cef8b 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(int pages)
    +thread_alloc(void)
     {
     	struct thread *td;
     
    @@ -291,7 +291,7 @@ thread_alloc(int pages)
     
     	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, pages)) {
    +	if (!vm_thread_new(td, 0)) {
     		uma_zfree(thread_zone, td);
     		return (NULL);
     	}
    @@ -299,17 +299,6 @@ thread_alloc(int pages)
     	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.
    @@ -323,6 +312,8 @@ 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/sys/proc.h b/sys/sys/proc.h
    index 6e5716788e9..b65db627a90 100644
    --- a/sys/sys/proc.h
    +++ b/sys/sys/proc.h
    @@ -267,6 +267,9 @@ 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. */
    @@ -847,8 +850,7 @@ 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(int pages);
    -int	thread_alloc_stack(struct thread *, int pages);
    +struct	thread *thread_alloc(void);
     void	thread_exit(void) __dead2;
     void	thread_free(struct thread *td);
     void	thread_link(struct thread *td, struct proc *p);
    diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h
    index 65b6c8e8e4a..53f76947ee8 100644
    --- a/sys/vm/vm_extern.h
    +++ b/sys/vm/vm_extern.h
    @@ -80,7 +80,9 @@ 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 234cde90523..9e43a3fe005 100644
    --- a/sys/vm/vm_glue.c
    +++ b/sys/vm/vm_glue.c
    @@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     
    -#include 
     #include 
     #include 
     #include 
    @@ -309,20 +308,6 @@ 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
    @@ -338,7 +323,6 @@ 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 */
    @@ -346,22 +330,6 @@ 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.
     	 */
    @@ -377,8 +345,7 @@ 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;
    @@ -409,13 +376,20 @@ vm_thread_new(struct thread *td, int pages)
     	return (1);
     }
     
    -static void
    -vm_thread_stack_dispose(vm_object_t ksobj, vm_offset_t ks, int pages)
    +/*
    + * Dispose of a thread's kernel stack.
    + */
    +void
    +vm_thread_dispose(struct thread *td)
     {
    +	vm_object_t ksobj;
    +	vm_offset_t ks;
     	vm_page_t m;
    -	int i;
    +	int i, pages;
     
    -	atomic_add_int(&kstacks, -1);
    +	pages = td->td_kstack_pages;
    +	ksobj = td->td_kstack_obj;
    +	ks = td->td_kstack;
     	pmap_qremove(ks, pages);
     	VM_OBJECT_LOCK(ksobj);
     	for (i = 0; i < pages; i++) {
    @@ -431,66 +405,9 @@ vm_thread_stack_dispose(vm_object_t ksobj, vm_offset_t ks, int pages)
     	vm_object_deallocate(ksobj);
     	kmem_free(kernel_map, ks - (KSTACK_GUARD_PAGES * PAGE_SIZE),
     	    (pages + KSTACK_GUARD_PAGES) * PAGE_SIZE);
    -}
    -
    -/*
    - * 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;
    -	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 = ks_ce;
    -		kstack_cache = ks_ce;
    -		mtx_unlock(&kstack_cache_mtx);
    -		return;
    -	}
    -	vm_thread_stack_dispose(ksobj, ks, pages);
     	td->td_kstack = 0;
    -	td->td_kstack_pages = 0;
     }
     
    -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.
      */
    @@ -550,6 +467,37 @@ 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,
    
    From 42cb3aa49200176511df655840bec8be41f47588 Mon Sep 17 00:00:00 2001
    From: Qing Li 
    Date: Sun, 30 Aug 2009 02:07:23 +0000
    Subject: [PATCH 268/453] Prefix on-link verification is being performed on
     statically configured prefixes. Since these statically configured prefixes do
     not have any associated advertising routers, these prefixes are treated as
     unreachable and those prefix routes are deleted from the routing table.
     Therefore bypass prefixes that are not learned from router advertisements
     during prefix on-link check.
    
    Reviewed by:	hrs
    ---
     sys/netinet6/nd6_rtr.c | 9 +++++++++
     1 file changed, 9 insertions(+)
    
    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) {
    
    From 43b4dc3625963237098b81d92dfc17ed98faa560 Mon Sep 17 00:00:00 2001
    From: Jonathan Chen 
    Date: Sun, 30 Aug 2009 05:12:37 +0000
    Subject: [PATCH 269/453] Prevents pam_lastlog from segfaulting on session
     close when tty is null.
    
    MFC after:	1 month
    ---
     lib/libpam/modules/pam_lastlog/pam_lastlog.c | 5 +++++
     1 file changed, 5 insertions(+)
    
    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')
    
    From e13d7b148698866868839f093ae25ee6a123b3cf Mon Sep 17 00:00:00 2001
    From: Hajimu UMEMOTO 
    Date: Sun, 30 Aug 2009 10:47:00 +0000
    Subject: [PATCH 270/453] AM/PM date format for ja_JP.eucJP and ja_JP.SJIS were
     localized by r193869.  However, ja_JP.UTF-8 wasn't. So, reflect it to
     ja_JP.UTF-8 as well.
    
    ---
     share/timedef/ja_JP.UTF-8.src | 6 ++----
     1 file changed, 2 insertions(+), 4 deletions(-)
    
    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
     #
    
    From 34903a55c3ba01f89b396e1323c2393f039479a5 Mon Sep 17 00:00:00 2001
    From: Hajimu UMEMOTO 
    Date: Sun, 30 Aug 2009 11:17:42 +0000
    Subject: [PATCH 271/453] Fix the problem that the entry broke into two lines
     with multi-byte AM/PM format.
    
    Reported by:	takawata
    ---
     usr.bin/w/extern.h  |  2 +-
     usr.bin/w/pr_time.c | 27 +++++++++++++++++++--------
     usr.bin/w/w.c       |  7 ++++---
     3 files changed, 24 insertions(+), 12 deletions(-)
    
    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..4576b5eb042 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];
    +	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);
    
    From ecc2fda872c83c4d497072474a7bb0b93e12db92 Mon Sep 17 00:00:00 2001
    From: "Bjoern A. Zeeb" 
    Date: Sun, 30 Aug 2009 14:38:17 +0000
    Subject: [PATCH 272/453] Make sure FreeBSD binaries without .note.ABI-tag
     section work correctly and do not match a colliding Debian GNU/kFreeBSD
     brandinfo statements. For this mark the Debian GNU/kFreeBSD brandinfo that it
     must have an .note.ABI-tag section and ignore the old EI_OSABI brandinfo when
     comparing a possibly colliding set of options.
    
    Due to SYSINIT we add the brandinfo in a non-deterministic order,
    so native FreeBSD is not always first. We may want to consider
    to force native FreeBSD to come first as well.
    
    The only way a problem could currently be noticed is when running an
    i386 binary without the .note.ABI-tag on amd64 and the Debian GNU/kFreeBSD
    brandinfo  was matched first,  as the fallback to ld-elf32.so.1 does
    not exist in that case.
    
    Reported and tested by:	ticso
    In collaboration with:	kib
    MFC after:		3 days
    ---
     sys/amd64/amd64/elf_machdep.c |  2 +-
     sys/compat/ia32/ia32_sysvec.c |  2 +-
     sys/i386/i386/elf_machdep.c   |  2 +-
     sys/kern/imgact_elf.c         | 18 +++++++++++++-----
     sys/sys/imgact_elf.h          |  5 +++--
     5 files changed, 19 insertions(+), 10 deletions(-)
    
    diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
    index ea48b252feb..d5e7a6ead78 100644
    --- a/sys/amd64/amd64/elf_machdep.c
    +++ b/sys/amd64/amd64/elf_machdep.c
    @@ -118,7 +118,7 @@ static Elf64_Brandinfo kfreebsd_brand_info = {
     	.sysvec		= &elf64_freebsd_sysvec,
     	.interp_newpath	= NULL,
     	.brand_note	= &elf64_kfreebsd_brandnote,
    -	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
    +	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
     };
     
     SYSINIT(kelf64, SI_SUB_EXEC, SI_ORDER_ANY,
    diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
    index 5c2c571f113..46e0b80d270 100644
    --- a/sys/compat/ia32/ia32_sysvec.c
    +++ b/sys/compat/ia32/ia32_sysvec.c
    @@ -180,7 +180,7 @@ static Elf32_Brandinfo kia32_brand_info = {
     	.interp_path	= "/lib/ld.so.1",
     	.sysvec		= &ia32_freebsd_sysvec,
     	.brand_note	= &elf32_kfreebsd_brandnote,
    -	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
    +	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
     };
     
     SYSINIT(kia32, SI_SUB_EXEC, SI_ORDER_ANY,
    diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
    index a4ff9e2160b..abfe147769b 100644
    --- a/sys/i386/i386/elf_machdep.c
    +++ b/sys/i386/i386/elf_machdep.c
    @@ -117,7 +117,7 @@ static Elf32_Brandinfo kfreebsd_brand_info = {
     	.sysvec		= &elf32_freebsd_sysvec,
     	.interp_newpath	= NULL,
     	.brand_note	= &elf32_kfreebsd_brandnote,
    -	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
    +	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
     };
     
     SYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY,
    diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
    index 68035239136..ba5833a5bd6 100644
    --- a/sys/kern/imgact_elf.c
    +++ b/sys/kern/imgact_elf.c
    @@ -238,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);
    @@ -249,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))
    @@ -260,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);
     		}
    @@ -269,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);
     	}
    diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
    index 3eecf85000b..4ccee5df082 100644
    --- a/sys/sys/imgact_elf.h
    +++ b/sys/sys/imgact_elf.h
    @@ -74,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);
    
    From 0375f536610ba6050efa6e921b3287a6a83d8ee4 Mon Sep 17 00:00:00 2001
    From: Motoyuki Konno 
    Date: Sun, 30 Aug 2009 14:45:09 +0000
    Subject: [PATCH 273/453] Fix the reference for the IPV6_V6ONLY option.  This
     option is described in RFC 3493, not 3542.
    
    PR:		docs/134127
    Submitted by:	Kenji Rikitake 
    MFC after:	2 weeks
    ---
     share/man/man4/ip6.4 | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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
    
    From 35713642d9b0971c902018842ab155337013e7fb Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 30 Aug 2009 15:06:03 +0000
    Subject: [PATCH 274/453] MFp4:  - Add SNTF support.  - Do not report
     meaningless transport/protocol versions.
    
    ---
     sys/dev/siis/siis.c | 36 +++++++++++++++++++++++++++++++-----
     1 file changed, 31 insertions(+), 5 deletions(-)
    
    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);
    
    From 4dbabf104928fdfab3de413b817df9c801d156ec Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 30 Aug 2009 15:20:13 +0000
    Subject: [PATCH 275/453] MFp4:  - Add Command Completion Coalescing support. 
     - Add SNTF support.  - Add two more power management modes (4, 5),
     implemented on driver level.  - Fix interface mode setting.  - Reduce
     interface reset time.  - Do not report meaningless protocol/transport
     versions.  - Report CAP2 register content.  - Some performance optimizations.
    
    ---
     share/man/man4/ahci.4 |  17 +++-
     sys/dev/ahci/ahci.c   | 214 +++++++++++++++++++++++++++++++-----------
     sys/dev/ahci/ahci.h   |  21 +++++
     3 files changed, 196 insertions(+), 56 deletions(-)
    
    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/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
    index 389648adf8e..536849063fb 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,31 @@ ahci_phy_check_events(device_t dev)
     	}
     }
     
    +static void
    +ahci_notify_events(device_t dev)
    +{
    +	struct ahci_channel *ch = device_get_softc(dev);
    +	struct cam_path *dpath;
    +	u_int32_t status;
    +	int i;
    +
    +	status = ATA_INL(ch->r_mem, AHCI_P_SNTF);
    +	if (status == 0)
    +		return;
    +	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,6 +926,23 @@ 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)
     {
    @@ -869,6 +954,8 @@ ahci_ch_intr(void *data)
     
     	/* 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);
    @@ -884,17 +971,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 +1022,9 @@ ahci_ch_intr(void *data)
     		if (ncq_err)
     			ahci_issue_read_log(dev);
     	}
    +	/* Process NOTIFY events */
    +	if ((istatus & AHCI_P_IX_SDB) && (ch->caps & AHCI_CAP_SSNTF))
    +		ahci_notify_events(dev);
     }
     
     /* Must be called with channel locked. */
    @@ -980,19 +1069,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 +1250,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 +1286,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 +1392,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 +1611,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 +1658,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 +1728,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 +1767,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 +1775,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 +1843,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,9 +1938,9 @@ 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;
     		cpi->ccb_h.status = CAM_REQ_CMP;
     		xpt_done(ccb);
    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;
    
    From 1ddbcde83259d8b72129827862a95fb207e18229 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 30 Aug 2009 15:36:56 +0000
    Subject: [PATCH 276/453] ATA_FLUSHCACHE is a 36bit format command, not 48.
    
    ---
     sys/cam/ata/ata_da.c | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
    index 42ba74566b9..77d7ccad51a 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_36bit_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);
    @@ -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_36bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
     		xpt_polled_action(&ccb);
     
     		if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
    @@ -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_36bit_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_36bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
     		xpt_polled_action(&ccb);
     
     		if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
    
    From 36cf18d4f90bbe79823fa6705a4d3a4f8468f38e Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 30 Aug 2009 16:08:25 +0000
    Subject: [PATCH 277/453] MFp4:  - Tune protocol version reporting,  - Add
     supported DMA/PIO modes reporting.  - Fix IDENTIFY for ATAPI devices.  -
     Remove confusing "-" for NCQ status.
    
    ---
     sbin/camcontrol/camcontrol.c | 147 ++++++++++++++++++++++++++++-------
     1 file changed, 120 insertions(+), 27 deletions(-)
    
    diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
    index d7bf96a3dad..beda74b301b 100644
    --- a/sbin/camcontrol/camcontrol.c
    +++ b/sbin/camcontrol/camcontrol.c
    @@ -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)
    +	if (cgd.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);
    +	else
    +		ata_36bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
     
     	/* Disable freezing the device queue */
     	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
    @@ -2588,46 +2647,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 +2757,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 +2789,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;
    
    From 7606b4450b7de96a350d2c4b4c9a21d05d9e18e4 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 30 Aug 2009 16:31:25 +0000
    Subject: [PATCH 278/453] Short ATA command format has 28bit address, not
     36bit. Rename ata_36bit_cmd() into ata_28bit_cmd(), while it didn't become
     legacy.
    
    MFC after:	2 days
    ---
     sbin/camcontrol/camcontrol.c |  4 ++--
     sys/cam/ata/ata_all.c        |  2 +-
     sys/cam/ata/ata_all.h        |  2 +-
     sys/cam/ata/ata_da.c         | 14 +++++++-------
     sys/cam/ata/ata_xpt.c        |  6 +++---
     5 files changed, 14 insertions(+), 14 deletions(-)
    
    diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
    index beda74b301b..d3450e0648a 100644
    --- a/sbin/camcontrol/camcontrol.c
    +++ b/sbin/camcontrol/camcontrol.c
    @@ -1212,9 +1212,9 @@ ataidentify(struct cam_device *device, int retry_count, int timeout)
     		      /*dxfer_len*/sizeof(struct ata_params),
     		      timeout ? timeout : 30 * 1000);
     	if (cgd.protocol == PROTO_ATA)
    -		ata_36bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
    +		ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
     	else
    -		ata_36bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
    +		ata_28bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
     
     	/* Disable freezing the device queue */
     	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
    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 77d7ccad51a..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_36bit_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_36bit_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_36bit_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_36bit_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 0be44fc2b77..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:
    @@ -375,7 +375,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
     		      /*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;
     	}
    
    From 4e931d31163c251d8f7da2307e706941bed76d3f Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 30 Aug 2009 19:40:09 +0000
    Subject: [PATCH 279/453] Fix build with INVARIANTS.
    
    ---
     sys/dev/ahci/ahci.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
    index 536849063fb..189ab121e12 100644
    --- a/sys/dev/ahci/ahci.c
    +++ b/sys/dev/ahci/ahci.c
    @@ -1072,7 +1072,7 @@ ahci_begin_transaction(device_t dev, union ccb *ccb)
     	while (ch->slot[tag].state != AHCI_SLOT_EMPTY) {
     		if (++tag >= ch->numslots)
     			tag = 0;
    -		KASSERT(tag != ch->lastslot, "ahci: ALL SLOTS BUSY!");
    +		KASSERT(tag != ch->lastslot, ("ahci: ALL SLOTS BUSY!"));
     	}
     	ch->lastslot = tag;
     	/* Occupy chosen slot. */
    
    From 8698b76c3d2dbfbfee3563aac3f5ffc533c0e83d Mon Sep 17 00:00:00 2001
    From: Kip Macy 
    Date: Sun, 30 Aug 2009 20:45:24 +0000
    Subject: [PATCH 280/453] add core dump support to blkfront
    
    Obtained from:	Frank Suchomel
    ---
     sys/dev/xen/blkfront/blkfront.c | 89 ++++++++++++++++++++++++++++++++-
     1 file changed, 87 insertions(+), 2 deletions(-)
    
    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 
    
    From 575c1d371cf48c919ade9447e6843deac59488f2 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 30 Aug 2009 21:03:40 +0000
    Subject: [PATCH 281/453] Add missing mountpoint vnode locking.
    
    This fixes panic on assertion with DEBUG_VFS_LOCKS and vfs.usermount=1 when
    regular user tries to mount dataset owned by him.
    
    MFC after:	1 week
    ---
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c | 5 +++++
     1 file changed, 5 insertions(+)
    
    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 16c6683b7af..8fc747c21eb 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
    @@ -729,7 +729,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,12 +743,15 @@ 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);
    
    From 5311e988ead13b99433c051718cb1ff4e6864641 Mon Sep 17 00:00:00 2001
    From: Qing Li 
    Date: Mon, 31 Aug 2009 00:14:37 +0000
    Subject: [PATCH 282/453] As part of r196609, a call to  "rtalloc" did not take
     the fib into account. So call the appropriate "rtalloc_ign_fib()" instead of
     calling "rtalloc_ign()".
    
    Reviewed by:i	pointed out by bz
    MFC after:	immediately
    ---
     sys/net/rtsock.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
    index e48ab9041d0..4bbd6e32fa9 100644
    --- a/sys/net/rtsock.c
    +++ b/sys/net/rtsock.c
    @@ -527,7 +527,7 @@ route_output(struct mbuf *m, struct socket *so)
     
     		bzero(&gw_ro, sizeof(gw_ro));
     		gw_ro.ro_dst = *info.rti_info[RTAX_GATEWAY];
    -		rtalloc_ign(&gw_ro, 0);
    +		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
    
    From 34f83c86f6cf9eb45a2ee7d36477809a5d6ec5e0 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Mon, 31 Aug 2009 09:26:04 +0000
    Subject: [PATCH 283/453] Remove spurious pfs_unlock().
    
    PR:	kern/137310
    Reviewed by:	des
    MFC after:	3 days
    ---
     sys/fs/pseudofs/pseudofs_vnops.c | 1 -
     1 file changed, 1 deletion(-)
    
    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);
     }
     
    
    From a505c2c72c170397e3f3bb58f6de7d1b2f94c9ea Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Mon, 31 Aug 2009 10:20:52 +0000
    Subject: [PATCH 284/453] Make the mnt_writeopcount and mnt_secondary_writes
     counters, used by the suspension code, not greater then mnt_ref reference
     counter value. Increment mnt_ref together with write counter in
     vn_start_write()/ vn_start_secondary_write(), releasing in
     vn_finished_write/vn_finished_secondary_write().
    
    Since r186197, unmount code requires that no writers occured after all
    references are expired. We still could get write counter incremented
    for freed or reused struct mount, but it seems to be innocent, since
    corresponding vnode should be referenced and reclaimed then.
    
    Reported by:	pho (last half a year), erwin
    Reviewed by:	attilio
    Tested by:	pho, erwin
    MFC after:	1 week
    ---
     sys/kern/vfs_vnops.c | 6 ++++--
     1 file changed, 4 insertions(+), 2 deletions(-)
    
    diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
    index f67064613e0..986bc8e880a 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)
    +		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");
    
    From f2e917f5851dd19e5cd22ce02364db847136007c Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 31 Aug 2009 16:19:06 +0000
    Subject: [PATCH 287/453] Manual page for mfiutil(8) is in section 8 now.
    
    ---
     share/man/man4/mfi.4 | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/share/man/man4/mfi.4 b/share/man/man4/mfi.4
    index 5025336bfe4..8ab8d938100 100644
    --- a/share/man/man4/mfi.4
    +++ b/share/man/man4/mfi.4
    @@ -102,9 +102,9 @@ management interface
     An attempt was made to remove a mounted volume.
     .El
     .Sh SEE ALSO
    -.Xr mfiutil 1 ,
     .Xr amr 4 ,
    -.Xr pci 4
    +.Xr pci 4 ,
    +.Xr mfiutil 8
     .Sh HISTORY
     The
     .Nm
    
    From 0bb9bb9e38d263f8a5eaa900fde5e056163f63be Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 31 Aug 2009 16:20:06 +0000
    Subject: [PATCH 288/453] Make it easier to find proper manual page for newer
     ServeRAID controllers.
    
    ---
     share/man/man4/ips.4 | 5 +++++
     1 file changed, 5 insertions(+)
    
    diff --git a/share/man/man4/ips.4 b/share/man/man4/ips.4
    index 26fc261a02d..49fb71909dc 100644
    --- a/share/man/man4/ips.4
    +++ b/share/man/man4/ips.4
    @@ -92,6 +92,10 @@ ServeRAID 6i/6M
     .It
     ServeRAID 7t/7k/7M
     .El
    +.Pp
    +Newer ServeRAID controllers are supported by the
    +.Xr aac 4
    +driver.
     .Sh DIAGNOSTICS
     Several error codes may be shown when the card initializes the
     .Tn IBM
    @@ -180,6 +184,7 @@ driver does not use the
     .Tn SCSI
     subsystem.
     .Sh SEE ALSO
    +.Xr aac 4 ,
     .Xr ch 4 ,
     .Xr da 4 ,
     .Xr sysctl 8
    
    From 26d060572733840aa3b7890e140d16de32280828 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 31 Aug 2009 16:27:00 +0000
    Subject: [PATCH 290/453] Backport the 'dirtying dbuf' panic fix from newer ZFS
     version.
    
    Reported by:	Thomas Backman 
    MFC after:	1 week
    ---
     .../opensolaris/uts/common/fs/zfs/dmu_send.c  |  7 ++--
     .../opensolaris/uts/common/fs/zfs/dnode.c     | 16 ++++-----
     .../uts/common/fs/zfs/dnode_sync.c            | 36 +++++++++++++------
     .../opensolaris/uts/common/fs/zfs/sys/dnode.h |  3 +-
     4 files changed, 40 insertions(+), 22 deletions(-)
    
    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/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];
    
    From f9d38c281cb88d19259132341416f91f28063e67 Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Mon, 31 Aug 2009 17:34:11 +0000
    Subject: [PATCH 291/453] Partially revert 196524: this part of change should
     not be committed as part of the changeset - it's an unrelated one.
    
    Reported by:	danfe
    ---
     sys/i386/isa/vesa.c | 45 +++++++++++++++++++++++++--------------------
     1 file changed, 25 insertions(+), 20 deletions(-)
    
    diff --git a/sys/i386/isa/vesa.c b/sys/i386/isa/vesa.c
    index 2cb19762e36..736daffbabe 100644
    --- a/sys/i386/isa/vesa.c
    +++ b/sys/i386/isa/vesa.c
    @@ -1074,11 +1074,6 @@ vesa_set_mode(video_adapter_t *adp, int mode)
     		(info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
     	vesa_adp->va_crtc_addr =
     		(vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
    -
    -	vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
    -	vesa_adp->va_window_size = info.vi_window_size;
    -	vesa_adp->va_window_gran = info.vi_window_gran;
    -
     	if (info.vi_flags & V_INFO_LINEAR) {
     #if VESA_DEBUG > 1
     		printf("VESA: setting up LFB\n");
    @@ -1088,31 +1083,41 @@ vesa_set_mode(video_adapter_t *adp, int mode)
     					vesa_adp_info->v_memsize*64*1024);
     		vesa_adp->va_buffer_size = info.vi_buffer_size;
     		vesa_adp->va_window = vesa_adp->va_buffer;
    +		vesa_adp->va_window_size = info.vi_buffer_size/info.vi_planes;
    +		vesa_adp->va_window_gran = info.vi_buffer_size/info.vi_planes;
     	} else {
     		vesa_adp->va_buffer = 0;
    -		vesa_adp->va_buffer_size = 0;
    +		vesa_adp->va_buffer_size = info.vi_buffer_size;
    +		vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
    +		vesa_adp->va_window_size = info.vi_window_size;
    +		vesa_adp->va_window_gran = info.vi_window_gran;
     	}
    -#if VESA_DEBUG > 1
    -	printf("VESA: buffer %x, buffer_size %d, window %x, window_size %d\n",
    -			vesa_adp->va_buffer,
    -			vesa_adp->va_buffer_size,
    -			vesa_adp->va_window,
    -			vesa_adp->va_window_size);
    -#endif
     	vesa_adp->va_window_orig = 0;
     	len = vesa_bios_get_line_length();
    -	if (info.vi_flags & V_INFO_GRAPHICS) {
    -		switch (info.vi_depth) {
    +	if (len > 0) {
    +		vesa_adp->va_line_width = len;
    +	} else if (info.vi_flags & V_INFO_GRAPHICS) {
    +		switch (info.vi_depth/info.vi_planes) {
    +		case 1:
    +			vesa_adp->va_line_width = info.vi_width/8;
    +			break;
    +		case 2:
    +			vesa_adp->va_line_width = info.vi_width/4;
    +			break;
     		case 4:
    -			vesa_adp->va_line_width = info.vi_width;
    +			vesa_adp->va_line_width = info.vi_width/2;
     			break;
     		case 8:
    +		default: /* shouldn't happen */
    +			vesa_adp->va_line_width = info.vi_width;
    +			break;
     		case 15:
     		case 16:
    +			vesa_adp->va_line_width = info.vi_width*2;
    +			break;
     		case 24:
     		case 32:
    -		default:
    -			vesa_adp->va_line_width = info.vi_width * (info.vi_depth / 8);
    +			vesa_adp->va_line_width = info.vi_width*4;
     			break;
     		}
     	} else {
    @@ -1121,8 +1126,8 @@ vesa_set_mode(video_adapter_t *adp, int mode)
     	vesa_adp->va_disp_start.x = 0;
     	vesa_adp->va_disp_start.y = 0;
     #if VESA_DEBUG > 0
    -	printf("vesa_set_mode(): vi_width:%d, len:%d, line_width:%d vi_mem_model:%d\n",
    -	       info.vi_width, len, vesa_adp->va_line_width, info.vi_mem_model);
    +	printf("vesa_set_mode(): vi_width:%d, len:%d, line_width:%d\n",
    +	       info.vi_width, len, vesa_adp->va_line_width);
     #endif
     	bcopy(&info, &vesa_adp->va_info, sizeof(vesa_adp->va_info));
     
    
    From 75e66e421a3c09a23c6a2fa36d4b48573eeef555 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Mon, 31 Aug 2009 17:42:52 +0000
    Subject: [PATCH 292/453] Improve pmap_change_attr() so that it is able to
     demote a large (2/4MB) page into 4KB pages as needed.  This should be fairly
     rare in practice on i386.  This includes merging the following changes from
     the amd64 pmap: 180430, 180485, 180845, 181043, 181077, and 196318. - Add
     basic support for changing attributes on PDEs to pmap_change_attr()   similar
     to the support in the initial version of pmap_change_attr() on   amd64
     including inlines for pmap_pde_attr() and pmap_pte_attr(). - Extend
     pmap_demote_pde() to include the ability to instantiate a new page   table
     page where none existed before. - Enhance pmap_change_attr().  Use
     pmap_demote_pde() to demote a 2/4MB page   mapping to 4KB page mappings when
     the specified attribute change only   applies to a portion of the 2/4MB page.
      Previously, in such cases,   pmap_change_attr() gave up and returned an
     error. - Correct a critical accounting error in pmap_demote_pde().
    
    Reviewed by:	alc
    MFC after:	3 days
    ---
     sys/i386/i386/pmap.c    | 229 +++++++++++++++++++++++++++++++---------
     sys/i386/include/pmap.h |   4 +
     2 files changed, 181 insertions(+), 52 deletions(-)
    
    diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
    index 405cbd30cfe..7ee7eac9156 100644
    --- a/sys/i386/i386/pmap.c
    +++ b/sys/i386/i386/pmap.c
    @@ -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,
    @@ -2289,32 +2292,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 +2381,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 +4461,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 +4606,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 +4635,93 @@ 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) {
    +	cache_bits_pde = cache_bits_pte = -1;
    +	changed = FALSE;
    +
    +	/*
    +	 * Pages that aren't mapped aren't supported.  Also break down
    +	 * 2/4MB pages into 4KB pages if required.
    +	 */
    +	PMAP_LOCK(kernel_pmap);
    +	for (tmpva = base; tmpva < base + size; ) {
     		pde = pmap_pde(kernel_pmap, tmpva);
    -		if (*pde & PG_PS)
    -			return (EINVAL);
    -		if (*pde == 0)
    +		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 (cache_bits_pde < 0)
    +				cache_bits_pde = pmap_cache_bits(mode, 1);
    +			if ((*pde & PG_PDE_CACHE) == cache_bits_pde) {
    +				tmpva = trunc_4mpage(tmpva) + NBPDR;
    +				continue;
    +			}
    +
    +			/*
    +			 * 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)
    +		if (*pte == 0) {
    +			PMAP_UNLOCK(kernel_pmap);
     			return (EINVAL);
    +		}
    +		tmpva += PAGE_SIZE;
     	}
    +	PMAP_UNLOCK(kernel_pmap);
     
     	changed = FALSE;
     
     	/*
    -	 * Ok, all the pages exist and are 4k, so run through them updating
    -	 * their cache mode.
    +	 * Ok, all the pages exist, so run through them updating their
    +	 * cache mode if required.
     	 */
    -	for (tmpva = base; size > 0; ) {
    -		pte = vtopte(tmpva);
    -
    -		/*
    -		 * 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;
    -		tmpva += PAGE_SIZE;
    -		size -= PAGE_SIZE;
    +	for (tmpva = base; tmpva < base + size; ) {
    +		pde = pmap_pde(kernel_pmap, 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;
    +			}
    +			tmpva = trunc_4mpage(tmpva) + NBPDR;
    +		} else {
    +			if (cache_bits_pte < 0)
    +				cache_bits_pte = pmap_cache_bits(mode, 0);
    +			pte = vtopte(tmpva);
    +			if ((*pte & PG_PTE_CACHE) != cache_bits_pte) {
    +				pmap_pte_attr(pte, cache_bits_pte);
    +				if (!changed)
    +					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/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:
    
    From 9e2bcb5a69240475ce0dd578bcb18308c80a7d56 Mon Sep 17 00:00:00 2001
    From: Doug Barton 
    Date: Mon, 31 Aug 2009 17:50:33 +0000
    Subject: [PATCH 293/453] Add support for INDEX-9 [1]
    
    While I'm here, strip off support for FreeBSD 5.x.
    
    Submitted by:	Alexey Shuvaev  [1]
    ---
     usr.sbin/pkg_install/lib/lib.h | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
    index acbd017c83c..6d5a9855ee9 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
    
    From 8101afb65624431d3cede99bfbf05bf793066562 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Mon, 31 Aug 2009 18:41:13 +0000
    Subject: [PATCH 294/453] Simplify pmap_change_attr() a bit: - Always calculate
     the cache bits instead of doing it on-demand. - Always set changed to TRUE
     rather than only doing it if it is false.
    
    Discussed with:	alc
    MFC after:	3 days
    ---
     sys/amd64/amd64/pmap.c | 22 +++++-----------------
     sys/i386/i386/pmap.c   | 17 ++++-------------
     2 files changed, 9 insertions(+), 30 deletions(-)
    
    diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
    index f0da536a012..4e35ef4aedb 100644
    --- a/sys/amd64/amd64/pmap.c
    +++ b/sys/amd64/amd64/pmap.c
    @@ -4476,7 +4476,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;
     
     	/*
    @@ -4493,8 +4494,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;
    @@ -4522,8 +4521,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;
    @@ -4557,12 +4554,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) {
    @@ -4588,12 +4582,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) {
    @@ -4616,13 +4607,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/i386/i386/pmap.c b/sys/i386/i386/pmap.c
    index 7ee7eac9156..548dbdb2ac6 100644
    --- a/sys/i386/i386/pmap.c
    +++ b/sys/i386/i386/pmap.c
    @@ -4635,7 +4635,8 @@ pmap_change_attr(vm_offset_t va, vm_size_t size, int mode)
     	if (base < VM_MIN_KERNEL_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;
     
     	/*
    @@ -4656,8 +4657,6 @@ pmap_change_attr(vm_offset_t va, vm_size_t size, int mode)
     			 * demote this page.  Just increment tmpva to
     			 * the next 2/4MB 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_4mpage(tmpva) + NBPDR;
     				continue;
    @@ -4688,8 +4687,6 @@ pmap_change_attr(vm_offset_t va, vm_size_t size, int mode)
     	}
     	PMAP_UNLOCK(kernel_pmap);
     
    -	changed = FALSE;
    -
     	/*
     	 * Ok, all the pages exist, so run through them updating their
     	 * cache mode if required.
    @@ -4697,22 +4694,16 @@ pmap_change_attr(vm_offset_t va, vm_size_t size, int mode)
     	for (tmpva = base; tmpva < base + size; ) {
     		pde = pmap_pde(kernel_pmap, 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;
     			}
     			tmpva = trunc_4mpage(tmpva) + NBPDR;
     		} else {
    -			if (cache_bits_pte < 0)
    -				cache_bits_pte = pmap_cache_bits(mode, 0);
     			pte = vtopte(tmpva);
     			if ((*pte & PG_PTE_CACHE) != cache_bits_pte) {
     				pmap_pte_attr(pte, cache_bits_pte);
    -				if (!changed)
    -					changed = TRUE;
    +				changed = TRUE;
     			}
     			tmpva += PAGE_SIZE;
     		}
    
    From 2bf078b30bb5e61a101c86e04000f3386866bece Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 31 Aug 2009 20:11:35 +0000
    Subject: [PATCH 295/453] Add regression test for ACLs on device files - mostly
     to make sure we don't crash on attempt to set ACL on them.
    
    ---
     tools/regression/acltools/tools-posix.test | 16 ++++++++++++++++
     1 file changed, 16 insertions(+)
    
    diff --git a/tools/regression/acltools/tools-posix.test b/tools/regression/acltools/tools-posix.test
    index 9ce94cdb5fd..bfb7ae003ad 100644
    --- a/tools/regression/acltools/tools-posix.test
    +++ b/tools/regression/acltools/tools-posix.test
    @@ -387,3 +387,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: 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: acl_get_file() failed: Operation not supported
    +$ ls -l ccc | cut -d' ' -f1
    +> crw-r--r--
    +
    +$ rm ccc
    
    From c5cb1e51b4ff53788e6508d5553481ef8fffa90c Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 31 Aug 2009 20:42:07 +0000
    Subject: [PATCH 296/453] Make the code more readable and fix chmod(1) on
     symlinks with NFSv4 enabled.
    
    ---
     bin/chmod/chmod.c | 28 +++++++++++++++-------------
     1 file changed, 15 insertions(+), 13 deletions(-)
    
    diff --git a/bin/chmod/chmod.c b/bin/chmod/chmod.c
    index d003b5fbc86..f70161120f4 100644
    --- a/bin/chmod/chmod.c
    +++ b/bin/chmod/chmod.c
    @@ -42,6 +42,7 @@ static char sccsid[] = "@(#)chmod.c	8.8 (Berkeley) 4/1/94";
     __FBSDID("$FreeBSD$");
     
     #include 
    +#include 
     #include 
     
     #include 
    @@ -54,7 +55,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 +63,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, fflag, fts_options, hflag, rval, error;
     	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 +140,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);
    @@ -186,10 +181,14 @@ 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) {
    +		if (hflag)
    +			error = lchmod(p->fts_accpath, newmode);
    +		else
    +			error = chmod(p->fts_accpath, newmode);
    +		if (error && !fflag) {
     			warn("%s", p->fts_path);
     			rval = 1;
     		} else {
    @@ -228,17 +227,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)
    
    From f7b8687a938048b590cc0b4689847e28a3c0d97c Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 31 Aug 2009 20:53:01 +0000
    Subject: [PATCH 297/453] Add NFSv4 ACL support to ls(1).
    
    ---
     bin/ls/print.c | 106 +++++++++++++++++++++++++------------------------
     1 file changed, 54 insertions(+), 52 deletions(-)
    
    diff --git a/bin/ls/print.c b/bin/ls/print.c
    index 4825d2e1052..2eb636e1708 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,69 @@ 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 (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;
    +	if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) ||
    +	    S_ISWHT(p->fts_statp->st_mode))
     		return;
    -	}
    -	if ((ret = pathconf(name, _PC_ACL_EXTENDED)) <= 0) {
    -		if (ret < 0 && errno != EINVAL)
    -			warn("%s", name);
    +
    +	if (previous_dev != p->fts_statp->st_dev) {
    +		previous_dev = p->fts_statp->st_dev;
    +		supports_acls = 0;
    +
    +		if (p->fts_level == FTS_ROOTLEVEL)
    +			snprintf(name, sizeof(name), "%s", p->fts_name);
     		else
    -			*haveacls = 0;
    +			snprintf(name, sizeof(name), "%s/%s",
    +			    p->fts_parent->fts_accpath, p->fts_name);
    +		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);
    +			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);
     }
    
    From 1bf38b12924824e34f6613213835ead8f1ce8170 Mon Sep 17 00:00:00 2001
    From: Qing Li 
    Date: Mon, 31 Aug 2009 21:02:48 +0000
    Subject: [PATCH 298/453] This patch fixes the following issues:
    
    - Routing messages are not generated when adding and removing
      interface address aliases.
    - Loopback route installed for an interface address alias is
      not deleted from the routing table when that address alias
      is removed from the associated interface.
    - Function in_ifscrub() is called extraneously.
    
    Reviewed by:	gnn, kmacy, sam
    MFC after:	3 days
    ---
     sys/netinet/in.c | 53 +++++++++++++++++++++++++++++++++++++++++++-----
     1 file changed, 48 insertions(+), 5 deletions(-)
    
    diff --git a/sys/netinet/in.c b/sys/netinet/in.c
    index 203f9e6be25..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 {
    
    From 394f34a5792b091a6722e5a804e4875f0b87f311 Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Mon, 31 Aug 2009 21:25:49 +0000
    Subject: [PATCH 299/453] On resume in sta mode program the beacon timers so
     when roaming (and the previous ap is no longer in range) the device will
     deliver bmiss interrupts and trigger the state machine.  Also arrange to sync
     the beacon timers on the next received beacon frame so that when we don't
     roam we re-synchronize with the ap.
    
    Tested by:	trasz
    MFC after:	1 week
    ---
     sys/dev/ath/if_ath.c | 11 ++++++++++-
     1 file changed, 10 insertions(+), 1 deletion(-)
    
    diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
    index a789f5ea298..5628addc33a 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);
     	}
    
    From 54d1bac5bb90a835bf60c9452a116abaf8d92d7a Mon Sep 17 00:00:00 2001
    From: Pyun YongHyeon 
    Date: Mon, 31 Aug 2009 22:09:48 +0000
    Subject: [PATCH 300/453] Make sure rx descriptor ring align on 16 bytes. I
     guess the alignment requirement could be multiple of 4 bytes but I think
     using descriptor size would make intention clearer. Previously the size of rx
     descriptor was not power of 2 so it caused panic in bus_dmamem_alloc(9).
    
    Reported by:	Jeff Blank (jb000003 <> mr-happy dot com)
    MFC after:	3 days
    ---
     sys/dev/txp/if_txp.c | 6 ++++--
     1 file changed, 4 insertions(+), 2 deletions(-)
    
    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);
    
    From 0ad6375395f8bab40563033c23801112bd014ffc Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Mon, 31 Aug 2009 23:30:39 +0000
    Subject: [PATCH 301/453] Shuffle pagezero() into the same location as in
     sys/i386/i386/pmap.c.
    
    ---
     sys/i386/xen/locore.s |  2 --
     sys/i386/xen/pmap.c   | 32 ++++++++++++++++----------------
     2 files changed, 16 insertions(+), 18 deletions(-)
    
    diff --git a/sys/i386/xen/locore.s b/sys/i386/xen/locore.s
    index a2c4a8db7b7..95d2afae841 100644
    --- a/sys/i386/xen/locore.s
    +++ b/sys/i386/xen/locore.s
    @@ -148,9 +148,7 @@ IdlePDPT:	.long	0		/* phys addr of kernel PDPT */
     	.globl	KPTphys
     #endif
     KPTphys:	.long	0		/* phys addr of kernel page tables */
    -#ifdef SMP
     	.globl	gdtset
    -#endif
     gdtset:		.long	0		/* GDT is valid */	
     
     	.globl	proc0kstack
    diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
    index 9dc077f8803..52b41e99d68 100644
    --- a/sys/i386/xen/pmap.c
    +++ b/sys/i386/xen/pmap.c
    @@ -328,22 +328,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)
     {
    @@ -3343,6 +3327,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.
    
    From 82fe1cca6703969e35ae716ab4abd075a79b429d Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Mon, 31 Aug 2009 23:35:59 +0000
    Subject: [PATCH 302/453] Revert previous commit; that was left-over junk in
     the tree.
    
    ---
     sys/i386/xen/locore.s | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/sys/i386/xen/locore.s b/sys/i386/xen/locore.s
    index 95d2afae841..a2c4a8db7b7 100644
    --- a/sys/i386/xen/locore.s
    +++ b/sys/i386/xen/locore.s
    @@ -148,7 +148,9 @@ IdlePDPT:	.long	0		/* phys addr of kernel PDPT */
     	.globl	KPTphys
     #endif
     KPTphys:	.long	0		/* phys addr of kernel page tables */
    +#ifdef SMP
     	.globl	gdtset
    +#endif
     gdtset:		.long	0		/* GDT is valid */	
     
     	.globl	proc0kstack
    
    From f8d44dbb7457ea2b281eb80247ea552837c83892 Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Tue, 1 Sep 2009 03:44:25 +0000
    Subject: [PATCH 303/453] Fix broken build.
    
    ---
     sys/i386/xen/pmap.c | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
    index 52b41e99d68..22692d042f2 100644
    --- a/sys/i386/xen/pmap.c
    +++ b/sys/i386/xen/pmap.c
    @@ -311,6 +311,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);
    
    From fa52c6106bb458388249d3b569b880f5887575a3 Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Tue, 1 Sep 2009 05:15:45 +0000
    Subject: [PATCH 304/453] Merge in the pat_works work from sys/i386/i386/pmap.c
     - primarily to reduce diff size.
    
    ---
     sys/i386/xen/pmap.c | 139 +++++++++++++++++++++++---------------------
     1 file changed, 74 insertions(+), 65 deletions(-)
    
    diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
    index 22692d042f2..433ca1c59c1 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
      */
    @@ -514,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);
     }
     
    @@ -769,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. */
    
    From fcae0ffd3dff7c381e5838f53ca57e958ed9bd69 Mon Sep 17 00:00:00 2001
    From: Maxim Konovalov 
    Date: Tue, 1 Sep 2009 05:55:10 +0000
    Subject: [PATCH 305/453] o Document MALLOC_PRODUCTION knob.
    
    PR:		docs/136029
    Submitted by:	anonymous
    MFC after:	2 weeks
    ---
     share/man/man5/make.conf.5 | 8 +++++++-
     1 file changed, 7 insertions(+), 1 deletion(-)
    
    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.
    
    From c0bb2b80581439199f82b3656b1d1b7bd3640e3f Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Tue, 1 Sep 2009 06:15:50 +0000
    Subject: [PATCH 306/453] Migrate to use cpuset_t.
    
    ---
     sys/i386/xen/pmap.c | 9 ++++-----
     1 file changed, 4 insertions(+), 5 deletions(-)
    
    diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
    index 433ca1c59c1..37c7d377658 100644
    --- a/sys/i386/xen/pmap.c
    +++ b/sys/i386/xen/pmap.c
    @@ -1729,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;
     
    @@ -1738,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)])++;
    @@ -1750,7 +1750,7 @@ pmap_lazyfix_action(void)
     }
     
     static void
    -pmap_lazyfix_self(u_int mymask)
    +pmap_lazyfix_self(cpumask_t mymask)
     {
     
     	if (rcr3() == lazyptd)
    @@ -1762,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) {
    
    From 8a945d109ce5702c5e8b9c642a354afe250b37d1 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Tue, 1 Sep 2009 11:41:51 +0000
    Subject: [PATCH 307/453] Reintroduce the r196640, after fixing the problem
     with my testing.
    
    Remove the altkstacks, instead instantiate threads with kernel stack
    allocated with the right size from the start. For the thread that has
    kernel stack cached, verify that requested stack size is equial to the
    actual, and reallocate the stack if sizes differ [1].
    
    This fixes the bug introduced by r173361 that was committed several days
    after r173004 and consisted of kthread_add(9) ignoring the non-default
    kernel stack size.
    
    Also, r173361 removed the caching of the kernel stacks for a non-first
    thread in the process. Introduce separate kernel stack cache that keeps
    some limited amount of preallocated kernel stacks to lower the latency
    of thread allocation. Add vm_lowmem handler to prune the cache on
    low memory condition. This way, system with reasonable amount of the
    threads get lower latency of thread creation, while still not exhausting
    significant portion of KVA for unused kstacks.
    
    Submitted by:	peter [1]
    Discussed with:	jhb, julian, peter
    Reviewed by:	jhb
    Tested by:	pho (and retested according to new test scenarious)
    MFC after:	1 week
    ---
     sys/arm/arm/vm_machdep.c |   3 -
     sys/kern/kern_fork.c     |  25 ++++---
     sys/kern/kern_kthread.c  |   5 +-
     sys/kern/kern_proc.c     |  10 ---
     sys/kern/kern_thr.c      |   2 +-
     sys/kern/kern_thread.c   |  17 +++--
     sys/sys/proc.h           |   6 +-
     sys/vm/vm_extern.h       |   2 -
     sys/vm/vm_glue.c         | 140 +++++++++++++++++++++++++++------------
     9 files changed, 128 insertions(+), 82 deletions(-)
    
    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/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_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_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_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/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/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,
    
    From 579b976090fcf16bc88300ebb57e8bd5c9901cc9 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Tue, 1 Sep 2009 12:05:39 +0000
    Subject: [PATCH 308/453] Fix mount reference leak when V_XSLEEP is specified
     to vn_start_write().
    
    Submitted by:	tegge
    ---
     sys/kern/vfs_vnops.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
    index 986bc8e880a..1b77352b1c6 100644
    --- a/sys/kern/vfs_vnops.c
    +++ b/sys/kern/vfs_vnops.c
    @@ -999,7 +999,7 @@ vn_start_write(vp, mpp, flags)
     		goto unlock;
     	mp->mnt_writeopcount++;
     unlock:
    -	if (error != 0)
    +	if (error != 0 || (flags & V_XSLEEP) != 0)
     		MNT_REL(mp);
     	MNT_IUNLOCK(mp);
     	return (error);
    
    From 56af96debe1cf7e3db80eecaa6b00cbe33b34d81 Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Tue, 1 Sep 2009 12:17:47 +0000
    Subject: [PATCH 309/453] Delete whitespace not in i386/pmap.c
    
    ---
     sys/i386/xen/pmap.c | 1 -
     1 file changed, 1 deletion(-)
    
    diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
    index 37c7d377658..4b81aae1699 100644
    --- a/sys/i386/xen/pmap.c
    +++ b/sys/i386/xen/pmap.c
    @@ -4171,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();
     }
    
    From 5f483c5f73e0d43a7f230e0ce8f6021caec91870 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Tue, 1 Sep 2009 15:51:36 +0000
    Subject: [PATCH 310/453] Adapt to the fact that ls(1) correctly prints '+' for
     symlinks with ACLs now.
    
    ---
     tools/regression/acltools/tools-posix.test | 3 +--
     1 file changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/tools/regression/acltools/tools-posix.test b/tools/regression/acltools/tools-posix.test
    index bfb7ae003ad..6ae31f36edd 100644
    --- a/tools/regression/acltools/tools-posix.test
    +++ b/tools/regression/acltools/tools-posix.test
    @@ -77,9 +77,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
    
    From cc7e9d4325763fce383cece2744c8525a144b806 Mon Sep 17 00:00:00 2001
    From: "Bjoern A. Zeeb" 
    Date: Tue, 1 Sep 2009 17:53:01 +0000
    Subject: [PATCH 311/453] In case an upper layer protocol tries to send a
     packet but the L2 code does not have the ethernet address for the destination
     within the broadcast domain in the table, we remember the original mbuf in
     `la_hold' in arpresolve() and send out a different packet with an arp
     request. In case there will be more upper layer packets to send we will free
     an earlier one held in `la_hold' and queue the new one.
    
    Once we get a packet in, with which we can perfect our arp table
    entry we send out the original 'on hold' packet, should there
    be any.
    Rather than continuing to process the packet that we received,
    we returned without freeing the packet that came in, which
    basically means that we leaked an mbuf for every arp request
    we sent.
    
    Rather than freeing the received packet and returning, continue
    to process the incoming arp packet as well.
    This should (a) improve some setups, also proxy-arp, in case it was an
    incoming arp request and (b) resembles the behaviour FreeBSD had
    from day 1, which alignes with RFC826 "Packet reception" (merge case).
    
    Rename 'm0' to 'hold' to make the code more understandable as
    well as diffable to earlier versions more easily.
    
    Handle the link-layer entry 'la' lock comepletely in the block
    where needed and release it as early as possible, rather than
    holding it longer, down to the end of the function.
    
    Found by:			pointyhat, ns1
    Bug hunting session with:	erwin, simon, rwatson
    Tested by:			simon on cluster machines
    Reviewed by:			ratson, kmacy, julian
    MFC after:			3 days
    ---
     sys/netinet/if_ether.c | 22 ++++++++++------------
     1 file changed, 10 insertions(+), 12 deletions(-)
    
    diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
    index 9d1c13afe86..e118cec0fa3 100644
    --- a/sys/netinet/if_ether.c
    +++ b/sys/netinet/if_ether.c
    @@ -462,11 +462,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
    @@ -631,11 +631,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 +657,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,15 +674,14 @@ 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)
    @@ -750,8 +752,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. */
    @@ -777,8 +777,6 @@ reply:
     	return;
     
     drop:
    -	if (la != NULL)
    -		LLE_WUNLOCK(la);
     	m_freem(m);
     }
     #endif
    
    From 2e7de509330cab915c59822a86434b7a6d56cd40 Mon Sep 17 00:00:00 2001
    From: "George V. Neville-Neil" 
    Date: Tue, 1 Sep 2009 17:55:37 +0000
    Subject: [PATCH 312/453] Add counters for the i7 architecture which were
     accidentally left out of the original commit of i7 support.  These are all
     the counters on pages A-32 and A-33 of the _Intel(R) 64 and IA32
     Architectures Software Developer's Manual Vol 3B_, June 2009.  Almost all of
     these counters relate to operations on the L2 cache.
    
    Reviewed by:	jkoshy
    MFC after:	1 month
    ---
     sys/dev/hwpmc/hwpmc_core.c | 23 ++++++++++++++
     sys/dev/hwpmc/pmc_events.h | 62 ++++++++++++++++++++++++++++++++++++--
     2 files changed, 82 insertions(+), 3 deletions(-)
    
    diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
    index f84e0f1548c..d4f065b6024 100644
    --- a/sys/dev/hwpmc/hwpmc_core.c
    +++ b/sys/dev/hwpmc/hwpmc_core.c
    @@ -1182,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),
    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) \
    
    From 59831d75959820cdd10600cd3e74c4a36c002f32 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Tue, 1 Sep 2009 18:30:17 +0000
    Subject: [PATCH 313/453] Fix regression introduced with NFSv4 ACL support -
     make acl_to_text(3) and acl_calc_mask(3) return error instead of crashing
     when acl passed to them is NULL.
    
    Submitted by:	markus
    Reviewed by:	rwatson
    MFC after:	3 days
    ---
     lib/libc/posix1e/acl_calc_mask.c | 13 +++++++------
     lib/libc/posix1e/acl_to_text.c   | 10 +++++-----
     2 files changed, 12 insertions(+), 11 deletions(-)
    
    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_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));
    
    From a01e019a265ef9faa3165d79891b31a1e9ec86c8 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Wed, 2 Sep 2009 00:39:59 +0000
    Subject: [PATCH 314/453] Don't attempt to bind the current thread to the CPU
     an IRQ is bound to when removing an interrupt handler from an IRQ during
     shutdown.  During shutdown we are already bound to CPU 0 and this was
     triggering a panic.
    
    MFC after:	3 days
    ---
     sys/amd64/amd64/local_apic.c | 21 ++++++++++++---------
     sys/i386/i386/local_apic.c   | 21 ++++++++++++---------
     2 files changed, 24 insertions(+), 18 deletions(-)
    
    diff --git a/sys/amd64/amd64/local_apic.c b/sys/amd64/amd64/local_apic.c
    index 13bd7743cb9..87bec91b6c4 100644
    --- a/sys/amd64/amd64/local_apic.c
    +++ b/sys/amd64/amd64/local_apic.c
    @@ -990,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). */
    diff --git a/sys/i386/i386/local_apic.c b/sys/i386/i386/local_apic.c
    index 5e79aa805c5..9b1d1b3173e 100644
    --- a/sys/i386/i386/local_apic.c
    +++ b/sys/i386/i386/local_apic.c
    @@ -994,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). */
    
    From f39e07f3aff75456e675f4e962b019834577aa89 Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Wed, 2 Sep 2009 04:26:34 +0000
    Subject: [PATCH 315/453] 1) Use isprint() instead of hardcoded values to
     detect non-printable. 2) Use (unsigned char) cast in waddch() calls. It fix
     highlighting bug: sign extension of 8bit to the attributes area. 3) Use
     setlocale() in any case.
    
    ---
     contrib/ee/ee.c | 18 +++++++++---------
     1 file changed, 9 insertions(+), 9 deletions(-)
    
    diff --git a/contrib/ee/ee.c b/contrib/ee/ee.c
    index 070bb9781fe..bd392a7fe25 100755
    --- a/contrib/ee/ee.c
    +++ b/contrib/ee/ee.c
    @@ -726,7 +726,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 +734,7 @@ int character;			/* new character			*/
     	}
     	else
     	{
    -		waddch(text_win, character);
    +		waddch(text_win, (unsigned char)character);
     		scr_pos = ++scr_horz;
     		point++;
     		position ++;
    @@ -969,17 +969,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 +1044,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 +1923,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++;
     		}
    @@ -5085,8 +5085,8 @@ strings_init()
     {
     	int counter;
     
    -#ifndef NO_CATGETS
     	setlocale(LC_ALL, "");
    +#ifndef NO_CATGETS
     	catalog = catopen("ee", NL_CAT_LOCALE);
     #endif /* NO_CATGETS */
     
    
    From db07ef76dabf8f663663a7e9ddfad42611c730a8 Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Wed, 2 Sep 2009 04:43:46 +0000
    Subject: [PATCH 316/453] Move  out of NO_CATGETS define too (as
     setlocale() in prev. commit)
    
    ---
     contrib/ee/ee.c | 3 +--
     1 file changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/contrib/ee/ee.c b/contrib/ee/ee.c
    index bd392a7fe25..4c95ac9bec3 100755
    --- a/contrib/ee/ee.c
    +++ b/contrib/ee/ee.c
    @@ -83,6 +83,7 @@ char *version = "@(#) ee, version "  EE_VERSION  " $Revision: 1.102 $";
     #include 
     #include 
     #include 
    +#include 
     
     #ifdef HAS_SYS_WAIT
     #include 
    @@ -100,9 +101,7 @@ char *version = "@(#) ee, version "  EE_VERSION  " $Revision: 1.102 $";
     #include 
     #endif
     
    -
     #ifndef NO_CATGETS
    -#include 
     #include 
     
     nl_catd catalog;
    
    From b9a10b58106882b8972792b65c32ddcd412c67ac Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Wed, 2 Sep 2009 04:56:30 +0000
    Subject: [PATCH 317/453] Use (unsigned char) cast for ctype macro
    
    ---
     lib/libc/stdtime/strptime.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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++;
    
    From f0246686c68e2a3279f3b98eeb7fbd3b20fffde6 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Wed, 2 Sep 2009 05:26:59 +0000
    Subject: [PATCH 318/453] - Don't include both  and 
    
    - Keep variables sorted
    
    - Fix logic error with -f and -v options - don't print
      the usual -v output if there was an error, whether or not
      we were passed -f
    
    - Don't call free(3) just before exit(2)
    
    - Whitespace fixes
    
    Submitted by:	bde
    ---
     bin/chmod/chmod.c | 15 ++++++---------
     1 file changed, 6 insertions(+), 9 deletions(-)
    
    diff --git a/bin/chmod/chmod.c b/bin/chmod/chmod.c
    index f70161120f4..dc51faa39b0 100644
    --- a/bin/chmod/chmod.c
    +++ b/bin/chmod/chmod.c
    @@ -41,7 +41,6 @@ static char sccsid[] = "@(#)chmod.c	8.8 (Berkeley) 4/1/94";
     #include 
     __FBSDID("$FreeBSD$");
     
    -#include 
     #include 
     #include 
     
    @@ -63,7 +62,7 @@ main(int argc, char *argv[])
     	FTS *ftsp;
     	FTSENT *p;
     	mode_t *set;
    -	int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval, error;
    +	int Hflag, Lflag, Rflag, ch, error, fflag, fts_options, hflag, rval;
     	int vflag;
     	char *mode;
     	mode_t newmode;
    @@ -170,7 +169,6 @@ done:	argv += optind;
     			 */
     			if (!hflag)
     				continue;
    -			/* else */
     			/* FALLTHROUGH */
     		default:
     			break;
    @@ -188,9 +186,11 @@ done:	argv += optind;
     			error = lchmod(p->fts_accpath, newmode);
     		else
     			error = chmod(p->fts_accpath, newmode);
    -		if (error && !fflag) {
    -			warn("%s", p->fts_path);
    -			rval = 1;
    +		if (error) {
    +			if (!fflag) {
    +				warn("%s", p->fts_path);
    +				rval = 1;
    +			}
     		} else {
     			if (vflag) {
     				(void)printf("%s", p->fts_path);
    @@ -201,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) |
    @@ -209,12 +208,10 @@ done:	argv += optind;
     				}
     				(void)printf("\n");
     			}
    -
     		}
     	}
     	if (errno)
     		err(1, "fts_read");
    -	free(set);
     	exit(rval);
     }
     
    
    From 2689ba27207a4511b743a651793173e8ddf041c2 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Wed, 2 Sep 2009 08:08:57 +0000
    Subject: [PATCH 319/453] Add NFSv4 ACL support to cp(1) and fix a few memory
     leaks.
    
    Note that this changes error reporting behaviour somewhat - before,
    no error was reported if ACL couldn't be copied because the target
    filesystem doesn't support ACLs.  Now, it will be reported - of course,
    only if there actually is an ACL to copy.
    
    Reviewed by:	rwatson
    ---
     bin/cp/utils.c | 127 ++++++++++++++++++++++++++++++++++++-------------
     1 file changed, 95 insertions(+), 32 deletions(-)
    
    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);
     }
     
    
    From 46681d6e454c3bf6c8ca85967d6c868a1b54a141 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Wed, 2 Sep 2009 11:39:19 +0000
    Subject: [PATCH 320/453] Improve HDA controller capabilities logging.
    
    ---
     sys/dev/sound/pci/hda/hdac.c         | 13 +++++++------
     sys/dev/sound/pci/hda/hdac_private.h |  1 +
     sys/dev/sound/pci/hda/hdac_reg.h     |  2 ++
     3 files changed, 10 insertions(+), 6 deletions(-)
    
    diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
    index 9f4264d98ec..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);
    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
    
    From 9e545c02160846396768901fc6395ce4d3605d1f Mon Sep 17 00:00:00 2001
    From: Florent Thoumie 
    Date: Wed, 2 Sep 2009 13:58:15 +0000
    Subject: [PATCH 321/453] - Bump PKG_INSTALL_VERSION to 20090902 after dougb's
     changes. - Change the comment to say that version must be changed when a
     non-cosmetic change is made.
    
    ---
     usr.sbin/pkg_install/lib/lib.h | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
    index 6d5a9855ee9..a3d04138797 100644
    --- a/usr.sbin/pkg_install/lib/lib.h
    +++ b/usr.sbin/pkg_install/lib/lib.h
    @@ -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)
    
    From b7f0127e7bb5735437dd46ca8818d44a84754309 Mon Sep 17 00:00:00 2001
    From: Florent Thoumie 
    Date: Wed, 2 Sep 2009 14:54:47 +0000
    Subject: [PATCH 322/453] - Remove BSD.{x11,x11-4}.dist as we merged prefixes a
     while ago and those files aren't used anymore. - Remove BSD.local.dist as the
     file moved to ports/Templates when we merged prefixes.
    
    ---
     etc/Makefile             |   3 +-
     etc/mtree/BSD.local.dist | 850 ---------------------------------------
     etc/mtree/BSD.x11-4.dist | 488 ----------------------
     etc/mtree/BSD.x11.dist   | 306 --------------
     4 files changed, 1 insertion(+), 1646 deletions(-)
     delete mode 100644 etc/mtree/BSD.local.dist
     delete mode 100644 etc/mtree/BSD.x11-4.dist
     delete mode 100644 etc/mtree/BSD.x11.dist
    
    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/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.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
    -        ..
    -    ..
    -..
    
    From f038eb6d37facddd0b3af7d09419e240667e2fc5 Mon Sep 17 00:00:00 2001
    From: Florent Thoumie 
    Date: Wed, 2 Sep 2009 14:56:23 +0000
    Subject: [PATCH 323/453] Remove BSD.{local,x11,x11-4}.dist mtree files as
     they're either obsolete or they've moved to ports.
    
    ---
     ObsoleteFiles.inc | 4 ++++
     1 file changed, 4 insertions(+)
    
    diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
    index e963f655351..54be9dd9ccb 100644
    --- a/ObsoleteFiles.inc
    +++ b/ObsoleteFiles.inc
    @@ -14,6 +14,10 @@
     # The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last.
     #
     
    +# 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
    
    From c9e881790201d01428ad2d6e5ae2d0659bfc778b Mon Sep 17 00:00:00 2001
    From: Jung-uk Kim 
    Date: Wed, 2 Sep 2009 16:02:48 +0000
    Subject: [PATCH 324/453] - Work around ACPI mode transition problem for recent
     NVIDIA 9400M chipset based Intel Macs.  Since r189055, these platforms
     started freezing when ACPI is being initialized for unknown reason.  For
     these platforms, we just use the old PAT layout.  Note this change is not
     enough to boot fully on these platforms because of other problems but it
     makes debugging possible. Note MacBook5,2 may be affected as well but it was
     not added here because of lack of hardware to test. - Initialize PAT MSR
     fully instead of reading and modifying it for safety.
    
    Reported by:	rpaulo, hps, Eygene Ryabinkin (rea-fbsd at codelabs dot ru)
    Reviewed by:	jhb
    ---
     sys/amd64/amd64/pmap.c | 115 +++++++++++++++++++++++++++++++----------
     sys/i386/i386/pmap.c   |  63 ++++++++++++++++------
     2 files changed, 133 insertions(+), 45 deletions(-)
    
    diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
    index 4e35ef4aedb..368513b687e 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. */
    diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
    index 548dbdb2ac6..1648126233e 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");
     
    @@ -478,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-.
     		 * 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)
    +		 * 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);
     }
    
    From c8e648e16768bdba73b8cc4b957907e2ac5fdc7c Mon Sep 17 00:00:00 2001
    From: Jung-uk Kim 
    Date: Wed, 2 Sep 2009 16:47:10 +0000
    Subject: [PATCH 325/453] Fix confusing comments about default PAT entries.
    
    ---
     sys/amd64/amd64/pmap.c | 4 ++--
     sys/i386/i386/pmap.c   | 4 ++--
     2 files changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
    index 368513b687e..4febfb3b886 100644
    --- a/sys/amd64/amd64/pmap.c
    +++ b/sys/amd64/amd64/pmap.c
    @@ -628,9 +628,9 @@ pmap_init_pat(void)
     
     	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 &= ~(PAT_MASK(4) | PAT_MASK(5));
     		pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
    diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
    index 1648126233e..9b832aefc95 100644
    --- a/sys/i386/i386/pmap.c
    +++ b/sys/i386/i386/pmap.c
    @@ -528,9 +528,9 @@ pmap_init_pat(void)
     
     	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 &= ~(PAT_MASK(4) | PAT_MASK(5));
     		pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
    
    From 8d3635c4dbe64a3fbc5694cc4df287bc660a55b4 Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Wed, 2 Sep 2009 17:33:51 +0000
    Subject: [PATCH 326/453] Fix some bugs related to adaptive spinning:
    
    In the lockmgr support:
    - GIANT_RESTORE() is just called when the sleep finishes, so the current
      code can ends up into a giant unlock problem.  Fix it by appropriately
      call GIANT_RESTORE() when needed.  Note that this is not exactly ideal
      because for any interation of the adaptive spinning we drop and restore
      Giant, but the overhead should be not a factor.
    - In the lock held in exclusive mode case, after the adaptive spinning is
      brought to completition, we should just retry to acquire the lock
      instead to fallthrough. Fix that.
    - Fix a style nit
    
    In the sx support:
    - Call GIANT_SAVE() before than looping. This saves some overhead because
      in the current code GIANT_SAVE() is called several times.
    
    Tested by:	Giovanni Trematerra 
    ---
     sys/kern/kern_lock.c | 13 +++++++++++--
     sys/kern/kern_sx.c   |  2 +-
     2 files changed, 12 insertions(+), 3 deletions(-)
    
    diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
    index 29ae4accfa7..e6f2f536249 100644
    --- a/sys/kern/kern_lock.c
    +++ b/sys/kern/kern_lock.c
    @@ -467,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) {
    @@ -491,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);
    @@ -511,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;
     			}
    @@ -704,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) {
    @@ -727,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_sx.c b/sys/kern/kern_sx.c
    index 4a78444c09c..c00b267e5d2 100644
    --- a/sys/kern/kern_sx.c
    +++ b/sys/kern/kern_sx.c
    @@ -531,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)
    
    From a34292623ff852613c5d61c2acc986692928b0ca Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Wed, 2 Sep 2009 20:50:39 +0000
    Subject: [PATCH 327/453] Fix regression introduced in r196712 - the 'name'
     string needs to be rewritten for each file we want to check ACL on.  Without
     this change, ls(1) would check only the ACL on the first file to list.
    
    ---
     bin/ls/print.c | 14 +++++++++-----
     1 file changed, 9 insertions(+), 5 deletions(-)
    
    diff --git a/bin/ls/print.c b/bin/ls/print.c
    index 2eb636e1708..3b80d93aefe 100644
    --- a/bin/ls/print.c
    +++ b/bin/ls/print.c
    @@ -623,15 +623,19 @@ aclmode(char *buf, const FTSENT *p)
     	    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);
    +
     	if (previous_dev != p->fts_statp->st_dev) {
     		previous_dev = p->fts_statp->st_dev;
     		supports_acls = 0;
     
    -		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);
     		ret = lpathconf(name, _PC_ACL_NFS4);
     		if (ret > 0) {
     			type = ACL_TYPE_NFS4;
    
    From 9b934d0930b6225b62c2752c3812c12679fde7de Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Thu, 3 Sep 2009 09:33:57 +0000
    Subject: [PATCH 328/453] Move libteken out of the syscons directory.
    
    I initially committed libteken to sys/dev/syscons/teken, but now that
    I'm working on a console driver myself, I noticed this was not a good
    decision. Move it to sys/teken to make it easier for other drivers to
    use a terminal emulator.
    
    Also list teken.c in sys/conf/files, instead of listing it in all the
    files.arch files separately.
    ---
     sys/conf/files                                  | 5 +++--
     sys/conf/files.amd64                            | 1 -
     sys/conf/files.i386                             | 1 -
     sys/conf/files.ia64                             | 1 -
     sys/conf/files.powerpc                          | 1 -
     sys/conf/files.sparc64                          | 1 -
     sys/dev/syscons/scterm-teken.c                  | 2 +-
     sys/{dev/syscons => }/teken/Makefile            | 0
     sys/{dev/syscons => }/teken/gensequences        | 0
     sys/{dev/syscons => }/teken/sequences           | 0
     sys/{dev/syscons => }/teken/teken.c             | 0
     sys/{dev/syscons => }/teken/teken.h             | 0
     sys/{dev/syscons => }/teken/teken_demo.c        | 0
     sys/{dev/syscons => }/teken/teken_scs.h         | 0
     sys/{dev/syscons => }/teken/teken_stress.c      | 0
     sys/{dev/syscons => }/teken/teken_subr.h        | 0
     sys/{dev/syscons => }/teken/teken_subr_compat.h | 0
     sys/{dev/syscons => }/teken/teken_wcwidth.h     | 0
     18 files changed, 4 insertions(+), 8 deletions(-)
     rename sys/{dev/syscons => }/teken/Makefile (100%)
     rename sys/{dev/syscons => }/teken/gensequences (100%)
     rename sys/{dev/syscons => }/teken/sequences (100%)
     rename sys/{dev/syscons => }/teken/teken.c (100%)
     rename sys/{dev/syscons => }/teken/teken.h (100%)
     rename sys/{dev/syscons => }/teken/teken_demo.c (100%)
     rename sys/{dev/syscons => }/teken/teken_scs.h (100%)
     rename sys/{dev/syscons => }/teken/teken_stress.c (100%)
     rename sys/{dev/syscons => }/teken/teken_subr.h (100%)
     rename sys/{dev/syscons => }/teken/teken_subr_compat.h (100%)
     rename sys/{dev/syscons => }/teken/teken_wcwidth.h (100%)
    
    diff --git a/sys/conf/files b/sys/conf/files
    index b5baadee14b..41a34b15d6f 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				   \
    @@ -2616,6 +2616,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/dev/syscons/scterm-teken.c b/sys/dev/syscons/scterm-teken.c
    index 36cfbb5d35f..6f51ac17035 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 *);
    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 100%
    rename from sys/dev/syscons/teken/teken.c
    rename to sys/teken/teken.c
    diff --git a/sys/dev/syscons/teken/teken.h b/sys/teken/teken.h
    similarity index 100%
    rename from sys/dev/syscons/teken/teken.h
    rename to sys/teken/teken.h
    diff --git a/sys/dev/syscons/teken/teken_demo.c b/sys/teken/teken_demo.c
    similarity index 100%
    rename from sys/dev/syscons/teken/teken_demo.c
    rename to sys/teken/teken_demo.c
    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
    
    From 5b1237b60004740269f922a7aa334bc1f49759ea Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= 
    Date: Thu, 3 Sep 2009 10:06:37 +0000
    Subject: [PATCH 329/453] Document the need for a cast when passing a char to a
     ctype function.
    
    MFC after:	2 weeks
    ---
     lib/libc/locale/ctype.3       |  9 ++++++++-
     lib/libc/locale/digittoint.3  | 11 ++++++++++-
     lib/libc/locale/isalnum.3     | 11 ++++++++++-
     lib/libc/locale/isalpha.3     | 11 ++++++++++-
     lib/libc/locale/isascii.3     | 11 ++++++++++-
     lib/libc/locale/isblank.3     | 11 ++++++++++-
     lib/libc/locale/iscntrl.3     | 11 ++++++++++-
     lib/libc/locale/isdigit.3     | 11 ++++++++++-
     lib/libc/locale/isgraph.3     | 11 ++++++++++-
     lib/libc/locale/isideogram.3  | 11 ++++++++++-
     lib/libc/locale/islower.3     | 11 ++++++++++-
     lib/libc/locale/isphonogram.3 | 11 ++++++++++-
     lib/libc/locale/isprint.3     | 11 ++++++++++-
     lib/libc/locale/ispunct.3     | 11 ++++++++++-
     lib/libc/locale/isrune.3      | 11 ++++++++++-
     lib/libc/locale/isspace.3     | 11 ++++++++++-
     lib/libc/locale/isspecial.3   | 11 ++++++++++-
     lib/libc/locale/isupper.3     | 11 ++++++++++-
     lib/libc/locale/isxdigit.3    | 11 ++++++++++-
     lib/libc/locale/toascii.3     | 11 ++++++++++-
     lib/libc/locale/tolower.3     | 11 ++++++++++-
     lib/libc/locale/toupper.3     | 11 ++++++++++-
     22 files changed, 218 insertions(+), 22 deletions(-)
    
    diff --git a/lib/libc/locale/ctype.3 b/lib/libc/locale/ctype.3
    index fdc135878f7..9d4ee5ea390 100644
    --- a/lib/libc/locale/ctype.3
    +++ b/lib/libc/locale/ctype.3
    @@ -28,7 +28,7 @@
     .\"     @(#)ctype.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd March 30, 2004
    +.Dd September 3, 2009
     .Dt CTYPE 3
     .Os
     .Sh NAME
    @@ -111,6 +111,13 @@ They are available as macros, defined in the include file
     .In ctype.h ,
     or as true functions in the C library.
     See the specific manual pages for more information.
    +.Pp
    +.Em NOTE :
    +if the value passed to one of these functions is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh SEE ALSO
     .Xr digittoint 3 ,
     .Xr isalnum 3 ,
    diff --git a/lib/libc/locale/digittoint.3 b/lib/libc/locale/digittoint.3
    index 372e00f2f8d..c7e2ac1179d 100644
    --- a/lib/libc/locale/digittoint.3
    +++ b/lib/libc/locale/digittoint.3
    @@ -28,7 +28,7 @@
     .\"	@(#)digittoint.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd April 6, 2001
    +.Dd September 3, 2009
     .Dt DIGITTOINT 3
     .Os
     .Sh NAME
    @@ -46,6 +46,15 @@ The
     function converts a numeric character to its corresponding integer value.
     The character can be any decimal digit or hexadecimal digit.
     With hexadecimal characters, the case of the values does not matter.
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn digittoint
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn digittoint
    diff --git a/lib/libc/locale/isalnum.3 b/lib/libc/locale/isalnum.3
    index 624a6e2335d..335ca9cc02d 100644
    --- a/lib/libc/locale/isalnum.3
    +++ b/lib/libc/locale/isalnum.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isalnum.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISALNUM 3
     .Os
     .Sh NAME
    @@ -75,6 +75,15 @@ In the ASCII character set, this includes the following characters
     .It "\&164\ ``t'' \t165\ ``u'' \t166\ ``v'' \t167\ ``w'' \t170\ ``x''"
     .It "\&171\ ``y'' \t172\ ``z''"
     .El
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isalnum
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isalnum
    diff --git a/lib/libc/locale/isalpha.3 b/lib/libc/locale/isalpha.3
    index 0bd3cda3c72..5a2680e03aa 100644
    --- a/lib/libc/locale/isalpha.3
    +++ b/lib/libc/locale/isalpha.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isalpha.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISALPHA 3
     .Os
     .Sh NAME
    @@ -73,6 +73,15 @@ In the ASCII character set, this includes the following characters
     .It "\&164\ ``t'' \t165\ ``u'' \t166\ ``v'' \t167\ ``w'' \t170\ ``x''"
     .It "\&171\ ``y'' \t172\ ``z''"
     .El
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isalpha
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isalpha
    diff --git a/lib/libc/locale/isascii.3 b/lib/libc/locale/isascii.3
    index f7e1325db59..294c5beaa19 100644
    --- a/lib/libc/locale/isascii.3
    +++ b/lib/libc/locale/isascii.3
    @@ -28,7 +28,7 @@
     .\"     @(#)isascii.3	8.2 (Berkeley) 12/11/93
     .\" $FreeBSD$
     .\"
    -.Dd October 6, 2002
    +.Dd September 3, 2009
     .Dt ISASCII 3
     .Os
     .Sh NAME
    @@ -47,6 +47,15 @@ function tests for an
     .Tn ASCII
     character, which is any character
     between 0 and octal 0177 inclusive.
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isascii
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh SEE ALSO
     .Xr ctype 3 ,
     .Xr iswascii 3 ,
    diff --git a/lib/libc/locale/isblank.3 b/lib/libc/locale/isblank.3
    index 4cc6bbbce80..e983b150761 100644
    --- a/lib/libc/locale/isblank.3
    +++ b/lib/libc/locale/isblank.3
    @@ -28,7 +28,7 @@
     .\"     @(#)isblank.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISBLANK 3
     .Os
     .Sh NAME
    @@ -57,6 +57,15 @@ The value of the argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isblank
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isblank
    diff --git a/lib/libc/locale/iscntrl.3 b/lib/libc/locale/iscntrl.3
    index a67e6a42bb6..c9e220b96b6 100644
    --- a/lib/libc/locale/iscntrl.3
    +++ b/lib/libc/locale/iscntrl.3
    @@ -32,7 +32,7 @@
     .\"     @(#)iscntrl.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISCNTRL 3
     .Os
     .Sh NAME
    @@ -65,6 +65,15 @@ In the ASCII character set, this includes the following characters
     .It "\&031\ EM \t032\ SUB \t033\ ESC \t034\ FS \t035\ GS"
     .It "\&036\ RS \t037\ US \t177\ DEL"
     .El
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn iscntrl
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn iscntrl
    diff --git a/lib/libc/locale/isdigit.3 b/lib/libc/locale/isdigit.3
    index 53b198606e7..019629fa2ed 100644
    --- a/lib/libc/locale/isdigit.3
    +++ b/lib/libc/locale/isdigit.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isdigit.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd May 4, 2007
    +.Dd September 3, 2009
     .Dt ISDIGIT 3
     .Os
     .Sh NAME
    @@ -68,6 +68,15 @@ The value of the argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isdigit
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isdigit
    diff --git a/lib/libc/locale/isgraph.3 b/lib/libc/locale/isgraph.3
    index 4ba78e3c4d9..00c0dc83634 100644
    --- a/lib/libc/locale/isgraph.3
    +++ b/lib/libc/locale/isgraph.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isgraph.3	8.2 (Berkeley) 12/11/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISGRAPH 3
     .Os
     .Sh NAME
    @@ -80,6 +80,15 @@ In the ASCII character set, this includes the following characters
     .It "\&166\ ``v'' \t167\ ``w'' \t170\ ``x'' \t171\ ``y'' \t172\ ``z''"
     .It "\&173\ ``{'' \t174\ ``|'' \t175\ ``}'' \t176\ ``~''"
     .El
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isgraph
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isgraph
    diff --git a/lib/libc/locale/isideogram.3 b/lib/libc/locale/isideogram.3
    index cbaa625e91d..7f1f756c601 100644
    --- a/lib/libc/locale/isideogram.3
    +++ b/lib/libc/locale/isideogram.3
    @@ -25,7 +25,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd March 30, 2004
    +.Dd September 3, 2009
     .Dt ISIDEOGRAM 3
     .Os
     .Sh NAME
    @@ -41,6 +41,15 @@
     The
     .Fn isideogram
     function tests for an ideographic character.
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isideogram
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isideogram
    diff --git a/lib/libc/locale/islower.3 b/lib/libc/locale/islower.3
    index d72e7cf5b12..5884815d7de 100644
    --- a/lib/libc/locale/islower.3
    +++ b/lib/libc/locale/islower.3
    @@ -32,7 +32,7 @@
     .\"     @(#)islower.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISLOWER 3
     .Os
     .Sh NAME
    @@ -64,6 +64,15 @@ In the ASCII character set, this includes the following characters
     .It "\&165\ ``u'' \t166\ ``v'' \t167\ ``w'' \t170\ ``x'' \t171\ ``y''"
     .It "\&172\ ``z''"
     .El
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn islower
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn islower
    diff --git a/lib/libc/locale/isphonogram.3 b/lib/libc/locale/isphonogram.3
    index b0d82c428cb..22a9ce7411a 100644
    --- a/lib/libc/locale/isphonogram.3
    +++ b/lib/libc/locale/isphonogram.3
    @@ -25,7 +25,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd March 30, 2004
    +.Dd September 3, 2009
     .Dt ISPHONOGRAM 3
     .Os
     .Sh NAME
    @@ -41,6 +41,15 @@
     The
     .Fn isphonogram
     function tests for a phonographic character.
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isphonogram
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isphonogram
    diff --git a/lib/libc/locale/isprint.3 b/lib/libc/locale/isprint.3
    index f3408501c29..b90f79a5f91 100644
    --- a/lib/libc/locale/isprint.3
    +++ b/lib/libc/locale/isprint.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isprint.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISPRINT 3
     .Os
     .Sh NAME
    @@ -78,6 +78,15 @@ In the ASCII character set, this includes the following characters
     .It "\&165\ ``u'' \t166\ ``v'' \t167\ ``w'' \t170\ ``x'' \t171\ ``y''"
     .It "\&172\ ``z'' \t173\ ``{'' \t174\ ``|'' \t175\ ``}'' \t176\ ``~''"
     .El
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isprint
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isprint
    diff --git a/lib/libc/locale/ispunct.3 b/lib/libc/locale/ispunct.3
    index aa0246107e4..fe1c0e3bb93 100644
    --- a/lib/libc/locale/ispunct.3
    +++ b/lib/libc/locale/ispunct.3
    @@ -32,7 +32,7 @@
     .\"	@(#)ispunct.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISPUNCT 3
     .Os
     .Sh NAME
    @@ -70,6 +70,15 @@ In the ASCII character set, this includes the following characters
     .It "\&136\ ``^'' \t137\ ``_'' \t140\ ```'' \t173\ ``{'' \t174\ ``|''"
     .It "\&175\ ``}'' \t176\ ``~''"
     .El
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn ispunct
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn ispunct
    diff --git a/lib/libc/locale/isrune.3 b/lib/libc/locale/isrune.3
    index 424c367d201..7f26a83dd28 100644
    --- a/lib/libc/locale/isrune.3
    +++ b/lib/libc/locale/isrune.3
    @@ -25,7 +25,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd March 30, 2004
    +.Dd September 3, 2009
     .Dt ISRUNE 3
     .Os
     .Sh NAME
    @@ -46,6 +46,15 @@ In the
     .Tn ASCII
     character set, this is equivalent to
     .Fn isascii .
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isrune
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isrune
    diff --git a/lib/libc/locale/isspace.3 b/lib/libc/locale/isspace.3
    index f1e08d6cdfe..f11ad8e90ac 100644
    --- a/lib/libc/locale/isspace.3
    +++ b/lib/libc/locale/isspace.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isspace.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISSPACE 3
     .Os
     .Sh NAME
    @@ -61,6 +61,15 @@ The value of the argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isspace
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isspace
    diff --git a/lib/libc/locale/isspecial.3 b/lib/libc/locale/isspecial.3
    index de361d28f96..990cad3cb9f 100644
    --- a/lib/libc/locale/isspecial.3
    +++ b/lib/libc/locale/isspecial.3
    @@ -25,7 +25,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd March 30, 2004
    +.Dd September 3, 2009
     .Dt ISSPECIAL 3
     .Os
     .Sh NAME
    @@ -41,6 +41,15 @@
     The
     .Fn isspecial
     function tests for a special character.
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isspecial
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isspecial
    diff --git a/lib/libc/locale/isupper.3 b/lib/libc/locale/isupper.3
    index 6aeb5ac9aa3..9d25ad65396 100644
    --- a/lib/libc/locale/isupper.3
    +++ b/lib/libc/locale/isupper.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isupper.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISUPPER 3
     .Os
     .Sh NAME
    @@ -64,6 +64,15 @@ In the ASCII character set, this includes the following characters
     .It "\&125\ ``U'' \t126\ ``V'' \t127\ ``W'' \t130\ ``X'' \t131\ ``Y''"
     .It "\&132\ ``Z''"
     .El
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isupper
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isupper
    diff --git a/lib/libc/locale/isxdigit.3 b/lib/libc/locale/isxdigit.3
    index 1fb54bf94f5..5925b73bb46 100644
    --- a/lib/libc/locale/isxdigit.3
    +++ b/lib/libc/locale/isxdigit.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isxdigit.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt ISXDIGIT 3
     .Os
     .Sh NAME
    @@ -71,6 +71,15 @@ The value of the argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn isxdigit
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isxdigit
    diff --git a/lib/libc/locale/toascii.3 b/lib/libc/locale/toascii.3
    index 97243cb53ac..584aa682337 100644
    --- a/lib/libc/locale/toascii.3
    +++ b/lib/libc/locale/toascii.3
    @@ -28,7 +28,7 @@
     .\"	@(#)toascii.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd June 4, 1993
    +.Dd September 3, 2009
     .Dt TOASCII 3
     .Os
     .Sh NAME
    @@ -45,6 +45,15 @@ The
     .Fn toascii
     function strips all but the low 7 bits from a letter,
     including parity or other marker bits.
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn toascii
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn toascii
    diff --git a/lib/libc/locale/tolower.3 b/lib/libc/locale/tolower.3
    index fce37fdc575..f70651a77f4 100644
    --- a/lib/libc/locale/tolower.3
    +++ b/lib/libc/locale/tolower.3
    @@ -32,7 +32,7 @@
     .\"	@(#)tolower.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt TOLOWER 3
     .Os
     .Sh NAME
    @@ -53,6 +53,15 @@ The argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn tolower
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     If the argument is an upper-case letter, the
     .Fn tolower
    diff --git a/lib/libc/locale/toupper.3 b/lib/libc/locale/toupper.3
    index 3a3c7f83368..e6ed8cc6659 100644
    --- a/lib/libc/locale/toupper.3
    +++ b/lib/libc/locale/toupper.3
    @@ -32,7 +32,7 @@
     .\"	@(#)toupper.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd July 17, 2005
    +.Dd September 3, 2009
     .Dt TOUPPER 3
     .Os
     .Sh NAME
    @@ -53,6 +53,15 @@ The argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    +.Pp
    +.Em NOTE :
    +if the value passed to the
    +.Fn toupper
    +function is a
    +.Vt signed char ,
    +as is usually the case, it must be cast to an
    +.Vt unsigned char
    +to avoid sign-extension errors.
     .Sh RETURN VALUES
     If the argument is a lower-case letter, the
     .Fn toupper
    
    From 19dbe46d28bcbdc6000be8930d2d8a631f7c1ecd Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Thu, 3 Sep 2009 12:37:17 +0000
    Subject: [PATCH 330/453] ATI SB600 can't handle 256 sectors transfers with
     FPDMA (NCQ).
    
    MFC after:	3 days
    ---
     sys/dev/ahci/ahci.c | 3 +++
     1 file changed, 3 insertions(+)
    
    diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
    index 189ab121e12..9264ee0593a 100644
    --- a/sys/dev/ahci/ahci.c
    +++ b/sys/dev/ahci/ahci.c
    @@ -1942,6 +1942,9 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
     		cpi->protocol = PROTO_ATA;
     		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, 255 * 512);
     		cpi->ccb_h.status = CAM_REQ_CMP;
     		xpt_done(ccb);
     		break;
    
    From 80002a63db2151fdbf4372dfeb3eb697d90c10ec Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Thu, 3 Sep 2009 13:40:41 +0000
    Subject: [PATCH 331/453] Add intermediate states for attaching and detaching
     that will be reused by the enhached newbus locking once it is checked in.
     This change can be easilly MFCed to STABLE_8 at the appropriate moment.
    
    Reviewed by:	jhb, scottl
    Tested by:	Giovanni Trematerra 
    ---
     sys/kern/subr_bus.c | 20 ++++++++++++++++++--
     sys/sys/bus.h       |  5 ++++-
     2 files changed, 22 insertions(+), 3 deletions(-)
    
    diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
    index f202631ce88..e4f99465891 100644
    --- a/sys/kern/subr_bus.c
    +++ b/sys/kern/subr_bus.c
    @@ -2625,10 +2625,16 @@ device_attach(device_t dev)
     {
     	int error;
     
    +	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 */
    @@ -2639,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);
    @@ -2674,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");
    @@ -2730,7 +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));
     }
    diff --git a/sys/sys/bus.h b/sys/sys/bus.h
    index 2362041dad2..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;
     
     /**
    
    From c32539d4c072b15cc1e749244d1073cc0bdc4abe Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Thu, 3 Sep 2009 16:24:21 +0000
    Subject: [PATCH 332/453] on transition to SLEEP state mark the station in
     power save, not awake
    
    MFC after:	3 days
    ---
     sys/net80211/ieee80211_sta.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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:
    
    From d9abb32630dadb873cd217870bb8a7a3a1d448e0 Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Thu, 3 Sep 2009 16:25:25 +0000
    Subject: [PATCH 333/453] Add la_LN.ISO8859-13 and lv_LV
    
    ---
     etc/mtree/BSD.usr.dist | 12 ++++++++++++
     1 file changed, 12 insertions(+)
    
    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
    
    From 8460188c5be1b9d59beab8781614d650ec408940 Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Thu, 3 Sep 2009 16:29:02 +0000
    Subject: [PATCH 334/453] correct timeout for doing NOL processing; need a
     ticks-relative value
    
    Obtained from:	Marvell
    MFC after:	3 days
    ---
     sys/net80211/ieee80211_dfs.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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);
     	}
     }
     
    
    From 4a6ecf078b305719d32266a5c7ea0756cc1ea06d Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Thu, 3 Sep 2009 16:31:11 +0000
    Subject: [PATCH 335/453] Expose the TF_REVERSE flag to the console driver.
    
    Right now libteken processes TF_REVERSE internally and returns the
    toggled colors to the console driver. This isn't entirely correct. This
    means that the bold flag is always processed by the foreground color,
    while reversing should be done after the foreground color has been set
    to a brighter version by the bold flag.
    
    This is no problem with the syscons driver, because with VGA it only
    supports 16 foreground and 8 background colors. My WIP console driver
    reconfigures the graphics hardware to disable the blink functionality
    and uses 16 foreground and 16 background colors. This means that this
    driver will handle the TF_REVERSE flag a little different from what
    syscons does right now.
    ---
     sys/dev/syscons/scterm-teken.c | 14 +++++++++++---
     sys/teken/teken.c              | 21 ---------------------
     sys/teken/teken.h              |  1 +
     sys/teken/teken_demo.c         |  2 ++
     4 files changed, 14 insertions(+), 24 deletions(-)
    
    diff --git a/sys/dev/syscons/scterm-teken.c b/sys/dev/syscons/scterm-teken.c
    index 6f51ac17035..133d6220805 100644
    --- a/sys/dev/syscons/scterm-teken.c
    +++ b/sys/dev/syscons/scterm-teken.c
    @@ -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/teken/teken.c b/sys/teken/teken.c
    index 5a16f8df47c..58f4f37162d 100644
    --- a/sys/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/teken/teken.h b/sys/teken/teken.h
    index dd19e76f6c1..e1a2cada7dd 100644
    --- a/sys/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/teken/teken_demo.c b/sys/teken/teken_demo.c
    index 02463a7f1b1..e68cca1ae77 100644
    --- a/sys/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);
    
    From c8b385c86fe1fa87c5cb2736814463a7b8ee233c Mon Sep 17 00:00:00 2001
    From: Remko Lodder 
    Date: Thu, 3 Sep 2009 16:34:20 +0000
    Subject: [PATCH 336/453] Do the first step in removing lukemftpd from the base
     system. Disconnect it from the build.
    
    If you are using the FTP daemon, please consider using the port ftp/tnftpd
    which is the same FTP server, but newer and might have more/better
    functionality.
    
    This results in us providing only one ftp daemon by default.
    
    Reviewed by:	bz
    Approved by:	imp (mentor, implicit)
    MFC after:	3 days
    Silence from:	obrien
    ---
     ObsoleteFiles.inc | 5 +++++
     etc/inetd.conf    | 2 --
     libexec/Makefile  | 1 -
     3 files changed, 5 insertions(+), 3 deletions(-)
    
    diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
    index 54be9dd9ccb..9e2d734db39 100644
    --- a/ObsoleteFiles.inc
    +++ b/ObsoleteFiles.inc
    @@ -14,6 +14,11 @@
     # 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
    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/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} \
    
    From b431ceaa9451d7391cebd894a5dc73a7772edadb Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Thu, 3 Sep 2009 16:53:11 +0000
    Subject: [PATCH 337/453] Add lv_LV, move lt_LT to common part
    
    ---
     share/colldef/Makefile                                   | 9 ++++++---
     .../{lt_LT.ISO8859-13.src => la_LN.ISO8859-13.src}       | 2 +-
     2 files changed, 7 insertions(+), 4 deletions(-)
     rename share/colldef/{lt_LT.ISO8859-13.src => la_LN.ISO8859-13.src} (94%)
    
    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/la_LN.ISO8859-13.src
    similarity index 94%
    rename from share/colldef/lt_LT.ISO8859-13.src
    rename to share/colldef/la_LN.ISO8859-13.src
    index 811db89f7c8..828e478131b 100644
    --- a/share/colldef/lt_LT.ISO8859-13.src
    +++ b/share/colldef/la_LN.ISO8859-13.src
    @@ -1,4 +1,4 @@
    -# Lithuanian (backward compatible with ASCII)
    +# Latin-7 / Baltic Rim (backward compatible with ASCII)
     #
     # $FreeBSD$
     #
    
    From 456b5dd815b2a25e7b20ce087a62a59c3e7d06cd Mon Sep 17 00:00:00 2001
    From: Warner Losh 
    Date: Thu, 3 Sep 2009 17:04:42 +0000
    Subject: [PATCH 338/453] Time for house-cleaning: o remove all entries before
     RELENG_7 was branched, as is tradition[*]. o Update examples...  nobody cares
     about 5.x upgrades. o minor format tweaking in a few places. o update
     copyright (although at best I hold an editors copyright these days). o Remove
     giving people permission to buy me beer.  I don't do enough for   this
     document for that anymore...
    
    ---
     UPDATING | 939 +++++++------------------------------------------------
     1 file changed, 116 insertions(+), 823 deletions(-)
    
    diff --git a/UPDATING b/UPDATING
    index 893744a2652..02a1c75696c 100644
    --- a/UPDATING
    +++ b/UPDATING
    @@ -1,51 +1,53 @@
     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 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
    +	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.)
     
     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.
    +	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:
    +	RELENG_8 branched.
     
     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
    @@ -53,79 +55,75 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.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
    @@ -134,24 +132,24 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.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:
    @@ -164,20 +162,18 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.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:
    @@ -768,730 +764,29 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.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
     	-----------------
    @@ -1513,9 +808,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
    @@ -1567,7 +862,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]
    @@ -1619,11 +914,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.
    @@ -1647,7 +943,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
    @@ -1665,9 +961,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.
     
    
    From effbd54b98dcd3c40d105d0a2e8fe58c5a8c4375 Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Thu, 3 Sep 2009 17:12:45 +0000
    Subject: [PATCH 339/453] Add lv_LV, move lt_LT to common part
    
    ---
     share/mklocale/Makefile                                  | 9 ++++++---
     .../{lt_LT.ISO8859-13.src => la_LN.ISO8859-13.src}       | 0
     2 files changed, 6 insertions(+), 3 deletions(-)
     rename share/mklocale/{lt_LT.ISO8859-13.src => la_LN.ISO8859-13.src} (100%)
    
    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/la_LN.ISO8859-13.src
    similarity index 100%
    rename from share/mklocale/lt_LT.ISO8859-13.src
    rename to share/mklocale/la_LN.ISO8859-13.src
    
    From 4a19f42fe70f32145d558a3a53d73960dabd9086 Mon Sep 17 00:00:00 2001
    From: Warner Losh 
    Date: Thu, 3 Sep 2009 17:13:54 +0000
    Subject: [PATCH 340/453] Actually, stable/8 is what was created...
    
    ---
     UPDATING | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/UPDATING b/UPDATING
    index 02a1c75696c..8db99bf804f 100644
    --- a/UPDATING
    +++ b/UPDATING
    @@ -28,7 +28,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
     	maintain stop_cpus() to just use a normal IPI_STOP on ia32 and amd64.
     
     20090803:
    -	RELENG_8 branched.
    +	stable/8 branch created in subversion.
     
     20090719:
     	Bump the shared library version numbers for all libraries that do not
    
    From 9da50145e6825ddf523db9a81bbb40392f560e56 Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Thu, 3 Sep 2009 17:37:23 +0000
    Subject: [PATCH 341/453] Add lv_LV
    
    ---
     share/numericdef/Makefile | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    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
    
    From ce531e6b836398fff1633185f8413543b693a673 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Thu, 3 Sep 2009 19:02:17 +0000
    Subject: [PATCH 342/453] Round maxio for ATI SB600 to 64K.
    
    Submitted by:	scottl@
    ---
     sys/dev/ahci/ahci.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
    index 9264ee0593a..2d8be431017 100644
    --- a/sys/dev/ahci/ahci.c
    +++ b/sys/dev/ahci/ahci.c
    @@ -1944,7 +1944,7 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
     		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, 255 * 512);
    +			cpi->maxio = min(cpi->maxio, 128 * 512);
     		cpi->ccb_h.status = CAM_REQ_CMP;
     		xpt_done(ccb);
     		break;
    
    From 54fc657d59324e260dd5cde0d6e7f60d43a41c60 Mon Sep 17 00:00:00 2001
    From: "George V. Neville-Neil" 
    Date: Thu, 3 Sep 2009 21:10:57 +0000
    Subject: [PATCH 343/453] Add ARP statistics to the kernel and netstat.
    
    New counters now exist for:
    requests sent
    replies sent
    requests received
    replies received
    packets received
    total packets dropped due to no ARP entry
    entrys timed out
    Duplicate IPs seen
    
    The new statistics are seen in the netstat command
    when it is given the -s command line switch.
    
    MFC after:	2 weeks
    In collaboration with: bz
    ---
     sys/net/if_arp.h          | 27 ++++++++++++++++++++++++-
     sys/netinet/if_ether.c    | 31 +++++++++++++++++++++++------
     usr.bin/netstat/inet.c    | 42 +++++++++++++++++++++++++++++++++++++++
     usr.bin/netstat/main.c    |  4 ++++
     usr.bin/netstat/netstat.h |  1 +
     5 files changed, 98 insertions(+), 7 deletions(-)
    
    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/netinet/if_ether.c b/sys/netinet/if_ether.c
    index e118cec0fa3..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:
    @@ -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)
    @@ -686,6 +703,7 @@ match:
     reply:
     	if (op != ARPOP_REQUEST)
     		goto drop;
    +	ARPSTAT_INC(rxrequests);
     
     	if (itaddr.s_addr == myaddr.s_addr) {
     		/* Shortcut.. the receiving interface is the target. */
    @@ -774,6 +792,7 @@ reply:
     	sa.sa_family = AF_ARP;
     	sa.sa_len = 2;
     	(*ifp->if_output)(ifp, m, &sa, NULL);
    +	ARPSTAT_INC(txreplies);
     	return;
     
     drop:
    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);
    
    From 1219197b46225a3842db479e355fc535a9cd6aa1 Mon Sep 17 00:00:00 2001
    From: Jack F Vogel 
    Date: Thu, 3 Sep 2009 22:00:42 +0000
    Subject: [PATCH 344/453] Stupid cut and paste error on a stats struct member,
     thanks to Ryan at Small Tree for finding this one.
    
    ---
     sys/dev/ixgbe/ixgbe.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
    index 23b185722b2..3c0f5edb7a9 100644
    --- a/sys/dev/ixgbe/ixgbe.c
    +++ b/sys/dev/ixgbe/ixgbe.c
    @@ -4507,7 +4507,7 @@ ixgbe_update_stats_counters(struct adapter *adapter)
     		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.gorc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
    +		adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
     		adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
     	}
     
    
    From 18e5fe284056aa2313fb53eb02bf8beb2ef434ec Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Thu, 3 Sep 2009 22:19:09 +0000
    Subject: [PATCH 345/453] Don't bother obtaining the ident if we are not going
     to print it.
    
    ---
     usr.sbin/diskinfo/diskinfo.c | 5 +----
     1 file changed, 1 insertion(+), 4 deletions(-)
    
    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");
    
    From a6b8e0e91597e48b4bae920cf6ddbebe55d940f1 Mon Sep 17 00:00:00 2001
    From: Weongyo Jeong 
    Date: Fri, 4 Sep 2009 05:28:09 +0000
    Subject: [PATCH 346/453] fix a TX issue on big endian machines like powerpc or
     sparc64.  Now zyd(4) should work on all architectures.
    
    Obtained from:	OpenBSD
    ---
     sys/dev/usb/wlan/if_zyd.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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;
    
    From 02c41ee985ad7bf60ec1b68074bed78390346386 Mon Sep 17 00:00:00 2001
    From: Julian Elischer 
    Date: Fri, 4 Sep 2009 05:40:06 +0000
    Subject: [PATCH 347/453] Bring i386 up to date with amd64 and others. The
     macros for PCPU can be slightly simplified, which makes the resulting tangle
     qa lot easier to understand when trying to read them.
    
    MFC after:	4 weeks
    ---
     sys/i386/include/pcpu.h | 10 +++++-----
     1 file changed, 5 insertions(+), 5 deletions(-)
    
    diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h
    index 594077cf723..bd25d5a6cbf 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)
    
    From 94bf429a6dc2747a6768ecffcff9a70fa995a643 Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Fri, 4 Sep 2009 05:54:45 +0000
    Subject: [PATCH 348/453] Add lv_LV
    
    PR:             105100
    Submitted by:   Aldis Berjoza 
    ---
     share/monetdef/Makefile             |  3 ++-
     share/monetdef/lv_LV.ISO8859-13.src | 36 +++++++++++++++++++++++++++++
     2 files changed, 38 insertions(+), 1 deletion(-)
     create mode 100644 share/monetdef/lv_LV.ISO8859-13.src
    
    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/monetdef/lv_LV.ISO8859-13.src b/share/monetdef/lv_LV.ISO8859-13.src
    new file mode 100644
    index 00000000000..647c4e69935
    --- /dev/null
    +++ b/share/monetdef/lv_LV.ISO8859-13.src
    @@ -0,0 +1,36 @@
    +# $FreeBSD$
    +#
    +# WARNING: spaces may be essential at the end of lines
    +# WARNING: empty lines are essential too
    +#
    +# int_curr_symbol (last character always SPACE)
    +LVL 
    +# currency_symbol
    +Ls
    +# mon_decimal_point
    +,
    +# mon_thousands_sep
    + 
    +# mon_grouping, separated by ;
    +3;3
    +# positive_sign
    +
    +# negative_sign
    +-
    +# int_frac_digits
    +2
    +# frac_digits
    +2
    +# p_cs_precedes
    +0
    +# p_sep_by_space
    +1
    +# n_cs_precedes
    +0
    +# n_sep_by_space
    +1
    +# p_sign_posn
    +1
    +# n_sign_posn
    +1
    +# EOF
    
    From a8e442a7605dc51b4ce2066889709cec45db4b7d Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Fri, 4 Sep 2009 06:19:37 +0000
    Subject: [PATCH 349/453] Add lv_LV
    
    PR:             105100
    Submitted by:   Aldis Berjoza 
    ---
     share/msgdef/Makefile             |  2 ++
     share/msgdef/lv_LV.ISO8859-13.src | 14 ++++++++++++++
     share/msgdef/lv_LV.UTF-8.src      | 14 ++++++++++++++
     3 files changed, 30 insertions(+)
     create mode 100644 share/msgdef/lv_LV.ISO8859-13.src
     create mode 100644 share/msgdef/lv_LV.UTF-8.src
    
    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/msgdef/lv_LV.ISO8859-13.src b/share/msgdef/lv_LV.ISO8859-13.src
    new file mode 100644
    index 00000000000..d744ad86b30
    --- /dev/null
    +++ b/share/msgdef/lv_LV.ISO8859-13.src
    @@ -0,0 +1,14 @@
    +# $FreeBSD$
    +#
    +# WARNING: spaces may be essential at the end of lines
    +# WARNING: empty lines are essential too
    +#
    +# yesexpr
    +^[jJyY].*
    +# noexpr
    +^[nN].*
    +# yesstr
    +j
    +# nostr
    +n
    +# EOF
    diff --git a/share/msgdef/lv_LV.UTF-8.src b/share/msgdef/lv_LV.UTF-8.src
    new file mode 100644
    index 00000000000..85f1a73fc1e
    --- /dev/null
    +++ b/share/msgdef/lv_LV.UTF-8.src
    @@ -0,0 +1,14 @@
    +# $FreeBSD$
    +#
    +# WARNING: spaces may be essential at the end of lines
    +# WARNING: empty lines are essential too
    +#
    +# yesexpr
    +^[jJyY].*
    +# noexpr
    +^[nN].*
    +# yesstr
    +jā
    +# nostr
    +nē
    +# EOF
    
    From 8e5b0cb0531ed6a3fda5481819ce508506dc52ba Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Fri, 4 Sep 2009 06:26:40 +0000
    Subject: [PATCH 350/453] Add lv_LV
    
    PR:             105100
    Submitted by:   Aldis Berjoza 
    ---
     share/timedef/Makefile             |   2 +
     share/timedef/lv_LV.ISO8859-13.src | 101 +++++++++++++++++++++++++++++
     share/timedef/lv_LV.UTF-8.src      | 101 +++++++++++++++++++++++++++++
     3 files changed, 204 insertions(+)
     create mode 100644 share/timedef/lv_LV.ISO8859-13.src
     create mode 100644 share/timedef/lv_LV.UTF-8.src
    
    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/lv_LV.ISO8859-13.src b/share/timedef/lv_LV.ISO8859-13.src
    new file mode 100644
    index 00000000000..5e5e3d1f40d
    --- /dev/null
    +++ b/share/timedef/lv_LV.ISO8859-13.src
    @@ -0,0 +1,101 @@
    +# $FreeBSD$
    +# WARNING: spaces may be essential at the end of lines
    +# WARNING: empty lines are essential too
    +#
    +# Short month names
    +#
    +Jan
    +Feb
    +Mar
    +Apr
    +Mai
    +Jn
    +Jl
    +Aug
    +Sep
    +Okt
    +Nov
    +Dec
    +#
    +# Long month names
    +#
    +janvris
    +februris
    +marts
    +aprlis
    +maijs
    +jnijs
    +jlijs
    +augusts
    +septembris
    +oktobris
    +novembris
    +decembris
    +#
    +# Short weekday names
    +#
    +Sv
    +Pr
    +Ot
    +Tr
    +Ct
    +Pk
    +Ss
    +#
    +# Long weekday names
    +#
    +Svtdiena
    +Pirmdiena
    +Otrdiena
    +Trediena
    +Ceturtdiena
    +Piektdiena
    +Sestdiena
    +#
    +# X_fmt
    +#
    +%H:%M:%S
    +#
    +# x_fmt
    +#
    +%d/%m/%Y
    +#
    +# c_fmt
    +# %A, %Y m. %B %e d. %T
    +%e. %b, %Y. gads %X
    +#
    +# am
    +#
    +
    +#
    +# pm
    +#
    +
    +#
    +# date_fmt
    +#
    +%A, %Y. gada %e. %B %T %Z
    +#
    +# Long month names in alternative form
    +#
    +janvris
    +februris
    +marts
    +aprlis
    +maijs
    +jnijs
    +jlijs
    +augusts
    +septembris
    +oktobris
    +novembris
    +decembris
    +#
    +# md_order
    +#
    +md
    +#
    +# ampm_fmt
    +#
    +
    +# EOF
    diff --git a/share/timedef/lv_LV.UTF-8.src b/share/timedef/lv_LV.UTF-8.src
    new file mode 100644
    index 00000000000..56d1cb40927
    --- /dev/null
    +++ b/share/timedef/lv_LV.UTF-8.src
    @@ -0,0 +1,101 @@
    +# $FreeBSD$
    +# WARNING: spaces may be essential at the end of lines
    +# WARNING: empty lines are essential too
    +#
    +# Short month names
    +#
    +Jan
    +Feb
    +Mar
    +Apr
    +Mai
    +Jūn
    +Jūl
    +Aug
    +Sep
    +Okt
    +Nov
    +Dec
    +#
    +# Long month names
    +#
    +janvāris
    +februāris
    +marts
    +aprīlis
    +maijs
    +jūnijs
    +jūlijs
    +augusts
    +septembris
    +oktobris
    +novembris
    +decembris
    +#
    +# Short weekday names
    +#
    +Sv
    +Pr
    +Ot
    +Tr
    +Ct
    +Pk
    +Ss
    +#
    +# Long weekday names
    +#
    +Svētdiena
    +Pirmdiena
    +Otrdiena
    +Trešdiena
    +Ceturtdiena
    +Piektdiena
    +Sestdiena
    +#
    +# X_fmt
    +#
    +%H:%M:%S
    +#
    +# x_fmt
    +#
    +%d/%m/%Y
    +#
    +# c_fmt
    +# %A, %Y m. %B %e d. %T
    +%e. %b, %Y. gads %X
    +#
    +# am
    +#
    +
    +#
    +# pm
    +#
    +
    +#
    +# date_fmt
    +#
    +%A, %Y. gada %e. %B %T %Z
    +#
    +# Long month names in alternative form
    +#
    +janvāris
    +februāris
    +marts
    +aprīlis
    +maijs
    +jūnijs
    +jūlijs
    +augusts
    +septembris
    +oktobris
    +novembris
    +decembris
    +#
    +# md_order
    +#
    +md
    +#
    +# ampm_fmt
    +#
    +
    +# EOF
    
    From d0ac01f1f6f2c218812a2771c063e38a674bff82 Mon Sep 17 00:00:00 2001
    From: Julian Elischer 
    Date: Fri, 4 Sep 2009 07:29:24 +0000
    Subject: [PATCH 351/453] whitespace commit
    
    Submitted by:	bde@
    ---
     sys/i386/include/pcpu.h | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h
    index bd25d5a6cbf..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(__res), 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(__val), 4)];		\
    +		u_char	__b[MIN(sizeof(__val), 4)];			\
     	} __s;								\
     									\
     	__val = (val);							\
    
    From 31dcbfad38ca0be7b770b50ae385a36222cca00a Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Fri, 4 Sep 2009 07:42:13 +0000
    Subject: [PATCH 352/453] 1) Remove single occurance of HAS_CTYPE ifdef, ctype
     functions used here for a long time and needs their header in anycase. 2) Add
     (unsigned char) casts to more ctype macros. 3) Simplify menu input handling
     using ctype instead of range unguarded hardcoded tricks.
    
    ---
     contrib/ee/ee.c | 16 ++++++----------
     1 file changed, 6 insertions(+), 10 deletions(-)
    
    diff --git a/contrib/ee/ee.c b/contrib/ee/ee.c
    index 4c95ac9bec3..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 
    @@ -1973,7 +1970,7 @@ int sensitive;
     		}
     		else
     		{
    -			if (toupper(*strng1) != toupper(*strng2))
    +			if (toupper((unsigned char)*strng1) != toupper((unsigned char)*strng2))
     				equal = FALSE;
     		}
     		strng1++;
    @@ -2445,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);
    @@ -2522,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;
    @@ -3437,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');
     			}
    
    From 234f1d7f1a161d3a4bc8bc22eeb35fbb6fc76edc Mon Sep 17 00:00:00 2001
    From: "Andrey A. Chernov" 
    Date: Fri, 4 Sep 2009 07:44:27 +0000
    Subject: [PATCH 353/453] Remove single occurance of HAS_CTYPE ifdef, ctype
     functions used here for a long time and needs their header in anycase.
    
    ---
     usr.bin/ee/Makefile | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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
    
    From ae02066b83bedf375e914b9d2adae89db0093d03 Mon Sep 17 00:00:00 2001
    From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= 
    Date: Fri, 4 Sep 2009 07:44:58 +0000
    Subject: [PATCH 354/453] Let the armchair generals handle this one.
    
    ---
     lib/libc/locale/ctype.3       |  9 +--------
     lib/libc/locale/digittoint.3  | 11 +----------
     lib/libc/locale/isalnum.3     | 11 +----------
     lib/libc/locale/isalpha.3     | 11 +----------
     lib/libc/locale/isascii.3     | 11 +----------
     lib/libc/locale/isblank.3     | 11 +----------
     lib/libc/locale/iscntrl.3     | 11 +----------
     lib/libc/locale/isdigit.3     | 11 +----------
     lib/libc/locale/isgraph.3     | 11 +----------
     lib/libc/locale/isideogram.3  | 11 +----------
     lib/libc/locale/islower.3     | 11 +----------
     lib/libc/locale/isphonogram.3 | 11 +----------
     lib/libc/locale/isprint.3     | 11 +----------
     lib/libc/locale/ispunct.3     | 11 +----------
     lib/libc/locale/isrune.3      | 11 +----------
     lib/libc/locale/isspace.3     | 11 +----------
     lib/libc/locale/isspecial.3   | 11 +----------
     lib/libc/locale/isupper.3     | 11 +----------
     lib/libc/locale/isxdigit.3    | 11 +----------
     lib/libc/locale/toascii.3     | 11 +----------
     lib/libc/locale/tolower.3     | 11 +----------
     lib/libc/locale/toupper.3     | 11 +----------
     22 files changed, 22 insertions(+), 218 deletions(-)
    
    diff --git a/lib/libc/locale/ctype.3 b/lib/libc/locale/ctype.3
    index 9d4ee5ea390..fdc135878f7 100644
    --- a/lib/libc/locale/ctype.3
    +++ b/lib/libc/locale/ctype.3
    @@ -28,7 +28,7 @@
     .\"     @(#)ctype.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd March 30, 2004
     .Dt CTYPE 3
     .Os
     .Sh NAME
    @@ -111,13 +111,6 @@ They are available as macros, defined in the include file
     .In ctype.h ,
     or as true functions in the C library.
     See the specific manual pages for more information.
    -.Pp
    -.Em NOTE :
    -if the value passed to one of these functions is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh SEE ALSO
     .Xr digittoint 3 ,
     .Xr isalnum 3 ,
    diff --git a/lib/libc/locale/digittoint.3 b/lib/libc/locale/digittoint.3
    index c7e2ac1179d..372e00f2f8d 100644
    --- a/lib/libc/locale/digittoint.3
    +++ b/lib/libc/locale/digittoint.3
    @@ -28,7 +28,7 @@
     .\"	@(#)digittoint.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd April 6, 2001
     .Dt DIGITTOINT 3
     .Os
     .Sh NAME
    @@ -46,15 +46,6 @@ The
     function converts a numeric character to its corresponding integer value.
     The character can be any decimal digit or hexadecimal digit.
     With hexadecimal characters, the case of the values does not matter.
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn digittoint
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn digittoint
    diff --git a/lib/libc/locale/isalnum.3 b/lib/libc/locale/isalnum.3
    index 335ca9cc02d..624a6e2335d 100644
    --- a/lib/libc/locale/isalnum.3
    +++ b/lib/libc/locale/isalnum.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isalnum.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISALNUM 3
     .Os
     .Sh NAME
    @@ -75,15 +75,6 @@ In the ASCII character set, this includes the following characters
     .It "\&164\ ``t'' \t165\ ``u'' \t166\ ``v'' \t167\ ``w'' \t170\ ``x''"
     .It "\&171\ ``y'' \t172\ ``z''"
     .El
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isalnum
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isalnum
    diff --git a/lib/libc/locale/isalpha.3 b/lib/libc/locale/isalpha.3
    index 5a2680e03aa..0bd3cda3c72 100644
    --- a/lib/libc/locale/isalpha.3
    +++ b/lib/libc/locale/isalpha.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isalpha.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISALPHA 3
     .Os
     .Sh NAME
    @@ -73,15 +73,6 @@ In the ASCII character set, this includes the following characters
     .It "\&164\ ``t'' \t165\ ``u'' \t166\ ``v'' \t167\ ``w'' \t170\ ``x''"
     .It "\&171\ ``y'' \t172\ ``z''"
     .El
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isalpha
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isalpha
    diff --git a/lib/libc/locale/isascii.3 b/lib/libc/locale/isascii.3
    index 294c5beaa19..f7e1325db59 100644
    --- a/lib/libc/locale/isascii.3
    +++ b/lib/libc/locale/isascii.3
    @@ -28,7 +28,7 @@
     .\"     @(#)isascii.3	8.2 (Berkeley) 12/11/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd October 6, 2002
     .Dt ISASCII 3
     .Os
     .Sh NAME
    @@ -47,15 +47,6 @@ function tests for an
     .Tn ASCII
     character, which is any character
     between 0 and octal 0177 inclusive.
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isascii
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh SEE ALSO
     .Xr ctype 3 ,
     .Xr iswascii 3 ,
    diff --git a/lib/libc/locale/isblank.3 b/lib/libc/locale/isblank.3
    index e983b150761..4cc6bbbce80 100644
    --- a/lib/libc/locale/isblank.3
    +++ b/lib/libc/locale/isblank.3
    @@ -28,7 +28,7 @@
     .\"     @(#)isblank.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISBLANK 3
     .Os
     .Sh NAME
    @@ -57,15 +57,6 @@ The value of the argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isblank
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isblank
    diff --git a/lib/libc/locale/iscntrl.3 b/lib/libc/locale/iscntrl.3
    index c9e220b96b6..a67e6a42bb6 100644
    --- a/lib/libc/locale/iscntrl.3
    +++ b/lib/libc/locale/iscntrl.3
    @@ -32,7 +32,7 @@
     .\"     @(#)iscntrl.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISCNTRL 3
     .Os
     .Sh NAME
    @@ -65,15 +65,6 @@ In the ASCII character set, this includes the following characters
     .It "\&031\ EM \t032\ SUB \t033\ ESC \t034\ FS \t035\ GS"
     .It "\&036\ RS \t037\ US \t177\ DEL"
     .El
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn iscntrl
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn iscntrl
    diff --git a/lib/libc/locale/isdigit.3 b/lib/libc/locale/isdigit.3
    index 019629fa2ed..53b198606e7 100644
    --- a/lib/libc/locale/isdigit.3
    +++ b/lib/libc/locale/isdigit.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isdigit.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd May 4, 2007
     .Dt ISDIGIT 3
     .Os
     .Sh NAME
    @@ -68,15 +68,6 @@ The value of the argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isdigit
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isdigit
    diff --git a/lib/libc/locale/isgraph.3 b/lib/libc/locale/isgraph.3
    index 00c0dc83634..4ba78e3c4d9 100644
    --- a/lib/libc/locale/isgraph.3
    +++ b/lib/libc/locale/isgraph.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isgraph.3	8.2 (Berkeley) 12/11/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISGRAPH 3
     .Os
     .Sh NAME
    @@ -80,15 +80,6 @@ In the ASCII character set, this includes the following characters
     .It "\&166\ ``v'' \t167\ ``w'' \t170\ ``x'' \t171\ ``y'' \t172\ ``z''"
     .It "\&173\ ``{'' \t174\ ``|'' \t175\ ``}'' \t176\ ``~''"
     .El
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isgraph
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isgraph
    diff --git a/lib/libc/locale/isideogram.3 b/lib/libc/locale/isideogram.3
    index 7f1f756c601..cbaa625e91d 100644
    --- a/lib/libc/locale/isideogram.3
    +++ b/lib/libc/locale/isideogram.3
    @@ -25,7 +25,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd March 30, 2004
     .Dt ISIDEOGRAM 3
     .Os
     .Sh NAME
    @@ -41,15 +41,6 @@
     The
     .Fn isideogram
     function tests for an ideographic character.
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isideogram
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isideogram
    diff --git a/lib/libc/locale/islower.3 b/lib/libc/locale/islower.3
    index 5884815d7de..d72e7cf5b12 100644
    --- a/lib/libc/locale/islower.3
    +++ b/lib/libc/locale/islower.3
    @@ -32,7 +32,7 @@
     .\"     @(#)islower.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISLOWER 3
     .Os
     .Sh NAME
    @@ -64,15 +64,6 @@ In the ASCII character set, this includes the following characters
     .It "\&165\ ``u'' \t166\ ``v'' \t167\ ``w'' \t170\ ``x'' \t171\ ``y''"
     .It "\&172\ ``z''"
     .El
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn islower
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn islower
    diff --git a/lib/libc/locale/isphonogram.3 b/lib/libc/locale/isphonogram.3
    index 22a9ce7411a..b0d82c428cb 100644
    --- a/lib/libc/locale/isphonogram.3
    +++ b/lib/libc/locale/isphonogram.3
    @@ -25,7 +25,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd March 30, 2004
     .Dt ISPHONOGRAM 3
     .Os
     .Sh NAME
    @@ -41,15 +41,6 @@
     The
     .Fn isphonogram
     function tests for a phonographic character.
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isphonogram
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isphonogram
    diff --git a/lib/libc/locale/isprint.3 b/lib/libc/locale/isprint.3
    index b90f79a5f91..f3408501c29 100644
    --- a/lib/libc/locale/isprint.3
    +++ b/lib/libc/locale/isprint.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isprint.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISPRINT 3
     .Os
     .Sh NAME
    @@ -78,15 +78,6 @@ In the ASCII character set, this includes the following characters
     .It "\&165\ ``u'' \t166\ ``v'' \t167\ ``w'' \t170\ ``x'' \t171\ ``y''"
     .It "\&172\ ``z'' \t173\ ``{'' \t174\ ``|'' \t175\ ``}'' \t176\ ``~''"
     .El
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isprint
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isprint
    diff --git a/lib/libc/locale/ispunct.3 b/lib/libc/locale/ispunct.3
    index fe1c0e3bb93..aa0246107e4 100644
    --- a/lib/libc/locale/ispunct.3
    +++ b/lib/libc/locale/ispunct.3
    @@ -32,7 +32,7 @@
     .\"	@(#)ispunct.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISPUNCT 3
     .Os
     .Sh NAME
    @@ -70,15 +70,6 @@ In the ASCII character set, this includes the following characters
     .It "\&136\ ``^'' \t137\ ``_'' \t140\ ```'' \t173\ ``{'' \t174\ ``|''"
     .It "\&175\ ``}'' \t176\ ``~''"
     .El
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn ispunct
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn ispunct
    diff --git a/lib/libc/locale/isrune.3 b/lib/libc/locale/isrune.3
    index 7f26a83dd28..424c367d201 100644
    --- a/lib/libc/locale/isrune.3
    +++ b/lib/libc/locale/isrune.3
    @@ -25,7 +25,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd March 30, 2004
     .Dt ISRUNE 3
     .Os
     .Sh NAME
    @@ -46,15 +46,6 @@ In the
     .Tn ASCII
     character set, this is equivalent to
     .Fn isascii .
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isrune
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isrune
    diff --git a/lib/libc/locale/isspace.3 b/lib/libc/locale/isspace.3
    index f11ad8e90ac..f1e08d6cdfe 100644
    --- a/lib/libc/locale/isspace.3
    +++ b/lib/libc/locale/isspace.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isspace.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISSPACE 3
     .Os
     .Sh NAME
    @@ -61,15 +61,6 @@ The value of the argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isspace
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isspace
    diff --git a/lib/libc/locale/isspecial.3 b/lib/libc/locale/isspecial.3
    index 990cad3cb9f..de361d28f96 100644
    --- a/lib/libc/locale/isspecial.3
    +++ b/lib/libc/locale/isspecial.3
    @@ -25,7 +25,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd March 30, 2004
     .Dt ISSPECIAL 3
     .Os
     .Sh NAME
    @@ -41,15 +41,6 @@
     The
     .Fn isspecial
     function tests for a special character.
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isspecial
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isspecial
    diff --git a/lib/libc/locale/isupper.3 b/lib/libc/locale/isupper.3
    index 9d25ad65396..6aeb5ac9aa3 100644
    --- a/lib/libc/locale/isupper.3
    +++ b/lib/libc/locale/isupper.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isupper.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISUPPER 3
     .Os
     .Sh NAME
    @@ -64,15 +64,6 @@ In the ASCII character set, this includes the following characters
     .It "\&125\ ``U'' \t126\ ``V'' \t127\ ``W'' \t130\ ``X'' \t131\ ``Y''"
     .It "\&132\ ``Z''"
     .El
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isupper
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isupper
    diff --git a/lib/libc/locale/isxdigit.3 b/lib/libc/locale/isxdigit.3
    index 5925b73bb46..1fb54bf94f5 100644
    --- a/lib/libc/locale/isxdigit.3
    +++ b/lib/libc/locale/isxdigit.3
    @@ -32,7 +32,7 @@
     .\"     @(#)isxdigit.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt ISXDIGIT 3
     .Os
     .Sh NAME
    @@ -71,15 +71,6 @@ The value of the argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn isxdigit
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn isxdigit
    diff --git a/lib/libc/locale/toascii.3 b/lib/libc/locale/toascii.3
    index 584aa682337..97243cb53ac 100644
    --- a/lib/libc/locale/toascii.3
    +++ b/lib/libc/locale/toascii.3
    @@ -28,7 +28,7 @@
     .\"	@(#)toascii.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd June 4, 1993
     .Dt TOASCII 3
     .Os
     .Sh NAME
    @@ -45,15 +45,6 @@ The
     .Fn toascii
     function strips all but the low 7 bits from a letter,
     including parity or other marker bits.
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn toascii
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     The
     .Fn toascii
    diff --git a/lib/libc/locale/tolower.3 b/lib/libc/locale/tolower.3
    index f70651a77f4..fce37fdc575 100644
    --- a/lib/libc/locale/tolower.3
    +++ b/lib/libc/locale/tolower.3
    @@ -32,7 +32,7 @@
     .\"	@(#)tolower.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt TOLOWER 3
     .Os
     .Sh NAME
    @@ -53,15 +53,6 @@ The argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn tolower
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     If the argument is an upper-case letter, the
     .Fn tolower
    diff --git a/lib/libc/locale/toupper.3 b/lib/libc/locale/toupper.3
    index e6ed8cc6659..3a3c7f83368 100644
    --- a/lib/libc/locale/toupper.3
    +++ b/lib/libc/locale/toupper.3
    @@ -32,7 +32,7 @@
     .\"	@(#)toupper.3	8.1 (Berkeley) 6/4/93
     .\" $FreeBSD$
     .\"
    -.Dd September 3, 2009
    +.Dd July 17, 2005
     .Dt TOUPPER 3
     .Os
     .Sh NAME
    @@ -53,15 +53,6 @@ The argument must be representable as an
     .Vt "unsigned char"
     or the value of
     .Dv EOF .
    -.Pp
    -.Em NOTE :
    -if the value passed to the
    -.Fn toupper
    -function is a
    -.Vt signed char ,
    -as is usually the case, it must be cast to an
    -.Vt unsigned char
    -to avoid sign-extension errors.
     .Sh RETURN VALUES
     If the argument is a lower-case letter, the
     .Fn toupper
    
    From e1996730263996fe1777c87eaed9e37e48c5d79e Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Fri, 4 Sep 2009 09:33:50 +0000
    Subject: [PATCH 355/453] Remove 'ad:' prefix from disk serial number. We don't
     want serial number to change when we reconnect the disk in a way that it is
     accessible through CAM for example.
    
    Discussed with:	trasz
    ---
     sys/dev/ata/ata-disk.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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);
    
    From e93f5e4d252eef9b69dedc761ed5406331adda20 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Fri, 4 Sep 2009 09:39:06 +0000
    Subject: [PATCH 356/453] Simplify g_disk_ident_adjust() function and allow any
     printable character in serial number.
    
    Discussed with:	trasz
    Obtained from:	Wheel Sp. z o.o. (http://www.wheel.pl)
    ---
     sys/geom/geom_disk.c | 41 ++++++++++++++---------------------------
     1 file changed, 14 insertions(+), 27 deletions(-)
    
    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);
    
    From 6cf918bc9ba252955fc9403ac3230fdf16f8a66b Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Fri, 4 Sep 2009 09:40:59 +0000
    Subject: [PATCH 357/453] Make serial numbers of daX disks visible by GEOM.
    
    No objections from:	scottl
    Obtained from:		Wheel Sp. z o.o. (http://www.wheel.pl)
    ---
     sys/cam/scsi/scsi_da.c | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
    index e331545032a..e3ad7e1abfa 100644
    --- a/sys/cam/scsi/scsi_da.c
    +++ b/sys/cam/scsi/scsi_da.c
    @@ -1266,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);
     
    
    From f49861e1992c181766516d3f4a811f19fafa674a Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Fri, 4 Sep 2009 09:48:18 +0000
    Subject: [PATCH 358/453] If crypto operation is finished with EAGAIN, don't
     repeat operation from the return context, but from the original context.
     Before repeating operation clear DONE flag and error.
    
    Reviewed by:	sam
    Obtained from:	Wheel Sp. z o.o. (http://www.wheel.pl)
    ---
     sys/opencrypto/cryptodev.c | 17 +++++++++--------
     1 file changed, 9 insertions(+), 8 deletions(-)
    
    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);
     }
    
    From c977dd609b72335cd8c128d2c25c64cd478f16fb Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Fri, 4 Sep 2009 09:57:03 +0000
    Subject: [PATCH 359/453] Make umass(4) pass device USB serial number to CAM,
     making it possible to e.g. retrieve it using camcontrol(8).
    
    Reviewed by:	scottl, hps (earlier version)
    Obtained from:	Wheel Sp. z o.o. (http://www.wheel.pl)
    ---
     sys/dev/usb/storage/umass.c | 46 +++++++++++++++++++++++++++++++++++++
     1 file changed, 46 insertions(+)
    
    diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
    index f09d1bab5c2..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 
    @@ -2977,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
    @@ -3193,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;
     
    
    From 83bd4cd043edf1437ab6db888d7fc0c0b978800c Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Fri, 4 Sep 2009 10:22:29 +0000
    Subject: [PATCH 360/453] Add NFSv4 ACL support to getfacl(1).
    
    Reviewed by:	rwatson
    ---
     bin/getfacl/getfacl.1 | 16 ++++++++--
     bin/getfacl/getfacl.c | 73 ++++++++++++++++++++++++++++++++++---------
     2 files changed, 72 insertions(+), 17 deletions(-)
    
    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;
     		}
    
    From 4dc50fc92deb256e44a87617a7ccc49bb9670d70 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Fri, 4 Sep 2009 14:53:12 +0000
    Subject: [PATCH 361/453] Add missing ';'.
    
    ---
     sys/i386/i386/machdep.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
    index 9c1ea0b143b..1a6b3c6015e 100644
    --- a/sys/i386/i386/machdep.c
    +++ b/sys/i386/i386/machdep.c
    @@ -2570,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]));
     	
    
    From 80976615e3207fbb987d41c744a4d519dc0b09d0 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Fri, 4 Sep 2009 18:21:40 +0000
    Subject: [PATCH 362/453] Add to `camcontrol cmd` support for sending arbitrary
     ATA commands.
    
    It could be used for broad range of tasks, such as configuring drive
    power management modes, caching, security and any other features and tasks,
    not supported by existing drivers.
    ---
     sbin/camcontrol/camcontrol.8 |  23 ++++-
     sbin/camcontrol/camcontrol.c | 170 +++++++++++++++++++++++++----------
     2 files changed, 141 insertions(+), 52 deletions(-)
    
    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 d3450e0648a..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
    @@ -2078,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);
    @@ -2094,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'))
    @@ -2194,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;
     		}
    @@ -2226,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,
    @@ -2279,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)) {
    @@ -2296,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)
    @@ -4029,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"
    
    From 996de02413513c011594e76cfc04a1aded441b10 Mon Sep 17 00:00:00 2001
    From: Kip Macy 
    Date: Fri, 4 Sep 2009 18:52:26 +0000
    Subject: [PATCH 363/453] remove stale references to RTF_CLONING and RTF_LLINFO
    
    MFC after:	3 days
    ---
     sbin/route/route.8 | 21 ---------------------
     1 file changed, 21 deletions(-)
    
    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
    
    From babbbb9c5732a43706b15b3d9723ea18f262e780 Mon Sep 17 00:00:00 2001
    From: Jamie Gritton 
    Date: Fri, 4 Sep 2009 19:00:48 +0000
    Subject: [PATCH 364/453] Allow a jail's name to be the same as its jid (which
     is the default if no name is specified), but still disallow other numeric
     names.
    
    Reviewed by:	zec
    Approved by:	bz (mentor)
    MFC after:	3 days
    ---
     sys/kern/kern_jail.c | 29 ++++++++++++++++++++---------
     1 file changed, 20 insertions(+), 9 deletions(-)
    
    diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
    index 47201d2b8df..0cc330cd5ad 100644
    --- a/sys/kern/kern_jail.c
    +++ b/sys/kern/kern_jail.c
    @@ -478,7 +478,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
     	struct vfsoptlist *opts;
     	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;
    @@ -907,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
    @@ -973,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,
    @@ -1000,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 =
    @@ -1412,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;
     		}
     		/*
    
    From af582ea7afc05fc6b15596dd3a058adc4d81cbf7 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Fri, 4 Sep 2009 19:20:46 +0000
    Subject: [PATCH 365/453] Remove artificial MAX_IO_SIZE constant, equal to
     DFLTPHYS * 2. Use MAXPHYS instead. It is NULL change for GENERIC kernel, but
     allows 'fast' mode to work on systems with increased MAXPHYS.
    
    ---
     sys/geom/stripe/g_stripe.c | 13 ++++++-------
     1 file changed, 6 insertions(+), 7 deletions(-)
    
    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;
     	}
    
    From fa2db9145a26f6194ece563aa6ac7f6217dc99e9 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Fri, 4 Sep 2009 20:01:16 +0000
    Subject: [PATCH 366/453] Add NFSv4 ACL support to find(1).
    
    Reviewed by:	rwatson
    ---
     usr.bin/find/function.c | 64 ++++++++++++++++++++++++-----------------
     1 file changed, 37 insertions(+), 27 deletions(-)
    
    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 *
    
    From 6b2eaa836f7e9985b3c25d1688103fccbbf37a81 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Fri, 4 Sep 2009 21:00:45 +0000
    Subject: [PATCH 367/453] Fill the reverse RSS map with 0xff's so that the
     subsequent loop to calculate the values will work properly.
    
    Reviewed by:	np
    MFC after:	1 month
    ---
     sys/dev/cxgb/cxgb_main.c | 3 +++
     1 file changed, 3 insertions(+)
    
    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;
    
    From 62efc229e7698562fbbdc9e0df27ebcb9a6e09b0 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Fri, 4 Sep 2009 21:49:37 +0000
    Subject: [PATCH 368/453] Add NFSv4 ACL support to mv(1).
    
    Reviewed by:	rwatson
    ---
     bin/mv/mv.c | 70 ++++++++++++++++++++++++++++++++++++++++++++---------
     1 file changed, 58 insertions(+), 12 deletions(-)
    
    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)
     {
    
    From e26b433febc5196d6b908eb71b61240ae2d83a9f Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Fri, 4 Sep 2009 22:34:57 +0000
    Subject: [PATCH 369/453] must also plumb static wep keys to the local sta db
     in sta mode; not sure when this became necessary and might be caused by some
     missing code to do auto-configuration of DWDS usage
    
    Noticed by:	Felix Feng 
    ---
     sys/dev/mwl/if_mwl.c | 4 ++++
     1 file changed, 4 insertions(+)
    
    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) {
     		/*
    
    From 0cde297e036c47f30128f5ab3e68e2272f79981c Mon Sep 17 00:00:00 2001
    From: Jack F Vogel 
    Date: Fri, 4 Sep 2009 22:45:07 +0000
    Subject: [PATCH 370/453] If an interface is brought up with no cable it will
     experience watchdog resets, this is due to a missing check for link in the
     new multiqueue start code.
    
    MFC: 3 days
    ---
     sys/dev/ixgbe/ixgbe.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
    index 3c0f5edb7a9..008ded88c11 100644
    --- a/sys/dev/ixgbe/ixgbe.c
    +++ b/sys/dev/ixgbe/ixgbe.c
    @@ -759,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);
     	}
    
    From 411c7658a8433ff0751efc4876dbd2c8b1f29166 Mon Sep 17 00:00:00 2001
    From: Warner Losh 
    Date: Sat, 5 Sep 2009 08:08:14 +0000
    Subject: [PATCH 371/453] Note migration of tunable from hw.bus.devctl_disable
     to hw.bus.devctl_queue.  The sysctl interface provides legacys upport for the
     latter sysctl, but the tunable support was removed.
    
    MFC after:	1 day
    ---
     UPDATING | 6 ++++++
     1 file changed, 6 insertions(+)
    
    diff --git a/UPDATING b/UPDATING
    index 8db99bf804f..8056923e579 100644
    --- a/UPDATING
    +++ b/UPDATING
    @@ -22,6 +22,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
     	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
    
    From f6a4f4b5215c81f3de9f68519aa42ee553687bf9 Mon Sep 17 00:00:00 2001
    From: Warner Losh 
    Date: Sat, 5 Sep 2009 08:09:35 +0000
    Subject: [PATCH 372/453] Go ahead and mention the CVS branch name as well as
     the svn branch name.
    
    ---
     UPDATING | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/UPDATING b/UPDATING
    index 8056923e579..ab922195f6b 100644
    --- a/UPDATING
    +++ b/UPDATING
    @@ -34,7 +34,8 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
     	maintain stop_cpus() to just use a normal IPI_STOP on ia32 and amd64.
     
     20090803:
    -	stable/8 branch created in subversion.
    +	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
    
    From 520998911a15d9d0f44770074ea88af4a13e1c9e Mon Sep 17 00:00:00 2001
    From: Warner Losh 
    Date: Sat, 5 Sep 2009 08:38:25 +0000
    Subject: [PATCH 373/453] These checks against BUSY aren't needed: the newbus
     layer does this already with the appropriate locks held...  There's no need
     to do it here, so just delete the checks.
    
    ---
     sys/dev/rp/rp_pci.c | 8 --------
     1 file changed, 8 deletions(-)
    
    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);
    
    From 1ecc75dfe3705bc9c5f496d23aee6bd4c6f5d75f Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Sat, 5 Sep 2009 13:32:05 +0000
    Subject: [PATCH 374/453] Handle zero size for posix_memalign. Return NULL or
     unique address according to the 'V' option.
    
    PR:	standards/138307
    MFC after:	1 week
    ---
     lib/libc/stdlib/malloc.c | 9 +++++++++
     1 file changed, 9 insertions(+)
    
    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);
     	}
     
    
    From a41422a93e1c16ae94a1715799b0b2ff3fb7fe9c Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Sat, 5 Sep 2009 15:08:58 +0000
    Subject: [PATCH 375/453] Improve wording.
    
    Discussed with:	pjd, cperciva, rink, wkoszek and des, in order of appearance.
    ---
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c | 12 ++++++++----
     1 file changed, 8 insertions(+), 4 deletions(-)
    
    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..1d00782aded 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 4 GB of RAM is present;\n"
    +		    "            to enable, add \"vfs.zfs.prefetch_disable=0\" "
    +		    "to /boot/loader.conf.\n");
     		zfs_prefetch_disable=1;
     	}
     #endif	
    
    From 9452b0d2de668433f9929010426b2e505f03ce08 Mon Sep 17 00:00:00 2001
    From: Qing Li 
    Date: Sat, 5 Sep 2009 16:43:16 +0000
    Subject: [PATCH 376/453] This patch fixes the following issues: - Interface
     link-local address is not reachable within the   node that owns the
     interface, this is due to the mismatch   in address scope as the result of
     the installed interface   address loopback route. Therefore for each
     interface   address loopback route, the rt_gateway field (of AF_LINK   type)
     will be used to track which interface a given   address belongs to. This will
     aid the address source to   use the proper interface for address scope/zone
     validation. - The loopback address is not reachable. The root cause is   the
     same as the above. - Empty nd6 entries are created for the IPv6 loopback
     addresses   only for validation reason. Doing so will eliminate as much   of
     the special case (loopback addresses) handling code   as possible, however,
     these empty nd6 entries should not   be returned to the userland applications
     such as the   "ndp" command. Since both of the above issues contain common
     files, these files are committed together.
    
    Reviewed by:	bz
    MFC after:	immediately
    ---
     sys/net/if_llatbl.c       |  9 +++++++++
     sys/netinet6/in6.c        | 11 +++++++----
     sys/netinet6/in6_src.c    | 30 +++++++++++++++++++-----------
     sys/netinet6/ip6_output.c | 15 +++++++++------
     4 files changed, 44 insertions(+), 21 deletions(-)
    
    diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
    index b66d6e154b2..fb94f735062 100644
    --- a/sys/net/if_llatbl.c
    +++ b/sys/net/if_llatbl.c
    @@ -263,6 +263,15 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
     		    __func__, dl->sdl_index);
     		return EINVAL;
     	}
    +	if (ifp->if_flags & IFF_LOOPBACK) {
    +		struct ifaddr *ia;
    +		ia = ifa_ifwithaddr(dst);
    +		if (ia != NULL) {
    +			ifp = ia->ifa_ifp;
    +			ifa_free(ia);
    +		} else 
    +			return EINVAL;
    +	}
     
     	switch (rtm->rtm_type) {
     	case RTM_ADD:
    diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
    index b0b25854027..9521e8e7a5e 100644
    --- a/sys/netinet6/in6.c
    +++ b/sys/netinet6/in6.c
    @@ -1201,8 +1201,8 @@ in6_purgeaddr(struct ifaddr *ifa)
     		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;
    @@ -1782,9 +1782,9 @@ 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)
    @@ -2495,6 +2495,9 @@ in6_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
     	} ndpc;
     	int i, error;
     
    +	if (ifp->if_flags & IFF_LOOPBACK)
    +		return 0;
    +
     	LLTABLE_LOCK_ASSERT();
     
     	error = 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_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;
     
    
    From 7dcdecb107a5c86c4d9837dbda0b9485c947b583 Mon Sep 17 00:00:00 2001
    From: Qing Li 
    Date: Sat, 5 Sep 2009 16:50:55 +0000
    Subject: [PATCH 377/453] This patch fixes an address scope violation.
     Considering the scenario where an anycast address is assigned on one
     interface, and a global address with the same scope is assigned on another
     interface. In other words, the interface owns the anycast address has only
     the link-local address as one other address. Without this patch, "ping6" the
     anycast address from another station will observe the source address of the
     returned ICMP6 echo reply has the link-local address, not the global address
     that exists on the other interface in the same node.
    
    Reviewed by:	bz
    MFC after:	immediately
    ---
     sys/netinet6/icmp6.c | 4 ++++
     1 file changed, 4 insertions(+)
    
    diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
    index 6f13c692d0c..04810c36273 100644
    --- a/sys/netinet6/icmp6.c
    +++ b/sys/netinet6/icmp6.c
    @@ -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;
    
    From cb58c0efadb22a4f13bf66ffa2000a011a9212be Mon Sep 17 00:00:00 2001
    From: "Bjoern A. Zeeb" 
    Date: Sat, 5 Sep 2009 16:51:51 +0000
    Subject: [PATCH 378/453] In the NEXTADDR macro use SA_SIZE() rather than
     directly using sizeof(), as introduced in r186119, for advancing the current
     position into the buffer. See comment in net/route.h for a description of the
     difference. This makes ndp -s work again.
    
    Reviewed by:	qingli
    X-MFC after:	now
    ---
     usr.sbin/ndp/ndp.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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;
    
    From d134008aa0f1aaf0d74dcc8d32567b140659363d Mon Sep 17 00:00:00 2001
    From: Qing Li 
    Date: Sat, 5 Sep 2009 20:24:37 +0000
    Subject: [PATCH 379/453] The addresses that are assigned to the loopback
     interface should be part of the kernel routing table.
    
    Reviewed by:	bz
    MFC after:	immediately
    ---
     sys/net/if_llatbl.c |  9 ---------
     sys/netinet6/in6.c  | 11 +++++++----
     2 files changed, 7 insertions(+), 13 deletions(-)
    
    diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
    index fb94f735062..b66d6e154b2 100644
    --- a/sys/net/if_llatbl.c
    +++ b/sys/net/if_llatbl.c
    @@ -263,15 +263,6 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
     		    __func__, dl->sdl_index);
     		return EINVAL;
     	}
    -	if (ifp->if_flags & IFF_LOOPBACK) {
    -		struct ifaddr *ia;
    -		ia = ifa_ifwithaddr(dst);
    -		if (ia != NULL) {
    -			ifp = ia->ifa_ifp;
    -			ifa_free(ia);
    -		} else 
    -			return EINVAL;
    -	}
     
     	switch (rtm->rtm_type) {
     	case RTM_ADD:
    diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
    index 9521e8e7a5e..c832305b162 100644
    --- a/sys/netinet6/in6.c
    +++ b/sys/netinet6/in6.c
    @@ -1192,9 +1192,10 @@ 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;
     
    @@ -1767,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};
    @@ -1788,7 +1791,7 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
     			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). */
    
    From 963feac4e98eaf3081dc32e60537258378558a28 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 6 Sep 2009 06:48:50 +0000
    Subject: [PATCH 380/453] For any given subcommand allow to specify multi-line
     usage (separated by \n).
    
    Submitted by:	Mel Flynn
    ---
     sbin/geom/core/geom.c | 14 ++++++++++++--
     1 file changed, 12 insertions(+), 2 deletions(-)
    
    diff --git a/sbin/geom/core/geom.c b/sbin/geom/core/geom.c
    index 8949b73f559..ef957887661 100644
    --- a/sbin/geom/core/geom.c
    +++ b/sbin/geom/core/geom.c
    @@ -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++) {
    
    From 87070efb4da77f13c1a6a93b837afe316d39cac9 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 6 Sep 2009 06:49:59 +0000
    Subject: [PATCH 381/453] Update copyright years.
    
    ---
     sbin/geom/core/geom.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sbin/geom/core/geom.c b/sbin/geom/core/geom.c
    index ef957887661..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
    
    From b740e905a4ccee4dffd374c6f410f2e07707c06c Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 6 Sep 2009 06:52:06 +0000
    Subject: [PATCH 382/453] Add support for changing providers priority.
    
    Submitted by:	Mel Flynn
    ---
     sbin/geom/class/mirror/geom_mirror.c |  9 ++--
     sbin/geom/class/mirror/gmirror.8     | 19 ++++++--
     sys/geom/mirror/g_mirror_ctl.c       | 71 ++++++++++++++++++++++++----
     3 files changed, 81 insertions(+), 18 deletions(-)
    
    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/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;
    
    From cfef209a719bec3ff2c0aaa4bbe3a19d8c23c712 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 6 Sep 2009 07:22:09 +0000
    Subject: [PATCH 383/453] Synchornize description in manual page with
     strerror() output.
    
    ---
     lib/libc/sys/intro.2 | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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
    
    From 360488410fe6c49f355aae1d6866cabc8a19a4d8 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 6 Sep 2009 07:29:22 +0000
    Subject: [PATCH 384/453] Correct comment.
    
    ---
     sys/netinet/ip_fastfwd.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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 *
    
    From cee0fa809bf9cb383f0c77a193da8743f041d944 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 6 Sep 2009 07:30:21 +0000
    Subject: [PATCH 385/453] Correct typo in comment.
    
    ---
     sys/netipsec/ipsec.h | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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 */
    
    From 950ab2f81e52396a59a006f88d9fb39e32da6078 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 6 Sep 2009 07:32:16 +0000
    Subject: [PATCH 386/453] Improve code a bit by eliminating goto and having one
     unlock per lock.
    
    ---
     sys/netipsec/key.c | 7 +++----
     1 file changed, 3 insertions(+), 4 deletions(-)
    
    diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
    index 99dce21b2f2..081e697eda4 100644
    --- a/sys/netipsec/key.c
    +++ b/sys/netipsec/key.c
    @@ -918,15 +918,14 @@ 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();
     
    -	return NULL;
    +	if (sah == NULL)
    +		return NULL;
     
    -    found:
     	/* search valid state */
     	for (stateidx = 0; stateidx < arraysize; stateidx++) {
     		sav = key_do_allocsa_policy(sah, state_valid[stateidx]);
    
    From 30fe9de0bbcb8acca8d38090e5958f5691c6f39f Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Sun, 6 Sep 2009 09:39:40 +0000
    Subject: [PATCH 387/453] Perform cleanups to the TTY headers:
    
    - Properly sort the ioctls in ioctl_compat.h. Also perform some
      whitespace fixes.
    - Properly comment all the unused/compat ioctls in ttycom.h.
    ---
     sys/sys/ioctl_compat.h | 24 ++++++++++++------------
     sys/sys/ttycom.h       | 21 ++++++++++-----------
     2 files changed, 22 insertions(+), 23 deletions(-)
    
    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/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 */
    
    From 61c177bf1115dc1fb7e0c7b4c677f30589b398ec Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Sun, 6 Sep 2009 09:59:02 +0000
    Subject: [PATCH 388/453] Remove unneeded minor numbers from /dev/null and
     /dev/zero.
    
    ---
     sys/dev/null/null.c | 11 ++++-------
     1 file changed, 4 insertions(+), 7 deletions(-)
    
    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:
    
    From 4d3b1aacfce673dc535917542c1844221f1fc9a5 Mon Sep 17 00:00:00 2001
    From: Ed Schouten 
    Date: Sun, 6 Sep 2009 10:27:45 +0000
    Subject: [PATCH 389/453] Move ptmx into pty(4).
    
    Now that pty(4) is a loadable kernel module, I'd better move /dev/ptmx
    in there as well. This means that pty(4) now provides almost all
    pseudo-terminal compatibility code. This means it's very easy to test
    whether applications use the proper library interfaces when allocating
    pseudo-terminals (namely posix_openpt and openpty).
    ---
     share/man/man4/pts.4 |  9 ---------
     share/man/man4/pty.4 | 13 +++++++++++--
     sys/dev/pty/pty.c    | 18 ++++++++++++++++++
     sys/kern/tty_pts.c   | 25 +++++--------------------
     sys/sys/tty.h        |  1 +
     5 files changed, 35 insertions(+), 31 deletions(-)
    
    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/sys/dev/pty/pty.c b/sys/dev/pty/pty.c
    index d3dce9f1746..c24396a69ca 100644
    --- a/sys/dev/pty/pty.c
    +++ b/sys/dev/pty/pty.c
    @@ -47,6 +47,9 @@ __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 = 1;
    @@ -118,6 +121,20 @@ pty_clone(void *arg, struct ucred *cr, char *name, int namelen,
     	    NULL, UID_ROOT, GID_WHEEL, 0666, "%s", name);
     }
     
    +static int
    +ptmx_fdopen(struct cdev *dev __unused, 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",
    +};
    +
     static int
     pty_modevent(module_t mod, int type, void *data)
     {
    @@ -125,6 +142,7 @@ 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;
    diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
    index b38070a3f12..350244b334d 100644
    --- a/sys/kern/tty_pts.c
    +++ b/sys/kern/tty_pts.c
    @@ -32,7 +32,7 @@ __FBSDID("$FreeBSD$");
     
     /* Add compatibility bits for FreeBSD. */
     #define PTS_COMPAT
    -/* Add /dev/ptyXX compat bits. */
    +/* Add pty(4) compat bits. */
     #define PTS_EXTERNAL
     /* Add bits to make Linux binaries work. */
     #define PTS_LINUX
    @@ -694,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;
    @@ -815,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/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);
     
    
    From db17314ea4ca7dd0709222982d9c6e3f6c4414b9 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Sun, 6 Sep 2009 11:44:46 +0000
    Subject: [PATCH 390/453] In fhopen, vfs_ref() the mount point while vnode is
     unlocked, to prevent vn_start_write(NULL, &mp) from operating on potentially
     freed or reused struct mount *.
    
    Remove unmatched vfs_rel() in cleanup.
    
    Noted and reviewed by:	tegge
    Tested by:	pho
    MFC after:	3 days
    ---
     sys/kern/vfs_syscalls.c | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
    index ed7f999ccef..0a8ef463957 100644
    --- a/sys/kern/vfs_syscalls.c
    +++ b/sys/kern/vfs_syscalls.c
    @@ -4439,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
    @@ -4516,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);
    
    From 5c61c646a368b9b1bec018d2c61f11583a4023c7 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Sun, 6 Sep 2009 11:46:51 +0000
    Subject: [PATCH 391/453] The clear_remove() and clear_inodedeps() call
     vn_start_write(NULL, &mp, V_NOWAIT) on the non-busied mount point. Unmount
     might free ufs-specific mp data, causing ffs_vgetf() to access freed memory.
    
    Busy mountpoint before dropping softdep lk.
    
    Noted and reviewed by:	tegge
    Tested by:	pho
    MFC after:	1 week
    ---
     sys/ufs/ffs/ffs_softdep.c | 32 ++++++++++++++++++++++++--------
     1 file changed, 24 insertions(+), 8 deletions(-)
    
    diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
    index 5f162806d1e..4d652c114dd 100644
    --- a/sys/ufs/ffs/ffs_softdep.c
    +++ b/sys/ufs/ffs/ffs_softdep.c
    @@ -5977,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);
    @@ -5991,6 +5998,7 @@ clear_remove(td)
     			drain_output(vp);
     			BO_UNLOCK(bo);
     			vput(vp);
    +		finish_write:
     			vn_finished_write(mp);
     			ACQUIRE_LOCK(&lk);
     			return;
    @@ -6050,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);
    
    From 3705c384870f9ca026a711a2385eb4b7b0bbad84 Mon Sep 17 00:00:00 2001
    From: Norikatsu Shigemura 
    Date: Sun, 6 Sep 2009 12:01:29 +0000
    Subject: [PATCH 392/453] Change 'dev.cpu.N.temperature', sysctl I (degC) to IK
     (Kelvin).
    
    Approved by:	re (rwatson)
    Reviewed by:	rpaulo
    Suggested by:	ume
    MFC After:	3 days
    ---
     sys/dev/coretemp/coretemp.c | 8 +++++---
     1 file changed, 5 insertions(+), 3 deletions(-)
    
    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));
     }
    
    From 1dfbeeaba1d82a135628e4d9cb97a57c82675b83 Mon Sep 17 00:00:00 2001
    From: Antoine Brodin 
    Date: Sun, 6 Sep 2009 13:26:51 +0000
    Subject: [PATCH 393/453] Update etc/mtree/Makefile:   There is no longer
     BSD.{local,x11-4,x11}.dist mtree files.   There is a BSD.sendmail.dist mtree
     file.
    
    ---
     etc/mtree/Makefile | 9 +++++----
     1 file changed, 5 insertions(+), 4 deletions(-)
    
    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
    
    From bf3f1fe0438b650a95090eb507b8946e7ebc8bf0 Mon Sep 17 00:00:00 2001
    From: Antoine Brodin 
    Date: Sun, 6 Sep 2009 13:31:05 +0000
    Subject: [PATCH 394/453] Change w_notrunning and w_stillcold from pointer to
     array so that sizeof returns what is expected.
    
    PR:		kern/138557
    Discussed with:	brucec@
    MFC after:	1 month
    ---
     sys/kern/subr_witness.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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[] = {
    
    From 4b861b15698091b25efa56333219da912407d068 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 6 Sep 2009 14:23:26 +0000
    Subject: [PATCH 395/453] Remove constraint, requiring request data to fulfill
     controller's alignment requirements. It is busdma task, to manage proper
     alignment by loading data to bounce buffers.
    
    PR:		kern/127316
    Reviewed by:	current@
    Tested by:	Ryan Rogers
    ---
     sys/dev/ata/ata-dma.c | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    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) {
    
    From 3b02c4a3d35884bb89529cabfffb5aa1a58c0be3 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 6 Sep 2009 18:09:25 +0000
    Subject: [PATCH 396/453] Initialize state_valid and arraysize variable so gcc
     won't complain.
    
    Reported by:	bz
    ---
     sys/netipsec/key.c | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
    index 081e697eda4..8183f5b19da 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;	/* silent gcc */
    +	arraysize = 0;		/* silent gcc */
    +
     	SAHTREE_LOCK();
     	LIST_FOREACH(sah, &V_sahtree, chain) {
     		if (sah->state == SADB_SASTATE_DEAD)
    @@ -922,7 +925,6 @@ key_allocsa_policy(const struct secasindex *saidx)
     		}
     	}
     	SAHTREE_UNLOCK();
    -
     	if (sah == NULL)
     		return NULL;
     
    
    From 788fb3767d953a9a81c762b7e0dba9159927f330 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 6 Sep 2009 18:40:48 +0000
    Subject: [PATCH 397/453] Avoid extra swi_sched() call, if this SIM is already
     queued. It reduces overhead for coalesced command completions.
    
    ---
     sys/cam/cam_xpt.c | 28 ++++++++++++++++------------
     1 file changed, 16 insertions(+), 12 deletions(-)
    
    diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
    index 1c2f61430a6..b29295d562c 100644
    --- a/sys/cam/cam_xpt.c
    +++ b/sys/cam/cam_xpt.c
    @@ -4198,12 +4198,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",
    @@ -4889,16 +4889,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
    
    From ad41300955a02fe7fe5efacabc1d04db89c7f1fd Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 6 Sep 2009 18:48:18 +0000
    Subject: [PATCH 398/453] MFp4: Report scbusX in xpt_announce_periph() to less
     confuse users by two different bus addressing schemes.
    
    ---
     sys/cam/cam_xpt.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
    index b29295d562c..f5e32745c41 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);
    
    From 70f2d0549944f134ead281cfc03a0a521fcf69ed Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 6 Sep 2009 18:56:08 +0000
    Subject: [PATCH 399/453] s/bus %d/scbus%d/ in some messages to correct
     terminology.
    
    ---
     sys/cam/cam_xpt.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
    index f5e32745c41..e7c71288d8b 100644
    --- a/sys/cam/cam_xpt.c
    +++ b/sys/cam/cam_xpt.c
    @@ -4605,7 +4605,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--;
    @@ -4616,7 +4616,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);
    
    From f96d66a41e6b861843a276c9ddb9b608443322ce Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 6 Sep 2009 18:59:46 +0000
    Subject: [PATCH 400/453] Remove unneeded CAM_SIM_MPSAFE check.
    
    ---
     sys/cam/cam_xpt.c | 5 +----
     1 file changed, 1 insertion(+), 4 deletions(-)
    
    diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
    index e7c71288d8b..15353e6482f 100644
    --- a/sys/cam/cam_xpt.c
    +++ b/sys/cam/cam_xpt.c
    @@ -4407,10 +4407,7 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
     		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
    
    From fc79063e66b10b261f455ed3b335565634cbb570 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sun, 6 Sep 2009 19:05:03 +0000
    Subject: [PATCH 401/453] Silent gcc? Yeah, you wish. What I ment was to
     silence gcc.
    
    Spotted by:	julian
    ---
     sys/netipsec/key.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
    index 8183f5b19da..bf9db684656 100644
    --- a/sys/netipsec/key.c
    +++ b/sys/netipsec/key.c
    @@ -906,8 +906,8 @@ key_allocsa_policy(const struct secasindex *saidx)
     	u_int stateidx, arraysize;
     	const u_int *state_valid;
     
    -	state_valid = NULL;	/* silent gcc */
    -	arraysize = 0;		/* silent gcc */
    +	state_valid = NULL;	/* silence gcc */
    +	arraysize = 0;		/* silence gcc */
     
     	SAHTREE_LOCK();
     	LIST_FOREACH(sah, &V_sahtree, chain) {
    
    From ee358e63766b39d924ca1a040caf9c32cbc0c27c Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 6 Sep 2009 19:06:50 +0000
    Subject: [PATCH 402/453] MFp4: Remove duplicate qfrozen_cnt variable from
     struct cam_ed. ccbq.queue.qfrozen_cnt should be used instead.
    
    ---
     sys/cam/cam_xpt.c          | 26 +++++++++++++-------------
     sys/cam/cam_xpt_internal.h |  1 -
     2 files changed, 13 insertions(+), 14 deletions(-)
    
    diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
    index 15353e6482f..b506481bb26 100644
    --- a/sys/cam/cam_xpt.c
    +++ b/sys/cam/cam_xpt.c
    @@ -2472,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;
    @@ -2931,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;
     	}
    @@ -3227,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;
     		}
     
    @@ -3250,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);
    @@ -3282,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... */
    @@ -4031,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
    @@ -4049,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
    @@ -4093,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
    @@ -4402,7 +4403,6 @@ 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;
    @@ -4971,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
    
    From 7fc019af65bb1b20dfcf7835129c72e770768742 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 6 Sep 2009 19:33:13 +0000
    Subject: [PATCH 403/453] MFp4: Remove msleep() timeout from
     g_io_schedule_up/down(). It works fine without it, saving few percents of CPU
     on high request rates without need to rearm callout twice per request.
    
    ---
     sys/geom/geom_io.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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);
     	}
     }
     
    
    From aed39f0d655695ec9cfea59fbf19d5603053eb1c Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Sun, 6 Sep 2009 21:22:24 +0000
    Subject: [PATCH 404/453] To save small bit of CPU time, hide part of SNTF
     register read latency behind other reads.
    
    ---
     sys/dev/ahci/ahci.c | 16 +++++++---------
     1 file changed, 7 insertions(+), 9 deletions(-)
    
    diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
    index 2d8be431017..273c276bd2a 100644
    --- a/sys/dev/ahci/ahci.c
    +++ b/sys/dev/ahci/ahci.c
    @@ -891,16 +891,12 @@ ahci_phy_check_events(device_t dev)
     }
     
     static void
    -ahci_notify_events(device_t dev)
    +ahci_notify_events(device_t dev, u_int32_t status)
     {
     	struct ahci_channel *ch = device_get_softc(dev);
     	struct cam_path *dpath;
    -	u_int32_t status;
     	int i;
     
    -	status = ATA_INL(ch->r_mem, AHCI_P_SNTF);
    -	if (status == 0)
    -		return;
     	ATA_OUTL(ch->r_mem, AHCI_P_SNTF, status);
     	if (bootverbose)
     		device_printf(dev, "SNTF 0x%04x\n", status);
    @@ -948,7 +944,7 @@ 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;
     
    @@ -958,8 +954,10 @@ ahci_ch_intr(void *data)
     		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);
    @@ -1023,8 +1021,8 @@ ahci_ch_intr(void *data)
     			ahci_issue_read_log(dev);
     	}
     	/* Process NOTIFY events */
    -	if ((istatus & AHCI_P_IX_SDB) && (ch->caps & AHCI_CAP_SSNTF))
    -		ahci_notify_events(dev);
    +	if (sntf)
    +		ahci_notify_events(dev, sntf);
     }
     
     /* Must be called with channel locked. */
    
    From b61d9eabb4bd029d54df104264865b9dbbb8d780 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 06:37:44 +0000
    Subject: [PATCH 405/453] Make sure to use up-to-date libarchive header files
     from source tree when compiling tar and not the ones from /usr/include/.
    
    Reviewed by:	kientzle
    Approved by:	kientzle
    ---
     usr.bin/tar/Makefile | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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
    
    From dcc3a33188bceb5b6e819efdb9c5f72d059084b6 Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Mon, 7 Sep 2009 09:30:37 +0000
    Subject: [PATCH 406/453] Import a vendor fix for a list overrun. This has been
     considered as a security hole on some specialized ml, but currently the
     secteam@ doesn't consider that way.
    
    Reviewed by:	emaste, des
    Sponsored by:	Sandvine Incorporated
    MFC after:	3 days
    ---
     contrib/gdtoa/gdtoaimp.h |  2 +-
     contrib/gdtoa/misc.c     | 18 ++++++++++++------
     2 files changed, 13 insertions(+), 7 deletions(-)
    
    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);
    +			}
     		}
     	}
     
    
    From 5e65224dafc3cfa4d8137f7994436f8e4d5e0adc Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 11:38:43 +0000
    Subject: [PATCH 407/453] bzero() on-stack argument, so mutex_init() won't
     misinterpret that the lock is already initialized if we have some garbage on
     the stack.
    
    PR:		kern/135480
    Reported by:	Emil Mikulic 
    MFC after:	3 days
    ---
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c | 1 +
     1 file changed, 1 insertion(+)
    
    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;
    
    From 6cc745d2d717eb3920a7b5cf2e6c924cbb1bf20f Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Mon, 7 Sep 2009 11:55:34 +0000
    Subject: [PATCH 408/453] insmntque_stddtr() clears vp->v_data and resets
     vp->v_op to dead_vnodeops before calling vgone(). Revert r189706 and
     corresponding part of the r186560.
    
    Noted and reviewed by:	tegge
    Approved by:	des (pseudofs part)
    MFC after:	3 days
    ---
     sys/fs/pseudofs/pseudofs_vncache.c | 1 +
     sys/ufs/ffs/ffs_vfsops.c           | 1 +
     2 files changed, 2 insertions(+)
    
    diff --git a/sys/fs/pseudofs/pseudofs_vncache.c b/sys/fs/pseudofs/pseudofs_vncache.c
    index 31458707b58..a92a44614bc 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);
     	}
    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);
     	}
    
    From 481208a815fc3abfaa71017e2f7a4aba08968e36 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Mon, 7 Sep 2009 12:10:41 +0000
    Subject: [PATCH 409/453] If a race is detected, pfs_vncache_alloc() may
     reclaim a vnode that had never been inserted into the pfs_vncache list. Since
     pfs_vncache_free() does not anticipate this case, it decrements
     pfs_vncache_entries unconditionally; if the vnode was not in the list,
     pfs_vncache_entries will no longer reflect the actual number of list entries.
     This may cause size of the cache to exceed the configured maximum. It may
     also trigger a panic during module unload or system shutdown.
    
    Do not decrement pfs_vncache_entries for the vnode that was not in the
    list.
    
    Submitted by:	tegge
    Reviewed by:	des
    MFC after:	1 week
    ---
     sys/fs/pseudofs/pseudofs_vncache.c | 8 +++++---
     1 file changed, 5 insertions(+), 3 deletions(-)
    
    diff --git a/sys/fs/pseudofs/pseudofs_vncache.c b/sys/fs/pseudofs/pseudofs_vncache.c
    index a92a44614bc..035f2c79dd7 100644
    --- a/sys/fs/pseudofs/pseudofs_vncache.c
    +++ b/sys/fs/pseudofs/pseudofs_vncache.c
    @@ -246,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);
    
    From 841bcfea21ab959a4ba95d2eabefe1c68d957ae3 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 14:16:50 +0000
    Subject: [PATCH 410/453] Changing provider size is not really supported by
     GEOM, but doing so when provider is closed should be ok.
    
    When administrator requests to change ZVOL size do it immediately if ZVOL
    is closed or do it on last ZVOL close.
    
    PR:		kern/136942
    Requested by:	Bernard Buri 
    MFC after:	1 week
    ---
     .../opensolaris/uts/common/fs/zfs/zvol.c      | 21 ++++++++++++++-----
     1 file changed, 16 insertions(+), 5 deletions(-)
    
    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 a43cfdcab00..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);
     
    @@ -1072,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);
    
    From 544bf7f1652fb2c44e045dd1f6aab44a379bfcae Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 14:44:04 +0000
    Subject: [PATCH 411/453] Teach zdb(8) how to obtain GEOM provider size.
    
    PR:		kern/133134
    Reported by:	Philipp Wuensche 
    MFC after:	3 days
    ---
     cddl/contrib/opensolaris/cmd/zdb/zdb.c | 8 ++++++++
     1 file changed, 8 insertions(+)
    
    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));
     
    
    From ad334ef0822b3f9ca8e19daa9cb01ab1db6a2c36 Mon Sep 17 00:00:00 2001
    From: Hajimu UMEMOTO 
    Date: Mon, 7 Sep 2009 15:22:54 +0000
    Subject: [PATCH 412/453] Suppress an options line when no bit is on.
    
    Reviewed by:	hrs
    MFC after:	3 days
    ---
     sbin/ifconfig/ifgif.c | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/sbin/ifconfig/ifgif.c b/sbin/ifconfig/ifgif.c
    index f9f3524e98e..aed6382b2fa 100644
    --- a/sbin/ifconfig/ifgif.c
    +++ b/sbin/ifconfig/ifgif.c
    @@ -71,6 +71,8 @@ gif_status(int s)
     	ifr.ifr_data = (caddr_t)&opts;
     	if (ioctl(s, GIFGOPTS, &ifr) == -1)
     		return;
    +	if (opts == 0)
    +		return;
     
     	printf("\toptions=%d<", opts);
     	for (i=0; i < sizeof(gif_opts)/sizeof(gif_opts[0]); i++) {
    
    From 53ac3451a7f80d34a2b0cb1b66aa7827ad6bea9e Mon Sep 17 00:00:00 2001
    From: Hiroki Sato 
    Date: Mon, 7 Sep 2009 15:52:15 +0000
    Subject: [PATCH 413/453] Use printb() instead of rolling its own routine to
     display bits in options=<>.
    
    Pointed out by:	ume
    MFC after:	3 days
    ---
     sbin/ifconfig/ifgif.c | 24 ++++--------------------
     1 file changed, 4 insertions(+), 20 deletions(-)
    
    diff --git a/sbin/ifconfig/ifgif.c b/sbin/ifconfig/ifgif.c
    index aed6382b2fa..f91508b53c7 100644
    --- a/sbin/ifconfig/ifgif.c
    +++ b/sbin/ifconfig/ifgif.c
    @@ -51,38 +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;
     	if (opts == 0)
     		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");
    +	printb("\toptions", opts, GIFBITS);
    +	putchar('\n');
     }
     
     static void
    
    From e72ae6eafd3f6d476bb88c74f5e92702cff049ff Mon Sep 17 00:00:00 2001
    From: Shteryana Shopova 
    Date: Mon, 7 Sep 2009 16:00:33 +0000
    Subject: [PATCH 414/453] When joining a multicast group, the
     inp_lookup_mcast_ifp call does a KASSERT that the group address is multicast,
     so the check if this is indeed true and eventually return a EINVAL if not,
     should be done before calling inp_lookup_mcast_ifp. This fixes a kernel crash
     when calling setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,...) with
     invalid group address.
    
    Reviewed by:	bms
    Approved by:	bms
    
    MFC after:	3 days
    ---
     sys/netinet/in_mcast.c | 9 ++++++---
     1 file changed, 6 insertions(+), 3 deletions(-)
    
    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);
     
    
    From 518de5f8374fb6319122967eb30dbbb975a2ae6e Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Mon, 7 Sep 2009 16:08:21 +0000
    Subject: [PATCH 415/453] correct typo that was a noop on 32-bit machines but a
     bug on 64-bit machines
    
    Submitted by:	phk
    ---
     sys/dev/ath/if_ath.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
    index 5628addc33a..b6fbaf857d6 100644
    --- a/sys/dev/ath/if_ath.c
    +++ b/sys/dev/ath/if_ath.c
    @@ -1452,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;
    
    From d5c613bdb29646b914ab4fd908de98246c7e92de Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Mon, 7 Sep 2009 16:12:07 +0000
    Subject: [PATCH 416/453] fix extraneous return that can cause a memory leak
    
    Submitted by:	phk
    MFC after:	1 week
    ---
     sys/dev/ath/ath_hal/ah_eeprom_v3.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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;
     }
    
    From 2ef29b4c336fc0e19274abd74d16e8ce56af7ddd Mon Sep 17 00:00:00 2001
    From: Sam Leffler 
    Date: Mon, 7 Sep 2009 16:18:16 +0000
    Subject: [PATCH 417/453] remove extranous return
    
    Submitted by:	phk
    MFC after:	1 week
    ---
     sys/dev/ath/ah_osdep.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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
    
    From 3f22187878a4406a0e30cf1820b7243dcb2c8bf7 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 7 Sep 2009 16:19:32 +0000
    Subject: [PATCH 418/453] Add NFSv4 support to setfacl(1).
    
    Reviewed by:	rwatson
    ---
     bin/setfacl/mask.c    |  11 +--
     bin/setfacl/merge.c   | 191 ++++++++++++++++++++++++++++++++++-------
     bin/setfacl/remove.c  | 170 ++++++++++++++++++-------------------
     bin/setfacl/setfacl.1 | 176 ++++++++++++++++++++++++++++++++++----
     bin/setfacl/setfacl.c | 193 ++++++++++++++++++++++++++----------------
     bin/setfacl/setfacl.h |  21 +++--
     6 files changed, 540 insertions(+), 222 deletions(-)
    
    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 */
    
    From 0103fcf5dc170bb1a1c77ad0628be20cd87cb32a Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 7 Sep 2009 16:26:03 +0000
    Subject: [PATCH 419/453] Add regression tests for NFSv4 ACLs and update
     POSIX.1e tests to the changed error messages.
    
    ---
     tools/regression/acltools/00.t             |  31 +-
     tools/regression/acltools/01.t             |  86 +++
     tools/regression/acltools/tools-nfs4.test  | 829 +++++++++++++++++++++
     tools/regression/acltools/tools-posix.test |  93 ++-
     4 files changed, 1013 insertions(+), 26 deletions(-)
     create mode 100644 tools/regression/acltools/01.t
     create mode 100644 tools/regression/acltools/tools-nfs4.test
    
    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/01.t b/tools/regression/acltools/01.t
    new file mode 100644
    index 00000000000..1f9968252ed
    --- /dev/null
    +++ b/tools/regression/acltools/01.t
    @@ -0,0 +1,86 @@
    +#!/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-nfs4.test on ZFS filesystem.
    +#
    +# WARNING: It uses hardcoded ZFS pool name "acltools"
    +#
    +# If any of the tests fails, here is how to debug it: go to
    +# the directory with problematic filesystem mounted on it,
    +# and do /path/to/test run /path/to/test tools-nfs4.test, e.g.
    +#
    +# /usr/src/tools/regression/acltools/run /usr/src/tools/regression/acltools/tools-nfs4.test
    +#
    +# Output should be obvious.
    +
    +echo "1..4"
    +
    +if [ `whoami` != "root" ]; then
    +	echo "not ok 1 - you need to be root to run this test."
    +	exit 1
    +fi
    +
    +TESTDIR=`dirname $0`
    +
    +# Set up the test filesystem.
    +MD=`mdconfig -at swap -s 64m`
    +MNT=`mktemp -dt acltools`
    +zpool create -R $MNT acltools /dev/$MD
    +if [ $? -ne 0 ]; then
    +	echo "not ok 1 - 'zpool create' failed."
    +	exit 1
    +fi
    +
    +echo "ok 1"
    +
    +cd $MNT
    +
    +# First, check whether we can crash the kernel by creating too many
    +# entries.  For some reason this won't work in the test file.
    +touch xxx
    +setfacl -x5 xxx
    +while :; do setfacl -a0 u:42:rwx:allow xxx 2> /dev/null; if [ $? -ne 0 ]; then break; fi; done
    +chmod 600 xxx
    +rm xxx
    +echo "ok 2"
    +
    +perl $TESTDIR/run $TESTDIR/tools-nfs4.test > /dev/null
    +
    +if [ $? -eq 0 ]; then
    +	echo "ok 3"
    +else
    +	echo "not ok 3"
    +fi
    +
    +cd /
    +zpool destroy -f acltools
    +rmdir $MNT
    +mdconfig -du $MD
    +
    +echo "ok 4"
    diff --git a/tools/regression/acltools/tools-nfs4.test b/tools/regression/acltools/tools-nfs4.test
    new file mode 100644
    index 00000000000..3e41add3ce5
    --- /dev/null
    +++ b/tools/regression/acltools/tools-nfs4.test
    @@ -0,0 +1,829 @@
    +# 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 NFSv4 ACL functionality.  Run it as root
    +# using ACL-enabled kernel:
    +#
    +# /usr/src/tools/regression/acltools/run /usr/src/tools/regression/acltools/tools-nfs4.test
    +#
    +# WARNING: Creates files in unsafe way.
    +
    +$ whoami
    +> root
    +$ umask 022
    +
    +# Smoke test for getfacl(1).
    +$ touch xxx
    +$ getfacl xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +$ getfacl -q xxx
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +# Check verbose mode formatting.
    +$ getfacl -v xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>             owner@:execute::deny
    +>             owner@:read_data/write_data/append_data/write_attributes/write_xattr/write_acl/write_owner::allow
    +>             group@:write_data/execute/append_data::deny
    +>             group@:read_data::allow
    +>          everyone@:write_data/execute/append_data/write_attributes/write_xattr/write_acl/write_owner::deny
    +>          everyone@:read_data/read_attributes/read_xattr/read_acl/synchronize::allow
    +
    +# Test setfacl -a.
    +$ setfacl -a2 u:0:write_acl:allow,g:1:read_acl:deny xxx
    +$ getfacl -n xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             user:0:-----------C--:------:allow
    +>            group:1:----------c---:------:deny
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +# Test user and group name resolving.
    +$ rm xxx
    +$ touch xxx
    +$ setfacl -a2 u:root:write_acl:allow,g:daemon:read_acl:deny xxx
    +$ getfacl xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>          user:root:-----------C--:------:allow
    +>       group:daemon:----------c---:------:deny
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +# Check whether ls correctly marks files with "+".
    +$ ls -l xxx | cut -d' ' -f1
    +> -rw-r--r--+
    +
    +# Test removing entries by number.
    +$ setfacl -x 4 xxx
    +$ setfacl -x 4 xxx
    +$ getfacl -n xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             user:0:-----------C--:------:allow
    +>            group:1:----------c---:------:deny
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +# Test setfacl -m.
    +$ setfacl -a0 everyone@:rwx:deny xxx
    +$ setfacl -a0 everyone@:rwx:deny xxx
    +$ setfacl -a0 everyone@:rwx:deny xxx
    +$ setfacl -m everyone@::deny xxx
    +$ getfacl -n xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>          everyone@:--------------:------:deny
    +>          everyone@:--------------:------:deny
    +>          everyone@:--------------:------:deny
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             user:0:-----------C--:------:allow
    +>            group:1:----------c---:------:deny
    +>          everyone@:--------------:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +# Test getfacl -i.
    +$ getfacl -i xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>          everyone@:--------------:------:deny
    +>          everyone@:--------------:------:deny
    +>          everyone@:--------------:------:deny
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>          user:root:-----------C--:------:allow:0
    +>       group:daemon:----------c---:------:deny:1
    +>          everyone@:--------------:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +# Make sure cp without any flags does not copy copy the ACL.
    +$ cp xxx yyy
    +$ ls -l yyy | cut -d' ' -f1
    +> -rw-r--r--
    +
    +# Make sure it does with the "-p" flag.
    +$ rm yyy
    +$ cp -p xxx yyy
    +$ getfacl -n yyy
    +> # file: yyy
    +> # owner: root
    +> # group: wheel
    +>          everyone@:--------------:------:deny
    +>          everyone@:--------------:------:deny
    +>          everyone@:--------------:------:deny
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             user:0:-----------C--:------:allow
    +>            group:1:----------c---:------:deny
    +>          everyone@:--------------:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +$ rm yyy
    +
    +# Test removing entries by...  by example?
    +$ setfacl -x everyone@::deny xxx
    +$ getfacl -n xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             user:0:-----------C--:------:allow
    +>            group:1:----------c---:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +# Test setfacl -b.
    +$ setfacl -b xxx
    +$ getfacl -n xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +$ ls -l xxx | cut -d' ' -f1
    +> -rw-r--r--
    +
    +# Check setfacl(1) and getfacl(1) with multiple files.
    +$ touch xxx yyy zzz
    +
    +$ ls -l xxx yyy zzz | cut -d' ' -f1
    +> -rw-r--r--
    +> -rw-r--r--
    +> -rw-r--r--
    +
    +$ setfacl -m u:42:x:allow,g:43:w:allow nnn xxx yyy zzz
    +> 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
    +> -rw-r--r--+
    +> -rw-r--r--+
    +> -rw-r--r--+
    +
    +$ getfacl -nq nnn xxx yyy zzz
    +> getfacl: nnn: stat() failed: No such file or directory
    +>            user:42:--x-----------:------:allow
    +>           group:43:-w------------:------:allow
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +>
    +>            user:42:--x-----------:------:allow
    +>           group:43:-w------------:------:allow
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +>
    +>            user:42:--x-----------:------:allow
    +>           group:43:-w------------:------:allow
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +$ setfacl -b nnn xxx yyy zzz
    +> 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
    +> -rw-r--r--
    +> -rw-r--r--
    +> -rw-r--r--
    +
    +$ rm xxx yyy zzz
    +
    +# Test applying mode to an ACL.
    +$ touch xxx
    +$ setfacl -a0 user:42:r:allow,user:43:w:deny,user:43:w:allow,user:44:x:allow -x everyone@::allow xxx
    +$ chmod 600 xxx
    +$ getfacl -n xxx
    +> # file: xxx
    +> # owner: root
    +> # group: wheel
    +>            user:42:r-------------:------:deny
    +>            user:42:r-------------:------:allow
    +>            user:43:-w------------:------:deny
    +>            user:43:-w------------:------:allow
    +>            user:44:--x-----------:------:deny
    +>            user:44:--x-----------:------:allow
    +>             owner@:--------------:------:deny
    +>             owner@:-------A-W-Co-:------:allow
    +>             group@:--------------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:-------A-W-Co-:------:deny
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:rwxp----------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:rwxp---A-W-Co-:------:deny
    +>          everyone@:------a-R-c--s:------:allow
    +$ ls -l xxx | cut -d' ' -f1
    +> -rw-------+
    +
    +$ rm xxx
    +$ touch xxx
    +$ chown 42 xxx
    +$ setfacl -a0 user:42:r:allow,user:43:w:deny,user:43:w:allow,user:44:x:allow xxx
    +$ chmod 600 xxx
    +$ getfacl -n xxx
    +> # file: xxx
    +> # owner: 42
    +> # group: wheel
    +>            user:42:--------------:------:deny
    +>            user:42:r-------------:------:allow
    +>            user:43:-w------------:------:deny
    +>            user:43:-w------------:------:allow
    +>            user:44:--x-----------:------:deny
    +>            user:44:--x-----------:------:allow
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:rwxp----------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:rwxp---A-W-Co-:------:deny
    +>          everyone@:------a-R-c--s:------:allow
    +$ ls -l xxx | cut -d' ' -f1
    +> -rw-------+
    +
    +$ rm xxx
    +$ touch xxx
    +$ chown 43 xxx
    +$ setfacl -a0 user:42:r:allow,user:43:w:deny,user:43:w:allow,user:44:x:allow xxx
    +$ chmod 124 xxx
    +$ getfacl -n xxx
    +> # file: xxx
    +> # owner: 43
    +> # group: wheel
    +>            user:42:r-------------:------:deny
    +>            user:42:r-------------:------:allow
    +>            user:43:-w------------:------:deny
    +>            user:43:-w------------:------:allow
    +>            user:44:--x-----------:------:deny
    +>            user:44:--x-----------:------:allow
    +>             owner@:rw-p----------:------:deny
    +>             owner@:--x----A-W-Co-:------:allow
    +>             group@:r-x-----------:------:deny
    +>             group@:-w-p----------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +$ ls -l xxx | cut -d' ' -f1
    +> ---x-w-r--+
    +
    +$ rm xxx
    +$ touch xxx
    +$ chown 43 xxx
    +$ setfacl -a0 user:42:r:allow,user:43:w:deny,user:43:w:allow,user:44:x:allow xxx
    +$ chmod 412 xxx
    +$ getfacl -n xxx
    +> # file: xxx
    +> # owner: 43
    +> # group: wheel
    +>            user:42:r-------------:------:deny
    +>            user:42:r-------------:------:allow
    +>            user:43:-w------------:------:deny
    +>            user:43:-w------------:------:allow
    +>            user:44:--------------:------:deny
    +>            user:44:--x-----------:------:allow
    +>             owner@:-wxp----------:------:deny
    +>             owner@:r------A-W-Co-:------:allow
    +>             group@:rw-p----------:------:deny
    +>             group@:--x-----------:------:allow
    +>          everyone@:r-x----A-W-Co-:------:deny
    +>          everyone@:-w-p--a-R-c--s:------:allow
    +$ ls -l xxx | cut -d' ' -f1
    +> -r----x-w-+
    +
    +$ mkdir ddd
    +$ setfacl -a0 group:44:rwapd:allow ddd
    +$ setfacl -a0 group:43:write_data/delete_child:d:deny,group@:ad:allow ddd
    +$ setfacl -a0 user:42:rx:fi:allow,group:42:write_data/delete_child:d:allow ddd
    +$ setfacl -m everyone@:-w-p--a-R-c--s:fi:allow ddd
    +$ getfacl -n ddd
    +> # file: ddd
    +> # owner: root
    +> # group: wheel
    +>            user:42:r-x-----------:f-i---:allow
    +>           group:42:-w--D---------:-d----:allow
    +>           group:43:-w--D---------:-d----:deny
    +>             group@:-----da-------:------:allow
    +>           group:44:rw-p-da-------:------:allow
    +>             owner@:--------------:------:deny
    +>             owner@:rwxp---A-W-Co-:------:allow
    +>             group@:-w-p----------:------:deny
    +>             group@:r-x-----------:------:allow
    +>          everyone@:-w-p---A-W-Co-:------:deny
    +>          everyone@:-w-p--a-R-c--s:f-i---:allow
    +$ chmod 777 ddd
    +$ getfacl -n ddd
    +> # file: ddd
    +> # owner: root
    +> # group: wheel
    +>            user:42:r-x-----------:f-i---:allow
    +>           group:42:-w--D---------:-di---:allow
    +>           group:42:--------------:------:deny
    +>           group:42:-w--D---------:------:allow
    +>           group:43:-w--D---------:-di---:deny
    +>           group:43:-w--D---------:------:deny
    +>             group@:-----da-------:------:allow
    +>           group:44:--------------:------:deny
    +>           group:44:rw-p-da-------:------:allow
    +>             owner@:--------------:------:deny
    +>             owner@:-------A-W-Co-:------:allow
    +>             group@:--------------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:-------A-W-Co-:------:deny
    +>          everyone@:-w-p--a-R-c--s:f-i---:allow
    +>             owner@:--------------:------:deny
    +>             owner@:rwxp---A-W-Co-:------:allow
    +>             group@:--------------:------:deny
    +>             group@:rwxp----------:------:allow
    +>          everyone@:-------A-W-Co-:------:deny
    +>          everyone@:rwxp--a-R-c--s:------:allow
    +
    +$ rmdir ddd
    +$ mkdir ddd
    +$ setfacl -a0 group:44:rwapd:allow ddd
    +$ setfacl -a0 group:43:write_data/delete_child:d:deny,group@:ad:allow ddd
    +$ setfacl -a0 user:42:rx:fi:allow,group:42:write_data/delete_child:d:allow ddd
    +$ setfacl -m everyone@:-w-p--a-R-c--s:fi:allow ddd
    +$ chmod 124 ddd
    +$ getfacl -n ddd
    +> # file: ddd
    +> # owner: root
    +> # group: wheel
    +>            user:42:r-x-----------:f-i---:allow
    +>           group:42:-w--D---------:-di---:allow
    +>           group:42:--------------:------:deny
    +>           group:42:----D---------:------:allow
    +>           group:43:-w--D---------:-di---:deny
    +>           group:43:-w--D---------:------:deny
    +>             group@:-----da-------:------:allow
    +>           group:44:r-------------:------:deny
    +>           group:44:r----da-------:------:allow
    +>             owner@:--------------:------:deny
    +>             owner@:-------A-W-Co-:------:allow
    +>             group@:--------------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:-------A-W-Co-:------:deny
    +>          everyone@:-w-p--a-R-c--s:f-i---:allow
    +>             owner@:rw-p----------:------:deny
    +>             owner@:--x----A-W-Co-:------:allow
    +>             group@:r-x-----------:------:deny
    +>             group@:-w-p----------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +$ rmdir ddd
    +$ mkdir ddd
    +$ setfacl -a0 group:44:rwapd:allow ddd
    +$ setfacl -a0 group:43:write_data/delete_child:d:deny,group@:ad:allow ddd
    +$ setfacl -a0 user:42:rx:allow,user:42:rx:fi:allow,group:42:write_data/delete_child:d:allow ddd
    +$ setfacl -m everyone@:-w-p--a-R-c--s:fi:allow ddd
    +$ chmod 412 ddd
    +$ getfacl -n ddd
    +> # file: ddd
    +> # owner: root
    +> # group: wheel
    +>            user:42:r-------------:------:deny
    +>            user:42:r-x-----------:------:allow
    +>            user:42:r-x-----------:f-i---:allow
    +>           group:42:-w--D---------:-di---:allow
    +>           group:42:-w------------:------:deny
    +>           group:42:-w--D---------:------:allow
    +>           group:43:-w--D---------:-di---:deny
    +>           group:43:-w--D---------:------:deny
    +>             group@:-----da-------:------:allow
    +>           group:44:rw-p----------:------:deny
    +>           group:44:rw-p-da-------:------:allow
    +>             owner@:--------------:------:deny
    +>             owner@:-------A-W-Co-:------:allow
    +>             group@:--------------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:-------A-W-Co-:------:deny
    +>          everyone@:-w-p--a-R-c--s:f-i---:allow
    +>             owner@:-wxp----------:------:deny
    +>             owner@:r------A-W-Co-:------:allow
    +>             group@:rw-p----------:------:deny
    +>             group@:--x-----------:------:allow
    +>          everyone@:r-x----A-W-Co-:------:deny
    +>          everyone@:-w-p--a-R-c--s:------:allow
    +
    +$ rmdir ddd
    +$ mkdir ddd
    +$ setfacl -a0 group:44:rwapd:allow ddd
    +$ setfacl -a0 group:43:write_data/delete_child:d:deny,group@:ad:allow ddd
    +$ setfacl -a0 user:42:rx:allow,user:42:rx:fi:allow,group:42:write_data/delete_child:d:allow ddd
    +$ setfacl -m everyone@:-w-p--a-R-c--s:fi:allow ddd
    +$ chown 42 ddd
    +$ chmod 412 ddd
    +$ getfacl -n ddd
    +> # file: ddd
    +> # owner: 42
    +> # group: wheel
    +>            user:42:--x-----------:------:deny
    +>            user:42:r-x-----------:------:allow
    +>            user:42:r-x-----------:f-i---:allow
    +>           group:42:-w--D---------:-di---:allow
    +>           group:42:-w------------:------:deny
    +>           group:42:-w--D---------:------:allow
    +>           group:43:-w--D---------:-di---:deny
    +>           group:43:-w--D---------:------:deny
    +>             group@:-----da-------:------:allow
    +>           group:44:rw-p----------:------:deny
    +>           group:44:rw-p-da-------:------:allow
    +>             owner@:--------------:------:deny
    +>             owner@:-------A-W-Co-:------:allow
    +>             group@:--------------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:-------A-W-Co-:------:deny
    +>          everyone@:-w-p--a-R-c--s:f-i---:allow
    +>             owner@:-wxp----------:------:deny
    +>             owner@:r------A-W-Co-:------:allow
    +>             group@:rw-p----------:------:deny
    +>             group@:--x-----------:------:allow
    +>          everyone@:r-x----A-W-Co-:------:deny
    +>          everyone@:-w-p--a-R-c--s:------:allow
    +
    +# Test applying ACL to mode.
    +$ rmdir ddd
    +$ mkdir ddd
    +$ setfacl -a0 u:42:rwx:fi:allow ddd
    +$ ls -ld ddd | cut -d' ' -f1
    +> drwxr-xr-x+
    +
    +$ rmdir ddd
    +$ mkdir ddd
    +$ chmod 0 ddd
    +$ setfacl -a0 owner@:r:allow,group@:w:deny,group@:wx:allow ddd
    +$ ls -ld ddd | cut -d' ' -f1
    +> dr----x---+
    +
    +# XXX: This one is fishy.  Shouldn't it be "dr---wx---+"?
    +$ rmdir ddd
    +$ mkdir ddd
    +$ chmod 0 ddd
    +$ setfacl -a0 owner@:r:allow,group@:w:fi:deny,group@:wx:allow ddd
    +$ ls -ld ddd | cut -d' ' -f1
    +> dr---wx---+
    +
    +$ rmdir ddd
    +$ mkdir ddd
    +$ chmod 0 ddd
    +$ setfacl -a0 owner@:r:allow,group:43:w:deny,group:43:wx:allow ddd
    +$ ls -ld ddd | cut -d' ' -f1
    +> dr--------+
    +
    +$ rmdir ddd
    +$ mkdir ddd
    +$ chmod 0 ddd
    +$ setfacl -a0 owner@:r:allow,user:43:w:deny,user:43:wx:allow ddd
    +$ ls -ld ddd | cut -d' ' -f1
    +> dr--------+
    +
    +# Test inheritance.
    +$ rmdir ddd
    +$ mkdir ddd
    +$ setfacl -a0 group:43:write_data/write_acl:fin:deny,u:43:rwxp:allow ddd
    +$ setfacl -a0 user:42:rx:fi:allow,group:42:write_data/delete_child:dn:deny ddd
    +$ setfacl -a0 user:42:write_acl/write_owner:fi:allow ddd
    +$ setfacl -a0 group:41:read_data/read_attributes:dni:allow ddd
    +$ setfacl -a0 user:41:write_data/write_attributes:fn:allow ddd
    +$ getfacl -qn ddd
    +>            user:41:-w-----A------:f--n--:allow
    +>           group:41:r-----a-------:-din--:allow
    +>            user:42:-----------Co-:f-i---:allow
    +>            user:42:r-x-----------:f-i---:allow
    +>           group:42:-w--D---------:-d-n--:deny
    +>           group:43:-w---------C--:f-in--:deny
    +>            user:43:rwxp----------:------:allow
    +>             owner@:--------------:------:deny
    +>             owner@:rwxp---A-W-Co-:------:allow
    +>             group@:-w-p----------:------:deny
    +>             group@:r-x-----------:------:allow
    +>          everyone@:-w-p---A-W-Co-:------:deny
    +>          everyone@:r-x---a-R-c--s:------:allow
    +
    +$ cd ddd
    +$ touch xxx
    +$ getfacl -qn xxx
    +>            user:41:-w------------:------:deny
    +>            user:41:-w-----A------:------:allow
    +>            user:42:--------------:------:deny
    +>            user:42:--------------:------:allow
    +>            user:42:--x-----------:------:deny
    +>            user:42:r-x-----------:------:allow
    +>           group:43:-w---------C--:------:deny
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +$ rm xxx
    +$ umask 077
    +$ touch xxx
    +$ getfacl -qn xxx
    +>            user:41:-w------------:------:deny
    +>            user:41:-w-----A------:------:allow
    +>            user:42:--------------:------:deny
    +>            user:42:--------------:------:allow
    +>            user:42:r-x-----------:------:deny
    +>            user:42:r-x-----------:------:allow
    +>           group:43:-w---------C--:------:deny
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:rwxp----------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:rwxp---A-W-Co-:------:deny
    +>          everyone@:------a-R-c--s:------:allow
    +
    +$ rm xxx
    +$ umask 770
    +$ touch xxx
    +$ getfacl -qn xxx
    +>            user:41:-w------------:------:deny
    +>            user:41:-w-----A------:------:allow
    +>            user:42:--------------:------:deny
    +>            user:42:--------------:------:allow
    +>            user:42:r-x-----------:------:deny
    +>            user:42:r-x-----------:------:allow
    +>           group:43:-w---------C--:------:deny
    +>             owner@:rwxp----------:------:deny
    +>             owner@:-------A-W-Co-:------:allow
    +>             group@:rwxp----------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:--x----A-W-Co-:------:deny
    +>          everyone@:rw-p--a-R-c--s:------:allow
    +
    +$ rm xxx
    +$ umask 707
    +$ touch xxx
    +$ getfacl -qn xxx
    +>            user:41:--------------:------:deny
    +>            user:41:-w-----A------:------:allow
    +>            user:42:--------------:------:deny
    +>            user:42:--------------:------:allow
    +>            user:42:--x-----------:------:deny
    +>            user:42:r-x-----------:------:allow
    +>           group:43:-w---------C--:------:deny
    +>             owner@:rwxp----------:------:deny
    +>             owner@:-------A-W-Co-:------:allow
    +>             group@:--x-----------:------:deny
    +>             group@:rw-p----------:------:allow
    +>          everyone@:rwxp---A-W-Co-:------:deny
    +>          everyone@:------a-R-c--s:------:allow
    +
    +$ umask 077
    +$ mkdir yyy
    +$ getfacl -qn yyy
    +>           group:41:r-------------:------:deny
    +>           group:41:r-----a-------:------:allow
    +>            user:42:-----------Co-:f-i---:allow
    +>            user:42:r-x-----------:f-i---:allow
    +>           group:42:-w--D---------:------:deny
    +>             owner@:--------------:------:deny
    +>             owner@:rwxp---A-W-Co-:------:allow
    +>             group@:rwxp----------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:rwxp---A-W-Co-:------:deny
    +>          everyone@:------a-R-c--s:------:allow
    +
    +$ rmdir yyy
    +$ umask 770
    +$ mkdir yyy
    +$ getfacl -qn yyy
    +>           group:41:r-------------:------:deny
    +>           group:41:r-----a-------:------:allow
    +>            user:42:-----------Co-:f-i---:allow
    +>            user:42:r-x-----------:f-i---:allow
    +>           group:42:-w--D---------:------:deny
    +>             owner@:rwxp----------:------:deny
    +>             owner@:-------A-W-Co-:------:allow
    +>             group@:rwxp----------:------:deny
    +>             group@:--------------:------:allow
    +>          everyone@:-------A-W-Co-:------:deny
    +>          everyone@:rwxp--a-R-c--s:------:allow
    +
    +$ rmdir yyy
    +$ umask 707
    +$ mkdir yyy
    +$ getfacl -qn yyy
    +>           group:41:--------------:------:deny
    +>           group:41:------a-------:------:allow
    +>            user:42:-----------Co-:f-i---:allow
    +>            user:42:r-x-----------:f-i---:allow
    +>           group:42:-w--D---------:------:deny
    +>             owner@:rwxp----------:------:deny
    +>             owner@:-------A-W-Co-:------:allow
    +>             group@:--------------:------:deny
    +>             group@:rwxp----------:------:allow
    +>          everyone@:rwxp---A-W-Co-:------:deny
    +>          everyone@:------a-R-c--s:------:allow
    +
    +# There is some complication regarding how write_acl and write_owner flags
    +# get inherited.  Make sure we got it right.
    +$ setfacl -b .
    +$ setfacl -a0 u:42:Co:f:allow .
    +$ setfacl -a0 u:43:Co:d:allow .
    +$ setfacl -a0 u:44:Co:fd:allow .
    +$ setfacl -a0 u:45:Co:fi:allow .
    +$ setfacl -a0 u:46:Co:di:allow .
    +$ setfacl -a0 u:47:Co:fdi:allow .
    +$ setfacl -a0 u:48:Co:fn:allow .
    +$ setfacl -a0 u:49:Co:dn:allow .
    +$ setfacl -a0 u:50:Co:fdn:allow .
    +$ setfacl -a0 u:51:Co:fni:allow .
    +$ setfacl -a0 u:52:Co:dni:allow .
    +$ setfacl -a0 u:53:Co:fdni:allow .
    +$ umask 022
    +$ rm xxx
    +$ touch xxx
    +$ getfacl -nq xxx
    +>            user:53:--------------:------:deny
    +>            user:53:--------------:------:allow
    +>            user:51:--------------:------:deny
    +>            user:51:--------------:------:allow
    +>            user:50:--------------:------:deny
    +>            user:50:--------------:------:allow
    +>            user:48:--------------:------:deny
    +>            user:48:--------------:------:allow
    +>            user:47:--------------:------:deny
    +>            user:47:--------------:------:allow
    +>            user:45:--------------:------:deny
    +>            user:45:--------------:------:allow
    +>            user:44:--------------:------:deny
    +>            user:44:--------------:------:allow
    +>            user:42:--------------:------:deny
    +>            user:42:--------------:------:allow
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +$ rmdir yyy
    +$ mkdir yyy
    +$ getfacl -nq yyy
    +>            user:53:--------------:------:deny
    +>            user:53:--------------:------:allow
    +>            user:52:--------------:------:deny
    +>            user:52:--------------:------:allow
    +>            user:50:--------------:------:deny
    +>            user:50:--------------:------:allow
    +>            user:49:--------------:------:deny
    +>            user:49:--------------:------:allow
    +>            user:47:-----------Co-:fdi---:allow
    +>            user:47:--------------:------:deny
    +>            user:47:--------------:------:allow
    +>            user:46:-----------Co-:-di---:allow
    +>            user:46:--------------:------:deny
    +>            user:46:--------------:------:allow
    +>            user:45:-----------Co-:f-i---:allow
    +>            user:44:-----------Co-:fdi---:allow
    +>            user:44:--------------:------:deny
    +>            user:44:--------------:------:allow
    +>            user:43:-----------Co-:-di---:allow
    +>            user:43:--------------:------:deny
    +>            user:43:--------------:------:allow
    +>            user:42:-----------Co-:f-i---:allow
    +>             owner@:--------------:------:deny
    +>             owner@:rwxp---A-W-Co-:------:allow
    +>             group@:-w-p----------:------:deny
    +>             group@:r-x-----------:------:allow
    +>          everyone@:-w-p---A-W-Co-:------:deny
    +>          everyone@:r-x---a-R-c--s:------:allow
    +
    +$ setfacl -b .
    +$ setfacl -a0 u:42:Co:f:deny .
    +$ setfacl -a0 u:43:Co:d:deny .
    +$ setfacl -a0 u:44:Co:fd:deny .
    +$ setfacl -a0 u:45:Co:fi:deny .
    +$ setfacl -a0 u:46:Co:di:deny .
    +$ setfacl -a0 u:47:Co:fdi:deny .
    +$ setfacl -a0 u:48:Co:fn:deny .
    +$ setfacl -a0 u:49:Co:dn:deny .
    +$ setfacl -a0 u:50:Co:fdn:deny .
    +$ setfacl -a0 u:51:Co:fni:deny .
    +$ setfacl -a0 u:52:Co:dni:deny .
    +$ setfacl -a0 u:53:Co:fdni:deny .
    +$ umask 022
    +$ rm xxx
    +$ touch xxx
    +$ getfacl -nq xxx
    +>            user:53:-----------Co-:------:deny
    +>            user:51:-----------Co-:------:deny
    +>            user:50:-----------Co-:------:deny
    +>            user:48:-----------Co-:------:deny
    +>            user:47:-----------Co-:------:deny
    +>            user:45:-----------Co-:------:deny
    +>            user:44:-----------Co-:------:deny
    +>            user:42:-----------Co-:------:deny
    +>             owner@:--x-----------:------:deny
    +>             owner@:rw-p---A-W-Co-:------:allow
    +>             group@:-wxp----------:------:deny
    +>             group@:r-------------:------:allow
    +>          everyone@:-wxp---A-W-Co-:------:deny
    +>          everyone@:r-----a-R-c--s:------:allow
    +
    +$ rmdir yyy
    +$ mkdir yyy
    +$ getfacl -nq yyy
    +>            user:53:-----------Co-:------:deny
    +>            user:52:-----------Co-:------:deny
    +>            user:50:-----------Co-:------:deny
    +>            user:49:-----------Co-:------:deny
    +>            user:47:-----------Co-:fdi---:deny
    +>            user:47:-----------Co-:------:deny
    +>            user:46:-----------Co-:-di---:deny
    +>            user:46:-----------Co-:------:deny
    +>            user:45:-----------Co-:f-i---:deny
    +>            user:44:-----------Co-:fdi---:deny
    +>            user:44:-----------Co-:------:deny
    +>            user:43:-----------Co-:-di---:deny
    +>            user:43:-----------Co-:------:deny
    +>            user:42:-----------Co-:f-i---:deny
    +>             owner@:--------------:------:deny
    +>             owner@:rwxp---A-W-Co-:------:allow
    +>             group@:-w-p----------:------:deny
    +>             group@:r-x-----------:------:allow
    +>          everyone@:-w-p---A-W-Co-:------:deny
    +>          everyone@:r-x---a-R-c--s:------:allow
    +
    +$ rmdir yyy
    +$ rm xxx
    +$ cd ..
    +$ rmdir ddd
    +
    +$ rm xxx
    +
    diff --git a/tools/regression/acltools/tools-posix.test b/tools/regression/acltools/tools-posix.test
    index 6ae31f36edd..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
    @@ -98,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
    @@ -117,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
    @@ -132,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
    @@ -144,7 +193,7 @@ $ getfacl xxx
     
     # Test setfacl -b.
     $ setfacl -b xxx
    -$ getfacl xxx
    +$ getfacl -n xxx
     > # file: xxx
     > # owner: root
     > # group: wheel
    @@ -157,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
    @@ -177,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
    @@ -185,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--
    @@ -209,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
    @@ -218,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
    @@ -232,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
    @@ -244,7 +293,7 @@ $ getfacl xxx
     > other::---
     
     $ chmod 060 xxx
    -$ getfacl xxx
    +$ getfacl -n xxx
     > # file: xxx
     > # owner: root
     > # group: wheel
    @@ -258,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
    @@ -268,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
    @@ -280,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-
    @@ -289,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-
    @@ -389,7 +438,7 @@ $ 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: acl_get_file() failed: Operation not supported
    +> setfacl: bbb: acl_get_file() failed: Operation not supported
     $ ls -l bbb | cut -d' ' -f1
     > brw-r--r--
     
    @@ -397,7 +446,7 @@ $ rm bbb
     
     $ mknod ccc c 1 1
     $ setfacl -m u:42:r,g:43:w ccc
    -> setfacl: acl_get_file() failed: Operation not supported
    +> setfacl: ccc: acl_get_file() failed: Operation not supported
     $ ls -l ccc | cut -d' ' -f1
     > crw-r--r--
     
    
    From 900b1670c419d23105d808e9af69b699c3660fa0 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 7 Sep 2009 16:56:41 +0000
    Subject: [PATCH 420/453] Prevent the line from wrapping.
    
    ---
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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 1d00782aded..64fded4712e 100644
    --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
    +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
    @@ -3567,7 +3567,7 @@ arc_init(void)
     	if ((((uint64_t)physmem * PAGESIZE) < (1ULL << 32)) &&
     	    prefetch_tunable_set == 0) {
     		printf("ZFS NOTICE: Prefetch is disabled by default if less "
    -		    "than 4 GB of RAM is present;\n"
    +		    "than 4GB of RAM is present;\n"
     		    "            to enable, add \"vfs.zfs.prefetch_disable=0\" "
     		    "to /boot/loader.conf.\n");
     		zfs_prefetch_disable=1;
    
    From 44a37a783b8ff7614eca910385afcda5c17813c5 Mon Sep 17 00:00:00 2001
    From: Ken Smith 
    Date: Mon, 7 Sep 2009 17:54:20 +0000
    Subject: [PATCH 421/453] Bring the layout of package-split.py more in line
     with where we're going with packages on the release media.  It looks like
     we'll be putting just the doc packages on the new "memory stick" image as
     well as disc1.  There will be no other packages on the CDROM-sized media. 
     The DVD sized media will include the doc packages plus whatever other
     packages we decide to make part of the release.
    
    This commit just brings the basic structure in line with being able to
    do this.  We still need to discuss with various people exactly which
    packages will be included on the DVD.
    
    If the environement variable "PKG_DVD" is set a tree suitable for the
    DVD media is generated.  Otherwise a tree suitable for the "memory stick"
    and disc1 is generated.
    
    MFC after:	3 days
    ---
     release/scripts/package-split.py | 121 ++++++++++++++-----------------
     1 file changed, 54 insertions(+), 67 deletions(-)
    
    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
    
    From 2ff6f0f89a77cafe05b384816bda5aac5714f4f0 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 18:23:26 +0000
    Subject: [PATCH 422/453] - Avoid holding mutex around M_WAITOK allocations. -
     Add locking for mnt_opt field.
    
    MFC after:	1 week
    ---
     .../compat/opensolaris/kern/opensolaris_vfs.c | 32 +++++++++++++++----
     1 file changed, 26 insertions(+), 6 deletions(-)
    
    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
    
    From c739b7b22b127c5fd35f5dc7e24a3b3524070d18 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 18:54:55 +0000
    Subject: [PATCH 423/453] Don't recheck ownership on update mount. This will
     eliminate LOR between vfs_busy() and mount mutex. We check ownership in
     vfs_domount() anyway.
    
    Noticed by:	kib
    Reviewed by:	kib
    MFC after:	1 week
    ---
     .../opensolaris/uts/common/fs/zfs/zfs_vfsops.c        | 11 ++++++-----
     1 file changed, 6 insertions(+), 5 deletions(-)
    
    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 8fc747c21eb..27e9c810d6e 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
    @@ -719,7 +719,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;
     
     			/*
    @@ -753,11 +756,9 @@ zfs_mount(vfs_t *vfsp)
     			}
     			VOP_UNLOCK(mvp, 0);
     #endif
    -
    -			secpolicy_fs_mount_clearopts(cr, vfsp);
    -		} else {
    -			goto out;
     		}
    +
    +		secpolicy_fs_mount_clearopts(cr, vfsp);
     	}
     
     	/*
    
    From 08780916dd92cf119ffc5eaa2564a9e115bfb313 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 19:22:44 +0000
    Subject: [PATCH 424/453] Defer thread start until we set priority.
    
    Reviewed by:	kib
    MFC after:	3 days
    ---
     sys/cddl/compat/opensolaris/sys/proc.h | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/sys/cddl/compat/opensolaris/sys/proc.h b/sys/cddl/compat/opensolaris/sys/proc.h
    index 52ef867d49e..e0b7bc5758e 100644
    --- a/sys/cddl/compat/opensolaris/sys/proc.h
    +++ b/sys/cddl/compat/opensolaris/sys/proc.h
    @@ -37,6 +37,7 @@
     #include 
     #include 
     #include 
    +#include 
     #include 
     
     #ifdef _KERNEL
    @@ -74,11 +75,12 @@ thread_create(caddr_t stk, size_t stksize, void (*proc)(void *), void *arg,
     	ASSERT(state == TS_RUN);
     	ASSERT(pp == &p0);
     
    -	error = kproc_kthread_add(proc, arg, &zfsproc, &td, 0,
    +	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);
    
    From 6839605389c1afe1229ce20c0077d61d2206945b Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 7 Sep 2009 19:40:22 +0000
    Subject: [PATCH 425/453] Add regression tests for NFSv4 ACL granular
     permission enforcement.
    
    ---
     tools/regression/fstest/Makefile            |   2 +-
     tools/regression/fstest/fstest.c            |  62 ++++++++-
     tools/regression/fstest/tests/chmod/12.t    |  32 +++++
     tools/regression/fstest/tests/granular/00.t | 110 +++++++++++++++
     tools/regression/fstest/tests/granular/01.t |  35 +++++
     tools/regression/fstest/tests/granular/02.t | 142 +++++++++++++++++++
     tools/regression/fstest/tests/granular/03.t | 132 ++++++++++++++++++
     tools/regression/fstest/tests/granular/04.t |  78 +++++++++++
     tools/regression/fstest/tests/granular/05.t | 147 ++++++++++++++++++++
     9 files changed, 738 insertions(+), 2 deletions(-)
     create mode 100644 tools/regression/fstest/tests/chmod/12.t
     create mode 100644 tools/regression/fstest/tests/granular/00.t
     create mode 100644 tools/regression/fstest/tests/granular/01.t
     create mode 100644 tools/regression/fstest/tests/granular/02.t
     create mode 100644 tools/regression/fstest/tests/granular/03.t
     create mode 100644 tools/regression/fstest/tests/granular/04.t
     create mode 100644 tools/regression/fstest/tests/granular/05.t
    
    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/chmod/12.t b/tools/regression/fstest/tests/chmod/12.t
    new file mode 100644
    index 00000000000..db8c9b8184b
    --- /dev/null
    +++ b/tools/regression/fstest/tests/chmod/12.t
    @@ -0,0 +1,32 @@
    +#!/bin/sh
    +# $FreeBSD$
    +
    +desc="verify SUID/SGID bit behaviour"
    +
    +dir=`dirname $0`
    +. ${dir}/../misc.sh
    +
    +echo "1..10"
    +
    +n0=`namegen`
    +n1=`namegen`
    +n2=`namegen`
    +
    +expect 0 mkdir ${n2} 0755
    +cdir=`pwd`
    +cd ${n2}
    +
    +# Check whether writing to the file by non-owner clears the SUID.
    +expect 0 create ${n0} 04777
    +expect 0 -u 65534 -g 65534 write ${n0}
    +expect 0777 stat ${n0} mode
    +expect 0 unlink ${n0}
    +
    +# Check whether writing to the file by non-owner clears the SGID.
    +expect 0 create ${n0} 02777
    +expect 0 -u 65534 -g 65534 write ${n0}
    +expect 0777 stat ${n0} mode
    +expect 0 unlink ${n0}
    +
    +cd ${cdir}
    +expect 0 rmdir ${n2}
    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}
    
    From 343775c0b4cbe410a0575ad5af7a340d81d07902 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 7 Sep 2009 19:43:13 +0000
    Subject: [PATCH 426/453] Enable NFSv4 ACL support in ZFS.
    
    Reviewed by:	pjd
    ---
     .../opensolaris/uts/common/fs/zfs/zfs_vnops.c | 37 ++++++++++++++++---
     1 file changed, 31 insertions(+), 6 deletions(-)
    
    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 de7c2930eba..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
    @@ -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:
    @@ -4425,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:
    @@ -4854,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.
    @@ -4928,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 = {
    @@ -4945,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
     };
    
    From 5d1b2674f83863d5f7f379fc4fc16f6090c34293 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 20:10:33 +0000
    Subject: [PATCH 427/453] Fix detection of file system being shared. After this
     change commands like:
    
    	# zfs unshare -a
    	# zfs destroy foo/bar
    	# zfs rename foo/bar foo/baz
    
    should properly remove exported file systems.
    
    MFC after:	3 days
    ---
     cddl/contrib/opensolaris/lib/libzfs/common/libzfs_mount.c | 5 +++++
     1 file changed, 5 insertions(+)
    
    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
     		}
     	}
     
    
    From 3110a4eb9c8a7ec48c739c0243a050b74ba91ab7 Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Mon, 7 Sep 2009 20:57:01 +0000
    Subject: [PATCH 428/453] Some of the controllers sold as ServeRAID (IBM 
     ServeRAID-MR10i, in particular) are actually mfi(4) devices.  Provide hints.
    
    Submitted by:	
    ---
     share/man/man4/ips.4 | 5 ++++-
     1 file changed, 4 insertions(+), 1 deletion(-)
    
    diff --git a/share/man/man4/ips.4 b/share/man/man4/ips.4
    index 49fb71909dc..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
    @@ -95,6 +95,8 @@ ServeRAID 7t/7k/7M
     .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
    @@ -185,6 +187,7 @@ driver does not use the
     subsystem.
     .Sh SEE ALSO
     .Xr aac 4 ,
    +.Xr mfi 4 ,
     .Xr ch 4 ,
     .Xr da 4 ,
     .Xr sysctl 8
    
    From 3f6043a57d48dbb6312bf1418ab5dbe94c39b4f3 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 21:46:51 +0000
    Subject: [PATCH 429/453] When snapshot mount point is busy (for example we are
     still in it) we will fail to unmount it, but it won't be removed from the
     tree, so in that case there is no need to reinsert it.
    
    This fixes a panic reproducable in the following steps:
    
    	# zfs create tank/foo
    	# zfs snapshot tank/foo@snap
    	# cd /tank/foo/.zfs/snapshot/snap
    	# umount /tank/foo
    	panic: avl_find() succeeded inside avl_add()
    
    Reported by:	trasz
    MFC after:	3 days
    ---
     .../contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c | 10 +++++++++-
     1 file changed, 9 insertions(+), 1 deletion(-)
    
    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 cf99d68e8bb..7430c83f27b 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
    @@ -1344,7 +1344,15 @@ 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);
    +				/*
    +				 * 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, NULL) == NULL)
    +					avl_add(&sdp->sd_snaps, sep);
     				break;
     			}
     		}
    
    From 28e449adf2cc2194c708d9c1f426d6c2872b4670 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Mon, 7 Sep 2009 21:58:54 +0000
    Subject: [PATCH 430/453] If we have to use avl_find(), optimize a bit and use
     avl_insert() instead of avl_add() (the latter is actually a wrapper around
     avl_find() + avl_insert()).
    
    Fix similar case in the code that is currently commented out.
    ---
     .../opensolaris/uts/common/fs/zfs/zfs_ctldir.c    | 15 ++++++++++-----
     1 file changed, 10 insertions(+), 5 deletions(-)
    
    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 7430c83f27b..72db1f065ff 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;
    @@ -1344,6 +1347,8 @@ 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_index_t where;
    +
     				/*
     				 * Before reinserting snapshot to the tree,
     				 * check if it was actually removed. For example
    @@ -1351,8 +1356,8 @@ zfsctl_umount_snapshots(vfs_t *vfsp, int fflags, cred_t *cr)
     				 * have an error here, but there will be no need
     				 * to reinsert snapshot.
     				 */
    -				if (avl_find(&sdp->sd_snaps, sep, NULL) == NULL)
    -					avl_add(&sdp->sd_snaps, sep);
    +				if (avl_find(&sdp->sd_snaps, sep, &where) == NULL)
    +					avl_insert(&sdp->sd_snaps, sep, where);
     				break;
     			}
     		}
    
    From b0d0537558baf6f1cdbd9d2f89c06211cbd0f068 Mon Sep 17 00:00:00 2001
    From: Sean Bruno 
    Date: Mon, 7 Sep 2009 23:16:27 +0000
    Subject: [PATCH 431/453] A few enhancements I made while working on the
     Firewire target (sbp_targ).
    
    Update the error handling in a couple of cases to exit gracefully if
    certain mandatory conditions aren't met.
    
    Reduce the maximum number of initiators to 8 for this example code.  While
    1024 is more correct, this example code would act like it was stalled out
    even though it was merely allocating the needed structures in init_ccbs()
    
    Reviewed by:	scottl@freebsd.org
    ---
     share/examples/scsi_target/scsi_target.c | 8 ++++++--
     share/examples/scsi_target/scsi_target.h | 2 +-
     2 files changed, 7 insertions(+), 3 deletions(-)
    
    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 */
    
    From 277dbce981351586cb317d4dbf2635927056d51f Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Tue, 8 Sep 2009 01:11:23 +0000
    Subject: [PATCH 432/453] Constify format string pointer, otherwise this would
     trigger warning when higher warning level is enabled.
    
    ---
     usr.bin/w/pr_time.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/usr.bin/w/pr_time.c b/usr.bin/w/pr_time.c
    index 4576b5eb042..acf6f8c987b 100644
    --- a/usr.bin/w/pr_time.c
    +++ b/usr.bin/w/pr_time.c
    @@ -58,7 +58,7 @@ pr_attime(time_t *started, time_t *now)
     	static wchar_t buf[256];
     	struct tm tp, tm;
     	time_t diff;
    -	wchar_t *fmt;
    +	const wchar_t *fmt;
     	int len, width, offset = 0;
     
     	tp = *localtime(started);
    
    From 26baaf01698f09bd5d5122376dcea458c83b3a04 Mon Sep 17 00:00:00 2001
    From: Tim Kientzle 
    Date: Tue, 8 Sep 2009 04:52:12 +0000
    Subject: [PATCH 433/453] Update tests to match r195873, which corrected how
     hardlinked files on iso9660 images were returned.  While I'm poking around,
     update some comments around this area to try to clarify what's going on and
     what still remains to be improved.
    
    ---
     .../archive_read_support_format_iso9660.c     | 29 +++++++++++++++----
     .../test/test_read_format_isojoliet_bz2.c     | 27 ++++++++++-------
     .../test/test_read_format_isorr_bz2.c         |  2 +-
     3 files changed, 40 insertions(+), 18 deletions(-)
    
    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_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);
    
    From 466017cf767efdfde89f9dfc0d177aeca0644c1d Mon Sep 17 00:00:00 2001
    From: Tim Kientzle 
    Date: Tue, 8 Sep 2009 05:02:41 +0000
    Subject: [PATCH 434/453] Fiz /usr/bin/unzip: A bug deep in libarchive's
     read-ahead logic (incorrect handling of zero-length reads before the copy
     buffer is allocated) is masked by the iso9660 taster.  Tar and cpio both
     enable that taster so were protected from the bug; unzip is susceptible.
    
    This both fixes the bug and updates the test harness to exercise
    this case.
    
    Submitted by: Ed Schouten diagnosed the bug and drafted a patch
    MFC after: 7 days
    ---
     lib/libarchive/archive_read.c         | 7 +++++--
     lib/libarchive/test/test_compat_zip.c | 2 +-
     2 files changed, 6 insertions(+), 3 deletions(-)
    
    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/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));
     
    
    From 18e42503ed3c8490164158171cd865e274c1c2b4 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Tue, 8 Sep 2009 05:46:38 +0000
    Subject: [PATCH 435/453] Do not check proper request alignment here in
     geom_dev in production. It will be checked any way later by g_io_check() in
     g_io_schedule_down(). It is only needed here to not trigger panic from
     additional check, when INVARIANTS enabled. So cover it with #ifdef
     INVARIANTS. It saves two 64bit divisions per request.
    
    ---
     sys/geom/geom_dev.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    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
    
    From 1ea356629466af5a54d585f499176396ef9b3c4a Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Tue, 8 Sep 2009 08:54:15 +0000
    Subject: [PATCH 436/453] Fix reference count leak for a case where snapshot's
     mount point is updated. Such situation is not supported.
    
    This problem was triggered by something like this:
    
    	# zpool create tank da0
    	# zfs snapshot tank@snap
    	# cd /tank/.zfs/snapshot/snap  (this will mount the snapshot)
    	# cd
    	# mount -u nosuid /tank/.zfs/snapshot/snap  (refcount leak)
    	# zpool export tank
    	cannot export 'tank': pool is busy
    
    MFC after:	1 week
    ---
     .../contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c     | 7 +++++++
     1 file changed, 7 insertions(+)
    
    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 27e9c810d6e..f5295aa9ebb 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
    @@ -336,6 +336,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
    
    From 211ddddce71b632a20ad5c822a3d48cdc9d67f0d Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Tue, 8 Sep 2009 09:17:34 +0000
    Subject: [PATCH 437/453] Lock Giant around vn_open_cred(). Remove innocent
     unnecessary call to NDFREE().
    
    Reported by:	marcel
    Reviewed and tested by:	pjd
    MFC after:	3 days
    ---
     sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c | 6 ++++--
     1 file changed, 4 insertions(+), 2 deletions(-)
    
    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);
     }
     
    
    From 2ac047d1fe1e62bf1caafc488b023476d72c7fc8 Mon Sep 17 00:00:00 2001
    From: Poul-Henning Kamp 
    Date: Tue, 8 Sep 2009 10:39:38 +0000
    Subject: [PATCH 438/453] Move the duplicate definition of struct
     sockaddr_storage to its own include file, and include this where the previous
     duplicate definitions were.
    
    Static program checkers like FlexeLint rightfully take a dim view of
    duplicate definitions, even if they currently are identical.
    ---
     sys/netinet/in.h            | 22 +--------------
     sys/sys/_sockaddr_storage.h | 54 +++++++++++++++++++++++++++++++++++++
     sys/sys/socket.h            | 21 +--------------
     3 files changed, 56 insertions(+), 41 deletions(-)
     create mode 100644 sys/sys/_sockaddr_storage.h
    
    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/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/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
     /*
    
    From a330ed7cd1527e7ec6ba9dd932510ab5c650e610 Mon Sep 17 00:00:00 2001
    From: Poul-Henning Kamp 
    Date: Tue, 8 Sep 2009 12:59:56 +0000
    Subject: [PATCH 439/453] Move multi-include protection back up to the top of
     the file and name after the physical file rather than the aliased name.
    
    ---
     sys/amd64/include/param.h | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    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_ */
    
    From b34421bf9cab5d0ad5822abfaa62febedef2d9a1 Mon Sep 17 00:00:00 2001
    From: Poul-Henning Kamp 
    Date: Tue, 8 Sep 2009 13:16:55 +0000
    Subject: [PATCH 440/453] Add necessary include.
    
    ---
     sys/cam/scsi/scsi_cd.c                    |    2 +-
     sys/contrib/dev/acpica/executer/exfldio.c |    1 +
     sys/dev/aac/aac.c                         |    2 +-
     sys/dev/ae/if_ae.c                        |    2 +
     sys/dev/amr/amr.c                         |    2 +-
     sys/dev/ata/ata-raid.c                    |    3 +-
     sys/dev/ata/chipsets/ata-acerlabs.c       |    1 +
     sys/dev/ata/chipsets/ata-marvell.c        |    2 +-
     sys/dev/ath/ah_osdep.c                    |    1 +
     sys/dev/ath/ath_hal/ah.c                  |    1 +
     sys/dev/ath/ath_hal/ah_eeprom_v3.c        |    2 +
     sys/dev/bce/if_bce.c                      |    8 +-
     sys/dev/e1000/if_em.c                     |    2 +-
     sys/dev/ep/if_ep.c                        |    1 +
     sys/dev/ep/if_epreg.h                     |    6 +-
     sys/dev/firewire/fwcrom.c                 |    4 +-
     sys/dev/firewire/fwdev.c                  |    1 +
     sys/dev/fxp/if_fxp.c                      |    1 +
     sys/dev/hptiop/hptiop.c                   |    2 +
     sys/dev/iir/iir.c                         |    1 +
     sys/dev/mpt/mpt_raid.c                    |    1 +
     sys/dev/msk/if_msk.c                      |    5 -
     sys/dev/usb/wlan/if_rum.c                 |    5 +-
     sys/dev/usb/wlan/if_rumreg.h              |    2 +-
     sys/dev/usb/wlan/if_urtw.c                | 2681 +++++++++++----------
     sys/dev/wi/if_wi.c                        |    1 +
     sys/fs/msdosfs/msdosfs_conv.c             |    1 +
     sys/kern/kern_jail.c                      |    1 +
     sys/kern/kern_linker.c                    |    1 +
     sys/kern/kern_lock.c                      |    1 +
     sys/kern/kern_mutex.c                     |   11 +-
     sys/net80211/ieee80211_action.c           |    2 +-
     sys/net80211/ieee80211_proto.h            |    2 +-
     sys/security/audit/audit_bsm_token.c      |    1 +
     34 files changed, 1395 insertions(+), 1365 deletions(-)
    
    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/contrib/dev/acpica/executer/exfldio.c b/sys/contrib/dev/acpica/executer/exfldio.c
    index f59dd6214c3..1b819c0d206 100644
    --- a/sys/contrib/dev/acpica/executer/exfldio.c
    +++ b/sys/contrib/dev/acpica/executer/exfldio.c
    @@ -992,6 +992,7 @@ AcpiExInsertIntoField (
     
         /* Get initial Datum from the input buffer */
     
    +    /* XXX: Flexelint sees arg 9 for bufferlen 8 */
         ACPI_MEMCPY (&RawDatum, Buffer,
             ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
                 BufferLength - BufferOffset));
    diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
    index f3d931aaf06..5c3180b8395 100644
    --- a/sys/dev/aac/aac.c
    +++ b/sys/dev/aac/aac.c
    @@ -3556,7 +3556,7 @@ aac_supported_features(struct aac_softc *sc, caddr_t uptr)
     	 * associated with the feature in the data field or perform whatever
     	 * action needed indicates in the data field.
     	 */
    -	 if (f.feat.fValue == 0) {
    +	if (f.feat.fValue == 0) {
     		f.feat.fBits.largeLBA =
     		    (sc->flags & AAC_FLAGS_LBA_64BIT) ? 1 : 0;
     		/* TODO: In the future, add other features state here as well */
    diff --git a/sys/dev/ae/if_ae.c b/sys/dev/ae/if_ae.c
    index da26ee79951..a5837c346f3 100644
    --- a/sys/dev/ae/if_ae.c
    +++ b/sys/dev/ae/if_ae.c
    @@ -1662,6 +1662,7 @@ ae_stop_rxmac(ae_softc_t *sc)
     	/*
     	 * Wait for IDLE state.
     	 */
    +	/* XXX: Flexelint  "<" test with -- */
     	for (i = 0; i < AE_IDLE_TIMEOUT; i--) {
     		val = AE_READ_4(sc, AE_IDLE_REG);
     		if ((val & (AE_IDLE_RXMAC | AE_IDLE_DMAWRITE)) == 0)
    @@ -1698,6 +1699,7 @@ ae_stop_txmac(ae_softc_t *sc)
     	/*
     	 * Wait for IDLE state.
     	 */
    +	/* XXX: Flexelint  "<" test with -- */
     	for (i = 0; i < AE_IDLE_TIMEOUT; i--) {
     		val = AE_READ_4(sc, AE_IDLE_REG);
     		if ((val & (AE_IDLE_TXMAC | AE_IDLE_DMAREAD)) == 0)
    diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
    index 2061fcc801f..463ec532879 100644
    --- a/sys/dev/amr/amr.c
    +++ b/sys/dev/amr/amr.c
    @@ -527,7 +527,7 @@ amr_rescan_drives(struct cdev *dev)
     		sc->amr_drive[i].al_disk)) != 0)
     		goto shutdown_out;
     
    -	     sc->amr_drive[i].al_disk = 0;
    +	    sc->amr_drive[i].al_disk = 0;
     	}
         }
     
    diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
    index fc6a23c0461..d31bcebf4e5 100644
    --- a/sys/dev/ata/ata-raid.c
    +++ b/sys/dev/ata/ata-raid.c
    @@ -407,7 +407,7 @@ ata_raid_strategy(struct bio *bp)
     	    if (rdp->status & AR_S_REBUILDING)
     		blk = ((lba / rdp->interleave) * rdp->width) * rdp->interleave +
     		      (rdp->interleave * (drv % rdp->width)) +
    -		      lba % rdp->interleave;;
    +		      lba % rdp->interleave;
     
     	    if (bp->bio_cmd == BIO_READ) {
     		int src_online =
    @@ -1138,6 +1138,7 @@ ata_raid_create(struct ata_ioc_raid_config *config)
     	rdp->type == AR_T_RAID5) {
     	int bit = 0;
     
    +	/* XXX: Flexelint not happy */
     	while (config->interleave >>= 1)
     	    bit++;
     	rdp->interleave = 1 << bit;
    diff --git a/sys/dev/ata/chipsets/ata-acerlabs.c b/sys/dev/ata/chipsets/ata-acerlabs.c
    index cf503c591b2..9d19fa0382c 100644
    --- a/sys/dev/ata/chipsets/ata-acerlabs.c
    +++ b/sys/dev/ata/chipsets/ata-acerlabs.c
    @@ -127,6 +127,7 @@ ata_ali_chipinit(device_t dev)
     		    RF_ACTIVE);
     		if (res->bars[i] == NULL) {
     			device_printf(dev, "Failed to allocate BAR %d\n", i);
    +			/* XXX: Flexelint: Reuse of for loop variable 'i' at 'line 124' could cause chaos */
     			for (i--; i >=0; i--)
     				bus_release_resource(dev, SYS_RES_IOPORT,
     				    PCIR_BAR(i), res->bars[i]);
    diff --git a/sys/dev/ata/chipsets/ata-marvell.c b/sys/dev/ata/chipsets/ata-marvell.c
    index 0544e199ed0..bab3267972b 100644
    --- a/sys/dev/ata/chipsets/ata-marvell.c
    +++ b/sys/dev/ata/chipsets/ata-marvell.c
    @@ -153,7 +153,7 @@ ata_marvell_pata_ch_attach(device_t dev)
     	return ENXIO;
      
         /* dont use 32 bit PIO transfers */
    -	ch->flags |= ATA_USE_16BIT;
    +    ch->flags |= ATA_USE_16BIT;
     
         return 0;
     }
    diff --git a/sys/dev/ath/ah_osdep.c b/sys/dev/ath/ah_osdep.c
    index 6b11b212fea..c37ef142659 100644
    --- a/sys/dev/ath/ah_osdep.c
    +++ b/sys/dev/ath/ah_osdep.c
    @@ -107,6 +107,7 @@ ath_hal_malloc(size_t size)
     	return malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO);
     }
     
    +/* XXX: FlexeLint return in void function ? */
     void
     ath_hal_free(void* p)
     {
    diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c
    index cff9613616a..db47dd24425 100644
    --- a/sys/dev/ath/ath_hal/ah.c
    +++ b/sys/dev/ath/ath_hal/ah.c
    @@ -566,6 +566,7 @@ ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
     	uint32_t *dp = dstbuf;
     	int i;
     
    +	/* XXX: FlexeLint: ">" test with ++ */
     	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
     		u_int r = regs[i].start;
     		u_int e = regs[i].end;
    diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v3.c b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
    index 89a23c9f9fd..fef9a459437 100644
    --- a/sys/dev/ath/ath_hal/ah_eeprom_v3.c
    +++ b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
    @@ -1753,6 +1753,8 @@ legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)
     /*
      * Reclaim any EEPROM-related storage.
      */
    +
    +/* XXX: FlexeLint: return in void function */
     static void
     legacyEepromDetach(struct ath_hal *ah)
     {
    diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
    index 431ed9f24f7..76e22d9b96f 100644
    --- a/sys/dev/bce/if_bce.c
    +++ b/sys/dev/bce/if_bce.c
    @@ -608,17 +608,17 @@ bce_print_adapter_info(struct bce_softc *sc)
     #endif
         if (sc->bce_flags & BCE_USING_MSI_FLAG) {
             if (i > 0) printf("|");
    -		printf("MSI"); i++;
    +	printf("MSI"); i++;
         }
     
         if (sc->bce_flags & BCE_USING_MSIX_FLAG) {
             if (i > 0) printf("|");
    -		printf("MSI-X "); i++;
    +	printf("MSI-X "); i++;
         }
     
         if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) {
             if (i > 0) printf("|");
    -		printf("2.5G"); i++;
    +	printf("2.5G"); i++;
         }
     
         if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) {
    @@ -628,7 +628,7 @@ bce_print_adapter_info(struct bce_softc *sc)
             printf(")\n");
         }
     
    -	DBEXIT(BCE_VERBOSE_LOAD);
    +    DBEXIT(BCE_VERBOSE_LOAD);
     }
     
     
    diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
    index 1def87631db..ee580dbfaae 100644
    --- a/sys/dev/e1000/if_em.c
    +++ b/sys/dev/e1000/if_em.c
    @@ -2826,7 +2826,7 @@ em_allocate_pci_resources(struct adapter *adapter)
      *  Setup the Legacy or MSI Interrupt handler
      *
      **********************************************************************/
    -int
    +static int
     em_allocate_legacy(struct adapter *adapter)
     {
     	device_t dev = adapter->dev;
    diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
    index f5fd475f85a..0a7e8085396 100644
    --- a/sys/dev/ep/if_ep.c
    +++ b/sys/dev/ep/if_ep.c
    @@ -666,6 +666,7 @@ rescan:
     						sc->tx_underrun++;
     #endif
     					} else {
    +						/* XXX: FlexeLint doesn't like ; */
     						if (status & TXS_JABBER);
     						else
     							++ifp->if_collisions;
    diff --git a/sys/dev/ep/if_epreg.h b/sys/dev/ep/if_epreg.h
    index f3c269f5561..8c464033608 100644
    --- a/sys/dev/ep/if_epreg.h
    +++ b/sys/dev/ep/if_epreg.h
    @@ -315,7 +315,11 @@
     				 S_TX_AVAIL|S_RX_COMPLETE|S_RX_EARLY)
     #define S_COMMAND_IN_PROGRESS	(u_short) (0x1000)
     
    -#define EP_BUSY_WAIT(sc) while (CSR_READ_2(sc, EP_STATUS) & S_COMMAND_IN_PROGRESS)
    +#define EP_BUSY_WAIT(sc) 							\
    +	do {									\
    +		while (CSR_READ_2(sc, EP_STATUS) & S_COMMAND_IN_PROGRESS)	\
    +			continue;						\
    +	} while (0)
     
     /* Address Config. Register.
      * Window 0/Port 06
    diff --git a/sys/dev/firewire/fwcrom.c b/sys/dev/firewire/fwcrom.c
    index 8a53bc7fae7..9bafd2193c5 100644
    --- a/sys/dev/firewire/fwcrom.c
    +++ b/sys/dev/firewire/fwcrom.c
    @@ -454,9 +454,9 @@ crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent,
     	len = strlen(buf);
     	if (len > MAX_TEXT) {
     #if defined(__DragonFly__) || __FreeBSD_version < 500000
    -		printf("text(%d) trancated to %d.\n", len, MAX_TEXT);
    +		printf("text(%d) truncated to %d.\n", len, MAX_TEXT);
     #else
    -		printf("text(%d) trancated to %td.\n", len, MAX_TEXT);
    +		printf("text(%d) truncated to %td.\n", len, MAX_TEXT);
     #endif
     		len = MAX_TEXT;
     	}
    diff --git a/sys/dev/firewire/fwdev.c b/sys/dev/firewire/fwdev.c
    index 0facb6e3963..57d68f8f291 100644
    --- a/sys/dev/firewire/fwdev.c
    +++ b/sys/dev/firewire/fwdev.c
    @@ -844,6 +844,7 @@ out:
     		err = copyout(ptr, crom_buf->ptr, len);
     		if (fwdev == NULL)
     			/* myself */
    +			/* XXX: Flexelint no sure about modified pointer */
     			free(ptr, M_FW);
     		break;
     	default:
    diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
    index 4fb890f02b0..57ac1fb0b53 100644
    --- a/sys/dev/fxp/if_fxp.c
    +++ b/sys/dev/fxp/if_fxp.c
    @@ -1597,6 +1597,7 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
     		cbp->tbd_number = nseg;
     	/* Configure TSO. */
     	if (m->m_pkthdr.csum_flags & CSUM_TSO) {
    +		/* XXX: FlexeLint: negative subscript */
     		cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16);
     		cbp->tbd[1].tb_size |= htole32(tcp_payload << 16);
     		cbp->ipcb_ip_schedule |= FXP_IPCB_LARGESEND_ENABLE |
    diff --git a/sys/dev/hptiop/hptiop.c b/sys/dev/hptiop/hptiop.c
    index 7218bc50442..5ad2106a314 100644
    --- a/sys/dev/hptiop/hptiop.c
    +++ b/sys/dev/hptiop/hptiop.c
    @@ -432,6 +432,7 @@ srb_complete:
     					sg_list), (u_int8_t *)&ccb->csio.sense_data, 
     					MIN(dxfer, sizeof(ccb->csio.sense_data)));
     			} else {
    +				/* XXX: Flexelint arg2 is 16 bytes, arg3 is 32 */
     				memcpy(&ccb->csio.sense_data, &req->sg_list, 
     					MIN(dxfer, sizeof(ccb->csio.sense_data)));
     			}
    @@ -575,6 +576,7 @@ static void hptiop_request_callback_mv(struct hpt_iop_hba * hba,
     			ccb->ccb_h.status = CAM_BUSY;
     			break;
     		case IOP_RESULT_CHECK_CONDITION:
    +			/* XXX: FlexeLint: arg2=16b arg3=32 */
     			memcpy(&ccb->csio.sense_data, &req->sg_list, 
     				MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
     			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
    diff --git a/sys/dev/iir/iir.c b/sys/dev/iir/iir.c
    index f5f6d7e667f..9bfa283ae8f 100644
    --- a/sys/dev/iir/iir.c
    +++ b/sys/dev/iir/iir.c
    @@ -1203,6 +1203,7 @@ gdt_internal_cache_cmd(struct gdt_softc *gdt,union ccb *ccb)
                     bzero( ccb->csio.data_ptr+copylen,
                            ccb->csio.dxfer_len - copylen );
                 page=((struct scsi_mode_sense_6 *)ccb->csio.cdb_io.cdb_bytes)->page;
    +	    /* XXX: FlexeLint: why ?? */
                 switch (page) {
                   default:
                     GDT_DPRINTF(GDT_D_MISC, ("MODE_SENSE_6: page 0x%x\n", page));
    diff --git a/sys/dev/mpt/mpt_raid.c b/sys/dev/mpt/mpt_raid.c
    index 6b7eb7b46c4..0a3fdca7dbb 100644
    --- a/sys/dev/mpt/mpt_raid.c
    +++ b/sys/dev/mpt/mpt_raid.c
    @@ -562,6 +562,7 @@ mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
     		break;
     	}
     	action_result = REQ_TO_RAID_ACTION_RESULT(req);
    +	/* XXX: FlexeLint: ActionData is only 4 bytes */
     	memcpy(&action_result->action_data, &reply->ActionData,
     	    sizeof(action_result->action_data));
     	action_result->action_status = le16toh(reply->ActionStatus);
    diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c
    index f5f94baad32..ca9ef277deb 100644
    --- a/sys/dev/msk/if_msk.c
    +++ b/sys/dev/msk/if_msk.c
    @@ -118,26 +118,21 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
     #include 
     
     #include 
    -#include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
     #include 
     #include 
     
    -#include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
    index 7abd10473f5..6af6ec2e2f3 100644
    --- a/sys/dev/usb/wlan/if_rum.c
    +++ b/sys/dev/usb/wlan/if_rum.c
    @@ -42,12 +42,9 @@ __FBSDID("$FreeBSD$");
     #include 
     
     #include 
    -#include 
    -#include 
     
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    @@ -1489,7 +1486,7 @@ rum_rf_write(struct rum_softc *sc, uint8_t reg, uint32_t val)
     		return;
     	}
     
    -	tmp = RT2573_RF_BUSY | RT2573_RF_20BIT | (val & 0xfffff) << 2 |
    +	tmp = RT2573_RF_BUSY | RT2573_RF_20BIT | ((val & 0xfffff) << 2) |
     	    (reg & 3);
     	rum_write(sc, RT2573_PHY_CSR4, tmp);
     
    diff --git a/sys/dev/usb/wlan/if_rumreg.h b/sys/dev/usb/wlan/if_rumreg.h
    index 75a51bcd4ad..44e627ad138 100644
    --- a/sys/dev/usb/wlan/if_rumreg.h
    +++ b/sys/dev/usb/wlan/if_rumreg.h
    @@ -139,7 +139,7 @@
     #define RT2573_BBP_BUSY	(1 << 16)
     /* possible flags for register PHY_CSR4 */
     #define RT2573_RF_20BIT	(20 << 24)
    -#define RT2573_RF_BUSY	(1 << 31)
    +#define RT2573_RF_BUSY	(1U << 31)
     
     /* LED values */
     #define RT2573_LED_RADIO	(1 << 8)
    diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c
    index 0cd8d3535a3..69b7bb1746e 100644
    --- a/sys/dev/usb/wlan/if_urtw.c
    +++ b/sys/dev/usb/wlan/if_urtw.c
    @@ -61,6 +61,8 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     
    +#define nitems(a)	(sizeof(a) / sizeof((a)[0]))
    +
     SYSCTL_NODE(_hw_usb, OID_AUTO, urtw, CTLFLAG_RW, 0, "USB Realtek 8187L");
     #ifdef URTW_DEBUG
     int urtw_debug = 0;
    @@ -175,6 +177,46 @@ struct urtw_pair {
     	uint32_t	val;
     };
     
    +static const uint8_t urtw_8187b_reg_table[][3] = {
    +	{ 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 },
    +	{ 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 },
    +	{ 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 },
    +	{ 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 },
    +	{ 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 },
    +	{ 0xff, 0x00, 0 },
    +
    +	{ 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 }, { 0x5a, 0x4b, 1 },
    +	{ 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 }, { 0x61, 0x09, 1 },
    +	{ 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 }, { 0xce, 0x0f, 1 },
    +	{ 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 }, { 0xe1, 0x0f, 1 },
    +	{ 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 }, { 0xf1, 0x01, 1 },
    +	{ 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 }, { 0xf4, 0x04, 1 },
    +	{ 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 }, { 0xf7, 0x07, 1 },
    +	{ 0xf8, 0x08, 1 },
    +
    +	{ 0x4e, 0x00, 2 }, { 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 },
    +	{ 0x22, 0x68, 2 }, { 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 },
    +	{ 0x25, 0x7d, 2 }, { 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 },
    +	{ 0x4d, 0x08, 2 }, { 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 },
    +	{ 0x52, 0x04, 2 }, { 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 },
    +	{ 0x55, 0x23, 2 }, { 0x56, 0x45, 2 }, { 0x57, 0x67, 2 },
    +	{ 0x58, 0x08, 2 }, { 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 },
    +	{ 0x5b, 0x08, 2 }, { 0x60, 0x08, 2 }, { 0x61, 0x08, 2 },
    +	{ 0x62, 0x08, 2 }, { 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 },
    +	{ 0x72, 0x56, 2 }, { 0x73, 0x9a, 2 },
    +
    +	{ 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 }, { 0x5b, 0x40, 0 },
    +	{ 0x84, 0x88, 0 }, { 0x85, 0x24, 0 }, { 0x88, 0x54, 0 },
    +	{ 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 }, { 0x8d, 0x00, 0 },
    +	{ 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 }, { 0x96, 0x00, 0 },
    +	{ 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 }, { 0x9f, 0x10, 0 },
    +	{ 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 }, { 0xdb, 0x00, 0 },
    +	{ 0xee, 0x00, 0 }, { 0x91, 0x03, 0 },
    +
    +	{ 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 },
    +	{ 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 }
    +};
    +
     static uint8_t urtw_8225_agc[] = {
     	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b,
     	0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
    @@ -190,21 +232,6 @@ static uint8_t urtw_8225_agc[] = {
     	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
     };
     
    -static uint8_t urtw_8225z2_agc[] = {
    -	0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51,
    -	0x4f, 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b,
    -	0x39, 0x37, 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25,
    -	0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f,
    -	0x0d, 0x0b, 0x09, 0x07, 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
    -	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x19, 0x19,
    -	0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x20, 0x21, 0x22, 0x23,
    -	0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a,
    -	0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
    -	0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31,
    -	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
    -	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
    -};
    -
     static uint32_t urtw_8225_channel[] = {
     	0x0000,		/* dummy channel 0  */
     	0x085c,		/* 1  */
    @@ -237,7 +264,7 @@ static struct urtw_pair urtw_8225_rf_part1[] = {
     	{ 0x00, 0x0067 }, { 0x01, 0x0fe0 }, { 0x02, 0x044d }, { 0x03, 0x0441 },
     	{ 0x04, 0x0486 }, { 0x05, 0x0bc0 }, { 0x06, 0x0ae6 }, { 0x07, 0x082a },
     	{ 0x08, 0x001f }, { 0x09, 0x0334 }, { 0x0a, 0x0fd4 }, { 0x0b, 0x0391 },
    -	{ 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 },
    +	{ 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 }
     };
     
     static struct urtw_pair urtw_8225_rf_part2[] = {
    @@ -279,7 +306,7 @@ static uint16_t urtw_8225_rxgain[] = {
     };
     
     static uint8_t urtw_8225_threshold[] = {
    -	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd,
    +	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
     };
     
     static uint8_t urtw_8225_tx_gain_cck_ofdm[] = {
    @@ -304,10 +331,29 @@ static uint8_t urtw_8225_txpwr_cck_ch14[] = {
     	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
     };
     
    -static uint8_t urtw_8225_txpwr_ofdm[]={
    +static uint8_t urtw_8225_txpwr_ofdm[] = {
     	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
     };
     
    +static uint8_t urtw_8225z2_agc[] = {
    +	0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57,
    +	0x55, 0x53, 0x51, 0x4f, 0x4d, 0x4b, 0x49, 0x47,
    +	0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
    +	0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27,
    +	0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17,
    +	0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
    +	0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    +	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    +	0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
    +	0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
    +	0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a,
    +	0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
    +	0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f,
    +	0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
    +	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
    +	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
    +};
    +
     static uint8_t urtw_8225v2_gain_bg[]={
     	0x23, 0x15, 0xa5,		/* -82-1dbm  */
     	0x23, 0x15, 0xb5,		/* -82-2dbm  */
    @@ -410,11 +456,7 @@ static uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = {
     	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
     	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
    -	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
    -};
    -
    -static uint8_t urtw_8225v2_txpwr_cck[] = {
    -	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
    +	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
     };
     
     static uint8_t urtw_8225v2_txpwr_cck_ch14[] = {
    @@ -428,6 +470,10 @@ static uint8_t urtw_8225v2b_txpwr_cck[] = {
     	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
     };
     
    +static uint8_t urtw_8225v2_txpwr_cck[] = {
    +	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
    +};
    +
     static uint8_t urtw_8225v2b_txpwr_cck_ch14[] = {
     	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
     	0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
    @@ -441,40 +487,6 @@ static struct urtw_pair urtw_ratetable[] = {
     	{ 96, 10 }, { 108, 11 }
     };
     
    -static const uint8_t urtw_8187b_reg_table[][3] = {
    -	{ 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 },
    -	{ 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 },
    -	{ 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 },
    -	{ 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 },
    -	{ 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 },
    -	{ 0xff, 0x00, 0 }, { 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 },
    -	{ 0x5a, 0x4b, 1 }, { 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 },
    -	{ 0x61, 0x09, 1 }, { 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 },
    -	{ 0xce, 0x0f, 1 }, { 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 },
    -	{ 0xe1, 0x0f, 1 }, { 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 },
    -	{ 0xf1, 0x01, 1 }, { 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 },
    -	{ 0xf4, 0x04, 1 }, { 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 },
    -	{ 0xf7, 0x07, 1 }, { 0xf8, 0x08, 1 }, { 0x4e, 0x00, 2 },
    -	{ 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 }, { 0x22, 0x68, 2 },
    -	{ 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 }, { 0x25, 0x7d, 2 },
    -	{ 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 }, { 0x4d, 0x08, 2 },
    -	{ 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 }, { 0x52, 0x04, 2 },
    -	{ 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 }, { 0x55, 0x23, 2 },
    -	{ 0x56, 0x45, 2 }, { 0x57, 0x67, 2 }, { 0x58, 0x08, 2 },
    -	{ 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 }, { 0x5b, 0x08, 2 },
    -	{ 0x60, 0x08, 2 }, { 0x61, 0x08, 2 }, { 0x62, 0x08, 2 },
    -	{ 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 }, { 0x72, 0x56, 2 },
    -	{ 0x73, 0x9a, 2 }, { 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 },
    -	{ 0x5b, 0x40, 0 }, { 0x84, 0x88, 0 }, { 0x85, 0x24, 0 },
    -	{ 0x88, 0x54, 0 }, { 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 },
    -	{ 0x8d, 0x00, 0 }, { 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 },
    -	{ 0x96, 0x00, 0 }, { 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 },
    -	{ 0x9f, 0x10, 0 }, { 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 },
    -	{ 0xdb, 0x00, 0 }, { 0xee, 0x00, 0 }, { 0x91, 0x03, 0 },
    -	{ 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 },
    -	{ 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 }
    -};
    -
     static usb_callback_t urtw_bulk_rx_callback;
     static usb_callback_t urtw_bulk_tx_callback;
     
    @@ -1034,7 +1046,6 @@ urtw_init(void *arg)
     static usb_error_t
     urtw_adapter_start_b(struct urtw_softc *sc)
     {
    -#define N(a)	(sizeof(a) / sizeof((a)[0]))
     	int i;
     	uint8_t data8;
     	usb_error_t error;
    @@ -1098,7 +1109,7 @@ urtw_adapter_start_b(struct urtw_softc *sc)
     		goto fail;
     
     	urtw_write8_m(sc, URTW_WPA_CONFIG, 0);
    -	for (i = 0; i < N(urtw_8187b_reg_table); i++) {
    +	for (i = 0; i < nitems(urtw_8187b_reg_table); i++) {
     		error = urtw_write8_i(sc, urtw_8187b_reg_table[i][0],
     		    urtw_8187b_reg_table[i][1], urtw_8187b_reg_table[i][2]);
     		if (error)
    @@ -1208,7 +1219,6 @@ urtw_adapter_start_b(struct urtw_softc *sc)
     
     fail:
     	return (error);
    -#undef N
     }
     
     static usb_error_t
    @@ -1273,19 +1283,6 @@ fail:
     	return (error);
     }
     
    -static usb_error_t
    -urtw_set_mode(struct urtw_softc *sc, uint32_t mode)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	urtw_read8_m(sc, URTW_EPROM_CMD, &data);
    -	data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT);
    -	data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK);
    -	urtw_write8_m(sc, URTW_EPROM_CMD, data);
    -fail:
    -	return (error);
    -}
     
     static usb_error_t
     urtw_8187b_cmd_reset(struct urtw_softc *sc)
    @@ -1394,56 +1391,6 @@ urtw_write32_i(struct urtw_softc *sc, int val, uint32_t data, int idx)
     	return (urtw_do_request(sc, &req, &data));
     }
     
    -static void
    -urtw_stop_locked(struct ifnet *ifp, int disable)
    -{
    -	struct urtw_softc *sc = ifp->if_softc;
    -	uint8_t data8;
    -	usb_error_t error;
    -
    -	(void)disable;
    -	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
    -
    -	error = urtw_intr_disable(sc);
    -	if (error)
    -		goto fail;
    -	urtw_read8_m(sc, URTW_CMD, &data8);
    -	data8 &= ~(URTW_CMD_RX_ENABLE | URTW_CMD_TX_ENABLE);
    -	urtw_write8_m(sc, URTW_CMD, data8);
    -
    -	error = sc->sc_rf_stop(sc);
    -	if (error != 0)
    -		goto fail;
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    -	if (error)
    -		goto fail;
    -	urtw_read8_m(sc, URTW_CONFIG4, &data8);
    -	urtw_write8_m(sc, URTW_CONFIG4, data8 | URTW_CONFIG4_VCOOFF);
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    -	if (error)
    -		goto fail;
    -fail:
    -	if (error)
    -		device_printf(sc->sc_dev, "failed to stop (%s)\n",
    -		    usbd_errstr(error));
    -
    -	usb_callout_stop(&sc->sc_led_ch);
    -	callout_stop(&sc->sc_watchdog_ch);
    -
    -	urtw_abort_xfers(sc);
    -}
    -
    -static void
    -urtw_stop(struct ifnet *ifp, int disable)
    -{
    -	struct urtw_softc *sc = ifp->if_softc;
    -
    -	URTW_LOCK(sc);
    -	urtw_stop_locked(ifp, disable);
    -	URTW_UNLOCK(sc);
    -}
    -
     static void
     urtw_abort_xfers(struct urtw_softc *sc)
     {
    @@ -1949,201 +1896,6 @@ urtw_set_multi(void *arg)
     	ifp->if_flags |= IFF_ALLMULTI;
     }
     
    -static usb_error_t
    -urtw_set_rate(struct urtw_softc *sc)
    -{
    -	int i, basic_rate, min_rr_rate, max_rr_rate;
    -	uint16_t data;
    -	usb_error_t error;
    -
    -	basic_rate = urtw_rate2rtl(48);
    -	min_rr_rate = urtw_rate2rtl(12);
    -	max_rr_rate = urtw_rate2rtl(48);
    -
    -	urtw_write8_m(sc, URTW_RESP_RATE,
    -	    max_rr_rate << URTW_RESP_MAX_RATE_SHIFT |
    -	    min_rr_rate << URTW_RESP_MIN_RATE_SHIFT);
    -
    -	urtw_read16_m(sc, URTW_BRSR, &data);
    -	data &= ~URTW_BRSR_MBR_8185;
    -
    -	for (i = 0; i <= basic_rate; i++)
    -		data |= (1 << i);
    -
    -	urtw_write16_m(sc, URTW_BRSR, data);
    -fail:
    -	return (error);
    -}
    -
    -static uint16_t
    -urtw_rate2rtl(int rate)
    -{
    -#define N(a)	(sizeof(a) / sizeof((a)[0]))
    -	int i;
    -
    -	for (i = 0; i < N(urtw_ratetable); i++) {
    -		if (rate == urtw_ratetable[i].reg)
    -			return urtw_ratetable[i].val;
    -	}
    -
    -	return (3);
    -#undef N
    -}
    -
    -static uint16_t
    -urtw_rtl2rate(int rate)
    -{
    -#define N(a)	(sizeof(a) / sizeof((a)[0]))
    -	int i;
    -
    -	for (i = 0; i < N(urtw_ratetable); i++) {
    -		if (rate == urtw_ratetable[i].val)
    -			return urtw_ratetable[i].reg;
    -	}
    -
    -	return (0);
    -#undef N
    -}
    -
    -static usb_error_t
    -urtw_update_msr(struct urtw_softc *sc)
    -{
    -	struct ifnet *ifp = sc->sc_ifp;
    -	struct ieee80211com *ic = ifp->if_l2com;
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	urtw_read8_m(sc, URTW_MSR, &data);
    -	data &= ~URTW_MSR_LINK_MASK;
    -
    -	if (sc->sc_state == IEEE80211_S_RUN) {
    -		switch (ic->ic_opmode) {
    -		case IEEE80211_M_STA:
    -		case IEEE80211_M_MONITOR:
    -			data |= URTW_MSR_LINK_STA;
    -			if (sc->sc_flags & URTW_RTL8187B)
    -				data |= URTW_MSR_LINK_ENEDCA;
    -			break;
    -		case IEEE80211_M_IBSS:
    -			data |= URTW_MSR_LINK_ADHOC;
    -			break;
    -		case IEEE80211_M_HOSTAP:
    -			data |= URTW_MSR_LINK_HOSTAP;
    -			break;
    -		default:
    -			panic("unsupported operation mode 0x%x\n",
    -			    ic->ic_opmode);
    -			/* never reach  */
    -		}
    -	} else
    -		data |= URTW_MSR_LINK_NONE;
    -
    -	urtw_write8_m(sc, URTW_MSR, data);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data)
    -{
    -	struct usb_device_request req;
    -	usb_error_t error;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_GETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint8_t));
    -
    -	error = urtw_do_request(sc, &req, data);
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data)
    -{
    -	struct usb_device_request req;
    -	usb_error_t error;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_GETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint16_t));
    -
    -	error = urtw_do_request(sc, &req, data);
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data)
    -{
    -	struct usb_device_request req;
    -	usb_error_t error;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_GETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint32_t));
    -
    -	error = urtw_do_request(sc, &req, data);
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data)
    -{
    -	struct usb_device_request req;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_SETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint8_t));
    -
    -	return (urtw_do_request(sc, &req, &data));
    -}
    -
    -static usb_error_t
    -urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data)
    -{
    -	struct usb_device_request req;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_SETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint16_t));
    -
    -	return (urtw_do_request(sc, &req, &data));
    -}
    -
    -static usb_error_t
    -urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data)
    -{
    -	struct usb_device_request req;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_SETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint32_t));
    -
    -	return (urtw_do_request(sc, &req, &data));
    -}
     
     static usb_error_t
     urtw_get_macaddr(struct urtw_softc *sc)
    @@ -2247,16 +1999,48 @@ fail:
     }
     
     static usb_error_t
    -urtw_eprom_cs(struct urtw_softc *sc, int able)
    +urtw_eprom_readbit(struct urtw_softc *sc, int16_t *data)
    +{
    +	uint8_t data8;
    +	usb_error_t error;
    +
    +	urtw_read8_m(sc, URTW_EPROM_CMD, &data8);
    +	*data = (data8 & URTW_EPROM_READBIT) ? 1 : 0;
    +	DELAY(URTW_EPROM_DELAY);
    +
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen)
    +{
    +	int i = 0;
    +	usb_error_t error = 0;
    +
    +	for (i = 0; i < buflen; i++) {
    +		error = urtw_eprom_writebit(sc, buf[i]);
    +		if (error != 0)
    +			goto fail;
    +		error = urtw_eprom_ck(sc);
    +		if (error != 0)
    +			goto fail;
    +	}
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_eprom_writebit(struct urtw_softc *sc, int16_t bit)
     {
     	uint8_t data;
     	usb_error_t error;
     
     	urtw_read8_m(sc, URTW_EPROM_CMD, &data);
    -	if (able == URTW_EPROM_ENABLE)
    -		urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CS);
    +	if (bit != 0)
    +		urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_WRITEBIT);
     	else
    -		urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CS);
    +		urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_WRITEBIT);
     	DELAY(URTW_EPROM_DELAY);
     fail:
     	return (error);
    @@ -2280,50 +2064,709 @@ fail:
     	return (error);
     }
     
    -static usb_error_t
    -urtw_eprom_readbit(struct urtw_softc *sc, int16_t *data)
    -{
    -	uint8_t data8;
    -	usb_error_t error;
    -
    -	urtw_read8_m(sc, URTW_EPROM_CMD, &data8);
    -	*data = (data8 & URTW_EPROM_READBIT) ? 1 : 0;
    -	DELAY(URTW_EPROM_DELAY);
    -
    -fail:
    -	return (error);
    -}
     
     static usb_error_t
    -urtw_eprom_writebit(struct urtw_softc *sc, int16_t bit)
    +urtw_eprom_cs(struct urtw_softc *sc, int able)
     {
     	uint8_t data;
     	usb_error_t error;
     
     	urtw_read8_m(sc, URTW_EPROM_CMD, &data);
    -	if (bit != 0)
    -		urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_WRITEBIT);
    +	if (able == URTW_EPROM_ENABLE)
    +		urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CS);
     	else
    -		urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_WRITEBIT);
    +		urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CS);
     	DELAY(URTW_EPROM_DELAY);
     fail:
     	return (error);
     }
     
    +
    +
     static usb_error_t
    -urtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen)
    +urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data)
    +{
    +	struct usb_device_request req;
    +	usb_error_t error;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_GETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint8_t));
    +
    +	error = urtw_do_request(sc, &req, data);
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_read8e(struct urtw_softc *sc, int val, uint8_t *data)
    +{
    +	struct usb_device_request req;
    +	usb_error_t error;
    +
    +	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_GETREGS_REQ;
    +	USETW(req.wValue, val | 0xfe00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint8_t));
    +
    +	error = urtw_do_request(sc, &req, data);
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data)
    +{
    +	struct usb_device_request req;
    +	usb_error_t error;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_GETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint16_t));
    +
    +	error = urtw_do_request(sc, &req, data);
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data)
    +{
    +	struct usb_device_request req;
    +	usb_error_t error;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_GETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint32_t));
    +
    +	error = urtw_do_request(sc, &req, data);
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data)
    +{
    +	struct usb_device_request req;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_SETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint8_t));
    +
    +	return (urtw_do_request(sc, &req, &data));
    +}
    +
    +static usb_error_t
    +urtw_write8e(struct urtw_softc *sc, int val, uint8_t data)
    +{
    +	struct usb_device_request req;
    +
    +	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_SETREGS_REQ;
    +	USETW(req.wValue, val | 0xfe00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint8_t));
    +
    +	return (urtw_do_request(sc, &req, &data));
    +}
    +
    +static usb_error_t
    +urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data)
    +{
    +	struct usb_device_request req;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_SETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint16_t));
    +
    +	return (urtw_do_request(sc, &req, &data));
    +}
    +
    +static usb_error_t
    +urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data)
    +{
    +	struct usb_device_request req;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_SETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint32_t));
    +
    +	return (urtw_do_request(sc, &req, &data));
    +}
    +
    +static usb_error_t
    +urtw_set_mode(struct urtw_softc *sc, uint32_t mode)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	urtw_read8_m(sc, URTW_EPROM_CMD, &data);
    +	data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT);
    +	data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK);
    +	urtw_write8_m(sc, URTW_EPROM_CMD, data);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    +	if (error)
    +		goto fail;
    +
    +	urtw_read8_m(sc, URTW_CONFIG3, &data);
    +	urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE);
    +	urtw_write32_m(sc, URTW_ANAPARAM, val);
    +	urtw_read8_m(sc, URTW_CONFIG3, &data);
    +	urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE);
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    +	if (error)
    +		goto fail;
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    +	if (error)
    +		goto fail;
    +
    +	urtw_read8_m(sc, URTW_CONFIG3, &data);
    +	urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE);
    +	urtw_write32_m(sc, URTW_ANAPARAM2, val);
    +	urtw_read8_m(sc, URTW_CONFIG3, &data);
    +	urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE);
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    +	if (error)
    +		goto fail;
    +fail:
    +	return (error);
    +}
    +
    +
    +static usb_error_t
    +urtw_intr_disable(struct urtw_softc *sc)
    +{
    +	usb_error_t error;
    +
    +	urtw_write16_m(sc, URTW_INTR_MASK, 0);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_reset(struct urtw_softc *sc)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    +	if (error)
    +		goto fail;
    +	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    +	if (error)
    +		goto fail;
    +
    +	error = urtw_intr_disable(sc);
    +	if (error)
    +		goto fail;
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +
    +	error = urtw_write8e(sc, 0x18, 0x10);
    +	if (error != 0)
    +		goto fail;
    +	error = urtw_write8e(sc, 0x18, 0x11);
    +	if (error != 0)
    +		goto fail;
    +	error = urtw_write8e(sc, 0x18, 0x00);
    +	if (error != 0)
    +		goto fail;
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +
    +	urtw_read8_m(sc, URTW_CMD, &data);
    +	data = (data & 0x2) | URTW_CMD_RST;
    +	urtw_write8_m(sc, URTW_CMD, data);
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +
    +	urtw_read8_m(sc, URTW_CMD, &data);
    +	if (data & URTW_CMD_RST) {
    +		device_printf(sc->sc_dev, "reset timeout\n");
    +		goto fail;
    +	}
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD);
    +	if (error)
    +		goto fail;
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +
    +	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    +	if (error)
    +		goto fail;
    +	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    +	if (error)
    +		goto fail;
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_led_on(struct urtw_softc *sc, int type)
    +{
    +	usb_error_t error;
    +
    +	if (type == URTW_LED_GPIO) {
    +		switch (sc->sc_gpio_ledpin) {
    +		case URTW_LED_PIN_GPIO0:
    +			urtw_write8_m(sc, URTW_GPIO, 0x01);
    +			urtw_write8_m(sc, URTW_GP_ENABLE, 0x00);
    +			break;
    +		default:
    +			panic("unsupported LED PIN type 0x%x",
    +			    sc->sc_gpio_ledpin);
    +			/* never reach  */
    +		}
    +	} else {
    +		panic("unsupported LED type 0x%x", type);
    +		/* never reach  */
    +	}
    +
    +	sc->sc_gpio_ledon = 1;
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_led_off(struct urtw_softc *sc, int type)
    +{
    +	usb_error_t error;
    +
    +	if (type == URTW_LED_GPIO) {
    +		switch (sc->sc_gpio_ledpin) {
    +		case URTW_LED_PIN_GPIO0:
    +			urtw_write8_m(sc, URTW_GPIO, URTW_GPIO_DATA_MAGIC1);
    +			urtw_write8_m(sc,
    +			    URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1);
    +			break;
    +		default:
    +			panic("unsupported LED PIN type 0x%x",
    +			    sc->sc_gpio_ledpin);
    +			/* never reach  */
    +		}
    +	} else {
    +		panic("unsupported LED type 0x%x", type);
    +		/* never reach  */
    +	}
    +
    +	sc->sc_gpio_ledon = 0;
    +
    +fail:
    +	return (error);
    +}
    +
    +
    +static usb_error_t
    +urtw_led_mode0(struct urtw_softc *sc, int mode)
    +{
    +
    +	switch (mode) {
    +	case URTW_LED_CTL_POWER_ON:
    +		sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK;
    +		break;
    +	case URTW_LED_CTL_TX:
    +		if (sc->sc_gpio_ledinprogress == 1)
    +			return (0);
    +
    +		sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL;
    +		sc->sc_gpio_blinktime = 2;
    +		break;
    +	case URTW_LED_CTL_LINK:
    +		sc->sc_gpio_ledstate = URTW_LED_ON;
    +		break;
    +	default:
    +		panic("unsupported LED mode 0x%x", mode);
    +		/* never reach  */
    +	}
    +
    +	switch (sc->sc_gpio_ledstate) {
    +	case URTW_LED_ON:
    +		if (sc->sc_gpio_ledinprogress != 0)
    +			break;
    +		urtw_led_on(sc, URTW_LED_GPIO);
    +		break;
    +	case URTW_LED_BLINK_NORMAL:
    +		if (sc->sc_gpio_ledinprogress != 0)
    +			break;
    +		sc->sc_gpio_ledinprogress = 1;
    +		sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ?
    +			URTW_LED_OFF : URTW_LED_ON;
    +		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
    +		break;
    +	case URTW_LED_POWER_ON_BLINK:
    +		urtw_led_on(sc, URTW_LED_GPIO);
    +		usb_pause_mtx(&sc->sc_mtx, 100);
    +		urtw_led_off(sc, URTW_LED_GPIO);
    +		break;
    +	default:
    +		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
    +		/* never reach  */
    +	}
    +	return (0);
    +}
    +
    +static usb_error_t
    +urtw_led_mode1(struct urtw_softc *sc, int mode)
    +{
    +
    +	return (USB_ERR_INVAL);
    +}
    +
    +static usb_error_t
    +urtw_led_mode2(struct urtw_softc *sc, int mode)
    +{
    +
    +	return (USB_ERR_INVAL);
    +}
    +
    +static usb_error_t
    +urtw_led_mode3(struct urtw_softc *sc, int mode)
    +{
    +
    +	return (USB_ERR_INVAL);
    +}
    +
    +static void
    +urtw_ledtask(void *arg, int pending)
    +{
    +	struct urtw_softc *sc = arg;
    +
    +	if (sc->sc_strategy != URTW_SW_LED_MODE0)
    +		panic("could not process a LED strategy 0x%x", sc->sc_strategy);
    +
    +	URTW_LOCK(sc);
    +	urtw_led_blink(sc);
    +	URTW_UNLOCK(sc);
    +}
    +
    +static usb_error_t
    +urtw_led_ctl(struct urtw_softc *sc, int mode)
     {
    -	int i = 0;
     	usb_error_t error = 0;
     
    -	for (i = 0; i < buflen; i++) {
    -		error = urtw_eprom_writebit(sc, buf[i]);
    -		if (error != 0)
    -			goto fail;
    -		error = urtw_eprom_ck(sc);
    -		if (error != 0)
    -			goto fail;
    +	switch (sc->sc_strategy) {
    +	case URTW_SW_LED_MODE0:
    +		error = urtw_led_mode0(sc, mode);
    +		break;
    +	case URTW_SW_LED_MODE1:
    +		error = urtw_led_mode1(sc, mode);
    +		break;
    +	case URTW_SW_LED_MODE2:
    +		error = urtw_led_mode2(sc, mode);
    +		break;
    +	case URTW_SW_LED_MODE3:
    +		error = urtw_led_mode3(sc, mode);
    +		break;
    +	default:
    +		panic("unsupported LED mode %d\n", sc->sc_strategy);
    +		/* never reach  */
     	}
    +
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_led_blink(struct urtw_softc *sc)
    +{
    +	uint8_t ing = 0;
    +	usb_error_t error;
    +
    +	if (sc->sc_gpio_blinkstate == URTW_LED_ON)
    +		error = urtw_led_on(sc, URTW_LED_GPIO);
    +	else
    +		error = urtw_led_off(sc, URTW_LED_GPIO);
    +	sc->sc_gpio_blinktime--;
    +	if (sc->sc_gpio_blinktime == 0)
    +		ing = 1;
    +	else {
    +		if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL &&
    +		    sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY &&
    +		    sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3)
    +			ing = 1;
    +	}
    +	if (ing == 1) {
    +		if (sc->sc_gpio_ledstate == URTW_LED_ON &&
    +		    sc->sc_gpio_ledon == 0)
    +			error = urtw_led_on(sc, URTW_LED_GPIO);
    +		else if (sc->sc_gpio_ledstate == URTW_LED_OFF &&
    +		    sc->sc_gpio_ledon == 1)
    +			error = urtw_led_off(sc, URTW_LED_GPIO);
    +
    +		sc->sc_gpio_blinktime = 0;
    +		sc->sc_gpio_ledinprogress = 0;
    +		return (0);
    +	}
    +
    +	sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ?
    +	    URTW_LED_ON : URTW_LED_OFF;
    +
    +	switch (sc->sc_gpio_ledstate) {
    +	case URTW_LED_BLINK_NORMAL:
    +		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
    +		break;
    +	default:
    +		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
    +		/* never reach  */
    +	}
    +	return (0);
    +}
    +
    +static usb_error_t
    +urtw_update_msr(struct urtw_softc *sc)
    +{
    +	struct ifnet *ifp = sc->sc_ifp;
    +	struct ieee80211com *ic = ifp->if_l2com;
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	urtw_read8_m(sc, URTW_MSR, &data);
    +	data &= ~URTW_MSR_LINK_MASK;
    +
    +	if (sc->sc_state == IEEE80211_S_RUN) {
    +		switch (ic->ic_opmode) {
    +		case IEEE80211_M_STA:
    +		case IEEE80211_M_MONITOR:
    +			data |= URTW_MSR_LINK_STA;
    +			if (sc->sc_flags & URTW_RTL8187B)
    +				data |= URTW_MSR_LINK_ENEDCA;
    +			break;
    +		case IEEE80211_M_IBSS:
    +			data |= URTW_MSR_LINK_ADHOC;
    +			break;
    +		case IEEE80211_M_HOSTAP:
    +			data |= URTW_MSR_LINK_HOSTAP;
    +			break;
    +		default:
    +			panic("unsupported operation mode 0x%x\n",
    +			    ic->ic_opmode);
    +			/* never reach  */
    +		}
    +	} else
    +		data |= URTW_MSR_LINK_NONE;
    +
    +	urtw_write8_m(sc, URTW_MSR, data);
    +fail:
    +	return (error);
    +}
    +
    +static uint16_t
    +urtw_rate2rtl(int rate)
    +{
    +	int i;
    +
    +	for (i = 0; i < nitems(urtw_ratetable); i++) {
    +		if (rate == urtw_ratetable[i].reg)
    +			return urtw_ratetable[i].val;
    +	}
    +
    +	return (3);
    +}
    +
    +static uint16_t
    +urtw_rtl2rate(int rate)
    +{
    +	int i;
    +
    +	for (i = 0; i < nitems(urtw_ratetable); i++) {
    +		if (rate == urtw_ratetable[i].val)
    +			return urtw_ratetable[i].reg;
    +	}
    +
    +	return (0);
    +}
    +
    +static usb_error_t
    +urtw_set_rate(struct urtw_softc *sc)
    +{
    +	int i, basic_rate, min_rr_rate, max_rr_rate;
    +	uint16_t data;
    +	usb_error_t error;
    +
    +	basic_rate = urtw_rate2rtl(48);
    +	min_rr_rate = urtw_rate2rtl(12);
    +	max_rr_rate = urtw_rate2rtl(48);
    +
    +	urtw_write8_m(sc, URTW_RESP_RATE,
    +	    max_rr_rate << URTW_RESP_MAX_RATE_SHIFT |
    +	    min_rr_rate << URTW_RESP_MIN_RATE_SHIFT);
    +
    +	urtw_read16_m(sc, URTW_BRSR, &data);
    +	data &= ~URTW_BRSR_MBR_8185;
    +
    +	for (i = 0; i <= basic_rate; i++)
    +		data |= (1 << i);
    +
    +	urtw_write16_m(sc, URTW_BRSR, data);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_intr_enable(struct urtw_softc *sc)
    +{
    +	usb_error_t error;
    +
    +	urtw_write16_m(sc, URTW_INTR_MASK, 0xffff);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_rx_setconf(struct urtw_softc *sc)
    +{
    +	struct ifnet *ifp = sc->sc_ifp;
    +	struct ieee80211com *ic = ifp->if_l2com;
    +	uint32_t data;
    +	usb_error_t error;
    +
    +	urtw_read32_m(sc, URTW_RX, &data);
    +	data = data &~ URTW_RX_FILTER_MASK;
    +	if (sc->sc_flags & URTW_RTL8187B) {
    +		data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA |
    +		    URTW_RX_FILTER_MCAST | URTW_RX_FILTER_BCAST |
    +		    URTW_RX_FILTER_NICMAC | URTW_RX_CHECK_BSSID |
    +		    URTW_RX_FIFO_THRESHOLD_NONE |
    +		    URTW_MAX_RX_DMA_2048 |
    +		    URTW_RX_AUTORESETPHY | URTW_RCR_ONLYERLPKT;
    +	} else {
    +		data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA;
    +		data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST;
    +
    +		if (ic->ic_opmode == IEEE80211_M_MONITOR) {
    +			data = data | URTW_RX_FILTER_ICVERR;
    +			data = data | URTW_RX_FILTER_PWR;
    +		}
    +		if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR)
    +			data = data | URTW_RX_FILTER_CRCERR;
    +
    +		if (ic->ic_opmode == IEEE80211_M_MONITOR ||
    +		    (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
    +			data = data | URTW_RX_FILTER_ALLMAC;
    +		} else {
    +			data = data | URTW_RX_FILTER_NICMAC;
    +			data = data | URTW_RX_CHECK_BSSID;
    +		}
    +
    +		data = data &~ URTW_RX_FIFO_THRESHOLD_MASK;
    +		data = data | URTW_RX_FIFO_THRESHOLD_NONE |
    +		    URTW_RX_AUTORESETPHY;
    +		data = data &~ URTW_MAX_RX_DMA_MASK;
    +		data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT;
    +	}
    +
    +	urtw_write32_m(sc, URTW_RX, data);
    +fail:
    +	return (error);
    +}
    +
    +
    +static usb_error_t
    +urtw_rx_enable(struct urtw_softc *sc)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	usbd_transfer_start((sc->sc_flags & URTW_RTL8187B) ?
    +	    sc->sc_xfer[URTW_8187B_BULK_RX] : sc->sc_xfer[URTW_8187L_BULK_RX]);
    +
    +	error = urtw_rx_setconf(sc);
    +	if (error != 0)
    +		goto fail;
    +
    +	urtw_read8_m(sc, URTW_CMD, &data);
    +	urtw_write8_m(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_tx_enable(struct urtw_softc *sc)
    +{
    +	uint8_t data8;
    +	uint32_t data;
    +	usb_error_t error;
    +
    +	if (sc->sc_flags & URTW_RTL8187B) {
    +		urtw_read32_m(sc, URTW_TX_CONF, &data);
    +		data &= ~URTW_TX_LOOPBACK_MASK;
    +		data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
    +		data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
    +		data &= ~URTW_TX_SWPLCPLEN;
    +		data |= URTW_TX_HW_SEQNUM | URTW_TX_DISREQQSIZE |
    +		    (7 << 8) |	/* short retry limit */
    +		    (7 << 0) |	/* long retry limit */
    +		    (7 << 21);	/* MAX TX DMA */
    +		urtw_write32_m(sc, URTW_TX_CONF, data);
    +
    +		urtw_read8_m(sc, URTW_CMD, &data8);
    +		urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE);
    +		return (error);
    +	}
    +
    +	urtw_read8_m(sc, URTW_CW_CONF, &data8);
    +	data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY);
    +	urtw_write8_m(sc, URTW_CW_CONF, data8);
    +
    +	urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8);
    +	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN;
    +	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL;
    +	data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT;
    +	urtw_write8_m(sc, URTW_TX_AGC_CTL, data8);
    +
    +	urtw_read32_m(sc, URTW_TX_CONF, &data);
    +	data &= ~URTW_TX_LOOPBACK_MASK;
    +	data |= URTW_TX_LOOPBACK_NONE;
    +	data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
    +	data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT;
    +	data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT;
    +	data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
    +	data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW;
    +	data &= ~URTW_TX_SWPLCPLEN;
    +	data |= URTW_TX_NOICV;
    +	urtw_write32_m(sc, URTW_TX_CONF, data);
    +
    +	urtw_read8_m(sc, URTW_CMD, &data8);
    +	urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE);
     fail:
     	return (error);
     }
    @@ -2488,112 +2931,6 @@ fail:
     	return (error);
     }
     
    -
    -static usb_error_t
    -urtw_8225_rf_init(struct urtw_softc *sc)
    -{
    -#define N(a)	(sizeof(a) / sizeof((a)[0]))
    -	int i;
    -	uint16_t data;
    -	usb_error_t error;
    -
    -	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    -	if (error)
    -		goto fail;
    -
    -	error = urtw_8225_usb_init(sc);
    -	if (error)
    -		goto fail;
    -
    -	urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008);
    -	urtw_read16_m(sc, URTW_BRSR, &data);		/* XXX ??? */
    -	urtw_write16_m(sc, URTW_BRSR, 0xffff);
    -	urtw_write32_m(sc, URTW_RF_PARA, 0x100044);
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    -	if (error)
    -		goto fail;
    -	urtw_write8_m(sc, URTW_CONFIG3, 0x44);
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    -	if (error)
    -		goto fail;
    -
    -	error = urtw_8185_rf_pins_enable(sc);
    -	if (error)
    -		goto fail;
    -	usb_pause_mtx(&sc->sc_mtx, 1000);
    -
    -	for (i = 0; i < N(urtw_8225_rf_part1); i++) {
    -		urtw_8225_write(sc, urtw_8225_rf_part1[i].reg,
    -		    urtw_8225_rf_part1[i].val);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -	}
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1);
    -	usb_pause_mtx(&sc->sc_mtx, 200);
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2);
    -	usb_pause_mtx(&sc->sc_mtx, 200);
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC3);
    -
    -	for (i = 0; i < 95; i++) {
    -		urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1));
    -		urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, urtw_8225_rxgain[i]);
    -	}
    -
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC4);
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC5);
    -
    -	for (i = 0; i < 128; i++) {
    -		urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -		urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -	}
    -
    -	for (i = 0; i < N(urtw_8225_rf_part2); i++) {
    -		urtw_8187_write_phy_ofdm(sc, urtw_8225_rf_part2[i].reg,
    -		    urtw_8225_rf_part2[i].val);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -	}
    -
    -	error = urtw_8225_setgain(sc, 4);
    -	if (error)
    -		goto fail;
    -
    -	for (i = 0; i < N(urtw_8225_rf_part3); i++) {
    -		urtw_8187_write_phy_cck(sc, urtw_8225_rf_part3[i].reg,
    -		    urtw_8225_rf_part3[i].val);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -	}
    -
    -	urtw_write8_m(sc, URTW_TESTR, 0x0d);
    -
    -	error = urtw_8225_set_txpwrlvl(sc, 1);
    -	if (error)
    -		goto fail;
    -
    -	urtw_8187_write_phy_cck(sc, 0x10, 0x9b);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -	urtw_8187_write_phy_ofdm(sc, 0x26, 0x90);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -
    -	/* TX ant A, 0x0 for B */
    -	error = urtw_8185_tx_antenna(sc, 0x3);
    -	if (error)
    -		goto fail;
    -	urtw_write32_m(sc, URTW_HSSI_PARA, 0x3dc00002);
    -
    -	error = urtw_8225_rf_set_chan(sc, 1);
    -fail:
    -	return (error);
    -#undef N
    -}
    -
     static usb_error_t
     urtw_8185_rf_pins_enable(struct urtw_softc *sc)
     {
    @@ -2758,68 +3095,6 @@ fail1:	free(req, M_80211_VAP);
     fail0:	return (error);
     }
     
    -static usb_error_t
    -urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan)
    -{
    -	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
    -	struct ieee80211_channel *c = ic->ic_curchan;
    -	usb_error_t error;
    -
    -	error = urtw_8225_set_txpwrlvl(sc, chan);
    -	if (error)
    -		goto fail;
    -	urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]);
    -	usb_pause_mtx(&sc->sc_mtx, 10);
    -
    -	urtw_write8_m(sc, URTW_SIFS, 0x22);
    -
    -	if (sc->sc_state == IEEE80211_S_ASSOC &&
    -	    ic->ic_flags & IEEE80211_F_SHSLOT)
    -		urtw_write8_m(sc, URTW_SLOT, 0x9);
    -	else
    -		urtw_write8_m(sc, URTW_SLOT, 0x14);
    -
    -	if (IEEE80211_IS_CHAN_G(c)) {
    -		/* for G */
    -		urtw_write8_m(sc, URTW_DIFS, 0x14);
    -		urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x14);
    -		urtw_write8_m(sc, URTW_CW_VAL, 0x73);
    -	} else {
    -		/* for B */
    -		urtw_write8_m(sc, URTW_DIFS, 0x24);
    -		urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x24);
    -		urtw_write8_m(sc, URTW_CW_VAL, 0xa5);
    -	}
    -
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8225_rf_set_sens(struct urtw_softc *sc, int sens)
    -{
    -	usb_error_t error;
    -
    -	if (sens < 0 || sens > 6)
    -		return -1;
    -
    -	if (sens > 4)
    -		urtw_8225_write(sc,
    -		    URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC1);
    -	else
    -		urtw_8225_write(sc,
    -		    URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC2);
    -
    -	sens = 6 - sens;
    -	error = urtw_8225_setgain(sc, sens);
    -	if (error)
    -		goto fail;
    -
    -	urtw_8187_write_phy_cck(sc, 0x41, urtw_8225_threshold[sens]);
    -
    -fail:
    -	return (error);
    -}
     
     static usb_error_t
     urtw_8225_set_txpwrlvl(struct urtw_softc *sc, int chan)
    @@ -2909,10 +3184,397 @@ fail:
     	return (error);
     }
     
    +
    +static usb_error_t
    +urtw_8225_rf_init(struct urtw_softc *sc)
    +{
    +	int i;
    +	uint16_t data;
    +	usb_error_t error;
    +
    +	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    +	if (error)
    +		goto fail;
    +
    +	error = urtw_8225_usb_init(sc);
    +	if (error)
    +		goto fail;
    +
    +	urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008);
    +	urtw_read16_m(sc, URTW_BRSR, &data);		/* XXX ??? */
    +	urtw_write16_m(sc, URTW_BRSR, 0xffff);
    +	urtw_write32_m(sc, URTW_RF_PARA, 0x100044);
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    +	if (error)
    +		goto fail;
    +	urtw_write8_m(sc, URTW_CONFIG3, 0x44);
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    +	if (error)
    +		goto fail;
    +
    +	error = urtw_8185_rf_pins_enable(sc);
    +	if (error)
    +		goto fail;
    +	usb_pause_mtx(&sc->sc_mtx, 1000);
    +
    +	for (i = 0; i < nitems(urtw_8225_rf_part1); i++) {
    +		urtw_8225_write(sc, urtw_8225_rf_part1[i].reg,
    +		    urtw_8225_rf_part1[i].val);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +	}
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1);
    +	usb_pause_mtx(&sc->sc_mtx, 200);
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2);
    +	usb_pause_mtx(&sc->sc_mtx, 200);
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC3);
    +
    +	for (i = 0; i < nitems(urtw_8225_rxgain); i++) {
    +		urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1));
    +		urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, urtw_8225_rxgain[i]);
    +	}
    +
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC4);
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC5);
    +
    +	for (i = 0; i < nitems(urtw_8225_agc); i++) {
    +		urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +		urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +	}
    +
    +	for (i = 0; i < nitems(urtw_8225_rf_part2); i++) {
    +		urtw_8187_write_phy_ofdm(sc, urtw_8225_rf_part2[i].reg,
    +		    urtw_8225_rf_part2[i].val);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +	}
    +
    +	error = urtw_8225_setgain(sc, 4);
    +	if (error)
    +		goto fail;
    +
    +	for (i = 0; i < nitems(urtw_8225_rf_part3); i++) {
    +		urtw_8187_write_phy_cck(sc, urtw_8225_rf_part3[i].reg,
    +		    urtw_8225_rf_part3[i].val);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +	}
    +
    +	urtw_write8_m(sc, URTW_TESTR, 0x0d);
    +
    +	error = urtw_8225_set_txpwrlvl(sc, 1);
    +	if (error)
    +		goto fail;
    +
    +	urtw_8187_write_phy_cck(sc, 0x10, 0x9b);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +	urtw_8187_write_phy_ofdm(sc, 0x26, 0x90);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +
    +	/* TX ant A, 0x0 for B */
    +	error = urtw_8185_tx_antenna(sc, 0x3);
    +	if (error)
    +		goto fail;
    +	urtw_write32_m(sc, URTW_HSSI_PARA, 0x3dc00002);
    +
    +	error = urtw_8225_rf_set_chan(sc, 1);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan)
    +{
    +	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
    +	struct ieee80211_channel *c = ic->ic_curchan;
    +	usb_error_t error;
    +
    +	error = urtw_8225_set_txpwrlvl(sc, chan);
    +	if (error)
    +		goto fail;
    +	urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]);
    +	usb_pause_mtx(&sc->sc_mtx, 10);
    +
    +	urtw_write8_m(sc, URTW_SIFS, 0x22);
    +
    +	if (sc->sc_state == IEEE80211_S_ASSOC &&
    +	    ic->ic_flags & IEEE80211_F_SHSLOT)
    +		urtw_write8_m(sc, URTW_SLOT, 0x9);
    +	else
    +		urtw_write8_m(sc, URTW_SLOT, 0x14);
    +
    +	if (IEEE80211_IS_CHAN_G(c)) {
    +		/* for G */
    +		urtw_write8_m(sc, URTW_DIFS, 0x14);
    +		urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x14);
    +		urtw_write8_m(sc, URTW_CW_VAL, 0x73);
    +	} else {
    +		/* for B */
    +		urtw_write8_m(sc, URTW_DIFS, 0x24);
    +		urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x24);
    +		urtw_write8_m(sc, URTW_CW_VAL, 0xa5);
    +	}
    +
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8225_rf_set_sens(struct urtw_softc *sc, int sens)
    +{
    +	usb_error_t error;
    +
    +	if (sens < 0 || sens > 6)
    +		return -1;
    +
    +	if (sens > 4)
    +		urtw_8225_write(sc,
    +		    URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC1);
    +	else
    +		urtw_8225_write(sc,
    +		    URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC2);
    +
    +	sens = 6 - sens;
    +	error = urtw_8225_setgain(sc, sens);
    +	if (error)
    +		goto fail;
    +
    +	urtw_8187_write_phy_cck(sc, 0x41, urtw_8225_threshold[sens]);
    +
    +fail:
    +	return (error);
    +}
    +
    +static void
    +urtw_stop_locked(struct ifnet *ifp, int disable)
    +{
    +	struct urtw_softc *sc = ifp->if_softc;
    +	uint8_t data8;
    +	usb_error_t error;
    +
    +	(void)disable;
    +	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
    +
    +	error = urtw_intr_disable(sc);
    +	if (error)
    +		goto fail;
    +	urtw_read8_m(sc, URTW_CMD, &data8);
    +	data8 &= ~(URTW_CMD_RX_ENABLE | URTW_CMD_TX_ENABLE);
    +	urtw_write8_m(sc, URTW_CMD, data8);
    +
    +	error = sc->sc_rf_stop(sc);
    +	if (error != 0)
    +		goto fail;
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    +	if (error)
    +		goto fail;
    +	urtw_read8_m(sc, URTW_CONFIG4, &data8);
    +	urtw_write8_m(sc, URTW_CONFIG4, data8 | URTW_CONFIG4_VCOOFF);
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    +	if (error)
    +		goto fail;
    +fail:
    +	if (error)
    +		device_printf(sc->sc_dev, "failed to stop (%s)\n",
    +		    usbd_errstr(error));
    +
    +	usb_callout_stop(&sc->sc_led_ch);
    +	callout_stop(&sc->sc_watchdog_ch);
    +
    +	urtw_abort_xfers(sc);
    +}
    +
    +static void
    +urtw_stop(struct ifnet *ifp, int disable)
    +{
    +	struct urtw_softc *sc = ifp->if_softc;
    +
    +	URTW_LOCK(sc);
    +	urtw_stop_locked(ifp, disable);
    +	URTW_UNLOCK(sc);
    +}
    +
    +
    +static int
    +urtw_isbmode(uint16_t rate)
    +{
    +
    +	rate = urtw_rtl2rate(rate);
    +
    +	return ((rate <= 22 && rate != 12 && rate != 18) ||
    +	    rate == 44) ? (1) : (0);
    +}
    +
    +static struct mbuf *
    +urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
    +    int8_t *nf_p)
    +{
    +	int actlen, flen, len, nf = -95, rssi;
    +	struct ieee80211_frame *wh;
    +	struct mbuf *m, *mnew;
    +	struct urtw_8187b_rxhdr *bhdr;
    +	struct urtw_softc *sc = data->sc;
    +	struct ifnet *ifp = sc->sc_ifp;
    +	struct ieee80211com *ic = ifp->if_l2com;
    +	uint8_t *desc, quality = 0, rate;
    +
    +	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
    +
    +	if (actlen < URTW_MIN_RXBUFSZ) {
    +		ifp->if_ierrors++;
    +		return (NULL);
    +	}
    +
    +	if (sc->sc_flags & URTW_RTL8187B) {
    +		len = actlen - (sizeof(struct urtw_8187b_rxhdr));
    +		bhdr = (struct urtw_8187b_rxhdr *)(data->buf + len);
    +		desc = data->buf + len;
    +		flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
    +		if (flen > actlen) {
    +			ifp->if_ierrors++;
    +			return (NULL);
    +		}
    +		rate = (le32toh(bhdr->flags) >> 20) & 0xf;
    +		rssi = 14 + (bhdr->rssi / 2);
    +		if (rssi > 95)
    +			rssi = 95;
    +	} else {
    +		/* 4 dword and 4 byte CRC  */
    +		len = actlen - (4 * 4);
    +		desc = data->buf + len;
    +		flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
    +		if (flen > actlen) {
    +			ifp->if_ierrors++;
    +			return (NULL);
    +		}
    +
    +		rate = (desc[2] & 0xf0) >> 4;
    +		quality = desc[4] & 0xff;
    +		/* XXX correct?  */
    +		rssi = (desc[6] & 0xfe) >> 1;
    +		if (!urtw_isbmode(rate)) {
    +			rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi);
    +			rssi = ((90 - rssi) * 100) / 65;
    +		} else {
    +			rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi);
    +			rssi = ((95 - rssi) * 100) / 65;
    +		}
    +	}
    +
    +	mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
    +	if (mnew == NULL) {
    +		ifp->if_ierrors++;
    +		return (NULL);
    +	}
    +
    +	m = data->m;
    +	data->m = mnew;
    +	data->buf = mtod(mnew, uint8_t *);
    +
    +	/* finalize mbuf */
    +	m->m_pkthdr.rcvif = ifp;
    +	m->m_pkthdr.len = m->m_len = flen - 4;
    +
    +	if (ieee80211_radiotap_active(ic)) {
    +		struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap;
    +
    +		/* XXX Are variables correct?  */
    +		tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
    +		tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
    +		tap->wr_dbm_antsignal = (int8_t)rssi;
    +	}
    +
    +	wh = mtod(m, struct ieee80211_frame *);
    +	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA)
    +		sc->sc_currate = (rate > 0) ? rate : sc->sc_currate;
    +	/* XXX correct?  */
    +	if ((sc->sc_flags & URTW_RTL8187B) == 0)
    +		nf = (quality > 64) ? 0 : ((64 - quality) * 100) / 64;
    +
    +	*rssi_p = rssi;
    +	*nf_p = nf;
    +
    +	return (m);
    +}
    +
    +static usb_error_t
    +urtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain)
    +{
    +	uint8_t *gainp;
    +	usb_error_t error;
    +
    +	/* XXX for A?  */
    +	gainp = urtw_8225v2_gain_bg;
    +	urtw_8187_write_phy_ofdm(sc, 0x0d, gainp[gain * 3]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +	urtw_8187_write_phy_ofdm(sc, 0x1b, gainp[gain * 3 + 1]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +	urtw_8187_write_phy_ofdm(sc, 0x1d, gainp[gain * 3 + 2]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +	urtw_8187_write_phy_ofdm(sc, 0x21, 0x17);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan)
    +{
    +	int i;
    +	uint8_t *cck_pwrtable;
    +	uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10;
    +	uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
    +	uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
    +	usb_error_t error;
    +
    +	/* CCK power setting */
    +	cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl;
    +	cck_pwrlvl += sc->sc_txpwr_cck_base;
    +	cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
    +	cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 :
    +	    urtw_8225v2_txpwr_cck;
    +
    +	for (i = 0; i < 8; i++)
    +		urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]);
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_CCK,
    +	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +
    +	/* OFDM power setting */
    +	ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ?
    +		ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min;
    +	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
    +	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
    +
    +	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    +	if (error)
    +		goto fail;
    +
    +	urtw_8187_write_phy_ofdm(sc, 2, 0x42);
    +	urtw_8187_write_phy_ofdm(sc, 5, 0x0);
    +	urtw_8187_write_phy_ofdm(sc, 6, 0x40);
    +	urtw_8187_write_phy_ofdm(sc, 7, 0x0);
    +	urtw_8187_write_phy_ofdm(sc, 8, 0x40);
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_OFDM,
    +	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +fail:
    +	return (error);
    +}
    +
    +
     static usb_error_t
     urtw_8225v2_rf_init(struct urtw_softc *sc)
     {
    -#define N(a)	(sizeof(a) / sizeof((a)[0]))
     	int i;
     	uint16_t data;
     	uint32_t data32;
    @@ -2945,7 +3607,7 @@ urtw_8225v2_rf_init(struct urtw_softc *sc)
     
     	usb_pause_mtx(&sc->sc_mtx, 500);
     
    -	for (i = 0; i < N(urtw_8225v2_rf_part1); i++) {
    +	for (i = 0; i < nitems(urtw_8225v2_rf_part1); i++) {
     		urtw_8225_write(sc, urtw_8225v2_rf_part1[i].reg,
     		    urtw_8225v2_rf_part1[i].val);
     	}
    @@ -3000,7 +3662,7 @@ urtw_8225v2_rf_init(struct urtw_softc *sc)
     		urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80);
     	}
     
    -	for (i = 0; i < N(urtw_8225v2_rf_part2); i++) {
    +	for (i = 0; i < nitems(urtw_8225v2_rf_part2); i++) {
     		urtw_8187_write_phy_ofdm(sc, urtw_8225v2_rf_part2[i].reg,
     		    urtw_8225v2_rf_part2[i].val);
     	}
    @@ -3009,7 +3671,7 @@ urtw_8225v2_rf_init(struct urtw_softc *sc)
     	if (error)
     		goto fail;
     
    -	for (i = 0; i < N(urtw_8225v2_rf_part3); i++) {
    +	for (i = 0; i < nitems(urtw_8225v2_rf_part3); i++) {
     		urtw_8187_write_phy_cck(sc, urtw_8225v2_rf_part3[i].reg,
     		    urtw_8225v2_rf_part3[i].val);
     	}
    @@ -3032,7 +3694,6 @@ urtw_8225v2_rf_init(struct urtw_softc *sc)
     	error = urtw_8225_rf_set_chan(sc, 1);
     fail:
     	return (error);
    -#undef N
     }
     
     static usb_error_t
    @@ -3164,73 +3825,6 @@ fail:
     }
     
     
    -static usb_error_t
    -urtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan)
    -{
    -	int i;
    -	uint8_t *cck_pwrtable;
    -	uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10;
    -	uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
    -	uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
    -	usb_error_t error;
    -
    -	/* CCK power setting */
    -	cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl;
    -	cck_pwrlvl += sc->sc_txpwr_cck_base;
    -	cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
    -	cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 :
    -	    urtw_8225v2_txpwr_cck;
    -
    -	for (i = 0; i < 8; i++)
    -		urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]);
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_CCK,
    -	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -
    -	/* OFDM power setting */
    -	ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ?
    -		ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min;
    -	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
    -	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
    -
    -	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    -	if (error)
    -		goto fail;
    -
    -	urtw_8187_write_phy_ofdm(sc, 2, 0x42);
    -	urtw_8187_write_phy_ofdm(sc, 5, 0x0);
    -	urtw_8187_write_phy_ofdm(sc, 6, 0x40);
    -	urtw_8187_write_phy_ofdm(sc, 7, 0x0);
    -	urtw_8187_write_phy_ofdm(sc, 8, 0x40);
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_OFDM,
    -	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain)
    -{
    -	uint8_t *gainp;
    -	usb_error_t error;
    -
    -	/* XXX for A?  */
    -	gainp = urtw_8225v2_gain_bg;
    -	urtw_8187_write_phy_ofdm(sc, 0x0d, gainp[gain * 3]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -	urtw_8187_write_phy_ofdm(sc, 0x1b, gainp[gain * 3 + 1]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -	urtw_8187_write_phy_ofdm(sc, 0x1d, gainp[gain * 3 + 2]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -	urtw_8187_write_phy_ofdm(sc, 0x21, 0x17);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -fail:
    -	return (error);
    -}
    -
     static usb_error_t
     urtw_8225_isv2(struct urtw_softc *sc, int *ret)
     {
    @@ -3265,477 +3859,6 @@ urtw_8225_isv2(struct urtw_softc *sc, int *ret)
     fail:
     	return (error);
     }
    -
    -static usb_error_t
    -urtw_8225v2b_rf_init(struct urtw_softc *sc)
    -{
    -#define N(a)	(sizeof(a) / sizeof((a)[0]))
    -	int i;
    -	usb_error_t error;
    -
    -	for (i = 0; i < N(urtw_8225v2b_rf_part1); i++)
    -		urtw_8225_write(sc, urtw_8225v2b_rf_part1[i].reg,
    -		    urtw_8225v2b_rf_part1[i].val);
    -
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC1);
    -
    -	for (i = 0; i < N(urtw_8225v2b_rxgain); i++) {
    -		urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1));
    -		urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC,
    -		    urtw_8225v2b_rxgain[i]);
    -	}
    -
    -	urtw_8225_write(sc, URTW_8225_ADDR_3_MAGIC, 0x080);
    -	urtw_8225_write(sc, URTW_8225_ADDR_5_MAGIC, 0x004);
    -	urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x0b7);
    -	urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0xc4d);
    -	urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0x44d);
    -	urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x2bf);
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_CCK, 0x03);
    -	urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 0x07);
    -	urtw_write8_m(sc, URTW_TX_ANTENNA, 0x03);
    -
    -	urtw_8187_write_phy_ofdm(sc, 0x80, 0x12);
    -	for (i = 0; i < N(urtw_8225z2_agc); i++) {
    -		urtw_8187_write_phy_ofdm(sc, 0xf, urtw_8225z2_agc[i]);
    -		urtw_8187_write_phy_ofdm(sc, 0xe, 0x80 + i);
    -		urtw_8187_write_phy_ofdm(sc, 0xe, 0);
    -	}
    -	urtw_8187_write_phy_ofdm(sc, 0x80, 0x10);
    -
    -	for (i = 0; i < N(urtw_8225v2b_rf_part2); i++)
    -		urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val);
    -
    -	urtw_write32_m(sc, 0xf0, (7 << 12) | (3 << 8) | 0x1c);
    -	urtw_write32_m(sc, 0xf4, (7 << 12) | (3 << 8) | 0x1c);
    -	urtw_write32_m(sc, 0xf8, (7 << 12) | (3 << 8) | 0x1c);
    -	urtw_write32_m(sc, 0xfc, (7 << 12) | (3 << 8) | 0x1c);
    -	urtw_write8_m(sc, URTW_ACM_CONTROL, 0);
    -
    -	urtw_8187_write_phy_ofdm(sc, 0x97, 0x46);
    -	urtw_8187_write_phy_ofdm(sc, 0xa4, 0xb6);
    -	urtw_8187_write_phy_ofdm(sc, 0x85, 0xfc);
    -	urtw_8187_write_phy_cck(sc, 0xc1, 0x88);
    -fail:
    -	return (error);
    -#undef N
    -}
    -
    -static usb_error_t
    -urtw_8225v2b_rf_set_chan(struct urtw_softc *sc, int chan)
    -{
    -	int ack;
    -	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
    -	usb_error_t error;
    -
    -	error = urtw_8225v2b_set_txpwrlvl(sc, chan);
    -	if (error)
    -		goto fail;
    -
    -	urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]);
    -	usb_pause_mtx(&sc->sc_mtx, 10);
    -
    -	urtw_write8_m(sc, URTW_SIFS, 0xa);
    -	if (ic->ic_flags & IEEE80211_F_SHSLOT) {
    -		urtw_write8_m(sc, URTW_SLOT, 0x9);
    -		urtw_write8_m(sc, URTW_DIFS, 0x1c);
    -		/* In 8187B, BRSR + 1 ==> EIFS register */
    -		urtw_write8_m(sc, URTW_BRSR + 1, 0x53);
    -
    -		ack = 112 + 48 + 0x1c;
    -		ack += (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
    -		    72 : 144;
    -		urtw_write8_m(sc, URTW_CARRIER_SCOUNT,
    -		    roundup2(ack, 4));
    -	} else {
    -		urtw_write8_m(sc, URTW_SLOT, 0x14);
    -		urtw_write8_m(sc, URTW_DIFS, 0x32);
    -		/* In 8187B, BRSR + 1 ==> EIFS register */
    -		urtw_write8_m(sc, URTW_BRSR + 1, 0x5b);
    -
    -		ack = 112 + 48 + 0x32;
    -		ack += (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
    -		    72 : 144;
    -		urtw_write8_m(sc, URTW_CARRIER_SCOUNT,
    -		    roundup2(ack, 4));
    -
    -	}
    -
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8225v2b_set_txpwrlvl(struct urtw_softc *sc, int chan)
    -{
    -	int i;
    -	uint8_t *cck_pwrtable;
    -	uint8_t cck_pwrlvl_max = 15;
    -	uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
    -	uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
    -	usb_error_t error;
    -
    -	/* CCK power setting */
    -	cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ?
    -	    ((sc->sc_flags & URTW_RTL8187B_REV_B) ? cck_pwrlvl_max : 22) :
    -	    (cck_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 0 : 7));
    -	cck_pwrlvl += sc->sc_txpwr_cck_base;
    -	cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
    -	cck_pwrtable = (chan == 14) ? urtw_8225v2b_txpwr_cck_ch14 :
    -	    urtw_8225v2b_txpwr_cck;
    -
    -	if (sc->sc_flags & URTW_RTL8187B_REV_B)
    -		cck_pwrtable += (cck_pwrlvl <= 6) ? 0 :
    -		    ((cck_pwrlvl <= 11) ? 8 : 16);
    -	else
    -		cck_pwrtable += (cck_pwrlvl <= 5) ? 0 :
    -		    ((cck_pwrlvl <= 11) ? 8 : ((cck_pwrlvl <= 17) ? 16 : 24));
    -
    -	for (i = 0; i < 8; i++)
    -		urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]);
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_CCK,
    -	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -
    -	/* OFDM power setting */
    -	ofdm_pwrlvl = (ofdm_pwrlvl > 15) ?
    -	    ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 17 : 25) :
    -	    (ofdm_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 2 : 10));
    -	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
    -	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_OFDM,
    -	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1);
    -
    -	if (sc->sc_flags & URTW_RTL8187B_REV_B) {
    -		if (ofdm_pwrlvl <= 11) {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x60);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x60);
    -		} else {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c);
    -		}
    -	} else {
    -		if (ofdm_pwrlvl <= 11) {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c);
    -		} else if (ofdm_pwrlvl <= 17) {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x54);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x54);
    -		} else {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x50);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x50);
    -		}
    -	}
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_read8e(struct urtw_softc *sc, int val, uint8_t *data)
    -{
    -	struct usb_device_request req;
    -	usb_error_t error;
    -
    -	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_GETREGS_REQ;
    -	USETW(req.wValue, val | 0xfe00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint8_t));
    -
    -	error = urtw_do_request(sc, &req, data);
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_write8e(struct urtw_softc *sc, int val, uint8_t data)
    -{
    -	struct usb_device_request req;
    -
    -	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_SETREGS_REQ;
    -	USETW(req.wValue, val | 0xfe00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint8_t));
    -
    -	return (urtw_do_request(sc, &req, &data));
    -}
    -
    -static usb_error_t
    -urtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    -	if (error)
    -		goto fail;
    -
    -	urtw_read8_m(sc, URTW_CONFIG3, &data);
    -	urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE);
    -	urtw_write32_m(sc, URTW_ANAPARAM, val);
    -	urtw_read8_m(sc, URTW_CONFIG3, &data);
    -	urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE);
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    -	if (error)
    -		goto fail;
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    -	if (error)
    -		goto fail;
    -
    -	urtw_read8_m(sc, URTW_CONFIG3, &data);
    -	urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE);
    -	urtw_write32_m(sc, URTW_ANAPARAM2, val);
    -	urtw_read8_m(sc, URTW_CONFIG3, &data);
    -	urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE);
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    -	if (error)
    -		goto fail;
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_intr_enable(struct urtw_softc *sc)
    -{
    -	usb_error_t error;
    -
    -	urtw_write16_m(sc, URTW_INTR_MASK, 0xffff);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_intr_disable(struct urtw_softc *sc)
    -{
    -	usb_error_t error;
    -
    -	urtw_write16_m(sc, URTW_INTR_MASK, 0);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_reset(struct urtw_softc *sc)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    -	if (error)
    -		goto fail;
    -	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    -	if (error)
    -		goto fail;
    -
    -	error = urtw_intr_disable(sc);
    -	if (error)
    -		goto fail;
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -
    -	error = urtw_write8e(sc, 0x18, 0x10);
    -	if (error != 0)
    -		goto fail;
    -	error = urtw_write8e(sc, 0x18, 0x11);
    -	if (error != 0)
    -		goto fail;
    -	error = urtw_write8e(sc, 0x18, 0x00);
    -	if (error != 0)
    -		goto fail;
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -
    -	urtw_read8_m(sc, URTW_CMD, &data);
    -	data = (data & 0x2) | URTW_CMD_RST;
    -	urtw_write8_m(sc, URTW_CMD, data);
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -
    -	urtw_read8_m(sc, URTW_CMD, &data);
    -	if (data & URTW_CMD_RST) {
    -		device_printf(sc->sc_dev, "reset timeout\n");
    -		goto fail;
    -	}
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD);
    -	if (error)
    -		goto fail;
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -
    -	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    -	if (error)
    -		goto fail;
    -	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    -	if (error)
    -		goto fail;
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_led_ctl(struct urtw_softc *sc, int mode)
    -{
    -	usb_error_t error = 0;
    -
    -	switch (sc->sc_strategy) {
    -	case URTW_SW_LED_MODE0:
    -		error = urtw_led_mode0(sc, mode);
    -		break;
    -	case URTW_SW_LED_MODE1:
    -		error = urtw_led_mode1(sc, mode);
    -		break;
    -	case URTW_SW_LED_MODE2:
    -		error = urtw_led_mode2(sc, mode);
    -		break;
    -	case URTW_SW_LED_MODE3:
    -		error = urtw_led_mode3(sc, mode);
    -		break;
    -	default:
    -		panic("unsupported LED mode %d\n", sc->sc_strategy);
    -		/* never reach  */
    -	}
    -
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_led_mode0(struct urtw_softc *sc, int mode)
    -{
    -
    -	switch (mode) {
    -	case URTW_LED_CTL_POWER_ON:
    -		sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK;
    -		break;
    -	case URTW_LED_CTL_TX:
    -		if (sc->sc_gpio_ledinprogress == 1)
    -			return (0);
    -
    -		sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL;
    -		sc->sc_gpio_blinktime = 2;
    -		break;
    -	case URTW_LED_CTL_LINK:
    -		sc->sc_gpio_ledstate = URTW_LED_ON;
    -		break;
    -	default:
    -		panic("unsupported LED mode 0x%x", mode);
    -		/* never reach  */
    -	}
    -
    -	switch (sc->sc_gpio_ledstate) {
    -	case URTW_LED_ON:
    -		if (sc->sc_gpio_ledinprogress != 0)
    -			break;
    -		urtw_led_on(sc, URTW_LED_GPIO);
    -		break;
    -	case URTW_LED_BLINK_NORMAL:
    -		if (sc->sc_gpio_ledinprogress != 0)
    -			break;
    -		sc->sc_gpio_ledinprogress = 1;
    -		sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ?
    -			URTW_LED_OFF : URTW_LED_ON;
    -		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
    -		break;
    -	case URTW_LED_POWER_ON_BLINK:
    -		urtw_led_on(sc, URTW_LED_GPIO);
    -		usb_pause_mtx(&sc->sc_mtx, 100);
    -		urtw_led_off(sc, URTW_LED_GPIO);
    -		break;
    -	default:
    -		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
    -		/* never reach  */
    -	}
    -	return (0);
    -}
    -
    -static usb_error_t
    -urtw_led_mode1(struct urtw_softc *sc, int mode)
    -{
    -
    -	return (USB_ERR_INVAL);
    -}
    -
    -static usb_error_t
    -urtw_led_mode2(struct urtw_softc *sc, int mode)
    -{
    -
    -	return (USB_ERR_INVAL);
    -}
    -
    -static usb_error_t
    -urtw_led_mode3(struct urtw_softc *sc, int mode)
    -{
    -
    -	return (USB_ERR_INVAL);
    -}
    -
    -static usb_error_t
    -urtw_led_on(struct urtw_softc *sc, int type)
    -{
    -	usb_error_t error;
    -
    -	if (type == URTW_LED_GPIO) {
    -		switch (sc->sc_gpio_ledpin) {
    -		case URTW_LED_PIN_GPIO0:
    -			urtw_write8_m(sc, URTW_GPIO, 0x01);
    -			urtw_write8_m(sc, URTW_GP_ENABLE, 0x00);
    -			break;
    -		default:
    -			panic("unsupported LED PIN type 0x%x",
    -			    sc->sc_gpio_ledpin);
    -			/* never reach  */
    -		}
    -	} else {
    -		panic("unsupported LED type 0x%x", type);
    -		/* never reach  */
    -	}
    -
    -	sc->sc_gpio_ledon = 1;
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_led_off(struct urtw_softc *sc, int type)
    -{
    -	usb_error_t error;
    -
    -	if (type == URTW_LED_GPIO) {
    -		switch (sc->sc_gpio_ledpin) {
    -		case URTW_LED_PIN_GPIO0:
    -			urtw_write8_m(sc, URTW_GPIO, URTW_GPIO_DATA_MAGIC1);
    -			urtw_write8_m(sc,
    -			    URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1);
    -			break;
    -		default:
    -			panic("unsupported LED PIN type 0x%x",
    -			    sc->sc_gpio_ledpin);
    -			/* never reach  */
    -		}
    -	} else {
    -		panic("unsupported LED type 0x%x", type);
    -		/* never reach  */
    -	}
    -
    -	sc->sc_gpio_ledon = 0;
    -
    -fail:
    -	return (error);
    -}
    -
     static void
     urtw_led_ch(void *arg)
     {
    @@ -3745,277 +3868,6 @@ urtw_led_ch(void *arg)
     
     	ieee80211_runtask(ic, &sc->sc_led_task);
     }
    -
    -static void
    -urtw_ledtask(void *arg, int pending)
    -{
    -	struct urtw_softc *sc = arg;
    -
    -	if (sc->sc_strategy != URTW_SW_LED_MODE0)
    -		panic("could not process a LED strategy 0x%x", sc->sc_strategy);
    -
    -	URTW_LOCK(sc);
    -	urtw_led_blink(sc);
    -	URTW_UNLOCK(sc);
    -}
    -
    -static usb_error_t
    -urtw_led_blink(struct urtw_softc *sc)
    -{
    -	uint8_t ing = 0;
    -	usb_error_t error;
    -
    -	if (sc->sc_gpio_blinkstate == URTW_LED_ON)
    -		error = urtw_led_on(sc, URTW_LED_GPIO);
    -	else
    -		error = urtw_led_off(sc, URTW_LED_GPIO);
    -	sc->sc_gpio_blinktime--;
    -	if (sc->sc_gpio_blinktime == 0)
    -		ing = 1;
    -	else {
    -		if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL &&
    -		    sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY &&
    -		    sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3)
    -			ing = 1;
    -	}
    -	if (ing == 1) {
    -		if (sc->sc_gpio_ledstate == URTW_LED_ON &&
    -		    sc->sc_gpio_ledon == 0)
    -			error = urtw_led_on(sc, URTW_LED_GPIO);
    -		else if (sc->sc_gpio_ledstate == URTW_LED_OFF &&
    -		    sc->sc_gpio_ledon == 1)
    -			error = urtw_led_off(sc, URTW_LED_GPIO);
    -
    -		sc->sc_gpio_blinktime = 0;
    -		sc->sc_gpio_ledinprogress = 0;
    -		return (0);
    -	}
    -
    -	sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ?
    -	    URTW_LED_ON : URTW_LED_OFF;
    -
    -	switch (sc->sc_gpio_ledstate) {
    -	case URTW_LED_BLINK_NORMAL:
    -		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
    -		break;
    -	default:
    -		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
    -		/* never reach  */
    -	}
    -	return (0);
    -}
    -
    -static usb_error_t
    -urtw_rx_enable(struct urtw_softc *sc)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	usbd_transfer_start((sc->sc_flags & URTW_RTL8187B) ?
    -	    sc->sc_xfer[URTW_8187B_BULK_RX] : sc->sc_xfer[URTW_8187L_BULK_RX]);
    -
    -	error = urtw_rx_setconf(sc);
    -	if (error != 0)
    -		goto fail;
    -
    -	urtw_read8_m(sc, URTW_CMD, &data);
    -	urtw_write8_m(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_tx_enable(struct urtw_softc *sc)
    -{
    -	uint8_t data8;
    -	uint32_t data;
    -	usb_error_t error;
    -
    -	if (sc->sc_flags & URTW_RTL8187B) {
    -		urtw_read32_m(sc, URTW_TX_CONF, &data);
    -		data &= ~URTW_TX_LOOPBACK_MASK;
    -		data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
    -		data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
    -		data &= ~URTW_TX_SWPLCPLEN;
    -		data |= URTW_TX_HW_SEQNUM | URTW_TX_DISREQQSIZE |
    -		    (7 << 8) |	/* short retry limit */
    -		    (7 << 0) |	/* long retry limit */
    -		    (7 << 21);	/* MAX TX DMA */
    -		urtw_write32_m(sc, URTW_TX_CONF, data);
    -
    -		urtw_read8_m(sc, URTW_CMD, &data8);
    -		urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE);
    -		return (error);
    -	}
    -
    -	urtw_read8_m(sc, URTW_CW_CONF, &data8);
    -	data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY);
    -	urtw_write8_m(sc, URTW_CW_CONF, data8);
    -
    -	urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8);
    -	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN;
    -	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL;
    -	data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT;
    -	urtw_write8_m(sc, URTW_TX_AGC_CTL, data8);
    -
    -	urtw_read32_m(sc, URTW_TX_CONF, &data);
    -	data &= ~URTW_TX_LOOPBACK_MASK;
    -	data |= URTW_TX_LOOPBACK_NONE;
    -	data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
    -	data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT;
    -	data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT;
    -	data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
    -	data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW;
    -	data &= ~URTW_TX_SWPLCPLEN;
    -	data |= URTW_TX_NOICV;
    -	urtw_write32_m(sc, URTW_TX_CONF, data);
    -
    -	urtw_read8_m(sc, URTW_CMD, &data8);
    -	urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_rx_setconf(struct urtw_softc *sc)
    -{
    -	struct ifnet *ifp = sc->sc_ifp;
    -	struct ieee80211com *ic = ifp->if_l2com;
    -	uint32_t data;
    -	usb_error_t error;
    -
    -	urtw_read32_m(sc, URTW_RX, &data);
    -	data = data &~ URTW_RX_FILTER_MASK;
    -	if (sc->sc_flags & URTW_RTL8187B) {
    -		data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA |
    -		    URTW_RX_FILTER_MCAST | URTW_RX_FILTER_BCAST |
    -		    URTW_RX_FILTER_NICMAC | URTW_RX_CHECK_BSSID |
    -		    URTW_RX_FIFO_THRESHOLD_NONE |
    -		    URTW_MAX_RX_DMA_2048 |
    -		    URTW_RX_AUTORESETPHY | URTW_RCR_ONLYERLPKT;
    -	} else {
    -		data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA;
    -		data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST;
    -
    -		if (ic->ic_opmode == IEEE80211_M_MONITOR) {
    -			data = data | URTW_RX_FILTER_ICVERR;
    -			data = data | URTW_RX_FILTER_PWR;
    -		}
    -		if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR)
    -			data = data | URTW_RX_FILTER_CRCERR;
    -
    -		if (ic->ic_opmode == IEEE80211_M_MONITOR ||
    -		    (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
    -			data = data | URTW_RX_FILTER_ALLMAC;
    -		} else {
    -			data = data | URTW_RX_FILTER_NICMAC;
    -			data = data | URTW_RX_CHECK_BSSID;
    -		}
    -
    -		data = data &~ URTW_RX_FIFO_THRESHOLD_MASK;
    -		data = data | URTW_RX_FIFO_THRESHOLD_NONE |
    -		    URTW_RX_AUTORESETPHY;
    -		data = data &~ URTW_MAX_RX_DMA_MASK;
    -		data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT;
    -	}
    -
    -	urtw_write32_m(sc, URTW_RX, data);
    -fail:
    -	return (error);
    -}
    -
    -static struct mbuf *
    -urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
    -    int8_t *nf_p)
    -{
    -	int actlen, flen, len, nf = -95, rssi;
    -	struct ieee80211_frame *wh;
    -	struct mbuf *m, *mnew;
    -	struct urtw_8187b_rxhdr *bhdr;
    -	struct urtw_softc *sc = data->sc;
    -	struct ifnet *ifp = sc->sc_ifp;
    -	struct ieee80211com *ic = ifp->if_l2com;
    -	uint8_t *desc, quality = 0, rate;
    -
    -	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
    -
    -	if (actlen < URTW_MIN_RXBUFSZ) {
    -		ifp->if_ierrors++;
    -		return (NULL);
    -	}
    -
    -	if (sc->sc_flags & URTW_RTL8187B) {
    -		len = actlen - (sizeof(struct urtw_8187b_rxhdr));
    -		bhdr = (struct urtw_8187b_rxhdr *)(data->buf + len);
    -		desc = data->buf + len;
    -		flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
    -		if (flen > actlen) {
    -			ifp->if_ierrors++;
    -			return (NULL);
    -		}
    -		rate = (le32toh(bhdr->flags) >> 20) & 0xf;
    -		rssi = 14 + (bhdr->rssi / 2);
    -		if (rssi > 95)
    -			rssi = 95;
    -	} else {
    -		/* 4 dword and 4 byte CRC  */
    -		len = actlen - (4 * 4);
    -		desc = data->buf + len;
    -		flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
    -		if (flen > actlen) {
    -			ifp->if_ierrors++;
    -			return (NULL);
    -		}
    -
    -		rate = (desc[2] & 0xf0) >> 4;
    -		quality = desc[4] & 0xff;
    -		/* XXX correct?  */
    -		rssi = (desc[6] & 0xfe) >> 1;
    -		if (!urtw_isbmode(rate)) {
    -			rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi);
    -			rssi = ((90 - rssi) * 100) / 65;
    -		} else {
    -			rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi);
    -			rssi = ((95 - rssi) * 100) / 65;
    -		}
    -	}
    -
    -	mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
    -	if (mnew == NULL) {
    -		ifp->if_ierrors++;
    -		return (NULL);
    -	}
    -
    -	m = data->m;
    -	data->m = mnew;
    -	data->buf = mtod(mnew, uint8_t *);
    -
    -	/* finalize mbuf */
    -	m->m_pkthdr.rcvif = ifp;
    -	m->m_pkthdr.len = m->m_len = flen - 4;
    -
    -	if (ieee80211_radiotap_active(ic)) {
    -		struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap;
    -
    -		/* XXX Are variables correct?  */
    -		tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
    -		tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
    -		tap->wr_dbm_antsignal = (int8_t)rssi;
    -	}
    -
    -	wh = mtod(m, struct ieee80211_frame *);
    -	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA)
    -		sc->sc_currate = (rate > 0) ? rate : sc->sc_currate;
    -	/* XXX correct?  */
    -	if ((sc->sc_flags & URTW_RTL8187B) == 0)
    -		nf = (quality > 64) ? 0 : ((64 - quality) * 100) / 64;
    -
    -	*rssi_p = rssi;
    -	*nf_p = nf;
    -
    -	return (m);
    -}
    -
     static void
     urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
     {
    @@ -4206,16 +4058,175 @@ urtw_getbuf(struct urtw_softc *sc)
     	return (bf);
     }
     
    -static int
    -urtw_isbmode(uint16_t rate)
    +static usb_error_t
    +urtw_8225v2b_rf_init(struct urtw_softc *sc)
     {
    +	int i;
    +	usb_error_t error;
     
    -	rate = urtw_rtl2rate(rate);
    +	for (i = 0; i < nitems(urtw_8225v2b_rf_part1); i++)
    +		urtw_8225_write(sc, urtw_8225v2b_rf_part1[i].reg,
    +		    urtw_8225v2b_rf_part1[i].val);
     
    -	return ((rate <= 22 && rate != 12 && rate != 18) ||
    -	    rate == 44) ? (1) : (0);
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC1);
    +
    +	for (i = 0; i < nitems(urtw_8225v2b_rxgain); i++) {
    +		urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1));
    +		urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC,
    +		    urtw_8225v2b_rxgain[i]);
    +	}
    +
    +	urtw_8225_write(sc, URTW_8225_ADDR_3_MAGIC, 0x080);
    +	urtw_8225_write(sc, URTW_8225_ADDR_5_MAGIC, 0x004);
    +	urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x0b7);
    +	urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0xc4d);
    +	urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0x44d);
    +	urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x2bf);
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_CCK, 0x03);
    +	urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 0x07);
    +	urtw_write8_m(sc, URTW_TX_ANTENNA, 0x03);
    +
    +	urtw_8187_write_phy_ofdm(sc, 0x80, 0x12);
    +	for (i = 0; i < nitems(urtw_8225z2_agc); i++) {
    +		urtw_8187_write_phy_ofdm(sc, 0xf, urtw_8225z2_agc[i]);
    +		urtw_8187_write_phy_ofdm(sc, 0xe, 0x80 + i);
    +		urtw_8187_write_phy_ofdm(sc, 0xe, 0);
    +	}
    +	urtw_8187_write_phy_ofdm(sc, 0x80, 0x10);
    +
    +	for (i = 0; i < nitems(urtw_8225v2b_rf_part2); i++)
    +		urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val);
    +
    +	urtw_write32_m(sc, 0xf0, (7 << 12) | (3 << 8) | 0x1c);
    +	urtw_write32_m(sc, 0xf4, (7 << 12) | (3 << 8) | 0x1c);
    +	urtw_write32_m(sc, 0xf8, (7 << 12) | (3 << 8) | 0x1c);
    +	urtw_write32_m(sc, 0xfc, (7 << 12) | (3 << 8) | 0x1c);
    +	urtw_write8_m(sc, URTW_ACM_CONTROL, 0);
    +
    +	urtw_8187_write_phy_ofdm(sc, 0x97, 0x46);
    +	urtw_8187_write_phy_ofdm(sc, 0xa4, 0xb6);
    +	urtw_8187_write_phy_ofdm(sc, 0x85, 0xfc);
    +	urtw_8187_write_phy_cck(sc, 0xc1, 0x88);
    +fail:
    +	return (error);
     }
     
    +
    +static usb_error_t
    +urtw_8225v2b_rf_set_chan(struct urtw_softc *sc, int chan)
    +{
    +	int ack;
    +	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
    +	usb_error_t error;
    +
    +	error = urtw_8225v2b_set_txpwrlvl(sc, chan);
    +	if (error)
    +		goto fail;
    +
    +	urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]);
    +	usb_pause_mtx(&sc->sc_mtx, 10);
    +
    +	urtw_write8_m(sc, URTW_SIFS, 0xa);
    +	if (ic->ic_flags & IEEE80211_F_SHSLOT) {
    +		urtw_write8_m(sc, URTW_SLOT, 0x9);
    +		urtw_write8_m(sc, URTW_DIFS, 0x1c);
    +		/* In 8187B, BRSR + 1 ==> EIFS register */
    +		urtw_write8_m(sc, URTW_BRSR + 1, 0x53);
    +
    +		ack = 112 + 48 + 0x1c;
    +		ack += (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
    +		    72 : 144;
    +		urtw_write8_m(sc, URTW_CARRIER_SCOUNT,
    +		    roundup2(ack, 4));
    +	} else {
    +		urtw_write8_m(sc, URTW_SLOT, 0x14);
    +		urtw_write8_m(sc, URTW_DIFS, 0x32);
    +		/* In 8187B, BRSR + 1 ==> EIFS register */
    +		urtw_write8_m(sc, URTW_BRSR + 1, 0x5b);
    +
    +		ack = 112 + 48 + 0x32;
    +		ack += (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
    +		    72 : 144;
    +		urtw_write8_m(sc, URTW_CARRIER_SCOUNT,
    +		    roundup2(ack, 4));
    +
    +	}
    +
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8225v2b_set_txpwrlvl(struct urtw_softc *sc, int chan)
    +{
    +	int i;
    +	uint8_t *cck_pwrtable;
    +	uint8_t cck_pwrlvl_max = 15;
    +	uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
    +	uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
    +	usb_error_t error;
    +
    +	/* CCK power setting */
    +	cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ?
    +	    ((sc->sc_flags & URTW_RTL8187B_REV_B) ? cck_pwrlvl_max : 22) :
    +	    (cck_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 0 : 7));
    +	cck_pwrlvl += sc->sc_txpwr_cck_base;
    +	cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
    +	cck_pwrtable = (chan == 14) ? urtw_8225v2b_txpwr_cck_ch14 :
    +	    urtw_8225v2b_txpwr_cck;
    +
    +	if (sc->sc_flags & URTW_RTL8187B_REV_B)
    +		cck_pwrtable += (cck_pwrlvl <= 6) ? 0 :
    +		    ((cck_pwrlvl <= 11) ? 8 : 16);
    +	else
    +		cck_pwrtable += (cck_pwrlvl <= 5) ? 0 :
    +		    ((cck_pwrlvl <= 11) ? 8 : ((cck_pwrlvl <= 17) ? 16 : 24));
    +
    +	for (i = 0; i < 8; i++)
    +		urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]);
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_CCK,
    +	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +
    +	/* OFDM power setting */
    +	ofdm_pwrlvl = (ofdm_pwrlvl > 15) ?
    +	    ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 17 : 25) :
    +	    (ofdm_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 2 : 10));
    +	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
    +	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_OFDM,
    +	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1);
    +
    +	if (sc->sc_flags & URTW_RTL8187B_REV_B) {
    +		if (ofdm_pwrlvl <= 11) {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x60);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x60);
    +		} else {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c);
    +		}
    +	} else {
    +		if (ofdm_pwrlvl <= 11) {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c);
    +		} else if (ofdm_pwrlvl <= 17) {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x54);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x54);
    +		} else {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x50);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x50);
    +		}
    +	}
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +fail:
    +	return (error);
    +}
    +
    +
     static device_method_t urtw_methods[] = {
     	DEVMETHOD(device_probe, urtw_match),
     	DEVMETHOD(device_attach, urtw_attach),
    diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
    index 616c5d7b330..74653d1e2a8 100644
    --- a/sys/dev/wi/if_wi.c
    +++ b/sys/dev/wi/if_wi.c
    @@ -1673,6 +1673,7 @@ wi_read_nicid(struct wi_softc *sc)
     		memset(ident, 0, sizeof(ident));
     		len = sizeof(ident);
     		/* value should be the format like "V2.00-11" */
    +		/* XXX: Flexelint: ident is local, p is arg */
     		if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
     		    *(p = (char *)ident) >= 'A' &&
     		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
    diff --git a/sys/fs/msdosfs/msdosfs_conv.c b/sys/fs/msdosfs/msdosfs_conv.c
    index 50dc1a06cc9..b9b6f4ad3fd 100644
    --- a/sys/fs/msdosfs/msdosfs_conv.c
    +++ b/sys/fs/msdosfs/msdosfs_conv.c
    @@ -266,6 +266,7 @@ dos2unixfn(dn, un, lower, pmp)
     		*un++ = c;
     		thislong++;
     	}
    +	/* XXX: FlexeLint: Not kosher, dn is an array, not a pointer */
     	dn += i;
     
     	/*
    diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
    index 0cc330cd5ad..47baeea70db 100644
    --- a/sys/kern/kern_jail.c
    +++ b/sys/kern/kern_jail.c
    @@ -1641,6 +1641,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
     #ifdef INET6
     	while (redo_ip6) {
     		ip6s = pr->pr_ip6s;
    +		/* XXX: FlexeLint claims mem leak */
     		ip6 = malloc(ip6s * sizeof(*ip6), M_PRISON, M_WAITOK);
     		mtx_lock(&pr->pr_mtx);
     		redo_ip6 = 0;
    diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
    index 9387ba8ea97..cfe316f952d 100644
    --- a/sys/kern/kern_linker.c
    +++ b/sys/kern/kern_linker.c
    @@ -1875,6 +1875,7 @@ linker_search_kld(const char *name)
     		return (linker_strdup(name));
     
     	/* traverse the linker path */
    +	/* XXX: FlexeLint: this is not safe, ep will count past NUL */
     	len = strlen(name);
     	for (ep = linker_path; *ep; ep++) {
     		cp = ep;
    diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
    index e6f2f536249..92009fa3a06 100644
    --- a/sys/kern/kern_lock.c
    +++ b/sys/kern/kern_lock.c
    @@ -312,6 +312,7 @@ lock_lockmgr(struct lock_object *lock, int how)
     	panic("lockmgr locks do not support sleep interlocking");
     }
     
    +/* XXX: flexelint retval */
     static int
     unlock_lockmgr(struct lock_object *lock)
     {
    diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c
    index 85ca646370d..4a425bb97f4 100644
    --- a/sys/kern/kern_mutex.c
    +++ b/sys/kern/kern_mutex.c
    @@ -133,28 +133,28 @@ struct lock_class lock_class_mtx_spin = {
     struct mtx blocked_lock;
     struct mtx Giant;
     
    -void
    +static void
     assert_mtx(struct lock_object *lock, int what)
     {
     
     	mtx_assert((struct mtx *)lock, what);
     }
     
    -void
    +static void
     lock_mtx(struct lock_object *lock, int how)
     {
     
     	mtx_lock((struct mtx *)lock);
     }
     
    -void
    +static void
     lock_spin(struct lock_object *lock, int how)
     {
     
     	panic("spin locks can only use msleep_spin");
     }
     
    -int
    +static int
     unlock_mtx(struct lock_object *lock)
     {
     	struct mtx *m;
    @@ -165,7 +165,8 @@ unlock_mtx(struct lock_object *lock)
     	return (0);
     }
     
    -int
    +/* XXX: FlexeLint retval */
    +static int
     unlock_spin(struct lock_object *lock)
     {
     
    diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c
    index 5371f6e975d..8c11471c89a 100644
    --- a/sys/net80211/ieee80211_action.c
    +++ b/sys/net80211/ieee80211_action.c
    @@ -105,7 +105,7 @@ ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f)
     		meshlm_send_action[act] = f;
     		return 0;
     	case IEEE80211_ACTION_CAT_MESHPATH:
    -		if (act > N(hwmp_send_action))
    +		if (act >= N(hwmp_send_action))
     			break;
     		hwmp_send_action[act] = f;
     		return 0;
    diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
    index 9bfbc61715f..b7c2c43f014 100644
    --- a/sys/net80211/ieee80211_proto.h
    +++ b/sys/net80211/ieee80211_proto.h
    @@ -315,7 +315,7 @@ struct ieee80211_beacon_offsets {
     	uint8_t		*bo_ath;	/* start of ATH parameters */
     	uint8_t		*bo_appie;	/* start of AppIE element */
     	uint16_t	bo_appie_len;	/* AppIE length in bytes */
    -	uint16_t	bo_csa_trailer_len;;
    +	uint16_t	bo_csa_trailer_len;
     	uint8_t		*bo_csa;	/* start of CSA element */
     	uint8_t		*bo_spare[4];
     };
    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 
    
    From 677843147820e9e8d581cf9841ea01a567324d3b Mon Sep 17 00:00:00 2001
    From: Poul-Henning Kamp 
    Date: Tue, 8 Sep 2009 13:19:05 +0000
    Subject: [PATCH 441/453] Revert previous commit and add myself to the list of
     people who should know better than to commit with a cat in the area.
    
    ---
     sys/cam/scsi/scsi_cd.c                    |    2 +-
     sys/contrib/dev/acpica/executer/exfldio.c |    1 -
     sys/dev/aac/aac.c                         |    2 +-
     sys/dev/ae/if_ae.c                        |    2 -
     sys/dev/amr/amr.c                         |    2 +-
     sys/dev/ata/ata-raid.c                    |    3 +-
     sys/dev/ata/chipsets/ata-acerlabs.c       |    1 -
     sys/dev/ata/chipsets/ata-marvell.c        |    2 +-
     sys/dev/ath/ah_osdep.c                    |    1 -
     sys/dev/ath/ath_hal/ah.c                  |    1 -
     sys/dev/ath/ath_hal/ah_eeprom_v3.c        |    2 -
     sys/dev/bce/if_bce.c                      |    8 +-
     sys/dev/e1000/if_em.c                     |    2 +-
     sys/dev/ep/if_ep.c                        |    1 -
     sys/dev/ep/if_epreg.h                     |    6 +-
     sys/dev/firewire/fwcrom.c                 |    4 +-
     sys/dev/firewire/fwdev.c                  |    1 -
     sys/dev/fxp/if_fxp.c                      |    1 -
     sys/dev/hptiop/hptiop.c                   |    2 -
     sys/dev/iir/iir.c                         |    1 -
     sys/dev/mpt/mpt_raid.c                    |    1 -
     sys/dev/msk/if_msk.c                      |    5 +
     sys/dev/usb/wlan/if_rum.c                 |    5 +-
     sys/dev/usb/wlan/if_rumreg.h              |    2 +-
     sys/dev/usb/wlan/if_urtw.c                | 2681 ++++++++++-----------
     sys/dev/wi/if_wi.c                        |    1 -
     sys/fs/msdosfs/msdosfs_conv.c             |    1 -
     sys/kern/kern_jail.c                      |    1 -
     sys/kern/kern_linker.c                    |    1 -
     sys/kern/kern_lock.c                      |    1 -
     sys/kern/kern_mutex.c                     |   11 +-
     sys/net80211/ieee80211_action.c           |    2 +-
     sys/net80211/ieee80211_proto.h            |    2 +-
     sys/security/audit/audit_bsm_token.c      |    1 -
     34 files changed, 1365 insertions(+), 1395 deletions(-)
    
    diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
    index 52f73113d64..287c6b626f3 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.mode_buf, M_SCSICD);
    +				free(¶ms, M_SCSICD);
     				cam_periph_unlock(periph);
     				break;
     			}
    diff --git a/sys/contrib/dev/acpica/executer/exfldio.c b/sys/contrib/dev/acpica/executer/exfldio.c
    index 1b819c0d206..f59dd6214c3 100644
    --- a/sys/contrib/dev/acpica/executer/exfldio.c
    +++ b/sys/contrib/dev/acpica/executer/exfldio.c
    @@ -992,7 +992,6 @@ AcpiExInsertIntoField (
     
         /* Get initial Datum from the input buffer */
     
    -    /* XXX: Flexelint sees arg 9 for bufferlen 8 */
         ACPI_MEMCPY (&RawDatum, Buffer,
             ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
                 BufferLength - BufferOffset));
    diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
    index 5c3180b8395..f3d931aaf06 100644
    --- a/sys/dev/aac/aac.c
    +++ b/sys/dev/aac/aac.c
    @@ -3556,7 +3556,7 @@ aac_supported_features(struct aac_softc *sc, caddr_t uptr)
     	 * associated with the feature in the data field or perform whatever
     	 * action needed indicates in the data field.
     	 */
    -	if (f.feat.fValue == 0) {
    +	 if (f.feat.fValue == 0) {
     		f.feat.fBits.largeLBA =
     		    (sc->flags & AAC_FLAGS_LBA_64BIT) ? 1 : 0;
     		/* TODO: In the future, add other features state here as well */
    diff --git a/sys/dev/ae/if_ae.c b/sys/dev/ae/if_ae.c
    index a5837c346f3..da26ee79951 100644
    --- a/sys/dev/ae/if_ae.c
    +++ b/sys/dev/ae/if_ae.c
    @@ -1662,7 +1662,6 @@ ae_stop_rxmac(ae_softc_t *sc)
     	/*
     	 * Wait for IDLE state.
     	 */
    -	/* XXX: Flexelint  "<" test with -- */
     	for (i = 0; i < AE_IDLE_TIMEOUT; i--) {
     		val = AE_READ_4(sc, AE_IDLE_REG);
     		if ((val & (AE_IDLE_RXMAC | AE_IDLE_DMAWRITE)) == 0)
    @@ -1699,7 +1698,6 @@ ae_stop_txmac(ae_softc_t *sc)
     	/*
     	 * Wait for IDLE state.
     	 */
    -	/* XXX: Flexelint  "<" test with -- */
     	for (i = 0; i < AE_IDLE_TIMEOUT; i--) {
     		val = AE_READ_4(sc, AE_IDLE_REG);
     		if ((val & (AE_IDLE_TXMAC | AE_IDLE_DMAREAD)) == 0)
    diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
    index 463ec532879..2061fcc801f 100644
    --- a/sys/dev/amr/amr.c
    +++ b/sys/dev/amr/amr.c
    @@ -527,7 +527,7 @@ amr_rescan_drives(struct cdev *dev)
     		sc->amr_drive[i].al_disk)) != 0)
     		goto shutdown_out;
     
    -	    sc->amr_drive[i].al_disk = 0;
    +	     sc->amr_drive[i].al_disk = 0;
     	}
         }
     
    diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
    index d31bcebf4e5..fc6a23c0461 100644
    --- a/sys/dev/ata/ata-raid.c
    +++ b/sys/dev/ata/ata-raid.c
    @@ -407,7 +407,7 @@ ata_raid_strategy(struct bio *bp)
     	    if (rdp->status & AR_S_REBUILDING)
     		blk = ((lba / rdp->interleave) * rdp->width) * rdp->interleave +
     		      (rdp->interleave * (drv % rdp->width)) +
    -		      lba % rdp->interleave;
    +		      lba % rdp->interleave;;
     
     	    if (bp->bio_cmd == BIO_READ) {
     		int src_online =
    @@ -1138,7 +1138,6 @@ ata_raid_create(struct ata_ioc_raid_config *config)
     	rdp->type == AR_T_RAID5) {
     	int bit = 0;
     
    -	/* XXX: Flexelint not happy */
     	while (config->interleave >>= 1)
     	    bit++;
     	rdp->interleave = 1 << bit;
    diff --git a/sys/dev/ata/chipsets/ata-acerlabs.c b/sys/dev/ata/chipsets/ata-acerlabs.c
    index 9d19fa0382c..cf503c591b2 100644
    --- a/sys/dev/ata/chipsets/ata-acerlabs.c
    +++ b/sys/dev/ata/chipsets/ata-acerlabs.c
    @@ -127,7 +127,6 @@ ata_ali_chipinit(device_t dev)
     		    RF_ACTIVE);
     		if (res->bars[i] == NULL) {
     			device_printf(dev, "Failed to allocate BAR %d\n", i);
    -			/* XXX: Flexelint: Reuse of for loop variable 'i' at 'line 124' could cause chaos */
     			for (i--; i >=0; i--)
     				bus_release_resource(dev, SYS_RES_IOPORT,
     				    PCIR_BAR(i), res->bars[i]);
    diff --git a/sys/dev/ata/chipsets/ata-marvell.c b/sys/dev/ata/chipsets/ata-marvell.c
    index bab3267972b..0544e199ed0 100644
    --- a/sys/dev/ata/chipsets/ata-marvell.c
    +++ b/sys/dev/ata/chipsets/ata-marvell.c
    @@ -153,7 +153,7 @@ ata_marvell_pata_ch_attach(device_t dev)
     	return ENXIO;
      
         /* dont use 32 bit PIO transfers */
    -    ch->flags |= ATA_USE_16BIT;
    +	ch->flags |= ATA_USE_16BIT;
     
         return 0;
     }
    diff --git a/sys/dev/ath/ah_osdep.c b/sys/dev/ath/ah_osdep.c
    index c37ef142659..6b11b212fea 100644
    --- a/sys/dev/ath/ah_osdep.c
    +++ b/sys/dev/ath/ah_osdep.c
    @@ -107,7 +107,6 @@ ath_hal_malloc(size_t size)
     	return malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO);
     }
     
    -/* XXX: FlexeLint return in void function ? */
     void
     ath_hal_free(void* p)
     {
    diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c
    index db47dd24425..cff9613616a 100644
    --- a/sys/dev/ath/ath_hal/ah.c
    +++ b/sys/dev/ath/ath_hal/ah.c
    @@ -566,7 +566,6 @@ ath_hal_getregdump(struct ath_hal *ah, const HAL_REGRANGE *regs,
     	uint32_t *dp = dstbuf;
     	int i;
     
    -	/* XXX: FlexeLint: ">" test with ++ */
     	for (i = 0; space >= 2*sizeof(uint32_t); i++) {
     		u_int r = regs[i].start;
     		u_int e = regs[i].end;
    diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v3.c b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
    index fef9a459437..89a23c9f9fd 100644
    --- a/sys/dev/ath/ath_hal/ah_eeprom_v3.c
    +++ b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
    @@ -1753,8 +1753,6 @@ legacyEepromGetSpurChan(struct ath_hal *ah, int ix, HAL_BOOL is2GHz)
     /*
      * Reclaim any EEPROM-related storage.
      */
    -
    -/* XXX: FlexeLint: return in void function */
     static void
     legacyEepromDetach(struct ath_hal *ah)
     {
    diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
    index 76e22d9b96f..431ed9f24f7 100644
    --- a/sys/dev/bce/if_bce.c
    +++ b/sys/dev/bce/if_bce.c
    @@ -608,17 +608,17 @@ bce_print_adapter_info(struct bce_softc *sc)
     #endif
         if (sc->bce_flags & BCE_USING_MSI_FLAG) {
             if (i > 0) printf("|");
    -	printf("MSI"); i++;
    +		printf("MSI"); i++;
         }
     
         if (sc->bce_flags & BCE_USING_MSIX_FLAG) {
             if (i > 0) printf("|");
    -	printf("MSI-X "); i++;
    +		printf("MSI-X "); i++;
         }
     
         if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) {
             if (i > 0) printf("|");
    -	printf("2.5G"); i++;
    +		printf("2.5G"); i++;
         }
     
         if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) {
    @@ -628,7 +628,7 @@ bce_print_adapter_info(struct bce_softc *sc)
             printf(")\n");
         }
     
    -    DBEXIT(BCE_VERBOSE_LOAD);
    +	DBEXIT(BCE_VERBOSE_LOAD);
     }
     
     
    diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
    index ee580dbfaae..1def87631db 100644
    --- a/sys/dev/e1000/if_em.c
    +++ b/sys/dev/e1000/if_em.c
    @@ -2826,7 +2826,7 @@ em_allocate_pci_resources(struct adapter *adapter)
      *  Setup the Legacy or MSI Interrupt handler
      *
      **********************************************************************/
    -static int
    +int
     em_allocate_legacy(struct adapter *adapter)
     {
     	device_t dev = adapter->dev;
    diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
    index 0a7e8085396..f5fd475f85a 100644
    --- a/sys/dev/ep/if_ep.c
    +++ b/sys/dev/ep/if_ep.c
    @@ -666,7 +666,6 @@ rescan:
     						sc->tx_underrun++;
     #endif
     					} else {
    -						/* XXX: FlexeLint doesn't like ; */
     						if (status & TXS_JABBER);
     						else
     							++ifp->if_collisions;
    diff --git a/sys/dev/ep/if_epreg.h b/sys/dev/ep/if_epreg.h
    index 8c464033608..f3c269f5561 100644
    --- a/sys/dev/ep/if_epreg.h
    +++ b/sys/dev/ep/if_epreg.h
    @@ -315,11 +315,7 @@
     				 S_TX_AVAIL|S_RX_COMPLETE|S_RX_EARLY)
     #define S_COMMAND_IN_PROGRESS	(u_short) (0x1000)
     
    -#define EP_BUSY_WAIT(sc) 							\
    -	do {									\
    -		while (CSR_READ_2(sc, EP_STATUS) & S_COMMAND_IN_PROGRESS)	\
    -			continue;						\
    -	} while (0)
    +#define EP_BUSY_WAIT(sc) while (CSR_READ_2(sc, EP_STATUS) & S_COMMAND_IN_PROGRESS)
     
     /* Address Config. Register.
      * Window 0/Port 06
    diff --git a/sys/dev/firewire/fwcrom.c b/sys/dev/firewire/fwcrom.c
    index 9bafd2193c5..8a53bc7fae7 100644
    --- a/sys/dev/firewire/fwcrom.c
    +++ b/sys/dev/firewire/fwcrom.c
    @@ -454,9 +454,9 @@ crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent,
     	len = strlen(buf);
     	if (len > MAX_TEXT) {
     #if defined(__DragonFly__) || __FreeBSD_version < 500000
    -		printf("text(%d) truncated to %d.\n", len, MAX_TEXT);
    +		printf("text(%d) trancated to %d.\n", len, MAX_TEXT);
     #else
    -		printf("text(%d) truncated to %td.\n", len, MAX_TEXT);
    +		printf("text(%d) trancated to %td.\n", len, MAX_TEXT);
     #endif
     		len = MAX_TEXT;
     	}
    diff --git a/sys/dev/firewire/fwdev.c b/sys/dev/firewire/fwdev.c
    index 57d68f8f291..0facb6e3963 100644
    --- a/sys/dev/firewire/fwdev.c
    +++ b/sys/dev/firewire/fwdev.c
    @@ -844,7 +844,6 @@ out:
     		err = copyout(ptr, crom_buf->ptr, len);
     		if (fwdev == NULL)
     			/* myself */
    -			/* XXX: Flexelint no sure about modified pointer */
     			free(ptr, M_FW);
     		break;
     	default:
    diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
    index 57ac1fb0b53..4fb890f02b0 100644
    --- a/sys/dev/fxp/if_fxp.c
    +++ b/sys/dev/fxp/if_fxp.c
    @@ -1597,7 +1597,6 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
     		cbp->tbd_number = nseg;
     	/* Configure TSO. */
     	if (m->m_pkthdr.csum_flags & CSUM_TSO) {
    -		/* XXX: FlexeLint: negative subscript */
     		cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16);
     		cbp->tbd[1].tb_size |= htole32(tcp_payload << 16);
     		cbp->ipcb_ip_schedule |= FXP_IPCB_LARGESEND_ENABLE |
    diff --git a/sys/dev/hptiop/hptiop.c b/sys/dev/hptiop/hptiop.c
    index 5ad2106a314..7218bc50442 100644
    --- a/sys/dev/hptiop/hptiop.c
    +++ b/sys/dev/hptiop/hptiop.c
    @@ -432,7 +432,6 @@ srb_complete:
     					sg_list), (u_int8_t *)&ccb->csio.sense_data, 
     					MIN(dxfer, sizeof(ccb->csio.sense_data)));
     			} else {
    -				/* XXX: Flexelint arg2 is 16 bytes, arg3 is 32 */
     				memcpy(&ccb->csio.sense_data, &req->sg_list, 
     					MIN(dxfer, sizeof(ccb->csio.sense_data)));
     			}
    @@ -576,7 +575,6 @@ static void hptiop_request_callback_mv(struct hpt_iop_hba * hba,
     			ccb->ccb_h.status = CAM_BUSY;
     			break;
     		case IOP_RESULT_CHECK_CONDITION:
    -			/* XXX: FlexeLint: arg2=16b arg3=32 */
     			memcpy(&ccb->csio.sense_data, &req->sg_list, 
     				MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
     			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
    diff --git a/sys/dev/iir/iir.c b/sys/dev/iir/iir.c
    index 9bfa283ae8f..f5f6d7e667f 100644
    --- a/sys/dev/iir/iir.c
    +++ b/sys/dev/iir/iir.c
    @@ -1203,7 +1203,6 @@ gdt_internal_cache_cmd(struct gdt_softc *gdt,union ccb *ccb)
                     bzero( ccb->csio.data_ptr+copylen,
                            ccb->csio.dxfer_len - copylen );
                 page=((struct scsi_mode_sense_6 *)ccb->csio.cdb_io.cdb_bytes)->page;
    -	    /* XXX: FlexeLint: why ?? */
                 switch (page) {
                   default:
                     GDT_DPRINTF(GDT_D_MISC, ("MODE_SENSE_6: page 0x%x\n", page));
    diff --git a/sys/dev/mpt/mpt_raid.c b/sys/dev/mpt/mpt_raid.c
    index 0a3fdca7dbb..6b7eb7b46c4 100644
    --- a/sys/dev/mpt/mpt_raid.c
    +++ b/sys/dev/mpt/mpt_raid.c
    @@ -562,7 +562,6 @@ mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
     		break;
     	}
     	action_result = REQ_TO_RAID_ACTION_RESULT(req);
    -	/* XXX: FlexeLint: ActionData is only 4 bytes */
     	memcpy(&action_result->action_data, &reply->ActionData,
     	    sizeof(action_result->action_data));
     	action_result->action_status = le16toh(reply->ActionStatus);
    diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c
    index ca9ef277deb..f5f94baad32 100644
    --- a/sys/dev/msk/if_msk.c
    +++ b/sys/dev/msk/if_msk.c
    @@ -118,21 +118,26 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
     #include 
     
     #include 
    +#include 
     #include 
     #include 
    +#include 
     
     #include 
     #include 
     #include 
     #include 
     
    +#include 
     #include 
    +#include 
     
     #include 
     #include 
    diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
    index 6af6ec2e2f3..7abd10473f5 100644
    --- a/sys/dev/usb/wlan/if_rum.c
    +++ b/sys/dev/usb/wlan/if_rum.c
    @@ -42,9 +42,12 @@ __FBSDID("$FreeBSD$");
     #include 
     
     #include 
    +#include 
    +#include 
     
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -1486,7 +1489,7 @@ rum_rf_write(struct rum_softc *sc, uint8_t reg, uint32_t val)
     		return;
     	}
     
    -	tmp = RT2573_RF_BUSY | RT2573_RF_20BIT | ((val & 0xfffff) << 2) |
    +	tmp = RT2573_RF_BUSY | RT2573_RF_20BIT | (val & 0xfffff) << 2 |
     	    (reg & 3);
     	rum_write(sc, RT2573_PHY_CSR4, tmp);
     
    diff --git a/sys/dev/usb/wlan/if_rumreg.h b/sys/dev/usb/wlan/if_rumreg.h
    index 44e627ad138..75a51bcd4ad 100644
    --- a/sys/dev/usb/wlan/if_rumreg.h
    +++ b/sys/dev/usb/wlan/if_rumreg.h
    @@ -139,7 +139,7 @@
     #define RT2573_BBP_BUSY	(1 << 16)
     /* possible flags for register PHY_CSR4 */
     #define RT2573_RF_20BIT	(20 << 24)
    -#define RT2573_RF_BUSY	(1U << 31)
    +#define RT2573_RF_BUSY	(1 << 31)
     
     /* LED values */
     #define RT2573_LED_RADIO	(1 << 8)
    diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c
    index 69b7bb1746e..0cd8d3535a3 100644
    --- a/sys/dev/usb/wlan/if_urtw.c
    +++ b/sys/dev/usb/wlan/if_urtw.c
    @@ -61,8 +61,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     
    -#define nitems(a)	(sizeof(a) / sizeof((a)[0]))
    -
     SYSCTL_NODE(_hw_usb, OID_AUTO, urtw, CTLFLAG_RW, 0, "USB Realtek 8187L");
     #ifdef URTW_DEBUG
     int urtw_debug = 0;
    @@ -177,46 +175,6 @@ struct urtw_pair {
     	uint32_t	val;
     };
     
    -static const uint8_t urtw_8187b_reg_table[][3] = {
    -	{ 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 },
    -	{ 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 },
    -	{ 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 },
    -	{ 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 },
    -	{ 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 },
    -	{ 0xff, 0x00, 0 },
    -
    -	{ 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 }, { 0x5a, 0x4b, 1 },
    -	{ 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 }, { 0x61, 0x09, 1 },
    -	{ 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 }, { 0xce, 0x0f, 1 },
    -	{ 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 }, { 0xe1, 0x0f, 1 },
    -	{ 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 }, { 0xf1, 0x01, 1 },
    -	{ 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 }, { 0xf4, 0x04, 1 },
    -	{ 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 }, { 0xf7, 0x07, 1 },
    -	{ 0xf8, 0x08, 1 },
    -
    -	{ 0x4e, 0x00, 2 }, { 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 },
    -	{ 0x22, 0x68, 2 }, { 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 },
    -	{ 0x25, 0x7d, 2 }, { 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 },
    -	{ 0x4d, 0x08, 2 }, { 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 },
    -	{ 0x52, 0x04, 2 }, { 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 },
    -	{ 0x55, 0x23, 2 }, { 0x56, 0x45, 2 }, { 0x57, 0x67, 2 },
    -	{ 0x58, 0x08, 2 }, { 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 },
    -	{ 0x5b, 0x08, 2 }, { 0x60, 0x08, 2 }, { 0x61, 0x08, 2 },
    -	{ 0x62, 0x08, 2 }, { 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 },
    -	{ 0x72, 0x56, 2 }, { 0x73, 0x9a, 2 },
    -
    -	{ 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 }, { 0x5b, 0x40, 0 },
    -	{ 0x84, 0x88, 0 }, { 0x85, 0x24, 0 }, { 0x88, 0x54, 0 },
    -	{ 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 }, { 0x8d, 0x00, 0 },
    -	{ 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 }, { 0x96, 0x00, 0 },
    -	{ 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 }, { 0x9f, 0x10, 0 },
    -	{ 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 }, { 0xdb, 0x00, 0 },
    -	{ 0xee, 0x00, 0 }, { 0x91, 0x03, 0 },
    -
    -	{ 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 },
    -	{ 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 }
    -};
    -
     static uint8_t urtw_8225_agc[] = {
     	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b,
     	0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
    @@ -232,6 +190,21 @@ static uint8_t urtw_8225_agc[] = {
     	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
     };
     
    +static uint8_t urtw_8225z2_agc[] = {
    +	0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51,
    +	0x4f, 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b,
    +	0x39, 0x37, 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25,
    +	0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f,
    +	0x0d, 0x0b, 0x09, 0x07, 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
    +	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x19, 0x19,
    +	0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x20, 0x21, 0x22, 0x23,
    +	0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a,
    +	0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
    +	0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31,
    +	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
    +	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
    +};
    +
     static uint32_t urtw_8225_channel[] = {
     	0x0000,		/* dummy channel 0  */
     	0x085c,		/* 1  */
    @@ -264,7 +237,7 @@ static struct urtw_pair urtw_8225_rf_part1[] = {
     	{ 0x00, 0x0067 }, { 0x01, 0x0fe0 }, { 0x02, 0x044d }, { 0x03, 0x0441 },
     	{ 0x04, 0x0486 }, { 0x05, 0x0bc0 }, { 0x06, 0x0ae6 }, { 0x07, 0x082a },
     	{ 0x08, 0x001f }, { 0x09, 0x0334 }, { 0x0a, 0x0fd4 }, { 0x0b, 0x0391 },
    -	{ 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 }
    +	{ 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 },
     };
     
     static struct urtw_pair urtw_8225_rf_part2[] = {
    @@ -306,7 +279,7 @@ static uint16_t urtw_8225_rxgain[] = {
     };
     
     static uint8_t urtw_8225_threshold[] = {
    -	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
    +	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd,
     };
     
     static uint8_t urtw_8225_tx_gain_cck_ofdm[] = {
    @@ -331,29 +304,10 @@ static uint8_t urtw_8225_txpwr_cck_ch14[] = {
     	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
     };
     
    -static uint8_t urtw_8225_txpwr_ofdm[] = {
    +static uint8_t urtw_8225_txpwr_ofdm[]={
     	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
     };
     
    -static uint8_t urtw_8225z2_agc[] = {
    -	0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57,
    -	0x55, 0x53, 0x51, 0x4f, 0x4d, 0x4b, 0x49, 0x47,
    -	0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
    -	0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27,
    -	0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17,
    -	0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
    -	0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    -	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    -	0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
    -	0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
    -	0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a,
    -	0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
    -	0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f,
    -	0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
    -	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
    -	0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
    -};
    -
     static uint8_t urtw_8225v2_gain_bg[]={
     	0x23, 0x15, 0xa5,		/* -82-1dbm  */
     	0x23, 0x15, 0xb5,		/* -82-2dbm  */
    @@ -456,7 +410,11 @@ static uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = {
     	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
     	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
    -	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
    +	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
    +};
    +
    +static uint8_t urtw_8225v2_txpwr_cck[] = {
    +	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
     };
     
     static uint8_t urtw_8225v2_txpwr_cck_ch14[] = {
    @@ -470,10 +428,6 @@ static uint8_t urtw_8225v2b_txpwr_cck[] = {
     	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
     };
     
    -static uint8_t urtw_8225v2_txpwr_cck[] = {
    -	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
    -};
    -
     static uint8_t urtw_8225v2b_txpwr_cck_ch14[] = {
     	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
     	0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
    @@ -487,6 +441,40 @@ static struct urtw_pair urtw_ratetable[] = {
     	{ 96, 10 }, { 108, 11 }
     };
     
    +static const uint8_t urtw_8187b_reg_table[][3] = {
    +	{ 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 },
    +	{ 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 },
    +	{ 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 },
    +	{ 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 },
    +	{ 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 },
    +	{ 0xff, 0x00, 0 }, { 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 },
    +	{ 0x5a, 0x4b, 1 }, { 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 },
    +	{ 0x61, 0x09, 1 }, { 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 },
    +	{ 0xce, 0x0f, 1 }, { 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 },
    +	{ 0xe1, 0x0f, 1 }, { 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 },
    +	{ 0xf1, 0x01, 1 }, { 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 },
    +	{ 0xf4, 0x04, 1 }, { 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 },
    +	{ 0xf7, 0x07, 1 }, { 0xf8, 0x08, 1 }, { 0x4e, 0x00, 2 },
    +	{ 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 }, { 0x22, 0x68, 2 },
    +	{ 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 }, { 0x25, 0x7d, 2 },
    +	{ 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 }, { 0x4d, 0x08, 2 },
    +	{ 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 }, { 0x52, 0x04, 2 },
    +	{ 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 }, { 0x55, 0x23, 2 },
    +	{ 0x56, 0x45, 2 }, { 0x57, 0x67, 2 }, { 0x58, 0x08, 2 },
    +	{ 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 }, { 0x5b, 0x08, 2 },
    +	{ 0x60, 0x08, 2 }, { 0x61, 0x08, 2 }, { 0x62, 0x08, 2 },
    +	{ 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 }, { 0x72, 0x56, 2 },
    +	{ 0x73, 0x9a, 2 }, { 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 },
    +	{ 0x5b, 0x40, 0 }, { 0x84, 0x88, 0 }, { 0x85, 0x24, 0 },
    +	{ 0x88, 0x54, 0 }, { 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 },
    +	{ 0x8d, 0x00, 0 }, { 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 },
    +	{ 0x96, 0x00, 0 }, { 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 },
    +	{ 0x9f, 0x10, 0 }, { 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 },
    +	{ 0xdb, 0x00, 0 }, { 0xee, 0x00, 0 }, { 0x91, 0x03, 0 },
    +	{ 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 },
    +	{ 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 }
    +};
    +
     static usb_callback_t urtw_bulk_rx_callback;
     static usb_callback_t urtw_bulk_tx_callback;
     
    @@ -1046,6 +1034,7 @@ urtw_init(void *arg)
     static usb_error_t
     urtw_adapter_start_b(struct urtw_softc *sc)
     {
    +#define N(a)	(sizeof(a) / sizeof((a)[0]))
     	int i;
     	uint8_t data8;
     	usb_error_t error;
    @@ -1109,7 +1098,7 @@ urtw_adapter_start_b(struct urtw_softc *sc)
     		goto fail;
     
     	urtw_write8_m(sc, URTW_WPA_CONFIG, 0);
    -	for (i = 0; i < nitems(urtw_8187b_reg_table); i++) {
    +	for (i = 0; i < N(urtw_8187b_reg_table); i++) {
     		error = urtw_write8_i(sc, urtw_8187b_reg_table[i][0],
     		    urtw_8187b_reg_table[i][1], urtw_8187b_reg_table[i][2]);
     		if (error)
    @@ -1219,6 +1208,7 @@ urtw_adapter_start_b(struct urtw_softc *sc)
     
     fail:
     	return (error);
    +#undef N
     }
     
     static usb_error_t
    @@ -1283,6 +1273,19 @@ fail:
     	return (error);
     }
     
    +static usb_error_t
    +urtw_set_mode(struct urtw_softc *sc, uint32_t mode)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	urtw_read8_m(sc, URTW_EPROM_CMD, &data);
    +	data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT);
    +	data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK);
    +	urtw_write8_m(sc, URTW_EPROM_CMD, data);
    +fail:
    +	return (error);
    +}
     
     static usb_error_t
     urtw_8187b_cmd_reset(struct urtw_softc *sc)
    @@ -1391,6 +1394,56 @@ urtw_write32_i(struct urtw_softc *sc, int val, uint32_t data, int idx)
     	return (urtw_do_request(sc, &req, &data));
     }
     
    +static void
    +urtw_stop_locked(struct ifnet *ifp, int disable)
    +{
    +	struct urtw_softc *sc = ifp->if_softc;
    +	uint8_t data8;
    +	usb_error_t error;
    +
    +	(void)disable;
    +	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
    +
    +	error = urtw_intr_disable(sc);
    +	if (error)
    +		goto fail;
    +	urtw_read8_m(sc, URTW_CMD, &data8);
    +	data8 &= ~(URTW_CMD_RX_ENABLE | URTW_CMD_TX_ENABLE);
    +	urtw_write8_m(sc, URTW_CMD, data8);
    +
    +	error = sc->sc_rf_stop(sc);
    +	if (error != 0)
    +		goto fail;
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    +	if (error)
    +		goto fail;
    +	urtw_read8_m(sc, URTW_CONFIG4, &data8);
    +	urtw_write8_m(sc, URTW_CONFIG4, data8 | URTW_CONFIG4_VCOOFF);
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    +	if (error)
    +		goto fail;
    +fail:
    +	if (error)
    +		device_printf(sc->sc_dev, "failed to stop (%s)\n",
    +		    usbd_errstr(error));
    +
    +	usb_callout_stop(&sc->sc_led_ch);
    +	callout_stop(&sc->sc_watchdog_ch);
    +
    +	urtw_abort_xfers(sc);
    +}
    +
    +static void
    +urtw_stop(struct ifnet *ifp, int disable)
    +{
    +	struct urtw_softc *sc = ifp->if_softc;
    +
    +	URTW_LOCK(sc);
    +	urtw_stop_locked(ifp, disable);
    +	URTW_UNLOCK(sc);
    +}
    +
     static void
     urtw_abort_xfers(struct urtw_softc *sc)
     {
    @@ -1896,6 +1949,201 @@ urtw_set_multi(void *arg)
     	ifp->if_flags |= IFF_ALLMULTI;
     }
     
    +static usb_error_t
    +urtw_set_rate(struct urtw_softc *sc)
    +{
    +	int i, basic_rate, min_rr_rate, max_rr_rate;
    +	uint16_t data;
    +	usb_error_t error;
    +
    +	basic_rate = urtw_rate2rtl(48);
    +	min_rr_rate = urtw_rate2rtl(12);
    +	max_rr_rate = urtw_rate2rtl(48);
    +
    +	urtw_write8_m(sc, URTW_RESP_RATE,
    +	    max_rr_rate << URTW_RESP_MAX_RATE_SHIFT |
    +	    min_rr_rate << URTW_RESP_MIN_RATE_SHIFT);
    +
    +	urtw_read16_m(sc, URTW_BRSR, &data);
    +	data &= ~URTW_BRSR_MBR_8185;
    +
    +	for (i = 0; i <= basic_rate; i++)
    +		data |= (1 << i);
    +
    +	urtw_write16_m(sc, URTW_BRSR, data);
    +fail:
    +	return (error);
    +}
    +
    +static uint16_t
    +urtw_rate2rtl(int rate)
    +{
    +#define N(a)	(sizeof(a) / sizeof((a)[0]))
    +	int i;
    +
    +	for (i = 0; i < N(urtw_ratetable); i++) {
    +		if (rate == urtw_ratetable[i].reg)
    +			return urtw_ratetable[i].val;
    +	}
    +
    +	return (3);
    +#undef N
    +}
    +
    +static uint16_t
    +urtw_rtl2rate(int rate)
    +{
    +#define N(a)	(sizeof(a) / sizeof((a)[0]))
    +	int i;
    +
    +	for (i = 0; i < N(urtw_ratetable); i++) {
    +		if (rate == urtw_ratetable[i].val)
    +			return urtw_ratetable[i].reg;
    +	}
    +
    +	return (0);
    +#undef N
    +}
    +
    +static usb_error_t
    +urtw_update_msr(struct urtw_softc *sc)
    +{
    +	struct ifnet *ifp = sc->sc_ifp;
    +	struct ieee80211com *ic = ifp->if_l2com;
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	urtw_read8_m(sc, URTW_MSR, &data);
    +	data &= ~URTW_MSR_LINK_MASK;
    +
    +	if (sc->sc_state == IEEE80211_S_RUN) {
    +		switch (ic->ic_opmode) {
    +		case IEEE80211_M_STA:
    +		case IEEE80211_M_MONITOR:
    +			data |= URTW_MSR_LINK_STA;
    +			if (sc->sc_flags & URTW_RTL8187B)
    +				data |= URTW_MSR_LINK_ENEDCA;
    +			break;
    +		case IEEE80211_M_IBSS:
    +			data |= URTW_MSR_LINK_ADHOC;
    +			break;
    +		case IEEE80211_M_HOSTAP:
    +			data |= URTW_MSR_LINK_HOSTAP;
    +			break;
    +		default:
    +			panic("unsupported operation mode 0x%x\n",
    +			    ic->ic_opmode);
    +			/* never reach  */
    +		}
    +	} else
    +		data |= URTW_MSR_LINK_NONE;
    +
    +	urtw_write8_m(sc, URTW_MSR, data);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data)
    +{
    +	struct usb_device_request req;
    +	usb_error_t error;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_GETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint8_t));
    +
    +	error = urtw_do_request(sc, &req, data);
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data)
    +{
    +	struct usb_device_request req;
    +	usb_error_t error;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_GETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint16_t));
    +
    +	error = urtw_do_request(sc, &req, data);
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data)
    +{
    +	struct usb_device_request req;
    +	usb_error_t error;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_GETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint32_t));
    +
    +	error = urtw_do_request(sc, &req, data);
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data)
    +{
    +	struct usb_device_request req;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_SETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint8_t));
    +
    +	return (urtw_do_request(sc, &req, &data));
    +}
    +
    +static usb_error_t
    +urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data)
    +{
    +	struct usb_device_request req;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_SETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint16_t));
    +
    +	return (urtw_do_request(sc, &req, &data));
    +}
    +
    +static usb_error_t
    +urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data)
    +{
    +	struct usb_device_request req;
    +
    +	URTW_ASSERT_LOCKED(sc);
    +
    +	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_SETREGS_REQ;
    +	USETW(req.wValue, val | 0xff00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint32_t));
    +
    +	return (urtw_do_request(sc, &req, &data));
    +}
     
     static usb_error_t
     urtw_get_macaddr(struct urtw_softc *sc)
    @@ -1999,48 +2247,16 @@ fail:
     }
     
     static usb_error_t
    -urtw_eprom_readbit(struct urtw_softc *sc, int16_t *data)
    -{
    -	uint8_t data8;
    -	usb_error_t error;
    -
    -	urtw_read8_m(sc, URTW_EPROM_CMD, &data8);
    -	*data = (data8 & URTW_EPROM_READBIT) ? 1 : 0;
    -	DELAY(URTW_EPROM_DELAY);
    -
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen)
    -{
    -	int i = 0;
    -	usb_error_t error = 0;
    -
    -	for (i = 0; i < buflen; i++) {
    -		error = urtw_eprom_writebit(sc, buf[i]);
    -		if (error != 0)
    -			goto fail;
    -		error = urtw_eprom_ck(sc);
    -		if (error != 0)
    -			goto fail;
    -	}
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_eprom_writebit(struct urtw_softc *sc, int16_t bit)
    +urtw_eprom_cs(struct urtw_softc *sc, int able)
     {
     	uint8_t data;
     	usb_error_t error;
     
     	urtw_read8_m(sc, URTW_EPROM_CMD, &data);
    -	if (bit != 0)
    -		urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_WRITEBIT);
    +	if (able == URTW_EPROM_ENABLE)
    +		urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CS);
     	else
    -		urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_WRITEBIT);
    +		urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CS);
     	DELAY(URTW_EPROM_DELAY);
     fail:
     	return (error);
    @@ -2064,709 +2280,50 @@ fail:
     	return (error);
     }
     
    +static usb_error_t
    +urtw_eprom_readbit(struct urtw_softc *sc, int16_t *data)
    +{
    +	uint8_t data8;
    +	usb_error_t error;
    +
    +	urtw_read8_m(sc, URTW_EPROM_CMD, &data8);
    +	*data = (data8 & URTW_EPROM_READBIT) ? 1 : 0;
    +	DELAY(URTW_EPROM_DELAY);
    +
    +fail:
    +	return (error);
    +}
     
     static usb_error_t
    -urtw_eprom_cs(struct urtw_softc *sc, int able)
    +urtw_eprom_writebit(struct urtw_softc *sc, int16_t bit)
     {
     	uint8_t data;
     	usb_error_t error;
     
     	urtw_read8_m(sc, URTW_EPROM_CMD, &data);
    -	if (able == URTW_EPROM_ENABLE)
    -		urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CS);
    +	if (bit != 0)
    +		urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_WRITEBIT);
     	else
    -		urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CS);
    +		urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_WRITEBIT);
     	DELAY(URTW_EPROM_DELAY);
     fail:
     	return (error);
     }
     
    -
    -
     static usb_error_t
    -urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data)
    -{
    -	struct usb_device_request req;
    -	usb_error_t error;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_GETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint8_t));
    -
    -	error = urtw_do_request(sc, &req, data);
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_read8e(struct urtw_softc *sc, int val, uint8_t *data)
    -{
    -	struct usb_device_request req;
    -	usb_error_t error;
    -
    -	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_GETREGS_REQ;
    -	USETW(req.wValue, val | 0xfe00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint8_t));
    -
    -	error = urtw_do_request(sc, &req, data);
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data)
    -{
    -	struct usb_device_request req;
    -	usb_error_t error;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_GETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint16_t));
    -
    -	error = urtw_do_request(sc, &req, data);
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data)
    -{
    -	struct usb_device_request req;
    -	usb_error_t error;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_GETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint32_t));
    -
    -	error = urtw_do_request(sc, &req, data);
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data)
    -{
    -	struct usb_device_request req;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_SETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint8_t));
    -
    -	return (urtw_do_request(sc, &req, &data));
    -}
    -
    -static usb_error_t
    -urtw_write8e(struct urtw_softc *sc, int val, uint8_t data)
    -{
    -	struct usb_device_request req;
    -
    -	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_SETREGS_REQ;
    -	USETW(req.wValue, val | 0xfe00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint8_t));
    -
    -	return (urtw_do_request(sc, &req, &data));
    -}
    -
    -static usb_error_t
    -urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data)
    -{
    -	struct usb_device_request req;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_SETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint16_t));
    -
    -	return (urtw_do_request(sc, &req, &data));
    -}
    -
    -static usb_error_t
    -urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data)
    -{
    -	struct usb_device_request req;
    -
    -	URTW_ASSERT_LOCKED(sc);
    -
    -	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    -	req.bRequest = URTW_8187_SETREGS_REQ;
    -	USETW(req.wValue, val | 0xff00);
    -	USETW(req.wIndex, 0);
    -	USETW(req.wLength, sizeof(uint32_t));
    -
    -	return (urtw_do_request(sc, &req, &data));
    -}
    -
    -static usb_error_t
    -urtw_set_mode(struct urtw_softc *sc, uint32_t mode)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	urtw_read8_m(sc, URTW_EPROM_CMD, &data);
    -	data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT);
    -	data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK);
    -	urtw_write8_m(sc, URTW_EPROM_CMD, data);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    -	if (error)
    -		goto fail;
    -
    -	urtw_read8_m(sc, URTW_CONFIG3, &data);
    -	urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE);
    -	urtw_write32_m(sc, URTW_ANAPARAM, val);
    -	urtw_read8_m(sc, URTW_CONFIG3, &data);
    -	urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE);
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    -	if (error)
    -		goto fail;
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    -	if (error)
    -		goto fail;
    -
    -	urtw_read8_m(sc, URTW_CONFIG3, &data);
    -	urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE);
    -	urtw_write32_m(sc, URTW_ANAPARAM2, val);
    -	urtw_read8_m(sc, URTW_CONFIG3, &data);
    -	urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE);
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    -	if (error)
    -		goto fail;
    -fail:
    -	return (error);
    -}
    -
    -
    -static usb_error_t
    -urtw_intr_disable(struct urtw_softc *sc)
    -{
    -	usb_error_t error;
    -
    -	urtw_write16_m(sc, URTW_INTR_MASK, 0);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_reset(struct urtw_softc *sc)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    -	if (error)
    -		goto fail;
    -	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    -	if (error)
    -		goto fail;
    -
    -	error = urtw_intr_disable(sc);
    -	if (error)
    -		goto fail;
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -
    -	error = urtw_write8e(sc, 0x18, 0x10);
    -	if (error != 0)
    -		goto fail;
    -	error = urtw_write8e(sc, 0x18, 0x11);
    -	if (error != 0)
    -		goto fail;
    -	error = urtw_write8e(sc, 0x18, 0x00);
    -	if (error != 0)
    -		goto fail;
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -
    -	urtw_read8_m(sc, URTW_CMD, &data);
    -	data = (data & 0x2) | URTW_CMD_RST;
    -	urtw_write8_m(sc, URTW_CMD, data);
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -
    -	urtw_read8_m(sc, URTW_CMD, &data);
    -	if (data & URTW_CMD_RST) {
    -		device_printf(sc->sc_dev, "reset timeout\n");
    -		goto fail;
    -	}
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD);
    -	if (error)
    -		goto fail;
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -
    -	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    -	if (error)
    -		goto fail;
    -	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    -	if (error)
    -		goto fail;
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_led_on(struct urtw_softc *sc, int type)
    -{
    -	usb_error_t error;
    -
    -	if (type == URTW_LED_GPIO) {
    -		switch (sc->sc_gpio_ledpin) {
    -		case URTW_LED_PIN_GPIO0:
    -			urtw_write8_m(sc, URTW_GPIO, 0x01);
    -			urtw_write8_m(sc, URTW_GP_ENABLE, 0x00);
    -			break;
    -		default:
    -			panic("unsupported LED PIN type 0x%x",
    -			    sc->sc_gpio_ledpin);
    -			/* never reach  */
    -		}
    -	} else {
    -		panic("unsupported LED type 0x%x", type);
    -		/* never reach  */
    -	}
    -
    -	sc->sc_gpio_ledon = 1;
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_led_off(struct urtw_softc *sc, int type)
    -{
    -	usb_error_t error;
    -
    -	if (type == URTW_LED_GPIO) {
    -		switch (sc->sc_gpio_ledpin) {
    -		case URTW_LED_PIN_GPIO0:
    -			urtw_write8_m(sc, URTW_GPIO, URTW_GPIO_DATA_MAGIC1);
    -			urtw_write8_m(sc,
    -			    URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1);
    -			break;
    -		default:
    -			panic("unsupported LED PIN type 0x%x",
    -			    sc->sc_gpio_ledpin);
    -			/* never reach  */
    -		}
    -	} else {
    -		panic("unsupported LED type 0x%x", type);
    -		/* never reach  */
    -	}
    -
    -	sc->sc_gpio_ledon = 0;
    -
    -fail:
    -	return (error);
    -}
    -
    -
    -static usb_error_t
    -urtw_led_mode0(struct urtw_softc *sc, int mode)
    -{
    -
    -	switch (mode) {
    -	case URTW_LED_CTL_POWER_ON:
    -		sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK;
    -		break;
    -	case URTW_LED_CTL_TX:
    -		if (sc->sc_gpio_ledinprogress == 1)
    -			return (0);
    -
    -		sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL;
    -		sc->sc_gpio_blinktime = 2;
    -		break;
    -	case URTW_LED_CTL_LINK:
    -		sc->sc_gpio_ledstate = URTW_LED_ON;
    -		break;
    -	default:
    -		panic("unsupported LED mode 0x%x", mode);
    -		/* never reach  */
    -	}
    -
    -	switch (sc->sc_gpio_ledstate) {
    -	case URTW_LED_ON:
    -		if (sc->sc_gpio_ledinprogress != 0)
    -			break;
    -		urtw_led_on(sc, URTW_LED_GPIO);
    -		break;
    -	case URTW_LED_BLINK_NORMAL:
    -		if (sc->sc_gpio_ledinprogress != 0)
    -			break;
    -		sc->sc_gpio_ledinprogress = 1;
    -		sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ?
    -			URTW_LED_OFF : URTW_LED_ON;
    -		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
    -		break;
    -	case URTW_LED_POWER_ON_BLINK:
    -		urtw_led_on(sc, URTW_LED_GPIO);
    -		usb_pause_mtx(&sc->sc_mtx, 100);
    -		urtw_led_off(sc, URTW_LED_GPIO);
    -		break;
    -	default:
    -		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
    -		/* never reach  */
    -	}
    -	return (0);
    -}
    -
    -static usb_error_t
    -urtw_led_mode1(struct urtw_softc *sc, int mode)
    -{
    -
    -	return (USB_ERR_INVAL);
    -}
    -
    -static usb_error_t
    -urtw_led_mode2(struct urtw_softc *sc, int mode)
    -{
    -
    -	return (USB_ERR_INVAL);
    -}
    -
    -static usb_error_t
    -urtw_led_mode3(struct urtw_softc *sc, int mode)
    -{
    -
    -	return (USB_ERR_INVAL);
    -}
    -
    -static void
    -urtw_ledtask(void *arg, int pending)
    -{
    -	struct urtw_softc *sc = arg;
    -
    -	if (sc->sc_strategy != URTW_SW_LED_MODE0)
    -		panic("could not process a LED strategy 0x%x", sc->sc_strategy);
    -
    -	URTW_LOCK(sc);
    -	urtw_led_blink(sc);
    -	URTW_UNLOCK(sc);
    -}
    -
    -static usb_error_t
    -urtw_led_ctl(struct urtw_softc *sc, int mode)
    +urtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen)
     {
    +	int i = 0;
     	usb_error_t error = 0;
     
    -	switch (sc->sc_strategy) {
    -	case URTW_SW_LED_MODE0:
    -		error = urtw_led_mode0(sc, mode);
    -		break;
    -	case URTW_SW_LED_MODE1:
    -		error = urtw_led_mode1(sc, mode);
    -		break;
    -	case URTW_SW_LED_MODE2:
    -		error = urtw_led_mode2(sc, mode);
    -		break;
    -	case URTW_SW_LED_MODE3:
    -		error = urtw_led_mode3(sc, mode);
    -		break;
    -	default:
    -		panic("unsupported LED mode %d\n", sc->sc_strategy);
    -		/* never reach  */
    +	for (i = 0; i < buflen; i++) {
    +		error = urtw_eprom_writebit(sc, buf[i]);
    +		if (error != 0)
    +			goto fail;
    +		error = urtw_eprom_ck(sc);
    +		if (error != 0)
    +			goto fail;
     	}
    -
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_led_blink(struct urtw_softc *sc)
    -{
    -	uint8_t ing = 0;
    -	usb_error_t error;
    -
    -	if (sc->sc_gpio_blinkstate == URTW_LED_ON)
    -		error = urtw_led_on(sc, URTW_LED_GPIO);
    -	else
    -		error = urtw_led_off(sc, URTW_LED_GPIO);
    -	sc->sc_gpio_blinktime--;
    -	if (sc->sc_gpio_blinktime == 0)
    -		ing = 1;
    -	else {
    -		if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL &&
    -		    sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY &&
    -		    sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3)
    -			ing = 1;
    -	}
    -	if (ing == 1) {
    -		if (sc->sc_gpio_ledstate == URTW_LED_ON &&
    -		    sc->sc_gpio_ledon == 0)
    -			error = urtw_led_on(sc, URTW_LED_GPIO);
    -		else if (sc->sc_gpio_ledstate == URTW_LED_OFF &&
    -		    sc->sc_gpio_ledon == 1)
    -			error = urtw_led_off(sc, URTW_LED_GPIO);
    -
    -		sc->sc_gpio_blinktime = 0;
    -		sc->sc_gpio_ledinprogress = 0;
    -		return (0);
    -	}
    -
    -	sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ?
    -	    URTW_LED_ON : URTW_LED_OFF;
    -
    -	switch (sc->sc_gpio_ledstate) {
    -	case URTW_LED_BLINK_NORMAL:
    -		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
    -		break;
    -	default:
    -		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
    -		/* never reach  */
    -	}
    -	return (0);
    -}
    -
    -static usb_error_t
    -urtw_update_msr(struct urtw_softc *sc)
    -{
    -	struct ifnet *ifp = sc->sc_ifp;
    -	struct ieee80211com *ic = ifp->if_l2com;
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	urtw_read8_m(sc, URTW_MSR, &data);
    -	data &= ~URTW_MSR_LINK_MASK;
    -
    -	if (sc->sc_state == IEEE80211_S_RUN) {
    -		switch (ic->ic_opmode) {
    -		case IEEE80211_M_STA:
    -		case IEEE80211_M_MONITOR:
    -			data |= URTW_MSR_LINK_STA;
    -			if (sc->sc_flags & URTW_RTL8187B)
    -				data |= URTW_MSR_LINK_ENEDCA;
    -			break;
    -		case IEEE80211_M_IBSS:
    -			data |= URTW_MSR_LINK_ADHOC;
    -			break;
    -		case IEEE80211_M_HOSTAP:
    -			data |= URTW_MSR_LINK_HOSTAP;
    -			break;
    -		default:
    -			panic("unsupported operation mode 0x%x\n",
    -			    ic->ic_opmode);
    -			/* never reach  */
    -		}
    -	} else
    -		data |= URTW_MSR_LINK_NONE;
    -
    -	urtw_write8_m(sc, URTW_MSR, data);
    -fail:
    -	return (error);
    -}
    -
    -static uint16_t
    -urtw_rate2rtl(int rate)
    -{
    -	int i;
    -
    -	for (i = 0; i < nitems(urtw_ratetable); i++) {
    -		if (rate == urtw_ratetable[i].reg)
    -			return urtw_ratetable[i].val;
    -	}
    -
    -	return (3);
    -}
    -
    -static uint16_t
    -urtw_rtl2rate(int rate)
    -{
    -	int i;
    -
    -	for (i = 0; i < nitems(urtw_ratetable); i++) {
    -		if (rate == urtw_ratetable[i].val)
    -			return urtw_ratetable[i].reg;
    -	}
    -
    -	return (0);
    -}
    -
    -static usb_error_t
    -urtw_set_rate(struct urtw_softc *sc)
    -{
    -	int i, basic_rate, min_rr_rate, max_rr_rate;
    -	uint16_t data;
    -	usb_error_t error;
    -
    -	basic_rate = urtw_rate2rtl(48);
    -	min_rr_rate = urtw_rate2rtl(12);
    -	max_rr_rate = urtw_rate2rtl(48);
    -
    -	urtw_write8_m(sc, URTW_RESP_RATE,
    -	    max_rr_rate << URTW_RESP_MAX_RATE_SHIFT |
    -	    min_rr_rate << URTW_RESP_MIN_RATE_SHIFT);
    -
    -	urtw_read16_m(sc, URTW_BRSR, &data);
    -	data &= ~URTW_BRSR_MBR_8185;
    -
    -	for (i = 0; i <= basic_rate; i++)
    -		data |= (1 << i);
    -
    -	urtw_write16_m(sc, URTW_BRSR, data);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_intr_enable(struct urtw_softc *sc)
    -{
    -	usb_error_t error;
    -
    -	urtw_write16_m(sc, URTW_INTR_MASK, 0xffff);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_rx_setconf(struct urtw_softc *sc)
    -{
    -	struct ifnet *ifp = sc->sc_ifp;
    -	struct ieee80211com *ic = ifp->if_l2com;
    -	uint32_t data;
    -	usb_error_t error;
    -
    -	urtw_read32_m(sc, URTW_RX, &data);
    -	data = data &~ URTW_RX_FILTER_MASK;
    -	if (sc->sc_flags & URTW_RTL8187B) {
    -		data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA |
    -		    URTW_RX_FILTER_MCAST | URTW_RX_FILTER_BCAST |
    -		    URTW_RX_FILTER_NICMAC | URTW_RX_CHECK_BSSID |
    -		    URTW_RX_FIFO_THRESHOLD_NONE |
    -		    URTW_MAX_RX_DMA_2048 |
    -		    URTW_RX_AUTORESETPHY | URTW_RCR_ONLYERLPKT;
    -	} else {
    -		data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA;
    -		data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST;
    -
    -		if (ic->ic_opmode == IEEE80211_M_MONITOR) {
    -			data = data | URTW_RX_FILTER_ICVERR;
    -			data = data | URTW_RX_FILTER_PWR;
    -		}
    -		if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR)
    -			data = data | URTW_RX_FILTER_CRCERR;
    -
    -		if (ic->ic_opmode == IEEE80211_M_MONITOR ||
    -		    (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
    -			data = data | URTW_RX_FILTER_ALLMAC;
    -		} else {
    -			data = data | URTW_RX_FILTER_NICMAC;
    -			data = data | URTW_RX_CHECK_BSSID;
    -		}
    -
    -		data = data &~ URTW_RX_FIFO_THRESHOLD_MASK;
    -		data = data | URTW_RX_FIFO_THRESHOLD_NONE |
    -		    URTW_RX_AUTORESETPHY;
    -		data = data &~ URTW_MAX_RX_DMA_MASK;
    -		data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT;
    -	}
    -
    -	urtw_write32_m(sc, URTW_RX, data);
    -fail:
    -	return (error);
    -}
    -
    -
    -static usb_error_t
    -urtw_rx_enable(struct urtw_softc *sc)
    -{
    -	uint8_t data;
    -	usb_error_t error;
    -
    -	usbd_transfer_start((sc->sc_flags & URTW_RTL8187B) ?
    -	    sc->sc_xfer[URTW_8187B_BULK_RX] : sc->sc_xfer[URTW_8187L_BULK_RX]);
    -
    -	error = urtw_rx_setconf(sc);
    -	if (error != 0)
    -		goto fail;
    -
    -	urtw_read8_m(sc, URTW_CMD, &data);
    -	urtw_write8_m(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_tx_enable(struct urtw_softc *sc)
    -{
    -	uint8_t data8;
    -	uint32_t data;
    -	usb_error_t error;
    -
    -	if (sc->sc_flags & URTW_RTL8187B) {
    -		urtw_read32_m(sc, URTW_TX_CONF, &data);
    -		data &= ~URTW_TX_LOOPBACK_MASK;
    -		data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
    -		data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
    -		data &= ~URTW_TX_SWPLCPLEN;
    -		data |= URTW_TX_HW_SEQNUM | URTW_TX_DISREQQSIZE |
    -		    (7 << 8) |	/* short retry limit */
    -		    (7 << 0) |	/* long retry limit */
    -		    (7 << 21);	/* MAX TX DMA */
    -		urtw_write32_m(sc, URTW_TX_CONF, data);
    -
    -		urtw_read8_m(sc, URTW_CMD, &data8);
    -		urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE);
    -		return (error);
    -	}
    -
    -	urtw_read8_m(sc, URTW_CW_CONF, &data8);
    -	data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY);
    -	urtw_write8_m(sc, URTW_CW_CONF, data8);
    -
    -	urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8);
    -	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN;
    -	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL;
    -	data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT;
    -	urtw_write8_m(sc, URTW_TX_AGC_CTL, data8);
    -
    -	urtw_read32_m(sc, URTW_TX_CONF, &data);
    -	data &= ~URTW_TX_LOOPBACK_MASK;
    -	data |= URTW_TX_LOOPBACK_NONE;
    -	data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
    -	data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT;
    -	data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT;
    -	data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
    -	data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW;
    -	data &= ~URTW_TX_SWPLCPLEN;
    -	data |= URTW_TX_NOICV;
    -	urtw_write32_m(sc, URTW_TX_CONF, data);
    -
    -	urtw_read8_m(sc, URTW_CMD, &data8);
    -	urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE);
     fail:
     	return (error);
     }
    @@ -2931,6 +2488,112 @@ fail:
     	return (error);
     }
     
    +
    +static usb_error_t
    +urtw_8225_rf_init(struct urtw_softc *sc)
    +{
    +#define N(a)	(sizeof(a) / sizeof((a)[0]))
    +	int i;
    +	uint16_t data;
    +	usb_error_t error;
    +
    +	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    +	if (error)
    +		goto fail;
    +
    +	error = urtw_8225_usb_init(sc);
    +	if (error)
    +		goto fail;
    +
    +	urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008);
    +	urtw_read16_m(sc, URTW_BRSR, &data);		/* XXX ??? */
    +	urtw_write16_m(sc, URTW_BRSR, 0xffff);
    +	urtw_write32_m(sc, URTW_RF_PARA, 0x100044);
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    +	if (error)
    +		goto fail;
    +	urtw_write8_m(sc, URTW_CONFIG3, 0x44);
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    +	if (error)
    +		goto fail;
    +
    +	error = urtw_8185_rf_pins_enable(sc);
    +	if (error)
    +		goto fail;
    +	usb_pause_mtx(&sc->sc_mtx, 1000);
    +
    +	for (i = 0; i < N(urtw_8225_rf_part1); i++) {
    +		urtw_8225_write(sc, urtw_8225_rf_part1[i].reg,
    +		    urtw_8225_rf_part1[i].val);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +	}
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1);
    +	usb_pause_mtx(&sc->sc_mtx, 200);
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2);
    +	usb_pause_mtx(&sc->sc_mtx, 200);
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC3);
    +
    +	for (i = 0; i < 95; i++) {
    +		urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1));
    +		urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, urtw_8225_rxgain[i]);
    +	}
    +
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC4);
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC5);
    +
    +	for (i = 0; i < 128; i++) {
    +		urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +		urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +	}
    +
    +	for (i = 0; i < N(urtw_8225_rf_part2); i++) {
    +		urtw_8187_write_phy_ofdm(sc, urtw_8225_rf_part2[i].reg,
    +		    urtw_8225_rf_part2[i].val);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +	}
    +
    +	error = urtw_8225_setgain(sc, 4);
    +	if (error)
    +		goto fail;
    +
    +	for (i = 0; i < N(urtw_8225_rf_part3); i++) {
    +		urtw_8187_write_phy_cck(sc, urtw_8225_rf_part3[i].reg,
    +		    urtw_8225_rf_part3[i].val);
    +		usb_pause_mtx(&sc->sc_mtx, 1);
    +	}
    +
    +	urtw_write8_m(sc, URTW_TESTR, 0x0d);
    +
    +	error = urtw_8225_set_txpwrlvl(sc, 1);
    +	if (error)
    +		goto fail;
    +
    +	urtw_8187_write_phy_cck(sc, 0x10, 0x9b);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +	urtw_8187_write_phy_ofdm(sc, 0x26, 0x90);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +
    +	/* TX ant A, 0x0 for B */
    +	error = urtw_8185_tx_antenna(sc, 0x3);
    +	if (error)
    +		goto fail;
    +	urtw_write32_m(sc, URTW_HSSI_PARA, 0x3dc00002);
    +
    +	error = urtw_8225_rf_set_chan(sc, 1);
    +fail:
    +	return (error);
    +#undef N
    +}
    +
     static usb_error_t
     urtw_8185_rf_pins_enable(struct urtw_softc *sc)
     {
    @@ -3095,6 +2758,68 @@ fail1:	free(req, M_80211_VAP);
     fail0:	return (error);
     }
     
    +static usb_error_t
    +urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan)
    +{
    +	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
    +	struct ieee80211_channel *c = ic->ic_curchan;
    +	usb_error_t error;
    +
    +	error = urtw_8225_set_txpwrlvl(sc, chan);
    +	if (error)
    +		goto fail;
    +	urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]);
    +	usb_pause_mtx(&sc->sc_mtx, 10);
    +
    +	urtw_write8_m(sc, URTW_SIFS, 0x22);
    +
    +	if (sc->sc_state == IEEE80211_S_ASSOC &&
    +	    ic->ic_flags & IEEE80211_F_SHSLOT)
    +		urtw_write8_m(sc, URTW_SLOT, 0x9);
    +	else
    +		urtw_write8_m(sc, URTW_SLOT, 0x14);
    +
    +	if (IEEE80211_IS_CHAN_G(c)) {
    +		/* for G */
    +		urtw_write8_m(sc, URTW_DIFS, 0x14);
    +		urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x14);
    +		urtw_write8_m(sc, URTW_CW_VAL, 0x73);
    +	} else {
    +		/* for B */
    +		urtw_write8_m(sc, URTW_DIFS, 0x24);
    +		urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x24);
    +		urtw_write8_m(sc, URTW_CW_VAL, 0xa5);
    +	}
    +
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8225_rf_set_sens(struct urtw_softc *sc, int sens)
    +{
    +	usb_error_t error;
    +
    +	if (sens < 0 || sens > 6)
    +		return -1;
    +
    +	if (sens > 4)
    +		urtw_8225_write(sc,
    +		    URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC1);
    +	else
    +		urtw_8225_write(sc,
    +		    URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC2);
    +
    +	sens = 6 - sens;
    +	error = urtw_8225_setgain(sc, sens);
    +	if (error)
    +		goto fail;
    +
    +	urtw_8187_write_phy_cck(sc, 0x41, urtw_8225_threshold[sens]);
    +
    +fail:
    +	return (error);
    +}
     
     static usb_error_t
     urtw_8225_set_txpwrlvl(struct urtw_softc *sc, int chan)
    @@ -3184,397 +2909,10 @@ fail:
     	return (error);
     }
     
    -
    -static usb_error_t
    -urtw_8225_rf_init(struct urtw_softc *sc)
    -{
    -	int i;
    -	uint16_t data;
    -	usb_error_t error;
    -
    -	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    -	if (error)
    -		goto fail;
    -
    -	error = urtw_8225_usb_init(sc);
    -	if (error)
    -		goto fail;
    -
    -	urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008);
    -	urtw_read16_m(sc, URTW_BRSR, &data);		/* XXX ??? */
    -	urtw_write16_m(sc, URTW_BRSR, 0xffff);
    -	urtw_write32_m(sc, URTW_RF_PARA, 0x100044);
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    -	if (error)
    -		goto fail;
    -	urtw_write8_m(sc, URTW_CONFIG3, 0x44);
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    -	if (error)
    -		goto fail;
    -
    -	error = urtw_8185_rf_pins_enable(sc);
    -	if (error)
    -		goto fail;
    -	usb_pause_mtx(&sc->sc_mtx, 1000);
    -
    -	for (i = 0; i < nitems(urtw_8225_rf_part1); i++) {
    -		urtw_8225_write(sc, urtw_8225_rf_part1[i].reg,
    -		    urtw_8225_rf_part1[i].val);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -	}
    -	usb_pause_mtx(&sc->sc_mtx, 100);
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1);
    -	usb_pause_mtx(&sc->sc_mtx, 200);
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2);
    -	usb_pause_mtx(&sc->sc_mtx, 200);
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC3);
    -
    -	for (i = 0; i < nitems(urtw_8225_rxgain); i++) {
    -		urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1));
    -		urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, urtw_8225_rxgain[i]);
    -	}
    -
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC4);
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC5);
    -
    -	for (i = 0; i < nitems(urtw_8225_agc); i++) {
    -		urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -		urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -	}
    -
    -	for (i = 0; i < nitems(urtw_8225_rf_part2); i++) {
    -		urtw_8187_write_phy_ofdm(sc, urtw_8225_rf_part2[i].reg,
    -		    urtw_8225_rf_part2[i].val);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -	}
    -
    -	error = urtw_8225_setgain(sc, 4);
    -	if (error)
    -		goto fail;
    -
    -	for (i = 0; i < nitems(urtw_8225_rf_part3); i++) {
    -		urtw_8187_write_phy_cck(sc, urtw_8225_rf_part3[i].reg,
    -		    urtw_8225_rf_part3[i].val);
    -		usb_pause_mtx(&sc->sc_mtx, 1);
    -	}
    -
    -	urtw_write8_m(sc, URTW_TESTR, 0x0d);
    -
    -	error = urtw_8225_set_txpwrlvl(sc, 1);
    -	if (error)
    -		goto fail;
    -
    -	urtw_8187_write_phy_cck(sc, 0x10, 0x9b);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -	urtw_8187_write_phy_ofdm(sc, 0x26, 0x90);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -
    -	/* TX ant A, 0x0 for B */
    -	error = urtw_8185_tx_antenna(sc, 0x3);
    -	if (error)
    -		goto fail;
    -	urtw_write32_m(sc, URTW_HSSI_PARA, 0x3dc00002);
    -
    -	error = urtw_8225_rf_set_chan(sc, 1);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan)
    -{
    -	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
    -	struct ieee80211_channel *c = ic->ic_curchan;
    -	usb_error_t error;
    -
    -	error = urtw_8225_set_txpwrlvl(sc, chan);
    -	if (error)
    -		goto fail;
    -	urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]);
    -	usb_pause_mtx(&sc->sc_mtx, 10);
    -
    -	urtw_write8_m(sc, URTW_SIFS, 0x22);
    -
    -	if (sc->sc_state == IEEE80211_S_ASSOC &&
    -	    ic->ic_flags & IEEE80211_F_SHSLOT)
    -		urtw_write8_m(sc, URTW_SLOT, 0x9);
    -	else
    -		urtw_write8_m(sc, URTW_SLOT, 0x14);
    -
    -	if (IEEE80211_IS_CHAN_G(c)) {
    -		/* for G */
    -		urtw_write8_m(sc, URTW_DIFS, 0x14);
    -		urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x14);
    -		urtw_write8_m(sc, URTW_CW_VAL, 0x73);
    -	} else {
    -		/* for B */
    -		urtw_write8_m(sc, URTW_DIFS, 0x24);
    -		urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x24);
    -		urtw_write8_m(sc, URTW_CW_VAL, 0xa5);
    -	}
    -
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8225_rf_set_sens(struct urtw_softc *sc, int sens)
    -{
    -	usb_error_t error;
    -
    -	if (sens < 0 || sens > 6)
    -		return -1;
    -
    -	if (sens > 4)
    -		urtw_8225_write(sc,
    -		    URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC1);
    -	else
    -		urtw_8225_write(sc,
    -		    URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC2);
    -
    -	sens = 6 - sens;
    -	error = urtw_8225_setgain(sc, sens);
    -	if (error)
    -		goto fail;
    -
    -	urtw_8187_write_phy_cck(sc, 0x41, urtw_8225_threshold[sens]);
    -
    -fail:
    -	return (error);
    -}
    -
    -static void
    -urtw_stop_locked(struct ifnet *ifp, int disable)
    -{
    -	struct urtw_softc *sc = ifp->if_softc;
    -	uint8_t data8;
    -	usb_error_t error;
    -
    -	(void)disable;
    -	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
    -
    -	error = urtw_intr_disable(sc);
    -	if (error)
    -		goto fail;
    -	urtw_read8_m(sc, URTW_CMD, &data8);
    -	data8 &= ~(URTW_CMD_RX_ENABLE | URTW_CMD_TX_ENABLE);
    -	urtw_write8_m(sc, URTW_CMD, data8);
    -
    -	error = sc->sc_rf_stop(sc);
    -	if (error != 0)
    -		goto fail;
    -
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    -	if (error)
    -		goto fail;
    -	urtw_read8_m(sc, URTW_CONFIG4, &data8);
    -	urtw_write8_m(sc, URTW_CONFIG4, data8 | URTW_CONFIG4_VCOOFF);
    -	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    -	if (error)
    -		goto fail;
    -fail:
    -	if (error)
    -		device_printf(sc->sc_dev, "failed to stop (%s)\n",
    -		    usbd_errstr(error));
    -
    -	usb_callout_stop(&sc->sc_led_ch);
    -	callout_stop(&sc->sc_watchdog_ch);
    -
    -	urtw_abort_xfers(sc);
    -}
    -
    -static void
    -urtw_stop(struct ifnet *ifp, int disable)
    -{
    -	struct urtw_softc *sc = ifp->if_softc;
    -
    -	URTW_LOCK(sc);
    -	urtw_stop_locked(ifp, disable);
    -	URTW_UNLOCK(sc);
    -}
    -
    -
    -static int
    -urtw_isbmode(uint16_t rate)
    -{
    -
    -	rate = urtw_rtl2rate(rate);
    -
    -	return ((rate <= 22 && rate != 12 && rate != 18) ||
    -	    rate == 44) ? (1) : (0);
    -}
    -
    -static struct mbuf *
    -urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
    -    int8_t *nf_p)
    -{
    -	int actlen, flen, len, nf = -95, rssi;
    -	struct ieee80211_frame *wh;
    -	struct mbuf *m, *mnew;
    -	struct urtw_8187b_rxhdr *bhdr;
    -	struct urtw_softc *sc = data->sc;
    -	struct ifnet *ifp = sc->sc_ifp;
    -	struct ieee80211com *ic = ifp->if_l2com;
    -	uint8_t *desc, quality = 0, rate;
    -
    -	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
    -
    -	if (actlen < URTW_MIN_RXBUFSZ) {
    -		ifp->if_ierrors++;
    -		return (NULL);
    -	}
    -
    -	if (sc->sc_flags & URTW_RTL8187B) {
    -		len = actlen - (sizeof(struct urtw_8187b_rxhdr));
    -		bhdr = (struct urtw_8187b_rxhdr *)(data->buf + len);
    -		desc = data->buf + len;
    -		flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
    -		if (flen > actlen) {
    -			ifp->if_ierrors++;
    -			return (NULL);
    -		}
    -		rate = (le32toh(bhdr->flags) >> 20) & 0xf;
    -		rssi = 14 + (bhdr->rssi / 2);
    -		if (rssi > 95)
    -			rssi = 95;
    -	} else {
    -		/* 4 dword and 4 byte CRC  */
    -		len = actlen - (4 * 4);
    -		desc = data->buf + len;
    -		flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
    -		if (flen > actlen) {
    -			ifp->if_ierrors++;
    -			return (NULL);
    -		}
    -
    -		rate = (desc[2] & 0xf0) >> 4;
    -		quality = desc[4] & 0xff;
    -		/* XXX correct?  */
    -		rssi = (desc[6] & 0xfe) >> 1;
    -		if (!urtw_isbmode(rate)) {
    -			rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi);
    -			rssi = ((90 - rssi) * 100) / 65;
    -		} else {
    -			rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi);
    -			rssi = ((95 - rssi) * 100) / 65;
    -		}
    -	}
    -
    -	mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
    -	if (mnew == NULL) {
    -		ifp->if_ierrors++;
    -		return (NULL);
    -	}
    -
    -	m = data->m;
    -	data->m = mnew;
    -	data->buf = mtod(mnew, uint8_t *);
    -
    -	/* finalize mbuf */
    -	m->m_pkthdr.rcvif = ifp;
    -	m->m_pkthdr.len = m->m_len = flen - 4;
    -
    -	if (ieee80211_radiotap_active(ic)) {
    -		struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap;
    -
    -		/* XXX Are variables correct?  */
    -		tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
    -		tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
    -		tap->wr_dbm_antsignal = (int8_t)rssi;
    -	}
    -
    -	wh = mtod(m, struct ieee80211_frame *);
    -	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA)
    -		sc->sc_currate = (rate > 0) ? rate : sc->sc_currate;
    -	/* XXX correct?  */
    -	if ((sc->sc_flags & URTW_RTL8187B) == 0)
    -		nf = (quality > 64) ? 0 : ((64 - quality) * 100) / 64;
    -
    -	*rssi_p = rssi;
    -	*nf_p = nf;
    -
    -	return (m);
    -}
    -
    -static usb_error_t
    -urtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain)
    -{
    -	uint8_t *gainp;
    -	usb_error_t error;
    -
    -	/* XXX for A?  */
    -	gainp = urtw_8225v2_gain_bg;
    -	urtw_8187_write_phy_ofdm(sc, 0x0d, gainp[gain * 3]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -	urtw_8187_write_phy_ofdm(sc, 0x1b, gainp[gain * 3 + 1]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -	urtw_8187_write_phy_ofdm(sc, 0x1d, gainp[gain * 3 + 2]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -	urtw_8187_write_phy_ofdm(sc, 0x21, 0x17);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan)
    -{
    -	int i;
    -	uint8_t *cck_pwrtable;
    -	uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10;
    -	uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
    -	uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
    -	usb_error_t error;
    -
    -	/* CCK power setting */
    -	cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl;
    -	cck_pwrlvl += sc->sc_txpwr_cck_base;
    -	cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
    -	cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 :
    -	    urtw_8225v2_txpwr_cck;
    -
    -	for (i = 0; i < 8; i++)
    -		urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]);
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_CCK,
    -	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -
    -	/* OFDM power setting */
    -	ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ?
    -		ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min;
    -	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
    -	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
    -
    -	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    -	if (error)
    -		goto fail;
    -
    -	urtw_8187_write_phy_ofdm(sc, 2, 0x42);
    -	urtw_8187_write_phy_ofdm(sc, 5, 0x0);
    -	urtw_8187_write_phy_ofdm(sc, 6, 0x40);
    -	urtw_8187_write_phy_ofdm(sc, 7, 0x0);
    -	urtw_8187_write_phy_ofdm(sc, 8, 0x40);
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_OFDM,
    -	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl]);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -fail:
    -	return (error);
    -}
    -
    -
     static usb_error_t
     urtw_8225v2_rf_init(struct urtw_softc *sc)
     {
    +#define N(a)	(sizeof(a) / sizeof((a)[0]))
     	int i;
     	uint16_t data;
     	uint32_t data32;
    @@ -3607,7 +2945,7 @@ urtw_8225v2_rf_init(struct urtw_softc *sc)
     
     	usb_pause_mtx(&sc->sc_mtx, 500);
     
    -	for (i = 0; i < nitems(urtw_8225v2_rf_part1); i++) {
    +	for (i = 0; i < N(urtw_8225v2_rf_part1); i++) {
     		urtw_8225_write(sc, urtw_8225v2_rf_part1[i].reg,
     		    urtw_8225v2_rf_part1[i].val);
     	}
    @@ -3662,7 +3000,7 @@ urtw_8225v2_rf_init(struct urtw_softc *sc)
     		urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80);
     	}
     
    -	for (i = 0; i < nitems(urtw_8225v2_rf_part2); i++) {
    +	for (i = 0; i < N(urtw_8225v2_rf_part2); i++) {
     		urtw_8187_write_phy_ofdm(sc, urtw_8225v2_rf_part2[i].reg,
     		    urtw_8225v2_rf_part2[i].val);
     	}
    @@ -3671,7 +3009,7 @@ urtw_8225v2_rf_init(struct urtw_softc *sc)
     	if (error)
     		goto fail;
     
    -	for (i = 0; i < nitems(urtw_8225v2_rf_part3); i++) {
    +	for (i = 0; i < N(urtw_8225v2_rf_part3); i++) {
     		urtw_8187_write_phy_cck(sc, urtw_8225v2_rf_part3[i].reg,
     		    urtw_8225v2_rf_part3[i].val);
     	}
    @@ -3694,6 +3032,7 @@ urtw_8225v2_rf_init(struct urtw_softc *sc)
     	error = urtw_8225_rf_set_chan(sc, 1);
     fail:
     	return (error);
    +#undef N
     }
     
     static usb_error_t
    @@ -3825,6 +3164,73 @@ fail:
     }
     
     
    +static usb_error_t
    +urtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan)
    +{
    +	int i;
    +	uint8_t *cck_pwrtable;
    +	uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10;
    +	uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
    +	uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
    +	usb_error_t error;
    +
    +	/* CCK power setting */
    +	cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl;
    +	cck_pwrlvl += sc->sc_txpwr_cck_base;
    +	cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
    +	cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 :
    +	    urtw_8225v2_txpwr_cck;
    +
    +	for (i = 0; i < 8; i++)
    +		urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]);
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_CCK,
    +	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +
    +	/* OFDM power setting */
    +	ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ?
    +		ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min;
    +	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
    +	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
    +
    +	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    +	if (error)
    +		goto fail;
    +
    +	urtw_8187_write_phy_ofdm(sc, 2, 0x42);
    +	urtw_8187_write_phy_ofdm(sc, 5, 0x0);
    +	urtw_8187_write_phy_ofdm(sc, 6, 0x40);
    +	urtw_8187_write_phy_ofdm(sc, 7, 0x0);
    +	urtw_8187_write_phy_ofdm(sc, 8, 0x40);
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_OFDM,
    +	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain)
    +{
    +	uint8_t *gainp;
    +	usb_error_t error;
    +
    +	/* XXX for A?  */
    +	gainp = urtw_8225v2_gain_bg;
    +	urtw_8187_write_phy_ofdm(sc, 0x0d, gainp[gain * 3]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +	urtw_8187_write_phy_ofdm(sc, 0x1b, gainp[gain * 3 + 1]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +	urtw_8187_write_phy_ofdm(sc, 0x1d, gainp[gain * 3 + 2]);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +	urtw_8187_write_phy_ofdm(sc, 0x21, 0x17);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +fail:
    +	return (error);
    +}
    +
     static usb_error_t
     urtw_8225_isv2(struct urtw_softc *sc, int *ret)
     {
    @@ -3859,6 +3265,477 @@ urtw_8225_isv2(struct urtw_softc *sc, int *ret)
     fail:
     	return (error);
     }
    +
    +static usb_error_t
    +urtw_8225v2b_rf_init(struct urtw_softc *sc)
    +{
    +#define N(a)	(sizeof(a) / sizeof((a)[0]))
    +	int i;
    +	usb_error_t error;
    +
    +	for (i = 0; i < N(urtw_8225v2b_rf_part1); i++)
    +		urtw_8225_write(sc, urtw_8225v2b_rf_part1[i].reg,
    +		    urtw_8225v2b_rf_part1[i].val);
    +
    +	urtw_8225_write(sc,
    +	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC1);
    +
    +	for (i = 0; i < N(urtw_8225v2b_rxgain); i++) {
    +		urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1));
    +		urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC,
    +		    urtw_8225v2b_rxgain[i]);
    +	}
    +
    +	urtw_8225_write(sc, URTW_8225_ADDR_3_MAGIC, 0x080);
    +	urtw_8225_write(sc, URTW_8225_ADDR_5_MAGIC, 0x004);
    +	urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x0b7);
    +	urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0xc4d);
    +	urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0x44d);
    +	urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x2bf);
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_CCK, 0x03);
    +	urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 0x07);
    +	urtw_write8_m(sc, URTW_TX_ANTENNA, 0x03);
    +
    +	urtw_8187_write_phy_ofdm(sc, 0x80, 0x12);
    +	for (i = 0; i < N(urtw_8225z2_agc); i++) {
    +		urtw_8187_write_phy_ofdm(sc, 0xf, urtw_8225z2_agc[i]);
    +		urtw_8187_write_phy_ofdm(sc, 0xe, 0x80 + i);
    +		urtw_8187_write_phy_ofdm(sc, 0xe, 0);
    +	}
    +	urtw_8187_write_phy_ofdm(sc, 0x80, 0x10);
    +
    +	for (i = 0; i < N(urtw_8225v2b_rf_part2); i++)
    +		urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val);
    +
    +	urtw_write32_m(sc, 0xf0, (7 << 12) | (3 << 8) | 0x1c);
    +	urtw_write32_m(sc, 0xf4, (7 << 12) | (3 << 8) | 0x1c);
    +	urtw_write32_m(sc, 0xf8, (7 << 12) | (3 << 8) | 0x1c);
    +	urtw_write32_m(sc, 0xfc, (7 << 12) | (3 << 8) | 0x1c);
    +	urtw_write8_m(sc, URTW_ACM_CONTROL, 0);
    +
    +	urtw_8187_write_phy_ofdm(sc, 0x97, 0x46);
    +	urtw_8187_write_phy_ofdm(sc, 0xa4, 0xb6);
    +	urtw_8187_write_phy_ofdm(sc, 0x85, 0xfc);
    +	urtw_8187_write_phy_cck(sc, 0xc1, 0x88);
    +fail:
    +	return (error);
    +#undef N
    +}
    +
    +static usb_error_t
    +urtw_8225v2b_rf_set_chan(struct urtw_softc *sc, int chan)
    +{
    +	int ack;
    +	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
    +	usb_error_t error;
    +
    +	error = urtw_8225v2b_set_txpwrlvl(sc, chan);
    +	if (error)
    +		goto fail;
    +
    +	urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]);
    +	usb_pause_mtx(&sc->sc_mtx, 10);
    +
    +	urtw_write8_m(sc, URTW_SIFS, 0xa);
    +	if (ic->ic_flags & IEEE80211_F_SHSLOT) {
    +		urtw_write8_m(sc, URTW_SLOT, 0x9);
    +		urtw_write8_m(sc, URTW_DIFS, 0x1c);
    +		/* In 8187B, BRSR + 1 ==> EIFS register */
    +		urtw_write8_m(sc, URTW_BRSR + 1, 0x53);
    +
    +		ack = 112 + 48 + 0x1c;
    +		ack += (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
    +		    72 : 144;
    +		urtw_write8_m(sc, URTW_CARRIER_SCOUNT,
    +		    roundup2(ack, 4));
    +	} else {
    +		urtw_write8_m(sc, URTW_SLOT, 0x14);
    +		urtw_write8_m(sc, URTW_DIFS, 0x32);
    +		/* In 8187B, BRSR + 1 ==> EIFS register */
    +		urtw_write8_m(sc, URTW_BRSR + 1, 0x5b);
    +
    +		ack = 112 + 48 + 0x32;
    +		ack += (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
    +		    72 : 144;
    +		urtw_write8_m(sc, URTW_CARRIER_SCOUNT,
    +		    roundup2(ack, 4));
    +
    +	}
    +
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8225v2b_set_txpwrlvl(struct urtw_softc *sc, int chan)
    +{
    +	int i;
    +	uint8_t *cck_pwrtable;
    +	uint8_t cck_pwrlvl_max = 15;
    +	uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
    +	uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
    +	usb_error_t error;
    +
    +	/* CCK power setting */
    +	cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ?
    +	    ((sc->sc_flags & URTW_RTL8187B_REV_B) ? cck_pwrlvl_max : 22) :
    +	    (cck_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 0 : 7));
    +	cck_pwrlvl += sc->sc_txpwr_cck_base;
    +	cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
    +	cck_pwrtable = (chan == 14) ? urtw_8225v2b_txpwr_cck_ch14 :
    +	    urtw_8225v2b_txpwr_cck;
    +
    +	if (sc->sc_flags & URTW_RTL8187B_REV_B)
    +		cck_pwrtable += (cck_pwrlvl <= 6) ? 0 :
    +		    ((cck_pwrlvl <= 11) ? 8 : 16);
    +	else
    +		cck_pwrtable += (cck_pwrlvl <= 5) ? 0 :
    +		    ((cck_pwrlvl <= 11) ? 8 : ((cck_pwrlvl <= 17) ? 16 : 24));
    +
    +	for (i = 0; i < 8; i++)
    +		urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]);
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_CCK,
    +	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1);
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +
    +	/* OFDM power setting */
    +	ofdm_pwrlvl = (ofdm_pwrlvl > 15) ?
    +	    ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 17 : 25) :
    +	    (ofdm_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 2 : 10));
    +	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
    +	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
    +
    +	urtw_write8_m(sc, URTW_TX_GAIN_OFDM,
    +	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1);
    +
    +	if (sc->sc_flags & URTW_RTL8187B_REV_B) {
    +		if (ofdm_pwrlvl <= 11) {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x60);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x60);
    +		} else {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c);
    +		}
    +	} else {
    +		if (ofdm_pwrlvl <= 11) {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c);
    +		} else if (ofdm_pwrlvl <= 17) {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x54);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x54);
    +		} else {
    +			urtw_8187_write_phy_ofdm(sc, 0x87, 0x50);
    +			urtw_8187_write_phy_ofdm(sc, 0x89, 0x50);
    +		}
    +	}
    +	usb_pause_mtx(&sc->sc_mtx, 1);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_read8e(struct urtw_softc *sc, int val, uint8_t *data)
    +{
    +	struct usb_device_request req;
    +	usb_error_t error;
    +
    +	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_GETREGS_REQ;
    +	USETW(req.wValue, val | 0xfe00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint8_t));
    +
    +	error = urtw_do_request(sc, &req, data);
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_write8e(struct urtw_softc *sc, int val, uint8_t data)
    +{
    +	struct usb_device_request req;
    +
    +	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    +	req.bRequest = URTW_8187_SETREGS_REQ;
    +	USETW(req.wValue, val | 0xfe00);
    +	USETW(req.wIndex, 0);
    +	USETW(req.wLength, sizeof(uint8_t));
    +
    +	return (urtw_do_request(sc, &req, &data));
    +}
    +
    +static usb_error_t
    +urtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    +	if (error)
    +		goto fail;
    +
    +	urtw_read8_m(sc, URTW_CONFIG3, &data);
    +	urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE);
    +	urtw_write32_m(sc, URTW_ANAPARAM, val);
    +	urtw_read8_m(sc, URTW_CONFIG3, &data);
    +	urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE);
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    +	if (error)
    +		goto fail;
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
    +	if (error)
    +		goto fail;
    +
    +	urtw_read8_m(sc, URTW_CONFIG3, &data);
    +	urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE);
    +	urtw_write32_m(sc, URTW_ANAPARAM2, val);
    +	urtw_read8_m(sc, URTW_CONFIG3, &data);
    +	urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE);
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
    +	if (error)
    +		goto fail;
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_intr_enable(struct urtw_softc *sc)
    +{
    +	usb_error_t error;
    +
    +	urtw_write16_m(sc, URTW_INTR_MASK, 0xffff);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_intr_disable(struct urtw_softc *sc)
    +{
    +	usb_error_t error;
    +
    +	urtw_write16_m(sc, URTW_INTR_MASK, 0);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_reset(struct urtw_softc *sc)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    +	if (error)
    +		goto fail;
    +	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    +	if (error)
    +		goto fail;
    +
    +	error = urtw_intr_disable(sc);
    +	if (error)
    +		goto fail;
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +
    +	error = urtw_write8e(sc, 0x18, 0x10);
    +	if (error != 0)
    +		goto fail;
    +	error = urtw_write8e(sc, 0x18, 0x11);
    +	if (error != 0)
    +		goto fail;
    +	error = urtw_write8e(sc, 0x18, 0x00);
    +	if (error != 0)
    +		goto fail;
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +
    +	urtw_read8_m(sc, URTW_CMD, &data);
    +	data = (data & 0x2) | URTW_CMD_RST;
    +	urtw_write8_m(sc, URTW_CMD, data);
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +
    +	urtw_read8_m(sc, URTW_CMD, &data);
    +	if (data & URTW_CMD_RST) {
    +		device_printf(sc->sc_dev, "reset timeout\n");
    +		goto fail;
    +	}
    +
    +	error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD);
    +	if (error)
    +		goto fail;
    +	usb_pause_mtx(&sc->sc_mtx, 100);
    +
    +	error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON);
    +	if (error)
    +		goto fail;
    +	error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON);
    +	if (error)
    +		goto fail;
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_led_ctl(struct urtw_softc *sc, int mode)
    +{
    +	usb_error_t error = 0;
    +
    +	switch (sc->sc_strategy) {
    +	case URTW_SW_LED_MODE0:
    +		error = urtw_led_mode0(sc, mode);
    +		break;
    +	case URTW_SW_LED_MODE1:
    +		error = urtw_led_mode1(sc, mode);
    +		break;
    +	case URTW_SW_LED_MODE2:
    +		error = urtw_led_mode2(sc, mode);
    +		break;
    +	case URTW_SW_LED_MODE3:
    +		error = urtw_led_mode3(sc, mode);
    +		break;
    +	default:
    +		panic("unsupported LED mode %d\n", sc->sc_strategy);
    +		/* never reach  */
    +	}
    +
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_led_mode0(struct urtw_softc *sc, int mode)
    +{
    +
    +	switch (mode) {
    +	case URTW_LED_CTL_POWER_ON:
    +		sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK;
    +		break;
    +	case URTW_LED_CTL_TX:
    +		if (sc->sc_gpio_ledinprogress == 1)
    +			return (0);
    +
    +		sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL;
    +		sc->sc_gpio_blinktime = 2;
    +		break;
    +	case URTW_LED_CTL_LINK:
    +		sc->sc_gpio_ledstate = URTW_LED_ON;
    +		break;
    +	default:
    +		panic("unsupported LED mode 0x%x", mode);
    +		/* never reach  */
    +	}
    +
    +	switch (sc->sc_gpio_ledstate) {
    +	case URTW_LED_ON:
    +		if (sc->sc_gpio_ledinprogress != 0)
    +			break;
    +		urtw_led_on(sc, URTW_LED_GPIO);
    +		break;
    +	case URTW_LED_BLINK_NORMAL:
    +		if (sc->sc_gpio_ledinprogress != 0)
    +			break;
    +		sc->sc_gpio_ledinprogress = 1;
    +		sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ?
    +			URTW_LED_OFF : URTW_LED_ON;
    +		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
    +		break;
    +	case URTW_LED_POWER_ON_BLINK:
    +		urtw_led_on(sc, URTW_LED_GPIO);
    +		usb_pause_mtx(&sc->sc_mtx, 100);
    +		urtw_led_off(sc, URTW_LED_GPIO);
    +		break;
    +	default:
    +		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
    +		/* never reach  */
    +	}
    +	return (0);
    +}
    +
    +static usb_error_t
    +urtw_led_mode1(struct urtw_softc *sc, int mode)
    +{
    +
    +	return (USB_ERR_INVAL);
    +}
    +
    +static usb_error_t
    +urtw_led_mode2(struct urtw_softc *sc, int mode)
    +{
    +
    +	return (USB_ERR_INVAL);
    +}
    +
    +static usb_error_t
    +urtw_led_mode3(struct urtw_softc *sc, int mode)
    +{
    +
    +	return (USB_ERR_INVAL);
    +}
    +
    +static usb_error_t
    +urtw_led_on(struct urtw_softc *sc, int type)
    +{
    +	usb_error_t error;
    +
    +	if (type == URTW_LED_GPIO) {
    +		switch (sc->sc_gpio_ledpin) {
    +		case URTW_LED_PIN_GPIO0:
    +			urtw_write8_m(sc, URTW_GPIO, 0x01);
    +			urtw_write8_m(sc, URTW_GP_ENABLE, 0x00);
    +			break;
    +		default:
    +			panic("unsupported LED PIN type 0x%x",
    +			    sc->sc_gpio_ledpin);
    +			/* never reach  */
    +		}
    +	} else {
    +		panic("unsupported LED type 0x%x", type);
    +		/* never reach  */
    +	}
    +
    +	sc->sc_gpio_ledon = 1;
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_led_off(struct urtw_softc *sc, int type)
    +{
    +	usb_error_t error;
    +
    +	if (type == URTW_LED_GPIO) {
    +		switch (sc->sc_gpio_ledpin) {
    +		case URTW_LED_PIN_GPIO0:
    +			urtw_write8_m(sc, URTW_GPIO, URTW_GPIO_DATA_MAGIC1);
    +			urtw_write8_m(sc,
    +			    URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1);
    +			break;
    +		default:
    +			panic("unsupported LED PIN type 0x%x",
    +			    sc->sc_gpio_ledpin);
    +			/* never reach  */
    +		}
    +	} else {
    +		panic("unsupported LED type 0x%x", type);
    +		/* never reach  */
    +	}
    +
    +	sc->sc_gpio_ledon = 0;
    +
    +fail:
    +	return (error);
    +}
    +
     static void
     urtw_led_ch(void *arg)
     {
    @@ -3868,6 +3745,277 @@ urtw_led_ch(void *arg)
     
     	ieee80211_runtask(ic, &sc->sc_led_task);
     }
    +
    +static void
    +urtw_ledtask(void *arg, int pending)
    +{
    +	struct urtw_softc *sc = arg;
    +
    +	if (sc->sc_strategy != URTW_SW_LED_MODE0)
    +		panic("could not process a LED strategy 0x%x", sc->sc_strategy);
    +
    +	URTW_LOCK(sc);
    +	urtw_led_blink(sc);
    +	URTW_UNLOCK(sc);
    +}
    +
    +static usb_error_t
    +urtw_led_blink(struct urtw_softc *sc)
    +{
    +	uint8_t ing = 0;
    +	usb_error_t error;
    +
    +	if (sc->sc_gpio_blinkstate == URTW_LED_ON)
    +		error = urtw_led_on(sc, URTW_LED_GPIO);
    +	else
    +		error = urtw_led_off(sc, URTW_LED_GPIO);
    +	sc->sc_gpio_blinktime--;
    +	if (sc->sc_gpio_blinktime == 0)
    +		ing = 1;
    +	else {
    +		if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL &&
    +		    sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY &&
    +		    sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3)
    +			ing = 1;
    +	}
    +	if (ing == 1) {
    +		if (sc->sc_gpio_ledstate == URTW_LED_ON &&
    +		    sc->sc_gpio_ledon == 0)
    +			error = urtw_led_on(sc, URTW_LED_GPIO);
    +		else if (sc->sc_gpio_ledstate == URTW_LED_OFF &&
    +		    sc->sc_gpio_ledon == 1)
    +			error = urtw_led_off(sc, URTW_LED_GPIO);
    +
    +		sc->sc_gpio_blinktime = 0;
    +		sc->sc_gpio_ledinprogress = 0;
    +		return (0);
    +	}
    +
    +	sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ?
    +	    URTW_LED_ON : URTW_LED_OFF;
    +
    +	switch (sc->sc_gpio_ledstate) {
    +	case URTW_LED_BLINK_NORMAL:
    +		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
    +		break;
    +	default:
    +		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
    +		/* never reach  */
    +	}
    +	return (0);
    +}
    +
    +static usb_error_t
    +urtw_rx_enable(struct urtw_softc *sc)
    +{
    +	uint8_t data;
    +	usb_error_t error;
    +
    +	usbd_transfer_start((sc->sc_flags & URTW_RTL8187B) ?
    +	    sc->sc_xfer[URTW_8187B_BULK_RX] : sc->sc_xfer[URTW_8187L_BULK_RX]);
    +
    +	error = urtw_rx_setconf(sc);
    +	if (error != 0)
    +		goto fail;
    +
    +	urtw_read8_m(sc, URTW_CMD, &data);
    +	urtw_write8_m(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_tx_enable(struct urtw_softc *sc)
    +{
    +	uint8_t data8;
    +	uint32_t data;
    +	usb_error_t error;
    +
    +	if (sc->sc_flags & URTW_RTL8187B) {
    +		urtw_read32_m(sc, URTW_TX_CONF, &data);
    +		data &= ~URTW_TX_LOOPBACK_MASK;
    +		data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
    +		data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
    +		data &= ~URTW_TX_SWPLCPLEN;
    +		data |= URTW_TX_HW_SEQNUM | URTW_TX_DISREQQSIZE |
    +		    (7 << 8) |	/* short retry limit */
    +		    (7 << 0) |	/* long retry limit */
    +		    (7 << 21);	/* MAX TX DMA */
    +		urtw_write32_m(sc, URTW_TX_CONF, data);
    +
    +		urtw_read8_m(sc, URTW_CMD, &data8);
    +		urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE);
    +		return (error);
    +	}
    +
    +	urtw_read8_m(sc, URTW_CW_CONF, &data8);
    +	data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY);
    +	urtw_write8_m(sc, URTW_CW_CONF, data8);
    +
    +	urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8);
    +	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN;
    +	data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL;
    +	data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT;
    +	urtw_write8_m(sc, URTW_TX_AGC_CTL, data8);
    +
    +	urtw_read32_m(sc, URTW_TX_CONF, &data);
    +	data &= ~URTW_TX_LOOPBACK_MASK;
    +	data |= URTW_TX_LOOPBACK_NONE;
    +	data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
    +	data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT;
    +	data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT;
    +	data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
    +	data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW;
    +	data &= ~URTW_TX_SWPLCPLEN;
    +	data |= URTW_TX_NOICV;
    +	urtw_write32_m(sc, URTW_TX_CONF, data);
    +
    +	urtw_read8_m(sc, URTW_CMD, &data8);
    +	urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE);
    +fail:
    +	return (error);
    +}
    +
    +static usb_error_t
    +urtw_rx_setconf(struct urtw_softc *sc)
    +{
    +	struct ifnet *ifp = sc->sc_ifp;
    +	struct ieee80211com *ic = ifp->if_l2com;
    +	uint32_t data;
    +	usb_error_t error;
    +
    +	urtw_read32_m(sc, URTW_RX, &data);
    +	data = data &~ URTW_RX_FILTER_MASK;
    +	if (sc->sc_flags & URTW_RTL8187B) {
    +		data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA |
    +		    URTW_RX_FILTER_MCAST | URTW_RX_FILTER_BCAST |
    +		    URTW_RX_FILTER_NICMAC | URTW_RX_CHECK_BSSID |
    +		    URTW_RX_FIFO_THRESHOLD_NONE |
    +		    URTW_MAX_RX_DMA_2048 |
    +		    URTW_RX_AUTORESETPHY | URTW_RCR_ONLYERLPKT;
    +	} else {
    +		data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA;
    +		data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST;
    +
    +		if (ic->ic_opmode == IEEE80211_M_MONITOR) {
    +			data = data | URTW_RX_FILTER_ICVERR;
    +			data = data | URTW_RX_FILTER_PWR;
    +		}
    +		if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR)
    +			data = data | URTW_RX_FILTER_CRCERR;
    +
    +		if (ic->ic_opmode == IEEE80211_M_MONITOR ||
    +		    (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
    +			data = data | URTW_RX_FILTER_ALLMAC;
    +		} else {
    +			data = data | URTW_RX_FILTER_NICMAC;
    +			data = data | URTW_RX_CHECK_BSSID;
    +		}
    +
    +		data = data &~ URTW_RX_FIFO_THRESHOLD_MASK;
    +		data = data | URTW_RX_FIFO_THRESHOLD_NONE |
    +		    URTW_RX_AUTORESETPHY;
    +		data = data &~ URTW_MAX_RX_DMA_MASK;
    +		data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT;
    +	}
    +
    +	urtw_write32_m(sc, URTW_RX, data);
    +fail:
    +	return (error);
    +}
    +
    +static struct mbuf *
    +urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
    +    int8_t *nf_p)
    +{
    +	int actlen, flen, len, nf = -95, rssi;
    +	struct ieee80211_frame *wh;
    +	struct mbuf *m, *mnew;
    +	struct urtw_8187b_rxhdr *bhdr;
    +	struct urtw_softc *sc = data->sc;
    +	struct ifnet *ifp = sc->sc_ifp;
    +	struct ieee80211com *ic = ifp->if_l2com;
    +	uint8_t *desc, quality = 0, rate;
    +
    +	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
    +
    +	if (actlen < URTW_MIN_RXBUFSZ) {
    +		ifp->if_ierrors++;
    +		return (NULL);
    +	}
    +
    +	if (sc->sc_flags & URTW_RTL8187B) {
    +		len = actlen - (sizeof(struct urtw_8187b_rxhdr));
    +		bhdr = (struct urtw_8187b_rxhdr *)(data->buf + len);
    +		desc = data->buf + len;
    +		flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
    +		if (flen > actlen) {
    +			ifp->if_ierrors++;
    +			return (NULL);
    +		}
    +		rate = (le32toh(bhdr->flags) >> 20) & 0xf;
    +		rssi = 14 + (bhdr->rssi / 2);
    +		if (rssi > 95)
    +			rssi = 95;
    +	} else {
    +		/* 4 dword and 4 byte CRC  */
    +		len = actlen - (4 * 4);
    +		desc = data->buf + len;
    +		flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
    +		if (flen > actlen) {
    +			ifp->if_ierrors++;
    +			return (NULL);
    +		}
    +
    +		rate = (desc[2] & 0xf0) >> 4;
    +		quality = desc[4] & 0xff;
    +		/* XXX correct?  */
    +		rssi = (desc[6] & 0xfe) >> 1;
    +		if (!urtw_isbmode(rate)) {
    +			rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi);
    +			rssi = ((90 - rssi) * 100) / 65;
    +		} else {
    +			rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi);
    +			rssi = ((95 - rssi) * 100) / 65;
    +		}
    +	}
    +
    +	mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
    +	if (mnew == NULL) {
    +		ifp->if_ierrors++;
    +		return (NULL);
    +	}
    +
    +	m = data->m;
    +	data->m = mnew;
    +	data->buf = mtod(mnew, uint8_t *);
    +
    +	/* finalize mbuf */
    +	m->m_pkthdr.rcvif = ifp;
    +	m->m_pkthdr.len = m->m_len = flen - 4;
    +
    +	if (ieee80211_radiotap_active(ic)) {
    +		struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap;
    +
    +		/* XXX Are variables correct?  */
    +		tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
    +		tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
    +		tap->wr_dbm_antsignal = (int8_t)rssi;
    +	}
    +
    +	wh = mtod(m, struct ieee80211_frame *);
    +	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA)
    +		sc->sc_currate = (rate > 0) ? rate : sc->sc_currate;
    +	/* XXX correct?  */
    +	if ((sc->sc_flags & URTW_RTL8187B) == 0)
    +		nf = (quality > 64) ? 0 : ((64 - quality) * 100) / 64;
    +
    +	*rssi_p = rssi;
    +	*nf_p = nf;
    +
    +	return (m);
    +}
    +
     static void
     urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
     {
    @@ -4058,175 +4206,16 @@ urtw_getbuf(struct urtw_softc *sc)
     	return (bf);
     }
     
    -static usb_error_t
    -urtw_8225v2b_rf_init(struct urtw_softc *sc)
    +static int
    +urtw_isbmode(uint16_t rate)
     {
    -	int i;
    -	usb_error_t error;
     
    -	for (i = 0; i < nitems(urtw_8225v2b_rf_part1); i++)
    -		urtw_8225_write(sc, urtw_8225v2b_rf_part1[i].reg,
    -		    urtw_8225v2b_rf_part1[i].val);
    +	rate = urtw_rtl2rate(rate);
     
    -	urtw_8225_write(sc,
    -	    URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC1);
    -
    -	for (i = 0; i < nitems(urtw_8225v2b_rxgain); i++) {
    -		urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1));
    -		urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC,
    -		    urtw_8225v2b_rxgain[i]);
    -	}
    -
    -	urtw_8225_write(sc, URTW_8225_ADDR_3_MAGIC, 0x080);
    -	urtw_8225_write(sc, URTW_8225_ADDR_5_MAGIC, 0x004);
    -	urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x0b7);
    -	urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0xc4d);
    -	urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0x44d);
    -	urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x2bf);
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_CCK, 0x03);
    -	urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 0x07);
    -	urtw_write8_m(sc, URTW_TX_ANTENNA, 0x03);
    -
    -	urtw_8187_write_phy_ofdm(sc, 0x80, 0x12);
    -	for (i = 0; i < nitems(urtw_8225z2_agc); i++) {
    -		urtw_8187_write_phy_ofdm(sc, 0xf, urtw_8225z2_agc[i]);
    -		urtw_8187_write_phy_ofdm(sc, 0xe, 0x80 + i);
    -		urtw_8187_write_phy_ofdm(sc, 0xe, 0);
    -	}
    -	urtw_8187_write_phy_ofdm(sc, 0x80, 0x10);
    -
    -	for (i = 0; i < nitems(urtw_8225v2b_rf_part2); i++)
    -		urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val);
    -
    -	urtw_write32_m(sc, 0xf0, (7 << 12) | (3 << 8) | 0x1c);
    -	urtw_write32_m(sc, 0xf4, (7 << 12) | (3 << 8) | 0x1c);
    -	urtw_write32_m(sc, 0xf8, (7 << 12) | (3 << 8) | 0x1c);
    -	urtw_write32_m(sc, 0xfc, (7 << 12) | (3 << 8) | 0x1c);
    -	urtw_write8_m(sc, URTW_ACM_CONTROL, 0);
    -
    -	urtw_8187_write_phy_ofdm(sc, 0x97, 0x46);
    -	urtw_8187_write_phy_ofdm(sc, 0xa4, 0xb6);
    -	urtw_8187_write_phy_ofdm(sc, 0x85, 0xfc);
    -	urtw_8187_write_phy_cck(sc, 0xc1, 0x88);
    -fail:
    -	return (error);
    +	return ((rate <= 22 && rate != 12 && rate != 18) ||
    +	    rate == 44) ? (1) : (0);
     }
     
    -
    -static usb_error_t
    -urtw_8225v2b_rf_set_chan(struct urtw_softc *sc, int chan)
    -{
    -	int ack;
    -	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
    -	usb_error_t error;
    -
    -	error = urtw_8225v2b_set_txpwrlvl(sc, chan);
    -	if (error)
    -		goto fail;
    -
    -	urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]);
    -	usb_pause_mtx(&sc->sc_mtx, 10);
    -
    -	urtw_write8_m(sc, URTW_SIFS, 0xa);
    -	if (ic->ic_flags & IEEE80211_F_SHSLOT) {
    -		urtw_write8_m(sc, URTW_SLOT, 0x9);
    -		urtw_write8_m(sc, URTW_DIFS, 0x1c);
    -		/* In 8187B, BRSR + 1 ==> EIFS register */
    -		urtw_write8_m(sc, URTW_BRSR + 1, 0x53);
    -
    -		ack = 112 + 48 + 0x1c;
    -		ack += (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
    -		    72 : 144;
    -		urtw_write8_m(sc, URTW_CARRIER_SCOUNT,
    -		    roundup2(ack, 4));
    -	} else {
    -		urtw_write8_m(sc, URTW_SLOT, 0x14);
    -		urtw_write8_m(sc, URTW_DIFS, 0x32);
    -		/* In 8187B, BRSR + 1 ==> EIFS register */
    -		urtw_write8_m(sc, URTW_BRSR + 1, 0x5b);
    -
    -		ack = 112 + 48 + 0x32;
    -		ack += (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ?
    -		    72 : 144;
    -		urtw_write8_m(sc, URTW_CARRIER_SCOUNT,
    -		    roundup2(ack, 4));
    -
    -	}
    -
    -fail:
    -	return (error);
    -}
    -
    -static usb_error_t
    -urtw_8225v2b_set_txpwrlvl(struct urtw_softc *sc, int chan)
    -{
    -	int i;
    -	uint8_t *cck_pwrtable;
    -	uint8_t cck_pwrlvl_max = 15;
    -	uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
    -	uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
    -	usb_error_t error;
    -
    -	/* CCK power setting */
    -	cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ?
    -	    ((sc->sc_flags & URTW_RTL8187B_REV_B) ? cck_pwrlvl_max : 22) :
    -	    (cck_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 0 : 7));
    -	cck_pwrlvl += sc->sc_txpwr_cck_base;
    -	cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
    -	cck_pwrtable = (chan == 14) ? urtw_8225v2b_txpwr_cck_ch14 :
    -	    urtw_8225v2b_txpwr_cck;
    -
    -	if (sc->sc_flags & URTW_RTL8187B_REV_B)
    -		cck_pwrtable += (cck_pwrlvl <= 6) ? 0 :
    -		    ((cck_pwrlvl <= 11) ? 8 : 16);
    -	else
    -		cck_pwrtable += (cck_pwrlvl <= 5) ? 0 :
    -		    ((cck_pwrlvl <= 11) ? 8 : ((cck_pwrlvl <= 17) ? 16 : 24));
    -
    -	for (i = 0; i < 8; i++)
    -		urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]);
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_CCK,
    -	    urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1);
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -
    -	/* OFDM power setting */
    -	ofdm_pwrlvl = (ofdm_pwrlvl > 15) ?
    -	    ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 17 : 25) :
    -	    (ofdm_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 2 : 10));
    -	ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
    -	ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
    -
    -	urtw_write8_m(sc, URTW_TX_GAIN_OFDM,
    -	    urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1);
    -
    -	if (sc->sc_flags & URTW_RTL8187B_REV_B) {
    -		if (ofdm_pwrlvl <= 11) {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x60);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x60);
    -		} else {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c);
    -		}
    -	} else {
    -		if (ofdm_pwrlvl <= 11) {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c);
    -		} else if (ofdm_pwrlvl <= 17) {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x54);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x54);
    -		} else {
    -			urtw_8187_write_phy_ofdm(sc, 0x87, 0x50);
    -			urtw_8187_write_phy_ofdm(sc, 0x89, 0x50);
    -		}
    -	}
    -	usb_pause_mtx(&sc->sc_mtx, 1);
    -fail:
    -	return (error);
    -}
    -
    -
     static device_method_t urtw_methods[] = {
     	DEVMETHOD(device_probe, urtw_match),
     	DEVMETHOD(device_attach, urtw_attach),
    diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
    index 74653d1e2a8..616c5d7b330 100644
    --- a/sys/dev/wi/if_wi.c
    +++ b/sys/dev/wi/if_wi.c
    @@ -1673,7 +1673,6 @@ wi_read_nicid(struct wi_softc *sc)
     		memset(ident, 0, sizeof(ident));
     		len = sizeof(ident);
     		/* value should be the format like "V2.00-11" */
    -		/* XXX: Flexelint: ident is local, p is arg */
     		if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
     		    *(p = (char *)ident) >= 'A' &&
     		    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
    diff --git a/sys/fs/msdosfs/msdosfs_conv.c b/sys/fs/msdosfs/msdosfs_conv.c
    index b9b6f4ad3fd..50dc1a06cc9 100644
    --- a/sys/fs/msdosfs/msdosfs_conv.c
    +++ b/sys/fs/msdosfs/msdosfs_conv.c
    @@ -266,7 +266,6 @@ dos2unixfn(dn, un, lower, pmp)
     		*un++ = c;
     		thislong++;
     	}
    -	/* XXX: FlexeLint: Not kosher, dn is an array, not a pointer */
     	dn += i;
     
     	/*
    diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
    index 47baeea70db..0cc330cd5ad 100644
    --- a/sys/kern/kern_jail.c
    +++ b/sys/kern/kern_jail.c
    @@ -1641,7 +1641,6 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
     #ifdef INET6
     	while (redo_ip6) {
     		ip6s = pr->pr_ip6s;
    -		/* XXX: FlexeLint claims mem leak */
     		ip6 = malloc(ip6s * sizeof(*ip6), M_PRISON, M_WAITOK);
     		mtx_lock(&pr->pr_mtx);
     		redo_ip6 = 0;
    diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
    index cfe316f952d..9387ba8ea97 100644
    --- a/sys/kern/kern_linker.c
    +++ b/sys/kern/kern_linker.c
    @@ -1875,7 +1875,6 @@ linker_search_kld(const char *name)
     		return (linker_strdup(name));
     
     	/* traverse the linker path */
    -	/* XXX: FlexeLint: this is not safe, ep will count past NUL */
     	len = strlen(name);
     	for (ep = linker_path; *ep; ep++) {
     		cp = ep;
    diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
    index 92009fa3a06..e6f2f536249 100644
    --- a/sys/kern/kern_lock.c
    +++ b/sys/kern/kern_lock.c
    @@ -312,7 +312,6 @@ lock_lockmgr(struct lock_object *lock, int how)
     	panic("lockmgr locks do not support sleep interlocking");
     }
     
    -/* XXX: flexelint retval */
     static int
     unlock_lockmgr(struct lock_object *lock)
     {
    diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c
    index 4a425bb97f4..85ca646370d 100644
    --- a/sys/kern/kern_mutex.c
    +++ b/sys/kern/kern_mutex.c
    @@ -133,28 +133,28 @@ struct lock_class lock_class_mtx_spin = {
     struct mtx blocked_lock;
     struct mtx Giant;
     
    -static void
    +void
     assert_mtx(struct lock_object *lock, int what)
     {
     
     	mtx_assert((struct mtx *)lock, what);
     }
     
    -static void
    +void
     lock_mtx(struct lock_object *lock, int how)
     {
     
     	mtx_lock((struct mtx *)lock);
     }
     
    -static void
    +void
     lock_spin(struct lock_object *lock, int how)
     {
     
     	panic("spin locks can only use msleep_spin");
     }
     
    -static int
    +int
     unlock_mtx(struct lock_object *lock)
     {
     	struct mtx *m;
    @@ -165,8 +165,7 @@ unlock_mtx(struct lock_object *lock)
     	return (0);
     }
     
    -/* XXX: FlexeLint retval */
    -static int
    +int
     unlock_spin(struct lock_object *lock)
     {
     
    diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c
    index 8c11471c89a..5371f6e975d 100644
    --- a/sys/net80211/ieee80211_action.c
    +++ b/sys/net80211/ieee80211_action.c
    @@ -105,7 +105,7 @@ ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f)
     		meshlm_send_action[act] = f;
     		return 0;
     	case IEEE80211_ACTION_CAT_MESHPATH:
    -		if (act >= N(hwmp_send_action))
    +		if (act > N(hwmp_send_action))
     			break;
     		hwmp_send_action[act] = f;
     		return 0;
    diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
    index b7c2c43f014..9bfbc61715f 100644
    --- a/sys/net80211/ieee80211_proto.h
    +++ b/sys/net80211/ieee80211_proto.h
    @@ -315,7 +315,7 @@ struct ieee80211_beacon_offsets {
     	uint8_t		*bo_ath;	/* start of ATH parameters */
     	uint8_t		*bo_appie;	/* start of AppIE element */
     	uint16_t	bo_appie_len;	/* AppIE length in bytes */
    -	uint16_t	bo_csa_trailer_len;
    +	uint16_t	bo_csa_trailer_len;;
     	uint8_t		*bo_csa;	/* start of CSA element */
     	uint8_t		*bo_spare[4];
     };
    diff --git a/sys/security/audit/audit_bsm_token.c b/sys/security/audit/audit_bsm_token.c
    index a050df11d7c..5523ea4ef13 100644
    --- a/sys/security/audit/audit_bsm_token.c
    +++ b/sys/security/audit/audit_bsm_token.c
    @@ -36,7 +36,6 @@
     #include 
     __FBSDID("$FreeBSD$");
     
    -#include 
     #include 
     #include 
     #include 
    
    From 0d07b627a39e631b3cb3eaf7abba109fd00ec1d6 Mon Sep 17 00:00:00 2001
    From: Poul-Henning Kamp 
    Date: Tue, 8 Sep 2009 13:24:36 +0000
    Subject: [PATCH 442/453] Having thrown the cat out of the house, add a
     necessary include.
    
    ---
     sys/security/audit/audit_bsm_token.c | 1 +
     1 file changed, 1 insertion(+)
    
    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 
    
    From 090110603032cd50ece19b2f14740223ac160510 Mon Sep 17 00:00:00 2001
    From: Poul-Henning Kamp 
    Date: Tue, 8 Sep 2009 15:18:25 +0000
    Subject: [PATCH 443/453] Add necessary include
    
    ---
     lib/libc/net/getifaddrs.c | 1 +
     1 file changed, 1 insertion(+)
    
    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 
    
    From 6f8e88e1dab0a1bef932abee2633307653b8ccab Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Tue, 8 Sep 2009 15:37:01 +0000
    Subject: [PATCH 444/453] Call ZFS_EXIT() after locking the vnode.
    
    MFC after:	1 week
    ---
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c | 4 +---
     1 file changed, 1 insertion(+), 3 deletions(-)
    
    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 f5295aa9ebb..ade6a891dd1 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
    @@ -1173,9 +1173,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);
     	}
     
    @@ -1197,7 +1196,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);
    
    From 2391003912b08bdf51c177599339bd1b7999a51d Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Tue, 8 Sep 2009 15:42:55 +0000
    Subject: [PATCH 445/453] On FreeBSD we don't have to look for snapshot's mount
     point, because fhtovp method is already called with proper mount point.
    
    MFC after:	1 week
    ---
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c | 6 ++++++
     1 file changed, 6 insertions(+)
    
    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 ade6a891dd1..c33f1f42a3f 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
    @@ -1130,6 +1130,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;
    @@ -1148,6 +1153,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;
    
    From f148fd9a4adee01580d968847244707361411123 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Tue, 8 Sep 2009 15:51:40 +0000
    Subject: [PATCH 446/453] When we automatically mount snapshot we want to
     return vnode of the mount point from the lookup and not covered vnode. This
     is one of the fixes for using .zfs/ over NFS.
    
    MFC after:	1 week
    ---
     .../uts/common/fs/zfs/zfs_ctldir.c            | 22 ++++++++++++++++---
     1 file changed, 19 insertions(+), 3 deletions(-)
    
    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 72db1f065ff..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
    @@ -882,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
    
    From d77fa177505921fdaa1a195cf466c09f1bf7dd4b Mon Sep 17 00:00:00 2001
    From: Roman Divacky 
    Date: Tue, 8 Sep 2009 15:55:13 +0000
    Subject: [PATCH 447/453] Add C/c/f/p/v switches plus a bunch of minor fixes
     and cleanups.
    
    Obtained from:	NetBSD
    Approved by:	des (maintainer)
    Approved by:	ed (mentor, implicit)
    ---
     usr.bin/unzip/unzip.1 |  41 ++++++-
     usr.bin/unzip/unzip.c | 266 ++++++++++++++++++++++++++++++++++++------
     2 files changed, 265 insertions(+), 42 deletions(-)
    
    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 Codan Smrgrav
      * 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;
    
    From d6b80392925dc7e549c637ce51e71e997e956131 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Tue, 8 Sep 2009 15:57:03 +0000
    Subject: [PATCH 448/453] We don't export individual snapshots, so mnt_export
     field in snapshot's mount point is NULL. That's why when we try to access
     snapshots over NFS use mnt_export field from the parent file system.
    
    MFC after:	1 week
    ---
     .../uts/common/fs/zfs/zfs_vfsops.c            | 23 +++++++++++++++++++
     1 file changed, 23 insertions(+)
    
    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 c33f1f42a3f..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,
     };
     
    @@ -1115,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)
     {
    
    From 216e03861cb162cb91e13df05204d5aff0dbc13d Mon Sep 17 00:00:00 2001
    From: Scott Long 
    Date: Tue, 8 Sep 2009 16:09:28 +0000
    Subject: [PATCH 449/453] Free the correct buffer in an error case.
    
    Submitted by:	phk
    ---
     sys/cam/scsi/scsi_cd.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    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;
     			}
    
    From d2111f569c3ff4dcf58f5df4f4de2e3e204e4c4e Mon Sep 17 00:00:00 2001
    From: Warner Losh 
    Date: Tue, 8 Sep 2009 16:37:18 +0000
    Subject: [PATCH 450/453] Cleanup tortured logic a big.  Noticed by FlexLint,
     per phk.
    
    # My reading of the docs suggests this can only happen on 10Base5 and
    # 10Base2 setups (and maybe only the former), which I can't test
    # adequately since I have nothing but 10BaseT, etc here.
    ---
     sys/dev/ep/if_ep.c | 15 +++++++--------
     1 file changed, 7 insertions(+), 8 deletions(-)
    
    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);
    
    From 3770996142959afc9ed750cd480a340745d1cf2c Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Tue, 8 Sep 2009 16:40:08 +0000
    Subject: [PATCH 451/453] Only log successful commands! Without this fix we log
     even unsuccessful commands executed by unprivileged users. Action is not
     really taken, but it is logged to pool history, which might be confusing.
    
    Reported by:	Denis Ahrens 
    MFC after:	3 days
    ---
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 6 ++++--
     1 file changed, 4 insertions(+), 2 deletions(-)
    
    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 69b126ed7f5..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);
     }
    
    From bb3fd7ff4fad764f60ecd63dec6492ad3b6c577a Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Tue, 8 Sep 2009 17:20:17 +0000
    Subject: [PATCH 452/453] Remove unused variable.
    
    ---
     sys/geom/geom_vfs.c | 2 --
     1 file changed, 2 deletions(-)
    
    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);
    
    From 2ff8f63aa6b7a81fd10e443a93f70ec6f84f3b7e Mon Sep 17 00:00:00 2001
    From: Edward Tomasz Napierala 
    Date: Tue, 8 Sep 2009 17:23:32 +0000
    Subject: [PATCH 453/453] Remove useless variable assignment.
    
    ---
     sys/ufs/ufs/ufs_acl.c | 3 ---
     1 file changed, 3 deletions(-)
    
    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);