## Automatically generated incremental diff
## From:   linux-2.4.13-pre3
## To:     linux-2.4.13-pre4
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.13-pre3/CREDITS linux/CREDITS
--- linux-2.4.13-pre3/CREDITS	Fri Oct  5 12:04:50 2001
+++ linux/CREDITS	Mon Dec  3 23:18:27 2001
@@ -2057,10 +2057,11 @@
 S: USA
 
 N: Patrick Mochel
-E: mochel@transmeta.com
+E: pat@osdl.org
+E: mochelp@infinity.powertie.org
 D: PCI Power Management, ACPI work
-S: 3940 Freedom Circle
-S: Santa Clara, CA 95054
+S: 15275 SW Koll Parkway, Suite H
+S: Beaverton, OR 97006 
 S: USA
 
 N: Eberhard Moenkeberg
diff -urN linux-2.4.13-pre3/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.13-pre3/Documentation/Configure.help	Mon Dec  3 23:18:17 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 23:18:27 2001
@@ -11609,26 +11609,14 @@
   The module will be called se401.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-USB ADMtek Pegasus-based ethernet device support
+Pegasus/Pegasus II based USB-Ethernet device support
 CONFIG_USB_PEGASUS
-  Say Y if you want to use your USB ethernet device. Supported
-  cards until now are:
-    ADMtek AN986 Pegasus (eval. board)
-    ADMtek ADM8511 Pegasus II (eval. board)
-    Accton 10/100
-    Billington USB-100
-    Corega FEter USB-TX
-    MELCO/BUFFALO LUA-TX
-    D-Link DSB-650TX, DSB-650TX-PNA, DSB-650, DU-E10, DU-E100
-    Linksys USB100TX, USB10TX
-    LANEED Ethernet LD-USB/TX
-    SMC 202
-    SOHOware NUB Ethernet
-    
-  Any Pegasus II based board also are supported.
-  If you have devices with vendor IDs other than noted above
-  you should add them in the driver code and send a message
-  to me (petkan@dce.bg) for update.
+  Say Y here if you know you have Pegasus or Pegasus II based adapter.
+  If in doubt then look at linux/drivers/usb/pegasus.h for the complete
+  list of supported devices.
+  If your particular adapter is not in the list and you are _sure_ it
+  is Pegasus or Pegasus II based then send me (pmanolov@lnxw.com) vendor
+  and device IDs.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
diff -urN linux-2.4.13-pre3/Documentation/README.DAC960 linux/Documentation/README.DAC960
--- linux-2.4.13-pre3/Documentation/README.DAC960	Thu Dec  7 17:05:41 2000
+++ linux/Documentation/README.DAC960	Mon Dec  3 23:18:27 2001
@@ -1,17 +1,17 @@
    Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
 
-			Version 2.2.9 for Linux 2.2.17
-			Version 2.4.9 for Linux 2.4.0
+			Version 2.2.11 for Linux 2.2.19
+			Version 2.4.11 for Linux 2.4.12
 
 			      PRODUCTION RELEASE
 
-			       7 September 2000
+				11 October 2001
 
 			       Leonard N. Zubkoff
 			       Dandelion Digital
 			       lnz@dandelion.com
 
-	 Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com>
+	 Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
 
 
 				 INTRODUCTION
@@ -20,7 +20,7 @@
 controllers.  Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont,
 California 94555, USA and can be reached at 510.796.6100 or on the World Wide
 Web at http://www.mylex.com.  Mylex Technical Support can be reached by
-electronic mail at support@mylex.com, by voice at 510.608.2400, or by FAX at
+electronic mail at mylexsup@us.ibm.com, by voice at 510.608.2400, or by FAX at
 510.745.7715.  Contact information for offices in Europe and Japan is available
 on their Web site.
 
@@ -120,7 +120,7 @@
 	    100MHz Intel i960RM RISC Processor
 	    16MB/32MB/64MB ECC SDRAM Memory
 
-AcceleRAID 160
+AcceleRAID 160 (AcceleRAID 170LP)
 	    1 Wide Ultra-160 LVD SCSI channel
 	    100MHz Intel i960RS RISC Processor
 	    Built in 16M ECC SDRAM Memory
@@ -170,6 +170,10 @@
 	    Intel i960 RISC Processor
 	    2MB/4MB/8MB/16MB/32MB DRAM Memory
 
+DAC960P	    1/2/3 Wide Fast SCSI-2 Channels
+	    Intel i960 RISC Processor
+	    2MB/4MB/8MB/16MB/32MB DRAM Memory
+
 For the eXtremeRAID 2000/3000 and AcceleRAID 352/170/160, firmware version
 6.00-01 or above is required.
 
@@ -180,36 +184,29 @@
 
 For the DAC960PJ and DAC960PG, firmware version 4.06-0-00 or above is required.
 
-For the DAC960PU, DAC960PD, and DAC960PL, firmware version 3.51-0-04 or above
-is required.
-
-Note that earlier revisions of the DAC960PU, DAC960PD, and DAC960PL controllers
-were delivered with version 2.xx firmware.  Version 2.xx firmware is not
-supported by this driver and no support is envisioned.  Contact Mylex RAID
-Technical Support to inquire about upgrading controllers with version 2.xx
-firmware to version 3.51-0-04.  Upgrading to version 3.xx firmware requires
-installation of higher capacity Flash ROM chips, and not all DAC960PD and
-DAC960PL controllers can be upgraded.
+For the DAC960PU, DAC960PD, DAC960PL, and DAC960P, either firmware version
+3.51-0-04 or above is required (for dual Flash ROM controllers), or firmware
+version 2.73-0-00 or above is required (for single Flash ROM controllers)
 
 Please note that not all SCSI disk drives are suitable for use with DAC960
 controllers, and only particular firmware versions of any given model may
 actually function correctly.  Similarly, not all motherboards have a BIOS that
 properly initializes the AcceleRAID 250, AcceleRAID 200, AcceleRAID 150,
 DAC960PJ, and DAC960PG because the Intel i960RD/RP is a multi-function device.
-If in doubt, contact Mylex RAID Technical Support (support@mylex.com) to verify
-compatibility.  Mylex makes available a hard disk compatibility list by FTP at
-ftp://ftp.mylex.com/pub/dac960/diskcomp.html.
+If in doubt, contact Mylex RAID Technical Support (mylexsup@us.ibm.com) to
+verify compatibility.  Mylex makes available a hard disk compatibility list at
+http://www.mylex.com/support/hdcomp/hd-lists.html.
 
 
 			      DRIVER INSTALLATION
 
-This distribution was prepared for Linux kernel version 2.2.17 or 2.4.0.
+This distribution was prepared for Linux kernel version 2.2.19 or 2.4.12.
 
 To install the DAC960 RAID driver, you may use the following commands,
 replacing "/usr/src" with wherever you keep your Linux kernel source tree:
 
   cd /usr/src
-  tar -xvzf DAC960-2.2.9.tar.gz (or DAC960-2.4.9.tar.gz)
+  tar -xvzf DAC960-2.2.11.tar.gz (or DAC960-2.4.11.tar.gz)
   mv README.DAC960 linux/Documentation
   mv DAC960.[ch] linux/drivers/block
   patch -p0 < DAC960.patch (if DAC960.patch is included)
@@ -374,11 +371,14 @@
 
     The "make-online" command changes the physical drive <channel>:<target-id>
     from status DEAD to status ONLINE.  In cases where multiple physical drives
-    have been killed simultaneously, this command may be used to bring them
-    back online, after which a consistency check is advisable.
+    have been killed simultaneously, this command may be used to bring all but
+    one of them back online, after which a rebuild to the final drive is
+    necessary.
 
     Warning: make-online should only be used on a dead physical drive that is
-    an active part of a drive group, never on a standby drive.
+    an active part of a drive group, never on a standby drive.  The command
+    should never be used on a dead drive that is part of a critical logical
+    drive; rebuild should be used if only a single drive is dead.
 
   make-standby <channel>:<target-id>
 
diff -urN linux-2.4.13-pre3/Documentation/usb/error-codes.txt linux/Documentation/usb/error-codes.txt
--- linux-2.4.13-pre3/Documentation/usb/error-codes.txt	Thu Dec  7 16:13:38 2000
+++ linux/Documentation/usb/error-codes.txt	Mon Dec  3 23:18:27 2001
@@ -79,8 +79,7 @@
 -EILSEQ			CRC mismatch
 
 USB_ST_STALL
--EPIPE			a) babble detect
-			b) endpoint stalled
+-EPIPE			endpoint stalled
 
 USB_ST_BUFFEROVERRUN
 -ECOMM			During an IN transfer, the host controller
@@ -95,7 +94,7 @@
 USB_ST_DATAOVERRUN
 -EOVERFLOW		The amount of data returned by the endpoint was
 			greater than either the max packet size of the
-			endpoint or the remaining buffer size
+			endpoint or the remaining buffer size.  "Babble".
 
 USB_ST_DATAUNDERRUN
 -EREMOTEIO		The endpoint returned less than max packet size
diff -urN linux-2.4.13-pre3/Documentation/usb/philips.txt linux/Documentation/usb/philips.txt
--- linux-2.4.13-pre3/Documentation/usb/philips.txt	Sun Aug 12 17:36:24 2001
+++ linux/Documentation/usb/philips.txt	Mon Dec  3 23:18:27 2001
@@ -22,21 +22,12 @@
 size
    Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
    'vga', for an image size of resp. 128x96, 160x120, 176x144,
-   320x240, 352x288 and 640x480 (of course, only for those cameras that support these resolutions).
+   320x240, 352x288 and 640x480 (of course, only for those cameras that 
+   support these resolutions).
 
 fps
    Specifies the desired framerate. Is an integer in the range of 4-30.
 
-palette
-   Specifies the desired colour order that should be delivered by read() and
-   mmap(). The string can be one of yuv420 or yuv420p; however, yuv420 will
-   be phased out, leaving only yuv420p, so this option will disappear
-   entirely.
-
-   Only the native yuv420/yuv420p format is supported by the in kernel driver. 
-   If you want to use other formats with in-kernel conversion download the
-   driver from the URL given. [Alan]
-
 fbufs
    This paramter specifies the number of internal buffers to use for storing 
    frames from the cam. This will help if the process that reads images from 
@@ -88,6 +79,26 @@
       
    The compression parameter only applies to the Vesta & ToUCam cameras.
    The 645 and 646 have fixed compression parameters.      
+
+leds
+   This settings takes 2 integers, that define the on/off time for the LED
+   (in milliseconds). One of the interesting things that you can do with
+   this is let the LED blink while the camera is in use. This:
+
+     leds=500,500
+      
+   will blink the LED once every second. But with:
+
+     leds=0,0
+
+   the LED never goes on, making it suitable for silent survaillance.
+
+   By default the camera's LED is on solid while in use, and turned off
+   when the camera is not used anymore.
+
+   This parameter works only with the ToUCam range of cameras (730, 740,
+   750). For other cameras this command is silently ignored, and the LED
+   cannot be controlled.
 
 trace
    In order to better detect problems, it is now possible to turn on a
diff -urN linux-2.4.13-pre3/Documentation/video4linux/bttv/CARDLIST linux/Documentation/video4linux/bttv/CARDLIST
--- linux-2.4.13-pre3/Documentation/video4linux/bttv/CARDLIST	Sun Aug  5 13:15:05 2001
+++ linux/Documentation/video4linux/bttv/CARDLIST	Mon Dec  3 23:18:27 2001
@@ -1,15 +1,15 @@
 bttv.o
-  card=0 -  *** UNKNOWN *** 
+  card=0 -  *** UNKNOWN/GENERIC *** 
   card=1 - MIRO PCTV
-  card=2 - Hauppauge old
+  card=2 - Hauppauge (bt848)
   card=3 - STB
   card=4 - Intel
   card=5 - Diamond DTV2000
   card=6 - AVerMedia TVPhone
   card=7 - MATRIX-Vision MV-Delta
-  card=8 - Fly Video II
+  card=8 - Fly Video II (Bt848)
   card=9 - TurboTV
-  card=10 - Hauppauge new (bt878)
+  card=10 - Hauppauge (bt878)
   card=11 - MIRO PCTV pro
   card=12 - ADS Technologies Channel Surfer TV
   card=13 - AVerMedia TVCapture 98
@@ -23,7 +23,7 @@
   card=21 - Lucky Star Image World ConferenceTV
   card=22 - Phoebe Tv Master + FM
   card=23 - Modular Technology MM205 PCTV, bt878
-  card=24 - Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)
+  card=24 - [many vendors] CPH05X/06X (bt878)
   card=25 - Terratec/Vobis TV-Boostar
   card=26 - Newer Hauppauge WinCam (bt878)
   card=27 - MAXI TV Video PCI2
@@ -34,10 +34,10 @@
   card=32 - Intel Create and Share PCI
   card=33 - Terratec TerraTValue
   card=34 - Leadtek WinFast 2000
-  card=35 - Chronos Video Shuttle II
-  card=36 - Typhoon TView TV/FM Tuner
+  card=35 - Flyvideo 98 (LR50Q) / Chronos Video Shuttle II
+  card=36 - Flyvideo 98FM (LR50Q) / Typhoon TView TV/FM Tuner
   card=37 - PixelView PlayTV pro
-  card=38 - TView99 CPH063
+  card=38 - TView99 CPH06X
   card=39 - Pinnacle PCTV Studio/Rave
   card=40 - STB2
   card=41 - AVerMedia TVPhone 98
@@ -49,11 +49,11 @@
   card=47 - Terratec TV/Radio+
   card=48 - Dynalink Magic TView 
   card=49 - GV-BCTV3
-  card=50 - Prolink PV-BT878P+4E (PixelView PlayTV PAK)
+  card=50 - Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP
   card=51 - Eagle Wireless Capricorn2 (bt878A)
   card=52 - Pinnacle PCTV Studio Pro
-  card=53 - Typhoon TView RDS / FM Stereo
-  card=54 - Lifetec LT 9415 TV
+  card=53 - Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS
+  card=54 - Lifetec LT 9415 TV (LR90 Rev.F)
   card=55 - BESTBUY Easy TV
   card=56 - FlyVideo '98/FM
   card=57 - GrandTec 'Grand Video Capture'
@@ -66,6 +66,12 @@
   card=64 - ATI TV-Wonder VE
   card=65 - FlyVideo 2000S
   card=66 - Terratec TValueRadio
+  card=67 - GV-BCTV4/PCI
+  card=68 - 3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)
+  card=69 - Active Imaging AIMMS
+  card=70 - PV-BT878P+
+  card=71 - Flyvideo 98EZ (capture only)
+  card=72 - Prolink PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)
 
 tuner.o
   type=0 - Temic PAL (4002 FH5)
@@ -82,7 +88,7 @@
   type=11 - Alps TSBB5
   type=12 - Alps TSBE5
   type=13 - Alps TSBC5
-  type=14 - Temic PAL_I (4006FH5)
+  type=14 - Temic PAL_BG (4006FH5)
   type=15 - Alps TSCH6
   type=16 - Temic PAL_DK (4016 FY5)
   type=17 - Philips NTSC_M (MK2)
@@ -99,3 +105,10 @@
   type=28 - LG PAL_BG+FM (TPI8PSB01D)
   type=29 - LG PAL_BG (TPI8PSB11D)
   type=30 - Temic PAL* auto + FM (4009 FN5)
+  type=31 - SHARP NTSC_JP (2U5JF5540)
+  type=32 - Samsung PAL TCPM9091PD27
+  type=33 - MT2032 universal
+  type=34 - Temic PAL_BG (4106 FH5)
+  type=35 - Temic PAL_DK/SECAM_L (4012 FY5)
+  type=36 - Temic NTSC (4136 FY5)
+  type=37 - LG PAL (newer TAPC series)
diff -urN linux-2.4.13-pre3/Documentation/video4linux/bttv/Cards linux/Documentation/video4linux/bttv/Cards
--- linux-2.4.13-pre3/Documentation/video4linux/bttv/Cards	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/Cards	Mon Dec  3 23:18:27 2001
@@ -0,0 +1,210 @@
+Suppported cards:
+
+
+Bt848/Bt848a/Bt849/Bt878/Bt879 cards
+------------------------------------
+
+All cards with Bt848/Bt848a/Bt849/Bt878/Bt879 and normal Composite/S-VHS inputs
+are supported.
+Teletext and Intercast support (PAL only) for ALL cards via VBI sample decoding
+in software.
+
+Some cards with additional multiplexing of inputs are only partially 
+supported (unless specifications by the card manufacturer are given).
+
+All other cards only differ by additional components as tuners, sound decoders,
+EEPROMs, teletext decoders ...
+
+
+MATRIX Vision
+-------------
+
+MV-Delta
+- Bt848A
+- 4 Composite inputs, 1 S-VHS input (shared with 4th composite)
+- EEPROM
+
+http://www.matrix-vision.de/
+
+This card has no tuner but supports all 4 composite (1 shared with an
+S-VHS input) of the Bt848A.
+Very nice card if you only have satellite TV but several tuners connected
+to the card via composite.
+
+Many thanks to Matrix-Vision for giving us 2 cards for free which made
+Bt848a/Bt849 single crytal operation support possible!!!
+
+
+
+Miro/Pinnacle PCTV
+------------------
+
+- Bt848 
+  some (all??) come with 2 crystals for PAL/SECAM and NTSC 
+- PAL, SECAM or NTSC TV tuner (Philips or TEMIC)
+- MSP34xx sound decoder on add on board
+  decoder is supported but AFAIK does not yet work 
+  (other sound MUX setting in GPIO port needed??? somebody who fixed this???)
+- 1 tuner, 1 composite and 1 S-VHS input
+- tuner type is autodetected
+
+http://www.miro.de/
+http://www.miro.com/
+
+
+Many thanks for the free card which made first NTSC support possible back
+in 1997!
+
+
+Hauppauge Win/TV pci
+--------------------
+
+There are many different versions of the Hauppauge cards with different 
+tuners (TV+Radio ...), teletext decoders.
+Note that even cards with same model numbers have (depending on the revision)
+different chips on it.
+
+- Bt848 (and others but always in 2 crystal operation???)
+  newer cards have a Bt878
+- PAL, SECAM, NTSC or tuner with or without Radio support
+
+e.g.:
+  PAL: 
+  TDA5737: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
+  TSA5522: 1.4 GHz I2C-bus controlled synthesizer, I2C 0xc2-0xc3
+  
+  NTSC:
+  TDA5731: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
+  TSA5518: no datasheet available on Philips site
+- Philips SAA5246 or SAA5284 ( or no) Teletext decoder chip	
+  with buffer RAM (e.g. Winbond W24257AS-35: 32Kx8 CMOS static RAM)
+  SAA5246 (I2C 0x22) is supported
+- 256 bytes EEPROM: Microchip 24LC02B or Philips 8582E2Y 
+  with configuration information
+  I2C address 0xa0 (24LC02B also responds to 0xa2-0xaf)
+- 1 tuner, 1 composite and (depending on model) 1 S-VHS input
+- 14052B: mux for selection of sound source
+- sound decoder: TDA9800, MSP34xx (stereo cards) 
+
+
+CPH-Series (CPH050, ...)
+------------------------
+Developed by TelSignal(?), OEMed by many vendors (Askey, Typhoon, 
+  Anubis, Dynalink)
+
+  Card series:
+    CPH01x: BT848 capture only
+    CPH03x: BT848
+    CPH05x: BT878 with FM
+    CPH06x: BT878 (w/o FM)
+    CPH07x: BT878 capture only
+ 
+  TV standards:
+     CPH0x0: NTSC-M/M
+     CPH0x1: PAL-B/G
+     CPH0x2: PAL-I/I
+     CPH0x3: PAL-D/K
+     CPH0x4: SECAM-L/L 
+     CPH0x5: SECAM-B/G 
+     CPH0x6: SECAM-D/K 
+     CPH0x7: PAL-N/N 
+     CPH0x8: PAL-B/H 
+     CPH0x9: PAL-M/M
+
+  CPH03x was often sold as "TV capturer".
+
+  Identifying:
+  1) 878 cards can be identified by PCI Subsystem-ID:
+      144f:3000 = CPH06x
+      144F:3002 = CPH05x w/ FM
+      144F:3005 = CPH06x_LC (w/o remote control)
+  1) The cards have a sticker with "CPH"-model on the back.
+  2) These cards have a number printed on the PCB just above the tuner metal box:
+      "80-CP2000300-x" = CPH03X
+      "80-CP2000500-x" = CPH05X
+      "80-CP2000600-x" = CPH06X / CPH06x_LC
+
+  Askey sells these cards as "Magic TView series", Brand "MagicXpress".
+  Other OEM often call these "Tview", "TView99" or else.
+
+Lifeview Flyvideo Series:
+-------------------------
+  The naming of these series differs in time and space.
+
+  Identifying:
+  1) Some models can be identified by PCI subsystem ID:
+      1852:1852 = Flyvideo 98 FM
+      1851:1850 = Flyvideo 98
+      1851:1851 = Flyvideo 98 EZ (capture only)
+  2) There is a print on the PCB:
+      LR25       = Flyvideo (Zoran)
+      LR37 Rev.C = Capture only (ZR36120 + SAA7110)
+      LR50 Rev.Q = Flyvideo 98 (w/eeprom and PCI subsystem ID)
+      LR50 Rev.W = Flyvideo 98 (no eeprom)
+      LR51 Rev.E = Flyvideo 98 EZ (capture only)
+      LR90       = Flyvideo 2000 series
+      LR90 Rev.F = Lifetec/Medion LT 9815
+      LR97       = Flyvideo DVBS
+
+  "Flyvideo II" had been the name for the 848 cards, nowadays (in Germany)
+  this name is re-used for LR50 Rev.W.
+  The Lifeview website has even more names: Flyvideo III,2100,3000,3100.
+  These cards are sold by many OEMs too.
+
+
+Typhoon TV card series:
+-----------------------
+  These can be CPH, Flyvideo, Pixelview or KNC1 series.
+  Typhoon is the brand of Anubis.
+  Model 50680 got re-used, some model no. had different contents over time.
+
+  Models:
+  50680 "TV Tuner PCI Pal BG"(old,red package)=can be CPH03x(bt848) or CPH06x(bt878)
+  50680 "TV Tuner Pal BG" (blue package)= Pixelview PV-BT878P+ (Rev 9B)
+  50681 "TV Tuner PCI Pal I" (variant of 50680)
+  50682 "TView TV/FM Tuner Pal BG"       = Flyvideo 98FM (LR50 Rev.Q)
+         Note: The package has a picture of CPH05x (which would be a real TView)
+  50683 "TV Tuner PCI SECAM" (variant of 50680)
+  50684 "TV Tuner Pal BG"                = Pixelview 878TV(Rev.3D)
+  50686 "TV Tuner"                       = KNC1 TV Station
+  50687 "TV Tuner stereo"                = KNC1 TV Station pro
+  50688 "TV Tuner RDS" (black package)   = KNC1 TV Station RDS
+  50692 "TV/FM Tuner" (small PCB)
+  50868 "TV/FM Tuner Pal I" (variant of 50682)
+  50999 "TV/FM Tuner Secam" (variant of 50682)
+
+
+Guillemot
+---------
+  Maxi TV Video 2 = LR50 Rev.Q (FI1216MF, PAL BG+SECAM)
+  Maxi TV Video 3 = CPH064 (PAL BG + SECAM)
+
+Mentor
+------
+  Mentor TV card ("55-878TV-U1") = Pixelview 878TV(Rev.3F) (w/FM w/Remote)
+
+Prolink
+-------
+   Pixelview Play TV Pro:
+     PV-BT878P+rev.9B (Play TV Pro w/FM w/NICAM)
+     PV-BT878P+rev.8X 
+     PV-BT878P+rev.4C (Play TV Pro) 
+     PV-BT878P+rev.4E (Play TV Pak) 
+     PV-BT878P+rev.2F 
+     PV-BT878TV 
+
+   PixelView Play TV 
+     PV-BT848P+
+
+Dynalink
+--------
+   These are CPH series.
+
+Phoebemicro
+-----------
+   TV Master    = CPH030 or CPH060
+   TV Master FM = CPH050
+
+Genius/Kye
+----------
+   Video Wonder/Genius Internet Video Kit = LR37 Rev.C
diff -urN linux-2.4.13-pre3/Documentation/video4linux/bttv/Insmod-options linux/Documentation/video4linux/bttv/Insmod-options
--- linux-2.4.13-pre3/Documentation/video4linux/bttv/Insmod-options	Sun Aug  5 13:15:05 2001
+++ linux/Documentation/video4linux/bttv/Insmod-options	Mon Dec  3 23:18:27 2001
@@ -1,6 +1,6 @@
 
 bttv.o
-	the bt848 (grabber chip) driver
+	the bt848/878 (grabber chip) driver
 
 	insmod args:
 		card=n		card type, see CARDLIST for a list.
@@ -10,12 +10,11 @@
 			0: don't use PLL
 			1: 28 MHz crystal installed
 			2: 35 MHz crystal installed
-		triton1=0/1     for Triton1 compatibility
-				Triton1 is automatically recognized
-				but this might also help with other chipsets
-		vsfx=0/1	yet another chipset bug compatibility flag
-				(bt878 docs mentiones via+sis, but no
-				specific chipsets with that problem).
+
+		triton1=0/1     for Triton1 (+others) compatibility
+		vsfx=0/1	yet another chipset bug compatibility bit
+				see README.quirks for details on these two.
+
 		bigendian=n	Set the endianness of the gfx framebuffer.
 				Default is native endian.
 		fieldnr=0/1	Count fields.  Some TV descrambling software
@@ -23,8 +22,8 @@
 				50 useless IRQs/sec.  default is 0 (off).
 		autoload=0/1	autoload helper modules (tuner, audio).
 				default is 1 (on).
-		bttv_verbose=0/1/2  verbose level (at insmod time, while looking
-				at the hardware).  default is 1.
+		bttv_verbose=0/1/2  verbose level (at insmod time, while
+				looking at the hardware).  default is 1.
 		bttv_debug=0/1	debug messages (for capture).
 				default is 0 (off).
 		irq_debug=0/1	irq handler debug messages.
@@ -80,12 +79,32 @@
 		tda9850  = 1	The tea6300 can't be autodetected and is
 		tda9855  = 1	therefore off by default, if you have
 		tda9873  = 1	this one on your card (STB uses these)
-		tea6300  = 0	you have to enable it explicitly.
-		tea6420  = 1	The two tda985x chips use the same i2c
-		pic16c54 = 1	address and can't be disturgished from
-				each other, you might have to disable
+		tda9874a = 1	you have to enable it explicitly.
+		tea6300  = 0	The two tda985x chips use the same i2c
+		tea6420  = 1	address and can't be disturgished from
+		pic16c54 = 1	each other, you might have to disable
 				the wrong one.
 		debug = 1	print debug messages
+
+	insmod args for tda9874a:
+		tda9874a_SIF=1/2	select sound IF input pin (1 or 2)
+					(default is pin 1)
+		tda9874a_STD=n		select TV sound standard (0..8):
+					0 - A2, B/G
+					1 - A2, M (Korea)
+					2 - A2, D/K (1)
+					3 - A2, D/K (2)
+					4 - A2, D/K (3)
+					5 - NICAM, I
+					6 - NICAM, B/G
+					7 - NICAM, D/K (default)
+					8 - NICAM, L
+
+	Note: tda9874a is very similar to tda9874 (without 'A'-suffix), but
+	this driver will not work for the latter device (will not load).
+	Note: tda9874a and tda9875 (which is supported separately by
+	tda9875.o) use the same i2c address so both modules should not be
+	used at the same time.
 
 msp3400.o
 	The driver for the msp34xx sound processor chips. If you have a
diff -urN linux-2.4.13-pre3/Documentation/video4linux/bttv/README.quirks linux/Documentation/video4linux/bttv/README.quirks
--- linux-2.4.13-pre3/Documentation/video4linux/bttv/README.quirks	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/README.quirks	Mon Dec  3 23:18:27 2001
@@ -0,0 +1,83 @@
+
+Below is what the bt878 data book says about the PCI bug compatibility
+modes of the bt878 chip.
+
+The triton1 insmod option sets the EN_TBFX bit in the control register.
+The vsfx insmod option does the same for EN_VSFX bit.  If you have
+stability problems you can try if one of these options makes your box
+work solid.
+
+drivers/pci/quirks.c knows about these issues, this way these bits are
+enabled automagically for known-buggy chipsets (look at the kernel
+messages, bttv tells you).
+
+HTH,
+
+  Gerd
+
+---------------------------- cut here --------------------------
+
+Normal PCI Mode
+---------------
+
+The PCI REQ signal is the logical-or of the incoming function requests.
+The inter-nal GNT[0:1] signals are gated asynchronously with GNT and
+demultiplexed by the audio request signal. Thus the arbiter defaults to
+the video function at power-up and parks there during no requests for
+bus access. This is desirable since the video will request the bus more
+often. However, the audio will have highest bus access priority. Thus
+the audio will have first access to the bus even when issuing a request
+after the video request but before the PCI external arbiter has granted
+access to the Bt879. Neither function can preempt the other once on the
+bus. The duration to empty the entire video PCI FIFO onto the PCI bus is
+very short compared to the bus access latency the audio PCI FIFO can
+tolerate.
+
+
+430FX Compatibility Mode
+------------------------
+
+When using the 430FX PCI, the following rules will ensure
+compatibility: 
+
+ (1) Deassert REQ at the same time as asserting FRAME. 
+ (2) Do not reassert REQ to request another bus transaction until after
+     finish-ing the previous transaction.
+
+Since the individual bus masters do not have direct control of REQ, a
+simple logical-or of video and audio requests would violate the rules.
+Thus, both the arbiter and the initiator contain 430FX compatibility
+mode logic. To enable 430FX mode, set the EN_TBFX bit as indicated in
+Device Control Register on page 104.
+
+When EN_TBFX is enabled, the arbiter ensures that the two compatibility
+rules are satisfied. Before GNT is asserted by the PCI arbiter, this
+internal arbiter may still logical-or the two requests. However, once
+the GNT is issued, this arbiter must lock in its decision and now route
+only the granted request to the REQ pin. The arbiter decision lock
+happens regardless of the state of FRAME because it does not know when
+FRAME will be asserted (typically - each initiator will assert FRAME on
+the cycle following GNT). When FRAME is asserted, it is the initiator s
+responsibility to remove its request at the same time. It is the
+arbiters responsibility to allow this request to flow through to REQ and
+not allow the other request to hold REQ asserted. The decision lock may
+be removed at the end of the transaction: for example, when the bus is
+idle (FRAME and IRDY). The arbiter decision may then continue
+asynchronously until GNT is again asserted.
+
+
+Interfacing with Non-PCI 2.1 Compliant Core Logic
+-------------------------------------------------
+
+A small percentage of core logic devices may start a bus transaction
+during the same cycle that GNT is de-asserted. This is non PCI 2.1
+compliant. To ensure compatibility when using PCs with these PCI
+controllers, the EN_VSFX bit must be enabled (refer to Device Control
+Register on page 104). When in this mode, the arbiter does not pass GNT
+to the internal functions unless REQ is asserted. This prevents a bus
+transaction from starting the same cycle as GNT is de-asserted. This
+also has the side effect of not being able to take advantage of bus
+parking, thus lowering arbitration performance. The Bt879 drivers must
+query for these non-compliant devices, and set the EN_VSFX bit only if
+required.
+
diff -urN linux-2.4.13-pre3/Documentation/video4linux/bttv/Sound-FAQ linux/Documentation/video4linux/bttv/Sound-FAQ
--- linux-2.4.13-pre3/Documentation/video4linux/bttv/Sound-FAQ	Sun Aug  5 13:15:05 2001
+++ linux/Documentation/video4linux/bttv/Sound-FAQ	Mon Dec  3 23:18:27 2001
@@ -126,6 +126,7 @@
 tuner_type      - same as tuner= insmod option
 *_modulename    - hint whenever some card needs this or that audio
                   module loaded to work properly.
+has_radio	- whenever this TV card has a radio tuner.
 
 If some config item is specified both from the tvcards array and as
 insmod option, the insmod option takes precedence.
diff -urN linux-2.4.13-pre3/Documentation/video4linux/bttv/Tuners linux/Documentation/video4linux/bttv/Tuners
--- linux-2.4.13-pre3/Documentation/video4linux/bttv/Tuners	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/Tuners	Mon Dec  3 23:18:27 2001
@@ -0,0 +1,88 @@
+
+SAMSUNG Tuner identification: (e.g. TCPM9091PD27)
+  TCP [ABCJLMNQ] 90[89][125] [DP] [ACD] 27 [ABCD]
+ [ABCJLMNQ]:
+   A= BG+DK
+   B= BG
+   C= I+DK
+   J= NTSC-Japan
+   L= Secam LL
+   M= BG+I+DK
+   N= NTSC 
+   Q= BG+I+DK+LL
+ [125]:
+   2: No FM
+   5: With FM
+ [DP]:
+   D= NTSC
+   P= PAL
+ [ACD]:
+   A= F-connector
+   C= Phono connector
+   D= Din Jack
+ [ABCD]:
+   3-wire/I2C tuning, 2-band/3-band
+
+Philips Tuner identification: (e.g. FM1216MF)
+  F[IRMQ]12[1345]{MF|ME|MP}
+  [IRMQ]:
+   I: Tuner Series
+   R: Tuner + Radio IF
+   M: Tuner + FM
+   Q,MR: specials
+   TD15xx: Digital Tuner ATSC
+  [1345]
+   1: PAL BG
+   3: NTSC
+   4: PAL I
+   5: Pal DK
+  {MF|ME|MP}
+   MF: w/ Secam
+   ME: BD DK I LL
+   MP: BG DK I
+   MR: BG DK M (?)
+   MG: BG DKI M (?)
+
+Temic Tuner identification: (.e.g 4006FH5)
+   4[01][0136][269]F[HYNR]5
+    40x2: Tuner (5V/33V), different I2C programming from Philips !
+    40x6: Tuner 5V
+    41xx: Tuner compact
+    40x9: Tuner+FM compact
+   [0136]
+    0: PAL BG
+    1: Pal DK, Secam LL
+    3: NTSC
+    6: PAL I
+   F[HYNR]5
+    FH5: Pal BG
+    FY5: others
+    FN5: multistandard
+    FR5: w/ FM radio
+   3X xxxx: order number with specific connector
+
+LG Innotek Tuner:
+  TPI8NSR11 : NTSC J/M    (TPI8NSR01 w/FM)  (P,210/497)
+  TPI8PSB11 : PAL B/G     (TPI8PSB01 w/FM)  (P,170/450)
+  TAPC-I701 : PAL I       (TAPC-I001 w/FM)  (P,170/450)
+  TPI8PSB12 : PAL D/K+B/G (TPI8PSB02 w/FM)  (P,170/450)
+  TAPC-H701P: NTSC_JP     (TAPC-H001P w/FM) (L,170/450)
+  TAPC-G701P: PAL B/G     (TAPC-G001P w/FM) (L,170/450)
+  TAPC-W701P: PAL I       (TAPC-W001P w/FM) (L,170/450)
+  TAPC-Q703P: PAL D/K     (TAPC-Q001P w/FM) (L,170/450)
+  TAPC-Q704P: PAL D/K+I   (L,170/450)
+  TAPC-G702P: PAL D/K+B/G (L,170/450)
+
+  TADC-H002F: NTSC (L,175/410?; 2-B, C-W+11, W+12-69)
+  TADC-M201D: PAL D/K+B/G+I (L,143/425)  (sound control at I2C address 0xc8)
+  TADC-T003F: NTSC Taiwan  (L,175/410?; 2-B, C-W+11, W+12-69)
+
+  (API,Lo-Hi-takeover/Hi-UHF-takeover)
+   I2C APIs:
+    L= LG programming (VHF_LO=0x01, VHF_HI=0x02, UHF=0x08, radio=0x04)
+    P= Philips progr. (VHF_LO=0xA0, VHF_HI=0x90, UHF=0x30, radio=0x04)
+    T= Temic progr.   (VHF_LO=0x02, VHF_HI=0x04, UHF=0x01)
+  Suffix: 
+    P= Standard phono female socket
+    D= IEC female socket
+    F= F-connector
diff -urN linux-2.4.13-pre3/MAINTAINERS linux/MAINTAINERS
--- linux-2.4.13-pre3/MAINTAINERS	Mon Dec  3 23:18:17 2001
+++ linux/MAINTAINERS	Mon Dec  3 23:18:27 2001
@@ -1121,6 +1121,12 @@
 W:	http://www.torque.net/linux-pp.html
 S:	Maintained
 
+PERSONALITY HANDLING
+P:	Christoph Hellwig
+M:	hch@caldera.de
+L:	linux-abi-devel@lists.sourceforge.net
+S:	Supported
+
 PCI ID DATABASE
 P:	Jens Maurer
 M:	jmaurer@cck.uni-kl.de
diff -urN linux-2.4.13-pre3/Makefile linux/Makefile
--- linux-2.4.13-pre3/Makefile	Mon Dec  3 23:18:17 2001
+++ linux/Makefile	Mon Dec  3 23:18:27 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 13
-EXTRAVERSION =-pre3
+EXTRAVERSION =-pre4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.13-pre3/arch/i386/defconfig linux/arch/i386/defconfig
--- linux-2.4.13-pre3/arch/i386/defconfig	Mon Dec  3 23:18:17 2001
+++ linux/arch/i386/defconfig	Mon Dec  3 23:18:27 2001
@@ -704,6 +704,8 @@
 #
 # CONFIG_USB_DEVICEFS is not set
 # CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_LONG_TIMEOUT is not set
+# CONFIG_USB_LARGE_CONFIG is not set
 
 #
 # USB Controllers
@@ -718,9 +720,13 @@
 # CONFIG_USB_BLUETOOTH is not set
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
 # CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -744,20 +750,18 @@
 #
 # USB Multimedia devices
 #
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_PWC is not set
-# CONFIG_USB_SE401 is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_DABUSB is not set
+
+#
+#   Video4Linux support is needed for USB Multimedia device support
+#
 
 #
 # USB Network adaptors
 #
 # CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_KAWETH is not set
 # CONFIG_USB_USBNET is not set
 
 #
@@ -769,9 +773,33 @@
 # USB Serial Converter support
 #
 # CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
 
 #
-# USB misc drivers
+# USB Miscellaneous drivers
 #
 # CONFIG_USB_RIO500 is not set
 
diff -urN linux-2.4.13-pre3/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.4.13-pre3/arch/i386/kernel/entry.S	Mon Oct  8 10:39:58 2001
+++ linux/arch/i386/kernel/entry.S	Mon Dec  3 23:18:27 2001
@@ -621,6 +621,7 @@
 	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved for TUX */
 	.long SYMBOL_NAME(sys_ni_syscall)	/* Reserved for Security */
 	.long SYMBOL_NAME(sys_gettid)
+	.long SYMBOL_NAME(sys_readahead)	/* 225 */
 
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long SYMBOL_NAME(sys_ni_syscall)
diff -urN linux-2.4.13-pre3/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c
--- linux-2.4.13-pre3/arch/i386/kernel/ldt.c	Thu Jul 26 13:29:45 2001
+++ linux/arch/i386/kernel/ldt.c	Mon Dec  3 23:18:27 2001
@@ -45,6 +45,25 @@
 	return err;
 }
 
+static int read_default_ldt(void * ptr, unsigned long bytecount)
+{
+	int err;
+	unsigned long size;
+	void *address;
+
+	err = 0;
+	address = &default_ldt[0];
+	size = sizeof(struct desc_struct);
+	if (size > bytecount)
+		size = bytecount;
+
+	err = size;
+	if (copy_to_user(ptr, address, size))
+		err = -EFAULT;
+
+	return err;
+}
+
 static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
 {
 	struct mm_struct * mm = current->mm;
@@ -139,6 +158,9 @@
 		break;
 	case 1:
 		ret = write_ldt(ptr, bytecount, 1);
+		break;
+	case 2:
+		ret = read_default_ldt(ptr, bytecount);
 		break;
 	case 0x11:
 		ret = write_ldt(ptr, bytecount, 0);
diff -urN linux-2.4.13-pre3/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c
--- linux-2.4.13-pre3/arch/i386/kernel/pci-irq.c	Wed Jul  4 15:39:28 2001
+++ linux/arch/i386/kernel/pci-irq.c	Mon Dec  3 23:18:27 2001
@@ -458,6 +458,8 @@
 	{ "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set },
 	{ "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4,
 	  pirq_serverworks_get, pirq_serverworks_set },
+	{ "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5,
+	  pirq_serverworks_get, pirq_serverworks_set },
 	{ "AMD756 VIPER", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B,
 		pirq_amd756_get, pirq_amd756_set },
 
diff -urN linux-2.4.13-pre3/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- linux-2.4.13-pre3/arch/ppc/8xx_io/enet.c	Mon Oct  8 11:40:13 2001
+++ linux/arch/ppc/8xx_io/enet.c	Mon Dec  3 23:18:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.enet.c 1.15 09/14/01 18:01:16 trini
+ * BK Id: SCCS/s.enet.c 1.17 10/11/01 11:55:47 trini
  */
 /*
  * Ethernet driver for Motorola MPC8xx.
@@ -147,7 +147,7 @@
 static int scc_enet_open(struct net_device *dev);
 static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int scc_enet_rx(struct net_device *dev);
-static void scc_enet_interrupt(void *dev_id);
+static void scc_enet_interrupt(void *dev_id, struct pt_regs *regs);
 static int scc_enet_close(struct net_device *dev);
 static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
@@ -303,7 +303,7 @@
  * This is called from the CPM handler, not the MPC core interrupt.
  */
 static void
-scc_enet_interrupt(void *dev_id)
+scc_enet_interrupt(void *dev_id, struct pt_regs *regs)
 {
 	struct	net_device *dev = dev_id;
 	volatile struct	scc_enet_private *cep;
@@ -805,22 +805,10 @@
 	ep->sen_iaddr4 = 0;
 
 	/* Set Ethernet station address.
-	 *
-	 * If we performed a MBX diskless boot, the Ethernet controller
-	 * has been initialized and we copy the address out into our
-	 * own structure.
-	 *
-	 * All other types of boards supply the address in the board
-	 * information structure, so we copy that into the controller.
 	 */
 	eap = (unsigned char *)&(ep->sen_paddrh);
-#ifndef CONFIG_MBX
 	for (i=5; i>=0; i--)
 		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
-#else
-	for (i=5; i>=0; i--)
-		dev->dev_addr[i] = *eap++;
-#endif
 
 	ep->sen_pper = 0;	/* 'cause the book says so */
 	ep->sen_taddrl = 0;	/* temp address (LSB) */
@@ -943,6 +931,14 @@
 	immap->im_ioport.iop_pcdat &= ~PC_BSE_LOOPBACK;
 #endif
 
+#ifdef CONFIG_FADS
+	cp->cp_pbpar |= PB_ENET_TENA;
+	cp->cp_pbdir |= PB_ENET_TENA;
+
+	/* Enable the EEST PHY.
+	*/
+	*((volatile uint *)BCSR1) &= ~BCSR1_ETHEN;
+#endif
 
 	dev->base_addr = (unsigned long)ep;
 	dev->priv = cep;
@@ -970,5 +966,3 @@
 
 	return 0;
 }
-
-
diff -urN linux-2.4.13-pre3/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c
--- linux-2.4.13-pre3/arch/ppc/8xx_io/fec.c	Mon Oct  8 11:40:13 2001
+++ linux/arch/ppc/8xx_io/fec.c	Mon Dec  3 23:18:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.fec.c 1.18 09/22/01 09:12:32 trini
+ * BK Id: SCCS/s.fec.c 1.20 10/11/01 11:55:47 trini
  */
 /*
  * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
@@ -868,6 +868,8 @@
 		*s |= PHY_STAT_FAULT;
 	if (mii_reg & 0x0020)
 		*s |= PHY_STAT_ANC;
+
+	fep->link = (*s & PHY_STAT_LINK) ? 1 : 0;
 }
 
 static void mii_parse_cr(uint mii_reg, struct net_device *dev)
@@ -1650,11 +1652,11 @@
 #endif
 
 #ifdef PHY_INTERRUPT
-	if (request_8xxirq(PHY_INTERRUPT, mii_link_interrupt, 0, "mii", dev) != 0)
-		panic("Could not allocate MII IRQ!");
-
 	((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |=
 		(0x80000000 >> PHY_INTERRUPT);
+
+	if (request_8xxirq(PHY_INTERRUPT, mii_link_interrupt, 0, "mii", dev) != 0)
+		panic("Could not allocate MII IRQ!");
 #endif
 
 	dev->base_addr = (unsigned long)fecp;
diff -urN linux-2.4.13-pre3/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- linux-2.4.13-pre3/arch/ppc/kernel/m8xx_setup.c	Mon Oct  8 11:40:13 2001
+++ linux/arch/ppc/kernel/m8xx_setup.c	Mon Dec  3 23:18:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.m8xx_setup.c 1.32 09/27/01 09:01:12 trini
+ * BK Id: SCCS/s.m8xx_setup.c 1.35 10/11/01 11:55:47 trini
  *
  *  linux/arch/ppc/kernel/setup.c
  *
@@ -52,7 +52,7 @@
 
 unsigned char __res[sizeof(bd_t)];
 
-extern void m8xx_ide_init();
+extern void m8xx_ide_init(void);
 
 #ifdef CONFIG_BLK_DEV_RAM
 extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
@@ -164,9 +164,9 @@
 	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = ~KAPWR_KEY;
 	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = ~KAPWR_KEY;
 	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk    = ~KAPWR_KEY;
-	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
-	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
-	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk    = KAPWR_KEY;
+	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk =  KAPWR_KEY;
+	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck =  KAPWR_KEY;
+	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk    =  KAPWR_KEY;
 
 	/* Disable the RTC one second and alarm interrupts. */
 	((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &=
diff -urN linux-2.4.13-pre3/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- linux-2.4.13-pre3/arch/sparc64/Makefile	Sat Jul 28 12:12:38 2001
+++ linux/arch/sparc64/Makefile	Mon Dec  3 23:18:27 2001
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.47 2001/07/27 09:42:22 davem Exp $
+# $Id: Makefile,v 1.48 2001/10/15 09:24:51 davem Exp $
 # sparc64/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -15,7 +15,7 @@
 CC		:= $(shell if gcc -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo gcc; else echo sparc64-linux-gcc; fi )
 
 NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
-NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
+NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
 UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; )
 
 export NEW_GCC
diff -urN linux-2.4.13-pre3/arch/sparc64/kernel/dtlb_base.S linux/arch/sparc64/kernel/dtlb_base.S
--- linux-2.4.13-pre3/arch/sparc64/kernel/dtlb_base.S	Wed Oct 10 23:42:46 2001
+++ linux/arch/sparc64/kernel/dtlb_base.S	Mon Dec  3 23:18:27 2001
@@ -1,4 +1,4 @@
-/* $Id: dtlb_base.S,v 1.16 2001/10/09 04:02:11 davem Exp $
+/* $Id: dtlb_base.S,v 1.17 2001/10/11 22:33:52 davem Exp $
  * dtlb_base.S:	Front end to DTLB miss replacement strategy.
  *              This is included directly into the trap table.
  *
@@ -71,8 +71,8 @@
 	be,pn		%xcc, 3f			! Yep, special processing
 	 CREATE_VPTE_OFFSET2(%g4, %g6)			! Create VPTE offset
 	cmp		%g5, 3				! Last trap level?
-	be,a,pn		%xcc, 1f			! Yep, use non-faulting load
-	 ldxa		[%g3 + %g6] ASI_SNF, %g5	! Load VPTE (no-VPTE-fault)
+	be,pn		%xcc, longpath			! Yep, cannot risk VPTE miss
+	 nop						! delay slot
 
 /* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses	*/
 	ldxa		[%g3 + %g6] ASI_S, %g5		! Load VPTE
diff -urN linux-2.4.13-pre3/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S
--- linux-2.4.13-pre3/arch/sparc64/kernel/entry.S	Tue Aug 28 07:09:44 2001
+++ linux/arch/sparc64/kernel/entry.S	Mon Dec  3 23:18:27 2001
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.134 2001/08/27 18:42:07 kanoj Exp $
+/* $Id: entry.S,v 1.135 2001/10/13 23:04:09 kanoj Exp $
  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -725,19 +725,14 @@
 __do_data_access_exception_tl1:
 	rdpr		%pstate, %g4
 	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
-	rdpr		%tl, %g3
-	cmp		%g3, 1
 	mov		TLB_SFSR, %g3
 	mov		DMMU_SFAR, %g5
 	ldxa		[%g3] ASI_DMMU, %g4	! Get SFSR
 	ldxa		[%g5] ASI_DMMU, %g5	! Get SFAR
 	stxa		%g0, [%g3] ASI_DMMU	! Clear SFSR.FaultValid bit
 	membar		#Sync
-	bgu,pn		%icc, winfix_dax
+	ba,pt		%xcc, winfix_dax
 	 rdpr		%tpc, %g3
-	sethi		%hi(109f), %g7
-	ba,pt		%xcc, etraptl1
-	 or		%g7, %lo(109f), %g7	! Merge in below
 __do_data_access_exception:
 	rdpr		%pstate, %g4
 	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
@@ -1186,7 +1181,7 @@
 	ldxa		[%g3] ASI_DMMU, %g5
 	stxa		%g0, [%g3] ASI_DMMU	! Clear FaultValid bit
 	membar		#Sync
-	bgu,pn		%icc, winfix_dax
+	bgu,pn		%icc, winfix_mna
 	 rdpr		%tpc, %g3
 
 1:	sethi		%hi(109f), %g7
diff -urN linux-2.4.13-pre3/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S
--- linux-2.4.13-pre3/arch/sparc64/kernel/rtrap.S	Tue Jun 12 11:08:46 2001
+++ linux/arch/sparc64/kernel/rtrap.S	Mon Dec  3 23:18:27 2001
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.55 2001/06/05 09:56:06 davem Exp $
+/* $Id: rtrap.S,v 1.56 2001/10/13 00:14:34 kanoj Exp $
  * rtrap.S: Preparing for return from trap on Sparc V9.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -82,12 +82,12 @@
 		 andn			%l1, %l4, %l1
 
 		.align			64
-		.globl			rtrap_clr_l6, rtrap
+		.globl			rtrap_clr_l6, rtrap, irqsz_patchme
 rtrap_clr_l6:	clr			%l6
 rtrap:		lduw			[%g6 + AOFF_task_processor], %l0
 		sethi			%hi(irq_stat), %l2	! &softirq_active
 		or			%l2, %lo(irq_stat), %l2	! &softirq_active
-		sllx			%l0, 6, %l0
+irqsz_patchme:	sllx			%l0, 0, %l0
 		lduw			[%l2 + %l0], %l1	! softirq_pending
 		cmp			%l1, 0
 
diff -urN linux-2.4.13-pre3/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- linux-2.4.13-pre3/arch/sparc64/kernel/setup.c	Mon Oct  1 09:19:56 2001
+++ linux/arch/sparc64/kernel/setup.c	Mon Dec  3 23:18:27 2001
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.67 2001/09/21 03:17:06 kanoj Exp $
+/*  $Id: setup.c,v 1.68 2001/10/13 00:14:34 kanoj Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -480,6 +480,18 @@
 	conswitchp = &prom_con;
 #endif
 
+#ifdef CONFIG_SMP
+	i = (unsigned long)&irq_stat[1] - (unsigned long)&irq_stat[0];
+	if ((i == SMP_CACHE_BYTES) || (i == (2 * SMP_CACHE_BYTES))) {
+		extern unsigned int irqsz_patchme[1];
+		irqsz_patchme[0] |= ((i == SMP_CACHE_BYTES) ? SMP_CACHE_BYTES_SHIFT : \
+							SMP_CACHE_BYTES_SHIFT + 1);
+		flushi((long)&irqsz_patchme[1]);
+	} else {
+		prom_printf("Unexpected size of irq_stat[] elements\n");
+		prom_halt();
+	}
+#endif
 	/* Work out if we are starfire early on */
 	check_if_starfire();
 
diff -urN linux-2.4.13-pre3/drivers/acpi/include/platform/acgcc.h linux/drivers/acpi/include/platform/acgcc.h
--- linux-2.4.13-pre3/drivers/acpi/include/platform/acgcc.h	Sun Sep 23 09:42:32 2001
+++ linux/drivers/acpi/include/platform/acgcc.h	Mon Dec  3 23:18:27 2001
@@ -39,7 +39,6 @@
 #define BREAKPOINT3
 #define disable() __cli()
 #define enable()  __sti()
-#define wbinvd()
 
 /*! [Begin] no source code translation */
 
diff -urN linux-2.4.13-pre3/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- linux-2.4.13-pre3/drivers/block/DAC960.c	Mon Sep 10 12:42:31 2001
+++ linux/drivers/block/DAC960.c	Mon Dec  3 23:18:27 2001
@@ -19,8 +19,8 @@
 */
 
 
-#define DAC960_DriverVersion			"2.4.10"
-#define DAC960_DriverDate			"23 July 2001"
+#define DAC960_DriverVersion			"2.4.11"
+#define DAC960_DriverDate			"11 October 2001"
 
 
 #include <linux/version.h>
@@ -42,6 +42,7 @@
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/uaccess.h>
@@ -99,7 +100,7 @@
 */
 
 static NotifierBlock_T
-  DAC960_NotifierBlock =    { DAC960_Finalize, NULL, 0 };
+  DAC960_NotifierBlock =    { DAC960_Notifier, NULL, 0 };
 
 
 /*
@@ -269,7 +270,9 @@
 
 /*
   DAC960_AllocateCommand allocates a Command structure from Controller's
-  free list.
+  free list.  During driver initialization, a special initialization command
+  has been placed on the free list to guarantee that command allocation can
+  never fail.
 */
 
 static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T
@@ -480,6 +483,52 @@
 
 
 /*
+  DAC960_P_QueueCommand queues Command for DAC960 P Series Controllers.
+*/
+
+static void DAC960_P_QueueCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
+  CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
+  switch (CommandMailbox->Common.CommandOpcode)
+    {
+    case DAC960_V1_Enquiry:
+      CommandMailbox->Common.CommandOpcode = DAC960_V1_Enquiry_Old;
+      break;
+    case DAC960_V1_GetDeviceState:
+      CommandMailbox->Common.CommandOpcode = DAC960_V1_GetDeviceState_Old;
+      break;
+    case DAC960_V1_Read:
+      CommandMailbox->Common.CommandOpcode = DAC960_V1_Read_Old;
+      DAC960_PD_To_P_TranslateReadWriteCommand(CommandMailbox);
+      break;
+    case DAC960_V1_Write:
+      CommandMailbox->Common.CommandOpcode = DAC960_V1_Write_Old;
+      DAC960_PD_To_P_TranslateReadWriteCommand(CommandMailbox);
+      break;
+    case DAC960_V1_ReadWithScatterGather:
+      CommandMailbox->Common.CommandOpcode =
+	DAC960_V1_ReadWithScatterGather_Old;
+      DAC960_PD_To_P_TranslateReadWriteCommand(CommandMailbox);
+      break;
+    case DAC960_V1_WriteWithScatterGather:
+      CommandMailbox->Common.CommandOpcode =
+	DAC960_V1_WriteWithScatterGather_Old;
+      DAC960_PD_To_P_TranslateReadWriteCommand(CommandMailbox);
+      break;
+    default:
+      break;
+    }
+  while (DAC960_PD_MailboxFullP(ControllerBaseAddress))
+    udelay(1);
+  DAC960_PD_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox);
+  DAC960_PD_NewCommand(ControllerBaseAddress);
+}
+
+
+/*
   DAC960_ExecuteCommand executes Command and waits for completion.
 */
 
@@ -522,6 +571,32 @@
 
 
 /*
+  DAC960_V1_ExecuteTypeB executes a DAC960 V1 Firmware Controller Type 3B
+  Command and waits for completion.  It returns true on success and false
+  on failure.
+*/
+
+static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
+				       DAC960_V1_CommandOpcode_T CommandOpcode,
+				       unsigned char CommandOpcode2,
+				       void *DataPointer)
+{
+  DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
+  DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
+  DAC960_V1_CommandStatus_T CommandStatus;
+  DAC960_V1_ClearCommand(Command);
+  Command->CommandType = DAC960_ImmediateCommand;
+  CommandMailbox->Type3B.CommandOpcode = CommandOpcode;
+  CommandMailbox->Type3B.CommandOpcode2 = CommandOpcode2;
+  CommandMailbox->Type3B.BusAddress = Virtual_to_Bus32(DataPointer);
+  DAC960_ExecuteCommand(Command);
+  CommandStatus = Command->V1.CommandStatus;
+  DAC960_DeallocateCommand(Command);
+  return (CommandStatus == DAC960_V1_NormalCompletion);
+}
+
+
+/*
   DAC960_V1_ExecuteType3D executes a DAC960 V1 Firmware Controller Type 3D
   Command and waits for completion.  It returns true on success and false
   on failure.
@@ -1055,7 +1130,17 @@
     DAC1164P		    5.06 and above
     DAC960PTL/PRL/PJ/PG	    4.06 and above
     DAC960PU/PD/PL	    3.51 and above
+    DAC960PU/PD/PL/P	    2.73 and above
   */
+  if (Enquiry2.FirmwareID.MajorVersion == 0)
+    {
+      Enquiry2.FirmwareID.MajorVersion =
+	Controller->V1.Enquiry.MajorFirmwareVersion;
+      Enquiry2.FirmwareID.MinorVersion =
+	Controller->V1.Enquiry.MinorFirmwareVersion;
+      Enquiry2.FirmwareID.FirmwareType = '0';
+      Enquiry2.FirmwareID.TurnID = 0;
+    }
   sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d",
 	  Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion,
 	  Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID);
@@ -1064,7 +1149,9 @@
 	(Controller->FirmwareVersion[0] == '4' &&
 	 strcmp(Controller->FirmwareVersion, "4.06") >= 0) ||
 	(Controller->FirmwareVersion[0] == '3' &&
-	 strcmp(Controller->FirmwareVersion, "3.51") >= 0)))
+	 strcmp(Controller->FirmwareVersion, "3.51") >= 0) ||
+	(Controller->FirmwareVersion[0] == '2' &&
+	 strcmp(Controller->FirmwareVersion, "2.73") >= 0)))
     {
       DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
       DAC960_Error("Firmware Version = '%s'\n", Controller,
@@ -1120,6 +1207,20 @@
       return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY");
     }
   /*
+    Initialize the Background Initialization Status.
+  */
+  if ((Controller->FirmwareVersion[0] == '4' &&
+      strcmp(Controller->FirmwareVersion, "4.08") >= 0) ||
+      (Controller->FirmwareVersion[0] == '5' &&
+       strcmp(Controller->FirmwareVersion, "5.08") >= 0))
+    {
+      Controller->V1.BackgroundInitializationStatusSupported = true;
+      DAC960_V1_ExecuteType3B(Controller,
+			      DAC960_V1_BackgroundInitializationControl, 0x20,
+			      &Controller->
+			       V1.LastBackgroundInitializationStatus);
+    }
+  /*
     Initialize the Logical Drive Initially Accessible flag.
   */
   for (LogicalDriveNumber = 0;
@@ -1573,7 +1674,7 @@
 	    DeviceState->DeviceType == DAC960_V1_DiskType)
 	  {
 	    if (Controller->V1.DeviceResetCount[Channel][TargetID] > 0)
-	      DAC960_Info("         Disk Status: %s, %d blocks, %d resets\n",
+	      DAC960_Info("         Disk Status: %s, %u blocks, %d resets\n",
 			  Controller,
 			  (DeviceState->DeviceState == DAC960_V1_Device_Dead
 			   ? "Dead"
@@ -1586,7 +1687,7 @@
 			  DeviceState->DiskSize,
 			  Controller->V1.DeviceResetCount[Channel][TargetID]);
 	    else
-	      DAC960_Info("         Disk Status: %s, %d blocks\n", Controller,
+	      DAC960_Info("         Disk Status: %s, %u blocks\n", Controller,
 			  (DeviceState->DeviceState == DAC960_V1_Device_Dead
 			   ? "Dead"
 			   : DeviceState->DeviceState
@@ -1615,7 +1716,7 @@
     {
       DAC960_V1_LogicalDriveInformation_T *LogicalDriveInformation =
 	&Controller->V1.LogicalDriveInformation[LogicalDriveNumber];
-      DAC960_Info("    /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n",
+      DAC960_Info("    /dev/rd/c%dd%d: RAID-%d, %s, %u blocks, %s\n",
 		  Controller, Controller->ControllerNumber, LogicalDriveNumber,
 		  LogicalDriveInformation->RAIDLevel,
 		  (LogicalDriveInformation->LogicalDriveState
@@ -1681,18 +1782,32 @@
       if (PhysicalDeviceInfo->PhysicalDeviceState ==
 	  DAC960_V2_Device_Unconfigured)
 	continue;
-      DAC960_Info("         Disk Status: %s, %d blocks\n", Controller,
+      DAC960_Info("         Disk Status: %s, %u blocks\n", Controller,
 		  (PhysicalDeviceInfo->PhysicalDeviceState
 		   == DAC960_V2_Device_Online
 		   ? "Online"
 		   : PhysicalDeviceInfo->PhysicalDeviceState
-		     == DAC960_V2_Device_WriteOnly
-		     ? "Write-Only"
+		     == DAC960_V2_Device_Rebuild
+		     ? "Rebuild"
 		     : PhysicalDeviceInfo->PhysicalDeviceState
-		       == DAC960_V2_Device_Dead
-		       ? "Dead" : "Standby"),
-		  PhysicalDeviceInfo
-		  ->ConfigurableDeviceSizeIn512ByteBlocksOrMB);
+		       == DAC960_V2_Device_Missing
+		       ? "Missing"
+		       : PhysicalDeviceInfo->PhysicalDeviceState
+			 == DAC960_V2_Device_Critical
+			 ? "Critical"
+			 : PhysicalDeviceInfo->PhysicalDeviceState
+			   == DAC960_V2_Device_Dead
+			   ? "Dead"
+			   : PhysicalDeviceInfo->PhysicalDeviceState
+			     == DAC960_V2_Device_SuspectedDead
+			     ? "Suspected-Dead"
+			     : PhysicalDeviceInfo->PhysicalDeviceState
+			       == DAC960_V2_Device_CommandedOffline
+			       ? "Commanded-Offline"
+			       : PhysicalDeviceInfo->PhysicalDeviceState
+				 == DAC960_V2_Device_Standby
+				 ? "Standby" : "Unknown"),
+		  PhysicalDeviceInfo->ConfigurableDeviceSize);
       if (PhysicalDeviceInfo->ParityErrors == 0 &&
 	  PhysicalDeviceInfo->SoftErrors == 0 &&
 	  PhysicalDeviceInfo->HardErrors == 0 &&
@@ -1734,7 +1849,7 @@
 					    "-", "-", "-", "-" };
       unsigned char *GeometryTranslation;
       if (LogicalDeviceInfo == NULL) continue;
-      switch(LogicalDeviceInfo->DriveGeometry)
+      switch (LogicalDeviceInfo->DriveGeometry)
 	{
 	case DAC960_V2_Geometry_128_32:
 	  GeometryTranslation = "128/32";
@@ -1748,7 +1863,7 @@
 		       Controller, LogicalDeviceInfo->DriveGeometry);
 	  break;
 	}
-      DAC960_Info("    /dev/rd/c%dd%d: RAID-%d, %s, %d blocks\n",
+      DAC960_Info("    /dev/rd/c%dd%d: RAID-%d, %s, %u blocks\n",
 		  Controller, Controller->ControllerNumber, LogicalDriveNumber,
 		  LogicalDeviceInfo->RAIDLevel,
 		  (LogicalDeviceInfo->LogicalDeviceState
@@ -1757,7 +1872,7 @@
 		   : LogicalDeviceInfo->LogicalDeviceState
 		     == DAC960_V2_LogicalDevice_Critical
 		     ? "Critical" : "Offline"),
-		  LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB);
+		  LogicalDeviceInfo->ConfigurableDeviceSize);
       DAC960_Info("                  Logical Device %s, BIOS Geometry: %s\n",
 		  Controller,
 		  (LogicalDeviceInfo->LogicalDeviceControl
@@ -1907,15 +2022,11 @@
   RequestQueue->queuedata = Controller;
   Controller->RequestQueue = RequestQueue;
   /*
-    Initialize the Disk Partitions array, Partition Sizes array, Block Sizes
-    array, and Max Sectors per Request array.
+    Initialize the Max Sectors per Request array.
   */
   for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++)
-    {
-      Controller->BlockSizes[MinorNumber] = BLOCK_SIZE;
-      Controller->MaxSectorsPerRequest[MinorNumber] =
-	Controller->MaxBlocksPerCommand;
-    }
+    Controller->MaxSectorsPerRequest[MinorNumber] =
+      Controller->MaxBlocksPerCommand;
   Controller->GenericDiskInfo.part = Controller->DiskPartitions;
   Controller->GenericDiskInfo.sizes = Controller->PartitionSizes;
   blksize_size[MajorNumber] = Controller->BlockSizes;
@@ -1931,7 +2042,8 @@
   Controller->GenericDiskInfo.major_name = "rd";
   Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits;
   Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions;
-  Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount;
+  Controller->GenericDiskInfo.nr_real = DAC960_MaxLogicalDrives;
+  Controller->GenericDiskInfo.real_devices = Controller;
   Controller->GenericDiskInfo.next = NULL;
   Controller->GenericDiskInfo.fops = &DAC960_BlockDeviceOperations;
   /*
@@ -1978,6 +2090,46 @@
 
 
 /*
+  DAC960_ComputeGenericDiskInfo computes the values for the Generic Disk
+  Information Partition Sector Counts and Block Sizes.
+*/
+
+static void DAC960_ComputeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo)
+{
+  DAC960_Controller_T *Controller =
+    (DAC960_Controller_T *) GenericDiskInfo->real_devices;
+  int LogicalDriveNumber, i;
+  for (LogicalDriveNumber = 0;
+       LogicalDriveNumber < DAC960_MaxLogicalDrives;
+       LogicalDriveNumber++)
+    {
+      int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber, 0);
+      if (Controller->FirmwareType == DAC960_V1_Controller)
+	{
+	  if (LogicalDriveNumber < Controller->LogicalDriveCount)
+	    GenericDiskInfo->part[MinorNumber].nr_sects =
+	      Controller->V1.LogicalDriveInformation
+			     [LogicalDriveNumber].LogicalDriveSize;
+	  else GenericDiskInfo->part[MinorNumber].nr_sects = 0;
+	}
+      else
+	{
+	  DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo =
+	    Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
+	  if (LogicalDeviceInfo != NULL)
+	    GenericDiskInfo->part[MinorNumber].nr_sects =
+	      LogicalDeviceInfo->ConfigurableDeviceSize;
+	  else GenericDiskInfo->part[MinorNumber].nr_sects = 0;
+	}
+      for (i = 0; i < DAC960_MaxPartitions; i++)
+	if (GenericDiskInfo->part[MinorNumber].nr_sects > 0)
+	  Controller->BlockSizes[MinorNumber + i] = BLOCK_SIZE;
+	else Controller->BlockSizes[MinorNumber + i] = 0;
+    }
+}
+
+
+/*
   DAC960_RegisterDisk registers the DAC960 Logical Disk Device for Logical
   Drive Number if it exists.
 */
@@ -1991,7 +2143,8 @@
       register_disk(&Controller->GenericDiskInfo,
 		    DAC960_KernelDevice(Controller->ControllerNumber,
 					LogicalDriveNumber, 0),
-		    DAC960_MaxPartitions, &DAC960_BlockDeviceOperations,
+		    DAC960_MaxPartitions,
+		    &DAC960_BlockDeviceOperations,
 		    Controller->V1.LogicalDriveInformation
 				   [LogicalDriveNumber].LogicalDriveSize);
     }
@@ -2003,9 +2156,9 @@
       register_disk(&Controller->GenericDiskInfo,
 		    DAC960_KernelDevice(Controller->ControllerNumber,
 					LogicalDriveNumber, 0),
-		    DAC960_MaxPartitions, &DAC960_BlockDeviceOperations,
-		    LogicalDeviceInfo
-		    ->ConfigurableDeviceSizeIn512ByteBlocksOrMB);
+		    DAC960_MaxPartitions,
+		    &DAC960_BlockDeviceOperations,
+		    LogicalDeviceInfo->ConfigurableDeviceSize);
     }
 }
 
@@ -2116,6 +2269,13 @@
       InterruptHandler = DAC960_PD_InterruptHandler;
       MemoryWindowSize = DAC960_PD_RegisterWindowSize;
       break;
+    case DAC960_P_Controller:
+      VendorID = PCI_VENDOR_ID_MYLEX;
+      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_P;
+      FirmwareType = DAC960_V1_Controller;
+      InterruptHandler = DAC960_P_InterruptHandler;
+      MemoryWindowSize = DAC960_PD_RegisterWindowSize;
+      break;
     }
   while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL)
     {
@@ -2151,6 +2311,10 @@
 	  IO_Address = pci_resource_start(PCI_Device, 0);
 	  PCI_Address = pci_resource_start(PCI_Device, 1);
 	  break;
+	case DAC960_P_Controller:
+	  IO_Address = pci_resource_start(PCI_Device, 0);
+	  PCI_Address = pci_resource_start(PCI_Device, 1);
+	  break;
 	}
       if (DAC960_ControllerCount == DAC960_MaxControllers)
 	{
@@ -2348,6 +2512,32 @@
 	  Controller->QueueReadWriteCommand =
 	    DAC960_V1_QueueReadWriteCommand;
 	  break;
+	case DAC960_P_Controller:
+	  request_region(Controller->IO_Address, 0x80,
+			 Controller->FullModelName);
+	  DAC960_PD_DisableInterrupts(BaseAddress);
+	  DAC960_PD_AcknowledgeStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_PD_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_PD_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
+	  DAC960_PD_EnableInterrupts(Controller->BaseAddress);
+	  Controller->QueueCommand = DAC960_P_QueueCommand;
+	  Controller->ReadControllerConfiguration =
+	    DAC960_V1_ReadControllerConfiguration;
+	  Controller->ReadDeviceConfiguration =
+	    DAC960_V1_ReadDeviceConfiguration;
+	  Controller->ReportDeviceConfiguration =
+	    DAC960_V1_ReportDeviceConfiguration;
+	  Controller->QueueReadWriteCommand =
+	    DAC960_V1_QueueReadWriteCommand;
+	  break;
 	}
       /*
 	Acquire shared access to the IRQ Channel.
@@ -2519,7 +2709,7 @@
   DAC960_Initialize initializes the DAC960 Driver.
 */
 
-void DAC960_Initialize(void)
+static int DAC960_Initialize(void)
 {
   int ControllerNumber;
   DAC960_DetectControllers(DAC960_BA_Controller);
@@ -2527,8 +2717,9 @@
   DAC960_DetectControllers(DAC960_LA_Controller);
   DAC960_DetectControllers(DAC960_PG_Controller);
   DAC960_DetectControllers(DAC960_PD_Controller);
+  DAC960_DetectControllers(DAC960_P_Controller);
   DAC960_SortControllers();
-  if (DAC960_ActiveControllerCount == 0) return;
+  if (DAC960_ActiveControllerCount == 0) return -ENODEV;
   for (ControllerNumber = 0;
        ControllerNumber < DAC960_ControllerCount;
        ControllerNumber++)
@@ -2537,6 +2728,7 @@
       int LogicalDriveNumber;
       if (Controller == NULL) continue;
       DAC960_InitializeController(Controller);
+      DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
       for (LogicalDriveNumber = 0;
 	   LogicalDriveNumber < DAC960_MaxLogicalDrives;
 	   LogicalDriveNumber++)
@@ -2544,6 +2736,7 @@
     }
   DAC960_CreateProcEntries();
   register_reboot_notifier(&DAC960_NotifierBlock);
+  return 0;
 }
 
 
@@ -2551,14 +2744,10 @@
   DAC960_Finalize finalizes the DAC960 Driver.
 */
 
-static int DAC960_Finalize(NotifierBlock_T *NotifierBlock,
-			   unsigned long Event,
-			   void *Buffer)
+static void DAC960_Finalize(void)
 {
   int ControllerNumber;
-  if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF))
-    return NOTIFY_DONE;
-  if (DAC960_ActiveControllerCount == 0) return NOTIFY_OK;
+  if (DAC960_ActiveControllerCount == 0) return;
   for (ControllerNumber = 0;
        ControllerNumber < DAC960_ControllerCount;
        ControllerNumber++)
@@ -2566,6 +2755,20 @@
       DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]);
   DAC960_DestroyProcEntries();
   unregister_reboot_notifier(&DAC960_NotifierBlock);
+}
+
+
+/*
+  DAC960_Notifier is the notifier for the DAC960 Driver.
+*/
+
+static int DAC960_Notifier(NotifierBlock_T *NotifierBlock,
+			   unsigned long Event,
+			   void *Buffer)
+{
+  if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF))
+    return NOTIFY_DONE;
+  DAC960_Finalize();
   return NOTIFY_OK;
 }
 
@@ -2599,11 +2802,9 @@
       char *LastDataEndPointer = NULL;
       int SegmentNumber = 0;
       if (Command->CommandType == DAC960_ReadCommand)
-	CommandMailbox->Type5.CommandOpcode =
-	  DAC960_V1_ReadWithOldScatterGather;
+	CommandMailbox->Type5.CommandOpcode = DAC960_V1_ReadWithScatterGather;
       else
-	CommandMailbox->Type5.CommandOpcode =
-	  DAC960_V1_WriteWithOldScatterGather;
+	CommandMailbox->Type5.CommandOpcode = DAC960_V1_WriteWithScatterGather;
       CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
       CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
       CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
@@ -2865,12 +3066,12 @@
 		   Controller, Command->V1.CommandStatus, CommandName);
       break;
     }
-  DAC960_Error("  /dev/rd/c%dd%d:   absolute blocks %d..%d\n",
+  DAC960_Error("  /dev/rd/c%dd%d:   absolute blocks %u..%u\n",
 	       Controller, Controller->ControllerNumber,
 	       Command->LogicalDriveNumber, Command->BlockNumber,
 	       Command->BlockNumber + Command->BlockCount - 1);
   if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
-    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %d..%d\n",
+    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
 		 Controller, Controller->ControllerNumber,
 		 Command->LogicalDriveNumber,
 		 DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
@@ -3027,6 +3228,8 @@
 				LogicalDriveNumber,
 				Controller->ControllerNumber,
 				LogicalDriveNumber);
+	      Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
+	      DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
 	    }
 	  if (NewEnquiry->NumberOfLogicalDrives < Controller->LogicalDriveCount)
 	    {
@@ -3037,8 +3240,9 @@
 				LogicalDriveNumber,
 				Controller->ControllerNumber,
 				LogicalDriveNumber);
+	      Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
+	      DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
 	    }
-	  Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
 	  if (NewEnquiry->StatusFlags.DeferredWriteError !=
 	      OldEnquiry->StatusFlags.DeferredWriteError)
 	    DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller,
@@ -3064,6 +3268,8 @@
 	      Controller->V1.NeedErrorTableInformation = true;
 	      Controller->V1.NeedDeviceStateInformation = true;
 	      Controller->V1.StartDeviceStateScan = true;
+	      Controller->V1.NeedBackgroundInitializationStatus =
+		Controller->V1.BackgroundInitializationStatusSupported;
 	      Controller->SecondaryMonitoringTime = jiffies;
 	    }
 	  if (NewEnquiry->RebuildFlag == DAC960_V1_StandbyRebuildInProgress ||
@@ -3186,7 +3392,7 @@
 			   AdditionalSenseCodeQualifier == 0x02))))
 		{
 		  DAC960_Critical("Physical Device %d:%d Error Log: "
-				  "Sense Key = %d, ASC = %02X, ASCQ = %02X\n",
+				  "Sense Key = %X, ASC = %02X, ASCQ = %02X\n",
 				  Controller,
 				  EventLogEntry->Channel,
 				  EventLogEntry->TargetID,
@@ -3396,6 +3602,77 @@
 	      Controller->EphemeralProgressMessage = false;
 	    }
 	}
+      else if (CommandOpcode == DAC960_V1_BackgroundInitializationControl)
+	{
+	  unsigned int LogicalDriveNumber =
+	    Controller->V1.BackgroundInitializationStatus.LogicalDriveNumber;
+	  unsigned int LogicalDriveSize =
+	    Controller->V1.BackgroundInitializationStatus.LogicalDriveSize;
+	  unsigned int BlocksCompleted =
+	    Controller->V1.BackgroundInitializationStatus.BlocksCompleted;
+	  switch (CommandStatus)
+	    {
+	    case DAC960_V1_NormalCompletion:
+	      switch (Controller->V1.BackgroundInitializationStatus.Status)
+		{
+		case DAC960_V1_BackgroundInitializationInvalid:
+		  break;
+		case DAC960_V1_BackgroundInitializationStarted:
+		  DAC960_Progress("Background Initialization Started\n",
+				  Controller);
+		  break;
+		case DAC960_V1_BackgroundInitializationInProgress:
+		  if (BlocksCompleted ==
+		      Controller->V1.LastBackgroundInitializationStatus
+				    .BlocksCompleted &&
+		      LogicalDriveNumber ==
+		      Controller->V1.LastBackgroundInitializationStatus
+				    .LogicalDriveNumber)
+		    break;
+		  Controller->EphemeralProgressMessage = true;
+		  DAC960_Progress("Background Initialization in Progress: "
+				  "Logical Drive %d (/dev/rd/c%dd%d) "
+				  "%d%% completed\n",
+				  Controller, LogicalDriveNumber,
+				  Controller->ControllerNumber,
+				  LogicalDriveNumber,
+				  (100 * (BlocksCompleted >> 7))
+				  / (LogicalDriveSize >> 7));
+		  Controller->EphemeralProgressMessage = false;
+		  break;
+		case DAC960_V1_BackgroundInitializationSuspended:
+		  DAC960_Progress("Background Initialization Suspended\n",
+				  Controller);
+		  break;
+		case DAC960_V1_BackgroundInitializationCancelled:
+		  DAC960_Progress("Background Initialization Cancelled\n",
+				  Controller);
+		  break;
+		}
+	      memcpy(&Controller->V1.LastBackgroundInitializationStatus,
+		     &Controller->V1.BackgroundInitializationStatus,
+		     sizeof(DAC960_V1_BackgroundInitializationStatus_T));
+	      break;
+	    case DAC960_V1_BackgroundInitSuccessful:
+	      if (Controller->V1.BackgroundInitializationStatus.Status ==
+		  DAC960_V1_BackgroundInitializationInProgress)
+		DAC960_Progress("Background Initialization "
+				"Completed Successfully\n", Controller);
+	      Controller->V1.BackgroundInitializationStatus.Status =
+		DAC960_V1_BackgroundInitializationInvalid;
+	      break;
+	    case DAC960_V1_BackgroundInitAborted:
+	      if (Controller->V1.BackgroundInitializationStatus.Status ==
+		  DAC960_V1_BackgroundInitializationInProgress)
+		DAC960_Progress("Background Initialization Aborted\n",
+				Controller);
+	      Controller->V1.BackgroundInitializationStatus.Status =
+		DAC960_V1_BackgroundInitializationInvalid;
+	      break;
+	    case DAC960_V1_NoBackgroundInitInProgress:
+	      break;
+	    }
+	}
     }
   if (CommandType == DAC960_MonitoringCommand)
     {
@@ -3562,6 +3839,17 @@
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
+      if (Controller->V1.NeedBackgroundInitializationStatus)
+	{
+	  Controller->V1.NeedBackgroundInitializationStatus = false;
+	  Command->V1.CommandMailbox.Type3B.CommandOpcode =
+	    DAC960_V1_BackgroundInitializationControl;
+	  Command->V1.CommandMailbox.Type3B.CommandOpcode2 = 0x20;
+	  Command->V1.CommandMailbox.Type3B.BusAddress =
+	    Virtual_to_Bus32(&Controller->V1.BackgroundInitializationStatus);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
       Controller->MonitoringTimerCount++;
       Controller->MonitoringTimer.expires =
 	jiffies + DAC960_MonitoringTimerInterval;
@@ -3642,12 +3930,12 @@
     }
   DAC960_Error("Error Condition %s on %s:\n", Controller,
 	       SenseErrors[Command->V2.RequestSense.SenseKey], CommandName);
-  DAC960_Error("  /dev/rd/c%dd%d:   absolute blocks %d..%d\n",
+  DAC960_Error("  /dev/rd/c%dd%d:   absolute blocks %u..%u\n",
 	       Controller, Controller->ControllerNumber,
 	       Command->LogicalDriveNumber, Command->BlockNumber,
 	       Command->BlockNumber + Command->BlockCount - 1);
   if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
-    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %d..%d\n",
+    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
 		 Controller, Controller->ControllerNumber,
 		 Command->LogicalDriveNumber,
 		 DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
@@ -3680,11 +3968,14 @@
       { 0x000B, "P Rebuild Failed due to Logical Drive Failure" },
       { 0x000C, "S Offline" },
       { 0x000D, "P Found" },
-      { 0x000E, "P Gone" },
+      { 0x000E, "P Removed" },
       { 0x000F, "P Unconfigured" },
       { 0x0010, "P Expand Capacity Started" },
       { 0x0011, "P Expand Capacity Completed" },
       { 0x0012, "P Expand Capacity Failed" },
+      { 0x0013, "P Command Timed Out" },
+      { 0x0014, "P Command Aborted" },
+      { 0x0015, "P Command Retried" },
       { 0x0016, "P Parity Error" },
       { 0x0017, "P Soft Error" },
       { 0x0018, "P Miscellaneous Error" },
@@ -3715,6 +4006,8 @@
       { 0x0031, "P Failed because BDT Write Operation Failed" },
       { 0x0039, "P Missing at Startup" },
       { 0x003A, "P Start Rebuild Failed due to Physical Drive Too Small" },
+      { 0x003C, "P Temporarily Offline Device Automatically Made Online" },
+      { 0x003D, "P Standby Rebuild Started" },
       /* Logical Device Events (0x0080 - 0x00FF) */
       { 0x0080, "M Consistency Check Started" },
       { 0x0081, "M Consistency Check Completed" },
@@ -3737,7 +4030,7 @@
       { 0x0092, "M Initialization Cancelled" },
       { 0x0093, "M Initialization Failed" },
       { 0x0094, "L Found" },
-      { 0x0095, "L Gone" },
+      { 0x0095, "L Deleted" },
       { 0x0096, "M Expand Capacity Started" },
       { 0x0097, "M Expand Capacity Completed" },
       { 0x0098, "M Expand Capacity Failed" },
@@ -3747,6 +4040,9 @@
       { 0x009C, "L Bad Data Block Found" },
       { 0x009E, "L Read of Data Block in BDT" },
       { 0x009F, "L Write Back Data for Disk Block Lost" },
+      { 0x00A0, "L Temporarily Offline RAID-5/3 Drive Made Online" },
+      { 0x00A1, "L Temporarily Offline RAID-6/1/0/7 Drive Made Online" },
+      { 0x00A2, "L Standby Rebuild Started" },
       /* Fault Management Events (0x0100 - 0x017F) */
       { 0x0140, "E Fan %d Failed" },
       { 0x0141, "E Fan %d OK" },
@@ -3754,24 +4050,31 @@
       { 0x0143, "E Power Supply %d Failed" },
       { 0x0144, "E Power Supply %d OK" },
       { 0x0145, "E Power Supply %d Not Present" },
-      { 0x0146, "E Temperature Sensor %d Failed" },
-      { 0x0147, "E Temperature Sensor %d Critical" },
-      { 0x0148, "E Temperature Sensor %d OK" },
+      { 0x0146, "E Temperature Sensor %d Temperature Exceeds Safe Limit" },
+      { 0x0147, "E Temperature Sensor %d Temperature Exceeds Working Limit" },
+      { 0x0148, "E Temperature Sensor %d Temperature Normal" },
       { 0x0149, "E Temperature Sensor %d Not Present" },
-      { 0x014A, "E Unit %d Access Critical" },
-      { 0x014B, "E Unit %d Access OK" },
-      { 0x014C, "E Unit %d Access Offline" },
+      { 0x014A, "E Enclosure Management Unit %d Access Critical" },
+      { 0x014B, "E Enclosure Management Unit %d Access OK" },
+      { 0x014C, "E Enclosure Management Unit %d Access Offline" },
       /* Controller Events (0x0180 - 0x01FF) */
       { 0x0181, "C Cache Write Back Error" },
       { 0x0188, "C Battery Backup Unit Found" },
       { 0x0189, "C Battery Backup Unit Charge Level Low" },
       { 0x018A, "C Battery Backup Unit Charge Level OK" },
       { 0x0193, "C Installation Aborted" },
-      { 0x0195, "C Mirror Race Recovery In Progress" },
-      { 0x0196, "C Mirror Race on Critical Drive" },
-      { 0x019E, "C Memory Soft ECC Error" },
-      { 0x019F, "C Memory Hard ECC Error" },
+      { 0x0195, "C Battery Backup Unit Physically Removed" },
+      { 0x0196, "C Memory Error During Warm Boot" },
+      { 0x019E, "C Memory Soft ECC Error Corrected" },
+      { 0x019F, "C Memory Hard ECC Error Corrected" },
       { 0x01A2, "C Battery Backup Unit Failed" },
+      { 0x01AB, "C Mirror Race Recovery Failed" },
+      { 0x01AC, "C Mirror Race on Critical Drive" },
+      /* Controller Internal Processor Events */
+      { 0x0380, "C Internal Controller Hung" },
+      { 0x0381, "C Internal Controller Firmware Breakpoint" },
+      { 0x0390, "C Internal Controller i960 Processor Specific Error" },
+      { 0x03A0, "C Internal Controller StrongARM Processor Specific Error" },
       { 0, "" } };
   int EventListIndex = 0, EventCode;
   unsigned char EventType, *EventMessage;
@@ -3821,7 +4124,7 @@
       DAC960_Critical("Physical Device %d:%d %s\n", Controller,
 		      Event->Channel, Event->TargetID, EventMessage);
       DAC960_Critical("Physical Device %d:%d Request Sense: "
-		      "Sense Key = %d, ASC = %02X, ASCQ = %02X\n",
+		      "Sense Key = %X, ASC = %02X, ASCQ = %02X\n",
 		      Controller,
 		      Event->Channel,
 		      Event->TargetID,
@@ -4142,22 +4445,34 @@
 	    {
 	      if (NewPhysicalDeviceInfo->PhysicalDeviceState !=
 		  PhysicalDeviceInfo->PhysicalDeviceState)
-		DAC960_Critical("Physical Device %d:%d is now %s\n", Controller,
-				NewPhysicalDeviceInfo->Channel,
-				NewPhysicalDeviceInfo->TargetID,
-				(NewPhysicalDeviceInfo->PhysicalDeviceState
-				 == DAC960_V2_Device_Unconfigured
-				 ? "UNCONFIGURED"
-				 : NewPhysicalDeviceInfo->PhysicalDeviceState
-				   == DAC960_V2_Device_Online
-				   ? "ONLINE"
-				   : NewPhysicalDeviceInfo->PhysicalDeviceState
-				     == DAC960_V2_Device_WriteOnly
-				     ? "WRITE-ONLY"
-				     : NewPhysicalDeviceInfo
-				       ->PhysicalDeviceState
-				       == DAC960_V2_Device_Dead
-				       ? "DEAD" : "STANDBY"));
+		DAC960_Critical(
+		  "Physical Device %d:%d is now %s\n", Controller,
+		  NewPhysicalDeviceInfo->Channel,
+		  NewPhysicalDeviceInfo->TargetID,
+		  (NewPhysicalDeviceInfo->PhysicalDeviceState
+		   == DAC960_V2_Device_Online
+		   ? "ONLINE"
+		   : NewPhysicalDeviceInfo->PhysicalDeviceState
+		     == DAC960_V2_Device_Rebuild
+		     ? "REBUILD"
+		     : NewPhysicalDeviceInfo->PhysicalDeviceState
+		       == DAC960_V2_Device_Missing
+		       ? "MISSING"
+		       : NewPhysicalDeviceInfo->PhysicalDeviceState
+			 == DAC960_V2_Device_Critical
+			 ? "CRITICAL"
+			 : NewPhysicalDeviceInfo->PhysicalDeviceState
+			   == DAC960_V2_Device_Dead
+			   ? "DEAD"
+			   : NewPhysicalDeviceInfo->PhysicalDeviceState
+			     == DAC960_V2_Device_SuspectedDead
+			     ? "SUSPECTED-DEAD"
+			     : NewPhysicalDeviceInfo->PhysicalDeviceState
+			       == DAC960_V2_Device_CommandedOffline
+			       ? "COMMANDED-OFFLINE"
+			       : NewPhysicalDeviceInfo->PhysicalDeviceState
+				 == DAC960_V2_Device_Standby
+				 ? "STANDBY" : "UNKNOWN"));
 	      if ((NewPhysicalDeviceInfo->ParityErrors !=
 		   PhysicalDeviceInfo->ParityErrors) ||
 		  (NewPhysicalDeviceInfo->SoftErrors !=
@@ -4263,13 +4578,16 @@
 			      (LogicalDeviceInfo != NULL
 			       ? "" : " - Allocation Failed"));
 	      if (LogicalDeviceInfo != NULL)
-		memset(LogicalDeviceInfo, 0,
-		       sizeof(DAC960_V2_LogicalDeviceInfo_T));
+		{
+		  memset(LogicalDeviceInfo, 0,
+			 sizeof(DAC960_V2_LogicalDeviceInfo_T));
+		  DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
+		}
 	    }
 	  if (LogicalDeviceInfo != NULL)
 	    {
 	      unsigned long LogicalDeviceSize =
-		NewLogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB;
+		NewLogicalDeviceInfo->ConfigurableDeviceSize;
 	      if (NewLogicalDeviceInfo->LogicalDeviceState !=
 		  LogicalDeviceInfo->LogicalDeviceState)
 		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
@@ -4380,6 +4698,7 @@
 	      kfree(LogicalDeviceInfo);
 	      Controller->LogicalDriveInitiallyAccessible
 			  [LogicalDriveNumber] = false;
+	      DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
 	    }
 	  Controller->V2.NeedLogicalDeviceInformation = false;
 	}
@@ -4785,6 +5104,85 @@
 
 
 /*
+  DAC960_P_InterruptHandler handles hardware interrupts from DAC960 P Series
+  Controllers.
+*/
+
+static void DAC960_P_InterruptHandler(int IRQ_Channel,
+				      void *DeviceIdentifier,
+				      Registers_T *InterruptRegisters)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags);
+  /*
+    Process Hardware Interrupts for Controller.
+  */
+  while (DAC960_PD_StatusAvailableP(ControllerBaseAddress))
+    {
+      DAC960_V1_CommandIdentifier_T CommandIdentifier =
+	DAC960_PD_ReadStatusCommandIdentifier(ControllerBaseAddress);
+      DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1];
+      DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
+      DAC960_V1_CommandOpcode_T CommandOpcode =
+	CommandMailbox->Common.CommandOpcode;
+      Command->V1.CommandStatus =
+	DAC960_PD_ReadStatusRegister(ControllerBaseAddress);
+      DAC960_PD_AcknowledgeInterrupt(ControllerBaseAddress);
+      DAC960_PD_AcknowledgeStatus(ControllerBaseAddress);
+      switch (CommandOpcode)
+	{
+	case DAC960_V1_Enquiry_Old:
+	  Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Enquiry;
+	  DAC960_P_To_PD_TranslateEnquiry(
+	    Bus32_to_Virtual(CommandMailbox->Type3.BusAddress));
+	  break;
+	case DAC960_V1_GetDeviceState_Old:
+	  Command->V1.CommandMailbox.Common.CommandOpcode =
+	    DAC960_V1_GetDeviceState;
+	  DAC960_P_To_PD_TranslateDeviceState(
+	    Bus32_to_Virtual(CommandMailbox->Type3.BusAddress));
+	  break;
+	case DAC960_V1_Read_Old:
+	  Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Read;
+	  DAC960_P_To_PD_TranslateReadWriteCommand(CommandMailbox);
+	  break;
+	case DAC960_V1_Write_Old:
+	  Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Write;
+	  DAC960_P_To_PD_TranslateReadWriteCommand(CommandMailbox);
+	  break;
+	case DAC960_V1_ReadWithScatterGather_Old:
+	  Command->V1.CommandMailbox.Common.CommandOpcode =
+	    DAC960_V1_ReadWithScatterGather;
+	  DAC960_P_To_PD_TranslateReadWriteCommand(CommandMailbox);
+	  break;
+	case DAC960_V1_WriteWithScatterGather_Old:
+	  Command->V1.CommandMailbox.Common.CommandOpcode =
+	    DAC960_V1_WriteWithScatterGather;
+	  DAC960_P_To_PD_TranslateReadWriteCommand(CommandMailbox);
+	  break;
+	default:
+	  break;
+	}
+      DAC960_V1_ProcessCompletedCommand(Command);
+    }
+  /*
+    Attempt to remove additional I/O Requests from the Controller's
+    I/O Request Queue and queue them to the Controller.
+  */
+  while (DAC960_ProcessRequest(Controller, false)) ;
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags);
+}
+
+
+/*
   DAC960_V1_QueueMonitoringCommand queues a Monitoring Command to DAC960 V1
   Firmware Controllers.
 */
@@ -4881,8 +5279,7 @@
 		Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
 	      if (LogicalDeviceInfo == NULL) continue;
 	      if (!LogicalDeviceInfo->LogicalDeviceControl
-				     .LogicalDeviceInitialized &&
-		  Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 0)
+				     .LogicalDeviceInitialized)
 		{
 		  ForceMonitoringCommand = true;
 		  break;
@@ -4970,6 +5367,7 @@
   if (!Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber])
     {
       Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true;
+      DAC960_ComputeGenericDiskInfo(&Controller->GenericDiskInfo);
       DAC960_RegisterDisk(Controller, LogicalDriveNumber);
     }
   if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
@@ -5049,7 +5447,7 @@
 	    Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
 	  if (LogicalDeviceInfo == NULL)
 	    return -EINVAL;
-	  switch(LogicalDeviceInfo->DriveGeometry)
+	  switch (LogicalDeviceInfo->DriveGeometry)
 	    {
 	    case DAC960_V2_Geometry_128_32:
 	      Geometry.heads = 128;
@@ -5065,7 +5463,7 @@
 	      return -EINVAL;
 	    }
 	  Geometry.cylinders =
-	    LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB
+	    LogicalDeviceInfo->ConfigurableDeviceSize
 	    / (Geometry.heads * Geometry.sectors);
 	}
       Geometry.start =
@@ -5074,19 +5472,22 @@
 			   sizeof(DiskGeometry_T)) ? -EFAULT : 0);
     case BLKGETSIZE:
       /* Get Device Size. */
+      if ((unsigned long *) Argument == NULL) return -EINVAL;
       return put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
 						 .nr_sects,
-		      (long *) Argument);
+		      (unsigned long *) Argument);
     case BLKGETSIZE64:
-      return put_user((u64)Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].nr_sects << 9,
+      if ((u64 *) Argument == NULL) return -EINVAL;
+      return put_user((u64) Controller->GenericDiskInfo
+				       .part[MINOR(Inode->i_rdev)]
+				       .nr_sects << 9,
 		      (u64 *) Argument);
     case BLKRAGET:
     case BLKRASET:
     case BLKFLSBUF:
     case BLKBSZGET:
     case BLKBSZSET:
-      return blk_ioctl (Inode->i_rdev, Request, Argument);
-
+      return blk_ioctl(Inode->i_rdev, Request, Argument);
     case BLKRRPART:
       /* Re-Read Partition Table. */
       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
@@ -5120,20 +5521,7 @@
 	  */
 	  set_blocksize(Device, BLOCK_SIZE);
 	}
-      if (Controller->FirmwareType == DAC960_V1_Controller)
-	grok_partitions(&Controller->GenericDiskInfo,
-			LogicalDriveNumber,
-			DAC960_MaxPartitions,
-			Controller->V1.LogicalDriveInformation
-				       [LogicalDriveNumber]
-				       .LogicalDriveSize);
-      else
-	grok_partitions(
-	  &Controller->GenericDiskInfo,
-	  LogicalDriveNumber,
-	  DAC960_MaxPartitions,
-	  Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]
-			 ->ConfigurableDeviceSizeIn512ByteBlocksOrMB);
+      DAC960_RegisterDisk(Controller, LogicalDriveNumber);
       return 0;
     }
   return -EINVAL;
@@ -6365,6 +6753,43 @@
 			   == DAC960_V2_NormalCompletion
 			   ? "Cancelled" : "Not Cancelled"));
     }
+  else if (strcmp(UserCommand, "perform-discovery") == 0)
+    {
+      CommandMailbox->Common.IOCTL_Opcode = DAC960_V2_StartDiscovery;
+      DAC960_ExecuteCommand(Command);
+      DAC960_UserCritical("Discovery %s\n", Controller,
+			  (Command->V2.CommandStatus
+			   == DAC960_V2_NormalCompletion
+			   ? "Initiated" : "Not Initiated"));
+      if (Command->V2.CommandStatus == DAC960_V2_NormalCompletion)
+	{
+	  CommandMailbox->ControllerInfo.CommandOpcode = DAC960_V2_IOCTL;
+	  CommandMailbox->ControllerInfo.CommandControlBits
+					.DataTransferControllerToHost = true;
+	  CommandMailbox->ControllerInfo.CommandControlBits
+					.NoAutoRequestSense = true;
+	  CommandMailbox->ControllerInfo.DataTransferSize =
+	    sizeof(DAC960_V2_ControllerInfo_T);
+	  CommandMailbox->ControllerInfo.ControllerNumber = 0;
+	  CommandMailbox->ControllerInfo.IOCTL_Opcode =
+	    DAC960_V2_GetControllerInfo;
+	  CommandMailbox->ControllerInfo.DataTransferMemoryAddress
+					.ScatterGatherSegments[0]
+					.SegmentDataPointer =
+	    Virtual_to_Bus64(&Controller->V2.NewControllerInformation);
+	  CommandMailbox->ControllerInfo.DataTransferMemoryAddress
+					.ScatterGatherSegments[0]
+					.SegmentByteCount =
+	    CommandMailbox->ControllerInfo.DataTransferSize;
+	  DAC960_ExecuteCommand(Command);
+	  while (Controller->V2.NewControllerInformation.PhysicalScanActive)
+	    {
+	      DAC960_ExecuteCommand(Command);
+	      sleep_on_timeout(&Controller->CommandWaitQueue, HZ);
+	    }
+	  DAC960_UserCritical("Discovery Completed\n", Controller);
+ 	}
+    }
   else if (strcmp(UserCommand, "suppress-enclosure-messages") == 0)
     Controller->SuppressEnclosureMessages = true;
   else DAC960_UserCritical("Illegal User Command: '%s'\n",
@@ -6587,24 +7012,5 @@
 }
 
 
-/*
-  Include Module support if requested.
-*/
-
-#ifdef MODULE
-
-
-int init_module(void)
-{
-  DAC960_Initialize();
-  return (DAC960_ActiveControllerCount > 0 ? 0 : -1);
-}
-
-
-void cleanup_module(void)
-{
-  DAC960_Finalize(&DAC960_NotifierBlock, SYS_RESTART, NULL);
-}
-
-
-#endif
+module_init(DAC960_Initialize);
+module_exit(DAC960_Finalize);
diff -urN linux-2.4.13-pre3/drivers/block/DAC960.h linux/drivers/block/DAC960.h
--- linux-2.4.13-pre3/drivers/block/DAC960.h	Mon Aug  6 10:34:38 2001
+++ linux/drivers/block/DAC960.h	Mon Dec  3 23:18:27 2001
@@ -224,9 +224,9 @@
   DAC960_V1_ReadExtendedWithScatterGather =	0xB3,
   DAC960_V1_WriteExtendedWithScatterGather =	0xB4,
   DAC960_V1_Read =				0x36,
-  DAC960_V1_ReadWithOldScatterGather =		0xB6,
+  DAC960_V1_ReadWithScatterGather =		0xB6,
   DAC960_V1_Write =				0x37,
-  DAC960_V1_WriteWithOldScatterGather =		0xB7,
+  DAC960_V1_WriteWithScatterGather =		0xB7,
   DAC960_V1_DCDB =				0x04,
   DAC960_V1_DCDBWithScatterGather =		0x84,
   DAC960_V1_Flush =				0x0A,
@@ -280,7 +280,14 @@
   DAC960_V1_RunDiagnostic =			0x32,
   /* Subsystem Service Commands */
   DAC960_V1_GetSubsystemData =			0x70,
-  DAC960_V1_SetSubsystemParameters =		0x71
+  DAC960_V1_SetSubsystemParameters =		0x71,
+  /* Version 2.xx Firmware Commands */
+  DAC960_V1_Enquiry_Old =			0x05,
+  DAC960_V1_GetDeviceState_Old =		0x14,
+  DAC960_V1_Read_Old =				0x02,
+  DAC960_V1_Write_Old =				0x03,
+  DAC960_V1_ReadWithScatterGather_Old =		0x82,
+  DAC960_V1_WriteWithScatterGather_Old =	0x83
 }
 __attribute__ ((packed))
 DAC960_V1_CommandOpcode_T;
@@ -327,6 +334,9 @@
 #define DAC960_V1_RebuildFailed_NewDriveFailed	0x0004	/* Consistency */
 #define DAC960_V1_RebuildSuccessful		0x0100	/* Consistency */
 #define DAC960_V1_RebuildSuccessfullyTerminated	0x0107	/* Consistency */
+#define DAC960_V1_BackgroundInitSuccessful	0x0100	/* Consistency */
+#define DAC960_V1_BackgroundInitAborted		0x0005	/* Consistency */
+#define DAC960_V1_NoBackgroundInitInProgress	0x0105	/* Consistency */
 #define DAC960_V1_AddCapacityInProgress		0x0004	/* Consistency */
 #define DAC960_V1_AddCapacityFailedOrSuspended	0x00F4	/* Consistency */
 #define DAC960_V1_Config2ChecksumError		0x0002	/* Configuration */
@@ -634,6 +644,8 @@
 
 /*
   Define the DAC960 V1 Firmware Get Device State Command reply structure.
+  The structure is padded by 2 bytes for compatibility with Version 2.xx
+  Firmware.
 */
 
 typedef struct DAC960_V1_DeviceState
@@ -658,6 +670,7 @@
   unsigned char SynchronousOffset:5;			/* Byte 5 Bits 0-4 */
   unsigned char :3;					/* Byte 5 Bits 5-7 */
   unsigned int DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
+  unsigned short :16;					/* Bytes 10-11 */
 }
 DAC960_V1_DeviceState_T;
 
@@ -676,6 +689,30 @@
 
 
 /*
+  Define the DAC960 V1 Firmware Background Initialization Status Command
+  reply structure.
+*/
+
+typedef struct DAC960_V1_BackgroundInitializationStatus
+{
+  unsigned int LogicalDriveSize;			/* Bytes 0-3 */
+  unsigned int BlocksCompleted;				/* Bytes 4-7 */
+  unsigned char Reserved1[12];				/* Bytes 8-19 */
+  unsigned int LogicalDriveNumber;			/* Bytes 20-23 */
+  unsigned char RAIDLevel;				/* Byte 24 */
+  enum {
+    DAC960_V1_BackgroundInitializationInvalid =	    0x00,
+    DAC960_V1_BackgroundInitializationStarted =	    0x02,
+    DAC960_V1_BackgroundInitializationInProgress =  0x04,
+    DAC960_V1_BackgroundInitializationSuspended =   0x05,
+    DAC960_V1_BackgroundInitializationCancelled =   0x06
+  } __attribute__ ((packed)) Status;			/* Byte 25 */
+  unsigned char Reserved2[6];				/* Bytes 26-31 */
+}
+DAC960_V1_BackgroundInitializationStatus_T;
+
+
+/*
   Define the DAC960 V1 Firmware Error Table Entry structure.
 */
 
@@ -853,6 +890,14 @@
   struct {
     DAC960_V1_CommandOpcode_T CommandOpcode;		/* Byte 0 */
     DAC960_V1_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char CommandOpcode2;			/* Byte 2 */
+    unsigned char Dummy1[5];				/* Bytes 3-7 */
+    DAC960_BusAddress32_T BusAddress;			/* Bytes 8-11 */
+    unsigned char Dummy2[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) Type3B;
+  struct {
+    DAC960_V1_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_V1_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
     unsigned char Dummy1[5];				/* Bytes 2-6 */
     unsigned char LogicalDriveNumber:6;			/* Byte 7 Bits 0-6 */
     boolean AutoRestore:1;				/* Byte 7 Bit 7 */
@@ -956,6 +1001,7 @@
   DAC960_V2_GetPhysicalDeviceInfoValid =	0x05,
   DAC960_V2_GetHealthStatus =			0x11,
   DAC960_V2_GetEvent =				0x15,
+  DAC960_V2_StartDiscovery =			0x81,
   DAC960_V2_SetDeviceState =			0x82,
   DAC960_V2_RebuildDeviceStart =		0x88,
   DAC960_V2_RebuildDeviceStop =			0x89,
@@ -982,7 +1028,10 @@
 
 #define DAC960_V2_NormalCompletion		0x00
 #define DAC960_V2_AbormalCompletion		0x02
+#define DAC960_V2_DeviceBusy			0x08
 #define DAC960_V2_DeviceNonresponsive		0x0E
+#define DAC960_V2_DeviceNonresponsive2		0x0F
+#define DAC960_V2_DeviceRevervationConflict	0x18
 
 typedef unsigned char DAC960_V2_CommandStatus_T;
 
@@ -1056,7 +1105,8 @@
     DAC960_V2_EXR2000P =			0x1C,
     DAC960_V2_EXR3000P =			0x1D,
     DAC960_V2_AcceleRAID352 =			0x1E,
-    DAC960_V2_AcceleRAID351 =			0x1F,
+    DAC960_V2_AcceleRAID170 =			0x1F,
+    DAC960_V2_AcceleRAID160 =			0x20,
     DAC960_V2_DAC960S =				0x60,
     DAC960_V2_DAC960SU =			0x61,
     DAC960_V2_DAC960SX =			0x62,
@@ -1073,7 +1123,9 @@
   unsigned char :8;					/* Byte 3 */
   unsigned short BusInterfaceSpeedMHz;			/* Bytes 4-5 */
   unsigned char BusWidthBits;				/* Byte 6 */
-  unsigned char Reserved1[9];				/* Bytes 7-15 */
+  unsigned char FlashCodeTypeOrProductID;		/* Byte 7 */
+  unsigned char NumberOfHostPortsPresent;		/* Byte 8 */
+  unsigned char Reserved1[7];				/* Bytes 9-15 */
   unsigned char BusInterfaceName[16];			/* Bytes 16-31 */
   unsigned char ControllerName[16];			/* Bytes 32-47 */
   unsigned char Reserved2[16];				/* Bytes 48-63 */
@@ -1102,17 +1154,17 @@
   unsigned char HardwareManufacturingMonth;		/* Byte 85 */
   unsigned char HardwareManufacturingYearHigh2Digits;	/* Byte 86 */
   unsigned char HardwareManufacturingYearLow2Digits;	/* Byte 87 */
-  unsigned char MaximumNumberOfPDDperXLDD;		/* Byte 88 */
-  unsigned char MaximumNumberOfILDDperXLDD;		/* Byte 89 */
+  unsigned char MaximumNumberOfPDDperXLD;		/* Byte 88 */
+  unsigned char MaximumNumberOfILDperXLD;		/* Byte 89 */
   unsigned short NonvolatileMemorySizeKB;		/* Bytes 90-91 */
-  unsigned char MaximumNumberOfXLDD;			/* Byte 92 */
+  unsigned char MaximumNumberOfXLD;			/* Byte 92 */
   unsigned int :24;					/* Bytes 93-95 */
   /* Unique Information per Controller */
   unsigned char ControllerSerialNumber[16];		/* Bytes 96-111 */
   unsigned char Reserved3[16];				/* Bytes 112-127 */
   /* Vendor Information */
   unsigned int :24;					/* Bytes 128-130 */
-  unsigned char OEM_Information;			/* Byte 131 */
+  unsigned char OEM_Code;				/* Byte 131 */
   unsigned char VendorName[16];				/* Bytes 132-147 */
   /* Other Physical/Controller/Operation Information */
   boolean BBU_Present:1;				/* Byte 148 Bit 0 */
@@ -1193,12 +1245,14 @@
   unsigned short PhysicalDeviceHostCommandAbortsDone;	/* Bytes 370-371 */
   unsigned short PhysicalDevicePredictedFailuresDetected; /* Bytes 372-373 */
   unsigned short PhysicalDeviceHostCommandsFailed;	/* Bytes 374-375 */
-  unsigned char Reserved9[8];				/* Bytes 376-383 */
+  unsigned short PhysicalDeviceHardErrors;		/* Bytes 376-377 */
+  unsigned char Reserved9[6];				/* Bytes 378-383 */
   /* Error Counters on Logical Devices */
   unsigned short LogicalDeviceSoftErrors;		/* Bytes 384-385 */
   unsigned short LogicalDeviceCommandsFailed;		/* Bytes 386-387 */
   unsigned short LogicalDeviceHostCommandAbortsDone;	/* Bytes 388-389 */
   unsigned short :16;					/* Bytes 390-391 */
+  /* Error Counters on Controller */
   unsigned short ControllerMemoryErrors;		/* Bytes 392-393 */
   unsigned short ControllerHostCommandAbortsDone;	/* Bytes 394-395 */
   unsigned int :32;					/* Bytes 396-399 */
@@ -1210,8 +1264,7 @@
   unsigned short RebuildsActive;			/* Bytes 408-409 */
   unsigned short OnlineExpansionsActive;		/* Bytes 410-411 */
   unsigned short PatrolActivitiesActive;		/* Bytes 412-413 */
-  unsigned char LongOperationStatus;			/* Byte 414 */
-  unsigned char :8;					/* Byte 415 */
+  unsigned short :16;					/* Bytes 414-415 */
   /* Flash ROM Information */
   unsigned char FlashType;				/* Byte 416 */
   unsigned char :8;					/* Byte 417 */
@@ -1234,8 +1287,7 @@
   unsigned short NumberOfConfigurationGroups;		/* Bytes 474-475 */
   boolean InstallationAbortStatus:1;			/* Byte 476 Bit 0 */
   boolean MaintenanceModeStatus:1;			/* Byte 476 Bit 1 */
-  unsigned int :6;					/* Byte 476 Bits 2-7 */
-  unsigned int :24;					/* Bytes 477-479 */
+  unsigned int :24;					/* Bytes 476-479 */
   unsigned char Reserved10[32];				/* Bytes 480-511 */
   unsigned char Reserved11[512];			/* Bytes 512-1023 */
 }
@@ -1311,7 +1363,7 @@
     DAC960_V2_Geometry_Reserved1 =		0x2,
     DAC960_V2_Geometry_Reserved2 =		0x3
   } __attribute__ ((packed)) DriveGeometry:2;		/* Byte 14 Bits 5-6 */
-  unsigned char :1;					/* Byte 14 Bit 7 */
+  boolean SuperReadAheadEnabled:1;			/* Byte 14 Bit 7 */
   unsigned char :8;					/* Byte 15 */
   /* Error Counters */
   unsigned short SoftErrors;				/* Bytes 16-17 */
@@ -1323,8 +1375,8 @@
   /* Device Size Information */
   unsigned short :16;					/* Bytes 32-33 */
   unsigned short DeviceBlockSizeInBytes;		/* Bytes 34-35 */
-  unsigned int OriginalDeviceSizeIn512ByteBlocksOrMB;	/* Bytes 36-39 */
-  unsigned int ConfigurableDeviceSizeIn512ByteBlocksOrMB; /* Bytes 40-43 */
+  unsigned int OriginalDeviceSize;			/* Bytes 36-39 */
+  unsigned int ConfigurableDeviceSize;			/* Bytes 40-43 */
   unsigned int :32;					/* Bytes 44-47 */
   unsigned char LogicalDeviceName[32];			/* Bytes 48-79 */
   unsigned char SCSI_InquiryData[36];			/* Bytes 80-115 */
@@ -1350,8 +1402,12 @@
 {
     DAC960_V2_Device_Unconfigured =		0x00,
     DAC960_V2_Device_Online =			0x01,
-    DAC960_V2_Device_WriteOnly =		0x03,
+    DAC960_V2_Device_Rebuild =			0x03,
+    DAC960_V2_Device_Missing =			0x04,
+    DAC960_V2_Device_Critical =			0x05,
     DAC960_V2_Device_Dead =			0x08,
+    DAC960_V2_Device_SuspectedDead =		0x0C,
+    DAC960_V2_Device_CommandedOffline =		0x10,
     DAC960_V2_Device_Standby =			0x21,
     DAC960_V2_Device_InvalidState =		0xFF
 }
@@ -1371,7 +1427,7 @@
   unsigned char LogicalUnit;				/* Byte 3 */
   /* Configuration Status Bits */
   boolean PhysicalDeviceFaultTolerant:1;		/* Byte 4 Bit 0 */
-  boolean :1;						/* Byte 4 Bit 1 */
+  boolean PhysicalDeviceConnected:1;			/* Byte 4 Bit 1 */
   boolean PhysicalDeviceLocalToController:1;		/* Byte 4 Bit 2 */
   unsigned char :5;					/* Byte 4 Bits 3-7 */
   /* Multiple Host/Controller Status Bits */
@@ -1407,15 +1463,15 @@
   unsigned int :32;					/* Bytes 44-47 */
   unsigned short :16;					/* Bytes 48-49 */
   unsigned short DeviceBlockSizeInBytes;		/* Bytes 50-51 */
-  unsigned int OriginalDeviceSizeIn512ByteBlocksOrMB;	/* Bytes 52-55 */
-  unsigned int ConfigurableDeviceSizeIn512ByteBlocksOrMB; /* Bytes 56-59 */
+  unsigned int OriginalDeviceSize;			/* Bytes 52-55 */
+  unsigned int ConfigurableDeviceSize;			/* Bytes 56-59 */
   unsigned int :32;					/* Bytes 60-63 */
   unsigned char PhysicalDeviceName[16];			/* Bytes 64-79 */
   unsigned char Reserved1[16];				/* Bytes 80-95 */
   unsigned char Reserved2[32];				/* Bytes 96-127 */
   unsigned char SCSI_InquiryData[36];			/* Bytes 128-163 */
-  unsigned char Reserved3[12];				/* Bytes 164-175 */
-  unsigned char Reserved4[16];				/* Bytes 176-191 */
+  unsigned char Reserved3[20];				/* Bytes 164-183 */
+  unsigned char Reserved4[8];				/* Bytes 184-191 */
   DAC960_ByteCount64_T LastReadBlockNumber;		/* Bytes 192-199 */
   DAC960_ByteCount64_T LastWrittenBlockNumber;		/* Bytes 200-207 */
   DAC960_ByteCount64_T ConsistencyCheckBlockNumber;	/* Bytes 208-215 */
@@ -1549,7 +1605,8 @@
   DAC960_V2_RAID_Channel =			0x03,
   DAC960_V2_Physical_Controller =		0x04,
   DAC960_V2_RAID_Controller =			0x05,
-  DAC960_V2_Configuration_Group =		0x10
+  DAC960_V2_Configuration_Group =		0x10,
+  DAC960_V2_Enclosure =				0x11
 }
 __attribute__ ((packed))
 DAC960_V2_OperationDevice_T;
@@ -1630,8 +1687,7 @@
     DAC960_V2_CommandIdentifier_T CommandIdentifier;	/* Bytes 0-1 */
     DAC960_V2_CommandOpcode_T CommandOpcode;		/* Byte 2 */
     DAC960_V2_CommandControlBits_T CommandControlBits;	/* Byte 3 */
-    DAC960_ByteCount32_T DataTransferSize:24;		/* Bytes 4-6 */
-    unsigned char DataTransferPageNumber;		/* Byte 7 */
+    DAC960_ByteCount32_T DataTransferSize;		/* Bytes 4-7 */
     DAC960_BusAddress64_T RequestSenseBusAddress;	/* Bytes 8-15 */
     DAC960_V2_PhysicalDevice_T PhysicalDevice;		/* Bytes 16-18 */
     DAC960_V2_CommandTimeout_T CommandTimeout;		/* Byte 19 */
@@ -1645,8 +1701,7 @@
     DAC960_V2_CommandIdentifier_T CommandIdentifier;	/* Bytes 0-1 */
     DAC960_V2_CommandOpcode_T CommandOpcode;		/* Byte 2 */
     DAC960_V2_CommandControlBits_T CommandControlBits;	/* Byte 3 */
-    DAC960_ByteCount32_T DataTransferSize:24;		/* Bytes 4-6 */
-    unsigned char DataTransferPageNumber;		/* Byte 7 */
+    DAC960_ByteCount32_T DataTransferSize;		/* Bytes 4-7 */
     DAC960_BusAddress64_T RequestSenseBusAddress;	/* Bytes 8-15 */
     DAC960_V2_PhysicalDevice_T PhysicalDevice;		/* Bytes 16-18 */
     DAC960_V2_CommandTimeout_T CommandTimeout;		/* Byte 19 */
@@ -1795,7 +1850,6 @@
       DataTransferMemoryAddress;			/* Bytes 32-63 */
   } DeviceOperation;
 }
-__attribute__ ((packed))
 DAC960_V2_CommandMailbox_T;
 
 
@@ -2074,7 +2128,8 @@
   DAC960_LP_Controller =			2,	/* AcceleRAID 352 */
   DAC960_LA_Controller =			3,	/* DAC1164P */
   DAC960_PG_Controller =			4,	/* DAC960PTL/PJ/PG */
-  DAC960_PD_Controller =			5	/* DAC960PU/PD/PL */
+  DAC960_PD_Controller =			5,	/* DAC960PU/PD/PL/P */
+  DAC960_P_Controller =				6	/* DAC960PU/PD/PL/P */
 }
 DAC960_HardwareType_T;
 
@@ -2336,6 +2391,7 @@
       unsigned short DeviceStateChannel;
       unsigned short DeviceStateTargetID;
       boolean DualModeMemoryMailboxInterface;
+      boolean BackgroundInitializationStatusSupported;
       boolean SAFTE_EnclosureManagementEnabled;
       boolean NeedLogicalDriveInformation;
       boolean NeedErrorTableInformation;
@@ -2344,6 +2400,7 @@
       boolean NeedDeviceSerialNumberInformation;
       boolean NeedRebuildProgress;
       boolean NeedConsistencyCheckProgress;
+      boolean NeedBackgroundInitializationStatus;
       boolean StartDeviceStateScan;
       boolean RebuildProgressFirst;
       boolean RebuildFlagPending;
@@ -2367,6 +2424,10 @@
       DAC960_V1_CommandStatus_T PendingRebuildStatus;
       DAC960_V1_LogicalDriveInformationArray_T LogicalDriveInformation;
       DAC960_V1_LogicalDriveInformationArray_T NewLogicalDriveInformation;
+      DAC960_V1_BackgroundInitializationStatus_T
+        BackgroundInitializationStatus;
+      DAC960_V1_BackgroundInitializationStatus_T
+        LastBackgroundInitializationStatus;
       DAC960_V1_DeviceState_T
 	DeviceState[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
       DAC960_V1_DeviceState_T NewDeviceState;
@@ -4143,13 +4204,46 @@
   return true;
 }
 
+static inline void DAC960_P_To_PD_TranslateEnquiry(void *Enquiry)
+{
+  memcpy(Enquiry + 132, Enquiry + 36, 64);
+  memset(Enquiry + 36, 0, 96);
+}
+
+static inline void DAC960_P_To_PD_TranslateDeviceState(void *DeviceState)
+{
+  memcpy(DeviceState + 2, DeviceState + 3, 1);
+  memcpy(DeviceState + 4, DeviceState + 5, 2);
+  memcpy(DeviceState + 6, DeviceState + 8, 4);
+}
+
+static inline
+void DAC960_PD_To_P_TranslateReadWriteCommand(DAC960_V1_CommandMailbox_T
+					      *CommandMailbox)
+{
+  int LogicalDriveNumber = CommandMailbox->Type5.LD.LogicalDriveNumber;
+  CommandMailbox->Bytes[3] &= 0x7;
+  CommandMailbox->Bytes[3] |= CommandMailbox->Bytes[7] << 6;
+  CommandMailbox->Bytes[7] = LogicalDriveNumber;
+}
+
+static inline
+void DAC960_P_To_PD_TranslateReadWriteCommand(DAC960_V1_CommandMailbox_T
+					      *CommandMailbox)
+{
+  int LogicalDriveNumber = CommandMailbox->Bytes[7];
+  CommandMailbox->Bytes[7] = CommandMailbox->Bytes[3] >> 6;
+  CommandMailbox->Bytes[3] &= 0x7;
+  CommandMailbox->Bytes[3] |= LogicalDriveNumber << 3;
+}
+
 
 /*
   Define prototypes for the forward referenced DAC960 Driver Internal Functions.
 */
 
 static void DAC960_FinalizeController(DAC960_Controller_T *);
-static int DAC960_Finalize(NotifierBlock_T *, unsigned long, void *);
+static int DAC960_Notifier(NotifierBlock_T *, unsigned long, void *);
 static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *);
 static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *);
 static void DAC960_RequestFunction(RequestQueue_T *);
@@ -4158,6 +4252,7 @@
 static void DAC960_LA_InterruptHandler(int, void *, Registers_T *);
 static void DAC960_PG_InterruptHandler(int, void *, Registers_T *);
 static void DAC960_PD_InterruptHandler(int, void *, Registers_T *);
+static void DAC960_P_InterruptHandler(int, void *, Registers_T *);
 static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *);
 static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *);
 static void DAC960_MonitoringTimerFunction(unsigned long);
diff -urN linux-2.4.13-pre3/drivers/block/genhd.c linux/drivers/block/genhd.c
--- linux-2.4.13-pre3/drivers/block/genhd.c	Mon Oct  1 10:19:22 2001
+++ linux/drivers/block/genhd.c	Mon Dec  3 23:18:27 2001
@@ -161,9 +161,6 @@
 
 
 extern int blk_dev_init(void);
-#ifdef CONFIG_BLK_DEV_DAC960
-extern void DAC960_Initialize(void);
-#endif
 #ifdef CONFIG_FUSION_BOOT
 extern int fusion_init(void);
 #endif
@@ -181,9 +178,6 @@
 	sti();
 #ifdef CONFIG_I2O
 	i2o_init();
-#endif
-#ifdef CONFIG_BLK_DEV_DAC960
-	DAC960_Initialize();
 #endif
 #ifdef CONFIG_FUSION_BOOT
 	fusion_init();
diff -urN linux-2.4.13-pre3/drivers/block/loop.c linux/drivers/block/loop.c
--- linux-2.4.13-pre3/drivers/block/loop.c	Mon Dec  3 23:18:17 2001
+++ linux/drivers/block/loop.c	Mon Dec  3 23:18:27 2001
@@ -77,7 +77,7 @@
 
 static int max_loop = 8;
 static struct loop_device *loop_dev;
-static unsigned long *loop_sizes;
+static int *loop_sizes;
 static int *loop_blksizes;
 static devfs_handle_t devfs_handle;      /*  For the directory */
 
@@ -865,7 +865,7 @@
 			err = -ENXIO;
 			break;
 		}
-		err = put_user(loop_sizes[lo->lo_number] << 1, (unsigned long *) arg);
+		err = put_user((unsigned long)loop_sizes[lo->lo_number] << 1, (unsigned long *) arg);
 		break;
 	case BLKGETSIZE64:
 		if (lo->lo_state != Lo_bound) {
@@ -1007,7 +1007,7 @@
 	if (!loop_dev)
 		return -ENOMEM;
 
-	loop_sizes = kmalloc(max_loop * sizeof(unsigned long), GFP_KERNEL);
+	loop_sizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL);
 	if (!loop_sizes)
 		goto out_sizes;
 
@@ -1027,7 +1027,7 @@
 		spin_lock_init(&lo->lo_lock);
 	}
 
-	memset(loop_sizes, 0, max_loop * sizeof(unsigned long));
+	memset(loop_sizes, 0, max_loop * sizeof(int));
 	memset(loop_blksizes, 0, max_loop * sizeof(int));
 	blk_size[MAJOR_NR] = loop_sizes;
 	blksize_size[MAJOR_NR] = loop_blksizes;
diff -urN linux-2.4.13-pre3/drivers/char/drm/drm_vm.h linux/drivers/char/drm/drm_vm.h
--- linux-2.4.13-pre3/drivers/char/drm/drm_vm.h	Wed Oct 10 23:45:21 2001
+++ linux/drivers/char/drm/drm_vm.h	Mon Dec  3 23:18:27 2001
@@ -175,7 +175,7 @@
 	page = pte_page(*pte);
 	get_page(page);
 
-	DRM_DEBUG("0x%08lx => 0x%08x\n", address, page_to_bus(page));
+	DRM_DEBUG("shm_nopage 0x%lx\n", address);
 #if LINUX_VERSION_CODE < 0x020317
 	return page_address(page);
 #else
@@ -299,8 +299,7 @@
 
 	get_page(page);
 
-	DRM_DEBUG("0x%08lx (page %lu) => 0x%08x\n", address, page_nr, 
-		  page_to_bus(page));
+	DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); 
 #if LINUX_VERSION_CODE < 0x020317
 	return page_address(page);
 #else
diff -urN linux-2.4.13-pre3/drivers/ieee1394/Makefile linux/drivers/ieee1394/Makefile
--- linux-2.4.13-pre3/drivers/ieee1394/Makefile	Sun Oct  7 16:41:35 2001
+++ linux/drivers/ieee1394/Makefile	Mon Dec  3 23:18:27 2001
@@ -4,11 +4,11 @@
 
 O_TARGET := ieee1394drv.o
 
-export-objs := ieee1394_syms.o ohci1394.o
+export-objs := ieee1394_core.o ohci1394.o
 
 list-multi := ieee1394.o
 ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
-		 highlevel.o csr.o nodemgr.o ieee1394_syms.o
+		 highlevel.o csr.o nodemgr.o
 
 obj-$(CONFIG_IEEE1394) += ieee1394.o
 obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
diff -urN linux-2.4.13-pre3/drivers/ieee1394/ieee1394.h linux/drivers/ieee1394/ieee1394.h
--- linux-2.4.13-pre3/drivers/ieee1394/ieee1394.h	Mon Dec 11 13:20:17 2000
+++ linux/drivers/ieee1394/ieee1394.h	Mon Dec  3 23:18:27 2001
@@ -47,7 +47,10 @@
 
 #define SPEED_100                0x0
 #define SPEED_200                0x1
-#define SPEED_400                0x2 
+#define SPEED_400                0x2
+
+/* Maps speed values above to a string representation */
+extern const char *hpsb_speedto_str[];
 
 #define SELFID_PWRCL_NO_POWER    0x0
 #define SELFID_PWRCL_PROVIDE_15W 0x1
diff -urN linux-2.4.13-pre3/drivers/ieee1394/ieee1394_core.c linux/drivers/ieee1394/ieee1394_core.c
--- linux-2.4.13-pre3/drivers/ieee1394/ieee1394_core.c	Mon Oct  1 21:24:24 2001
+++ linux/drivers/ieee1394/ieee1394_core.c	Mon Dec  3 23:18:27 2001
@@ -30,6 +30,7 @@
 #include "ieee1394_transactions.h"
 #include "csr.h"
 #include "nodemgr.h"
+#include "ieee1394_hotplug.h"
 
 /*
  * Disable the nodemgr detection and config rom reading functionality.
@@ -38,8 +39,13 @@
 MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
 static int disable_nodemgr = 0;
 
+/* We are GPL, so treat us special */
+MODULE_LICENSE("GPL");
+
 static kmem_cache_t *hpsb_packet_cache;
 
+/* Some globals used */
+const char *hpsb_speedto_str[] = { "S100", "S200", "S400" };
 
 static void dump_packet(const char *text, quadlet_t *data, int size)
 {
@@ -805,3 +811,68 @@
 
 module_init(ieee1394_init);
 module_exit(ieee1394_cleanup);
+
+/* Exported symbols */
+EXPORT_SYMBOL(hpsb_register_lowlevel);
+EXPORT_SYMBOL(hpsb_unregister_lowlevel);
+EXPORT_SYMBOL(hpsb_get_host);
+EXPORT_SYMBOL(hpsb_inc_host_usage);
+EXPORT_SYMBOL(hpsb_dec_host_usage);
+EXPORT_SYMBOL(hpsb_speedto_str);
+
+EXPORT_SYMBOL(alloc_hpsb_packet);
+EXPORT_SYMBOL(free_hpsb_packet);
+EXPORT_SYMBOL(hpsb_send_packet);
+EXPORT_SYMBOL(hpsb_reset_bus);
+EXPORT_SYMBOL(hpsb_bus_reset);
+EXPORT_SYMBOL(hpsb_selfid_received);
+EXPORT_SYMBOL(hpsb_selfid_complete);
+EXPORT_SYMBOL(hpsb_packet_sent);
+EXPORT_SYMBOL(hpsb_packet_received);
+
+EXPORT_SYMBOL(get_tlabel);
+EXPORT_SYMBOL(free_tlabel);
+EXPORT_SYMBOL(fill_async_readquad);
+EXPORT_SYMBOL(fill_async_readquad_resp);
+EXPORT_SYMBOL(fill_async_readblock);
+EXPORT_SYMBOL(fill_async_readblock_resp);
+EXPORT_SYMBOL(fill_async_writequad);
+EXPORT_SYMBOL(fill_async_writeblock);
+EXPORT_SYMBOL(fill_async_write_resp);
+EXPORT_SYMBOL(fill_async_lock);
+EXPORT_SYMBOL(fill_async_lock_resp);
+EXPORT_SYMBOL(fill_iso_packet);
+EXPORT_SYMBOL(fill_phy_packet);
+EXPORT_SYMBOL(hpsb_make_readqpacket);
+EXPORT_SYMBOL(hpsb_make_readbpacket);
+EXPORT_SYMBOL(hpsb_make_writeqpacket);
+EXPORT_SYMBOL(hpsb_make_writebpacket);
+EXPORT_SYMBOL(hpsb_make_lockpacket);
+EXPORT_SYMBOL(hpsb_make_phypacket);
+EXPORT_SYMBOL(hpsb_packet_success);
+EXPORT_SYMBOL(hpsb_make_packet);
+EXPORT_SYMBOL(hpsb_read);
+EXPORT_SYMBOL(hpsb_write);
+EXPORT_SYMBOL(hpsb_lock);
+
+EXPORT_SYMBOL(hpsb_register_highlevel);
+EXPORT_SYMBOL(hpsb_unregister_highlevel);
+EXPORT_SYMBOL(hpsb_register_addrspace);
+EXPORT_SYMBOL(hpsb_listen_channel);
+EXPORT_SYMBOL(hpsb_unlisten_channel);
+EXPORT_SYMBOL(highlevel_read);
+EXPORT_SYMBOL(highlevel_write);
+EXPORT_SYMBOL(highlevel_lock);
+EXPORT_SYMBOL(highlevel_lock64);
+EXPORT_SYMBOL(highlevel_add_host);
+EXPORT_SYMBOL(highlevel_remove_host);
+EXPORT_SYMBOL(highlevel_host_reset);
+EXPORT_SYMBOL(highlevel_add_one_host);
+
+EXPORT_SYMBOL(hpsb_guid_get_entry);
+EXPORT_SYMBOL(hpsb_nodeid_get_entry);
+EXPORT_SYMBOL(hpsb_get_host_by_ne);
+EXPORT_SYMBOL(hpsb_guid_fill_packet);
+EXPORT_SYMBOL(hpsb_register_protocol);
+EXPORT_SYMBOL(hpsb_unregister_protocol);
+EXPORT_SYMBOL(hpsb_release_unit_directory);
diff -urN linux-2.4.13-pre3/drivers/ieee1394/ieee1394_types.h linux/drivers/ieee1394/ieee1394_types.h
--- linux-2.4.13-pre3/drivers/ieee1394/ieee1394_types.h	Mon Oct  1 21:24:24 2001
+++ linux/drivers/ieee1394/ieee1394_types.h	Mon Dec  3 23:18:27 2001
@@ -20,6 +20,23 @@
 #define INIT_TQ_HEAD(tq) INIT_LIST_HEAD(&(tq))
 #endif
 
+/* This showed up around this time */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,12)
+
+# ifndef MODULE_LICENSE
+# define MODULE_LICENSE(x)
+# endif
+
+# ifndef min
+# define min(x,y) ({ \
+	const typeof(x) _x = (x);       \
+	const typeof(y) _y = (y);       \
+	(void) (&_x == &_y);            \
+	_x < _y ? _x : _y; })
+# endif
+
+#endif /* Linux version < 2.4.12 */
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
 #include <asm/spinlock.h>
 #else
@@ -49,6 +66,10 @@
 #define NODE_MASK 0x003f
 #define LOCAL_BUS 0xffc0
 #define ALL_NODES 0x003f
+
+#define NODE_BUS_FMT    "%d:%d"
+#define NODE_BUS_ARGS(nodeid) \
+	(nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
 
 #define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args)
 
diff -urN linux-2.4.13-pre3/drivers/ieee1394/nodemgr.c linux/drivers/ieee1394/nodemgr.c
--- linux-2.4.13-pre3/drivers/ieee1394/nodemgr.c	Mon Oct  1 21:24:24 2001
+++ linux/drivers/ieee1394/nodemgr.c	Mon Dec  3 23:18:27 2001
@@ -27,11 +27,8 @@
 #include "nodemgr.h"
 
 
-#define NODE_BUS_FMT	"%d:%d"
-#define NODE_BUS_ARGS(nodeid) \
-	(nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
-
-/* Basically what we do here is start off retrieving the bus_info block.
+/* 
+ * Basically what we do here is start off retrieving the bus_info block.
  * From there will fill in some info about the node, verify it is of IEEE
  * 1394 type, and that the crc checks out ok. After that we start off with
  * the root directory, and subdirectories. To do this, we retrieve the
@@ -42,9 +39,7 @@
  * We verify CRC's along the way for each directory/block/leaf. The
  * entire node structure is generic, and simply stores the information in
  * a way that's easy to parse by the protocol interface.
- *
- * XXX: Most of this isn't done yet :)  */
-
+ */
 
 static LIST_HEAD(node_list);
 static rwlock_t node_lock = RW_LOCK_UNLOCKED;
diff -urN linux-2.4.13-pre3/drivers/ieee1394/sbp2.c linux/drivers/ieee1394/sbp2.c
--- linux-2.4.13-pre3/drivers/ieee1394/sbp2.c	Mon Oct  1 21:24:25 2001
+++ linux/drivers/ieee1394/sbp2.c	Mon Dec  3 23:18:27 2001
@@ -130,6 +130,10 @@
  *	  add some init code to the kernel to support this... and modules are much
  *	  more flexible anyway.   ;-)
  *
+ *     - The scsi stack in recent kernels pass down the data transfer
+ *       direction as scsicmd->sc_data_direction, which we should use
+ *       instead of the sbp2scsi_direction_table.
+ *
  *
  * History:
  *
@@ -355,23 +359,23 @@
 
 
 #if CONFIG_IEEE1394_SBP2_DEBUG >= 2
-#define SBP2_DEBUG(fmt, args...)	HPSB_ERR(fmt, ## args)	
-#define SBP2_INFO(fmt, args...)		HPSB_ERR(fmt, ## args)	
-#define SBP2_NOTICE(fmt, args...)	HPSB_ERR(fmt, ## args)	
-#define SBP2_WARN(fmt, args...)		HPSB_ERR(fmt, ## args)
+#define SBP2_DEBUG(fmt, args...)	HPSB_ERR("sbp2: "fmt, ## args)
+#define SBP2_INFO(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)
+#define SBP2_NOTICE(fmt, args...)	HPSB_ERR("sbp2: "fmt, ## args)
+#define SBP2_WARN(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)
 #elif CONFIG_IEEE1394_SBP2_DEBUG == 1
-#define SBP2_DEBUG(fmt, args...)	HPSB_DEBUG(fmt, ## args)
-#define SBP2_INFO(fmt, args...)		HPSB_INFO(fmt, ## args)
-#define SBP2_NOTICE(fmt, args...)	HPSB_NOTICE(fmt, ## args)
-#define SBP2_WARN(fmt, args...)		HPSB_WARN(fmt, ## args)
+#define SBP2_DEBUG(fmt, args...)	HPSB_DEBUG("sbp2: "fmt, ## args)
+#define SBP2_INFO(fmt, args...)		HPSB_INFO("sbp2: "fmt, ## args)
+#define SBP2_NOTICE(fmt, args...)	HPSB_NOTICE("sbp2: "fmt, ## args)
+#define SBP2_WARN(fmt, args...)		HPSB_WARN("sbp2: "fmt, ## args)
 #else 
-#define SBP2_DEBUG(fmt, args...)	
-#define SBP2_INFO(fmt, args...)	
-#define SBP2_NOTICE(fmt, args...)	
-#define SBP2_WARN(fmt, args...)	
+#define SBP2_DEBUG(fmt, args...)
+#define SBP2_INFO(fmt, args...)
+#define SBP2_NOTICE(fmt, args...)
+#define SBP2_WARN(fmt, args...)
 #endif
 
-#define SBP2_ERR(fmt, args...)		HPSB_ERR(fmt, ## args)
+#define SBP2_ERR(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)
 
 /*
  * Spinlock debugging stuff. I'm playing it safe until the driver has been
@@ -393,6 +397,8 @@
 
 Scsi_Host_Template *global_scsi_tpnt = NULL;
 
+static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 };
+
 static LIST_HEAD(sbp2_host_info_list);
 static int sbp2_host_count = 0;
 
@@ -477,7 +483,7 @@
 		packet = alloc_hpsb_packet(8);
 
 		if (!packet) {
-			SBP2_ERR("sbp2: sbp2util_create_request_packet_pool - packet allocation failed!");
+			SBP2_ERR("sbp2util_create_request_packet_pool - packet allocation failed!");
 			return(-ENOMEM);
 		}
 
@@ -593,7 +599,7 @@
 		list_add_tail(&request_packet->list, &hi->sbp2_req_inuse);
 
 	} else {
-		SBP2_ERR("sbp2: sbp2util_allocate_request_packet - no packets available!");
+		SBP2_ERR("sbp2util_allocate_request_packet - no packets available!");
 	}
 	sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);
 
@@ -766,7 +772,7 @@
 		command->linked = 0;
 		list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);
 	} else {
-		SBP2_ERR("sbp2: sbp2util_allocate_command_orb - No orbs available!");
+		SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
 	}
 	sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
 	return (command);
@@ -825,7 +831,7 @@
  */
 int sbp2_init(void)
 {
-	SBP2_DEBUG("sbp2: sbp2_init");
+	SBP2_DEBUG("sbp2_init");
 
 	/*
 	 * Register our high level driver with 1394 stack
@@ -833,7 +839,7 @@
 	sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME, &sbp2_hl_ops);
 
 	if (sbp2_hl_handle == NULL) {
-		SBP2_ERR("sbp2: sbp2 failed to register with ieee1394 highlevel");
+		SBP2_ERR("sbp2 failed to register with ieee1394 highlevel");
 		return(-ENOMEM);
 	}
 
@@ -854,7 +860,7 @@
  */
 void sbp2_cleanup(void)
 {
-	SBP2_DEBUG("sbp2: sbp2_cleanup");
+	SBP2_DEBUG("sbp2_cleanup");
 
 	hpsb_unregister_protocol(&sbp2_driver);
 
@@ -869,7 +875,7 @@
 {
 	struct sbp2scsi_host_info *hi;
 
-	SBP2_DEBUG("sbp2: sbp2_probe");
+	SBP2_DEBUG("sbp2_probe");
 	hi = sbp2_find_host_info(ud->ne->host);
 
 	return sbp2_start_device(hi, ud);
@@ -880,7 +886,7 @@
 	struct sbp2scsi_host_info *hi;
 	struct scsi_id_instance_data *scsi_id = ud->driver_data;
 
-	SBP2_DEBUG("sbp2: sbp2_disconnect");
+	SBP2_DEBUG("sbp2_disconnect");
 	hi = sbp2_find_host_info(ud->ne->host);
 
 	if (hi != NULL)
@@ -893,7 +899,7 @@
 	struct scsi_id_instance_data *scsi_id = ud->driver_data;
 	unsigned long flags;
 
-	SBP2_DEBUG("sbp2: sbp2_update");
+	SBP2_DEBUG("sbp2_update");
 	hi = sbp2_find_host_info(ud->ne->host);
 
 	if (sbp2_reconnect_device(hi, scsi_id)) {
@@ -907,7 +913,7 @@
 			 * unvalidated, so that he gets cleaned up
 			 * later.
 			 */
-			SBP2_ERR("sbp2: sbp2_reconnect_device failed!");
+			SBP2_ERR("sbp2_reconnect_device failed!");
 			sbp2_remove_device(hi, scsi_id);
 			return;
 		}
@@ -940,14 +946,14 @@
 	struct sbp2scsi_host_info *hi;
 	unsigned long flags;
 
-	SBP2_DEBUG("sbp2: sbp2_add_host");
+	SBP2_DEBUG("sbp2_add_host");
 
 	/* Allocate some memory for our host info structure */
 	hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info),
 						  GFP_KERNEL);
 
 	if (hi == NULL) {
-		SBP2_ERR("sbp2: out of memory in sbp2_add_host");
+		SBP2_ERR("out of memory in sbp2_add_host");
 		return;
 	}
 
@@ -962,7 +968,7 @@
 
 	/* Create our request packet pool (pool of packets for use in I/O) */
 	if (sbp2util_create_request_packet_pool(hi)) {
-		SBP2_ERR("sbp2: sbp2util_create_request_packet_pool failed!");
+		SBP2_ERR("sbp2util_create_request_packet_pool failed!");
 		return;
 	}
 
@@ -1005,7 +1011,7 @@
 	unsigned long flags;
 	int i;
 
-	SBP2_DEBUG("sbp2: sbp2_remove_host");
+	SBP2_DEBUG("sbp2_remove_host");
 
 	sbp2_spin_lock(&sbp2_host_info_lock, flags);
 
@@ -1030,7 +1036,7 @@
 		kfree(hi);
 	}
 	else
-		SBP2_ERR("sbp2: attempt to remove unknown host %p", host);
+		SBP2_ERR("attempt to remove unknown host %p", host);
 
 	sbp2_spin_unlock(&sbp2_host_info_lock, flags);
 }
@@ -1045,7 +1051,7 @@
 	struct node_entry *ne;
 	int i;
 
-	SBP2_DEBUG("sbp2: sbp2_start_device");
+	SBP2_DEBUG("sbp2_start_device");
 	ne = ud->ne;
 
 	/*
@@ -1114,7 +1120,7 @@
 
 		kfree(scsi_id);
 alloc_fail_first:
-		SBP2_ERR ("sbp2: Could not allocate memory for scsi_id");
+		SBP2_ERR ("Could not allocate memory for scsi_id");
 		return(-ENOMEM);
 	}
 	SBP2_DMA_ALLOC("consistent DMA region for login ORB");
@@ -1125,7 +1131,7 @@
 	scsi_id->ne = ne;
 	scsi_id->ud = ud;
 	scsi_id->speed_code = SPEED_100;
-	scsi_id->max_payload_size = MAX_PAYLOAD_S100;
+	scsi_id->max_payload_size = sbp2_speedto_maxrec[SPEED_100];
 	ud->driver_data = scsi_id;
 
 	init_waitqueue_head(&scsi_id->sbp2_login_wait);
@@ -1169,7 +1175,7 @@
 		if (!hi->scsi_id[i]) {
 			hi->scsi_id[i] = scsi_id;
 			scsi_id->id = i;
-			SBP2_DEBUG("sbp2: New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i);
+			SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i);
 			break;
 		}
 	}
@@ -1178,7 +1184,7 @@
 	 * Create our command orb pool
 	 */
 	if (sbp2util_create_command_orb_pool(scsi_id, hi)) {
-		SBP2_ERR("sbp2: sbp2util_create_command_orb_pool failed!");
+		SBP2_ERR("sbp2util_create_command_orb_pool failed!");
 		sbp2_remove_device(hi, scsi_id);
 		return -ENOMEM;
 	}
@@ -1187,7 +1193,7 @@
 	 * Make sure we are not out of space
 	 */
 	if (i == SBP2SCSI_MAX_SCSI_IDS) {
-		SBP2_ERR("sbp2: No slots left for SBP-2 device");
+		SBP2_ERR("No slots left for SBP-2 device");
 		sbp2_remove_device(hi, scsi_id);
 		return -EBUSY;
 	}
@@ -1201,7 +1207,7 @@
 		 * Login failed... so, just mark him as unvalidated, so
 		 * that he gets cleaned up later.
 		 */
-		SBP2_ERR("sbp2: sbp2_login_device failed");
+		SBP2_ERR("sbp2_login_device failed");
 		sbp2_remove_device(hi, scsi_id);
 		return -EBUSY;
 	}
@@ -1270,7 +1276,7 @@
 		SBP2_DMA_FREE("single logout orb");
 	}
 
-	SBP2_DEBUG("sbp2: Unvalidated SBP-2 device removed, SCSI ID = %d", 
+	SBP2_DEBUG("Unvalidated SBP-2 device removed, SCSI ID = %d", 
 		   scsi_id->id);
 	hi->scsi_id[scsi_id->id] = NULL;
 	kfree(scsi_id);
@@ -1291,43 +1297,43 @@
 	quadlet_t data[2];
 	unsigned long flags;
 
-	SBP2_DEBUG("sbp2: sbp2_login_device");
+	SBP2_DEBUG("sbp2_login_device");
 
 	if (!scsi_id->login_orb) {
-		SBP2_DEBUG("sbp2: sbp2_login_device: login_orb not alloc'd!");
+		SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");
 		return(-EIO);
 	}
 
 	/* Set-up login ORB, assume no password */
 	scsi_id->login_orb->password_hi = 0; 
 	scsi_id->login_orb->password_lo = 0;
-	SBP2_DEBUG("sbp2: sbp2_login_device: password_hi/lo initialized");
+	SBP2_DEBUG("sbp2_login_device: password_hi/lo initialized");
 
 	scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma;
 	scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
-	SBP2_DEBUG("sbp2: sbp2_login_device: login_response_hi/lo initialized");
+	SBP2_DEBUG("sbp2_login_device: login_response_hi/lo initialized");
 
 	scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(LOGIN_REQUEST);
 	scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0);	/* One second reconnect time */
 	scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(1);	/* Exclusive access to device */
 	scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);		/* Notify us of login complete */
-	SBP2_DEBUG("sbp2: sbp2_login_device: lun_misc initialized");
+	SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
 
 	scsi_id->login_orb->passwd_resp_lengths =
 		ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
-	SBP2_DEBUG("sbp2: sbp2_login_device: passwd_resp_lengths initialized");
+	SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
 
 	scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
 	scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
 					      SBP2_STATUS_FIFO_ADDRESS_HI);
-	SBP2_DEBUG("sbp2: sbp2_login_device: status FIFO initialized");
+	SBP2_DEBUG("sbp2_login_device: status FIFO initialized");
 
 	/*
 	 * Byte swap ORB if necessary
 	 */
 	sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb));
 
-	SBP2_DEBUG("sbp2: sbp2_login_device: orb byte-swapped");
+	SBP2_DEBUG("sbp2_login_device: orb byte-swapped");
 
 	/*
 	 * Initialize login response and status fifo
@@ -1335,7 +1341,7 @@
 	memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));
 	memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
 
-	SBP2_DEBUG("sbp2: sbp2_login_device: login_response/status FIFO memset");
+	SBP2_DEBUG("sbp2_login_device: login_response/status FIFO memset");
 
 	/*
 	 * Ok, let's write to the target's management agent register
@@ -1344,9 +1350,9 @@
 	data[1] = scsi_id->login_orb_dma;
 	sbp2util_cpu_to_be32_buffer(data, 8);
 
-	SBP2_DEBUG("sbp2: sbp2_login_device: prepared to write");
+	SBP2_DEBUG("sbp2_login_device: prepared to write");
 	hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
-	SBP2_DEBUG("sbp2: sbp2_login_device: written");
+	SBP2_DEBUG("sbp2_login_device: written");
 
 	/*
 	 * Wait for login status... but, only if the device has not
@@ -1360,18 +1366,18 @@
 		sleep_on_timeout(&scsi_id->sbp2_login_wait, 10*HZ);
 	restore_flags(flags);
 
-	SBP2_DEBUG("sbp2: sbp2_login_device: initial check");
+	SBP2_DEBUG("sbp2_login_device: initial check");
 
 	/*
 	 * Match status to the login orb. If they do not match, it's
 	 * probably because the login timed-out.
 	 */
 	if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
-		SBP2_ERR("sbp2: Error logging into SBP-2 device - login timed-out");
+		SBP2_ERR("Error logging into SBP-2 device - login timed-out");
 		return(-EIO);
 	}
 
-	SBP2_DEBUG("sbp2: sbp2_login_device: second check");
+	SBP2_DEBUG("sbp2_login_device: second check");
 
 	/*
 	 * Check status
@@ -1380,7 +1386,7 @@
 	    STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
 	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
 
-		SBP2_ERR("sbp2: Error logging into SBP-2 device - login failed");
+		SBP2_ERR("Error logging into SBP-2 device - login failed");
 		return(-EIO);
 	}
 
@@ -1393,9 +1399,9 @@
 	/*
 	 * Grab our command block agent address from the login response.
 	 */
-	SBP2_DEBUG("sbp2: command_block_agent_hi = %x",
+	SBP2_DEBUG("command_block_agent_hi = %x",
 		   (unsigned int)scsi_id->login_response->command_block_agent_hi);
-	SBP2_DEBUG("sbp2: command_block_agent_lo = %x",
+	SBP2_DEBUG("command_block_agent_lo = %x",
 		   (unsigned int)scsi_id->login_response->command_block_agent_lo);
 
 	scsi_id->sbp2_command_block_agent_addr =
@@ -1403,7 +1409,7 @@
 	scsi_id->sbp2_command_block_agent_addr |= ((u64)scsi_id->login_response->command_block_agent_lo);
 	scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL;
 
-	SBP2_INFO("sbp2: Logged into SBP-2 device");
+	SBP2_INFO("Logged into SBP-2 device");
 
 	return(0);
 
@@ -1417,7 +1423,7 @@
 {
 	quadlet_t data[2];
 
-	SBP2_DEBUG("sbp2: sbp2_logout_device");
+	SBP2_DEBUG("sbp2_logout_device");
 
 	/*
 	 * Set-up logout ORB
@@ -1455,7 +1461,7 @@
 	/* Wait for device to logout...1 second. */
 	sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);
 
-	SBP2_INFO("sbp2: Logged out of SBP-2 device");
+	SBP2_INFO("Logged out of SBP-2 device");
 
 	return(0);
 
@@ -1470,7 +1476,7 @@
 	quadlet_t data[2];
 	unsigned long flags;
 
-	SBP2_DEBUG("sbp2: sbp2_reconnect_device");
+	SBP2_DEBUG("sbp2_reconnect_device");
 
 	/*
 	 * Set-up reconnect ORB
@@ -1527,7 +1533,7 @@
 	 * probably because the reconnect timed-out.
 	 */
 	if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
-		SBP2_ERR("sbp2: Error reconnecting to SBP-2 device - reconnect timed-out");
+		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
 		return(-EIO);
 	}
 
@@ -1538,11 +1544,11 @@
 	    STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||
 	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
 
-		SBP2_ERR("sbp2: Error reconnecting to SBP-2 device - reconnect failed");
+		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed");
 		return(-EIO);
 	}
 
-	SBP2_INFO("sbp2: Reconnected to SBP-2 device");
+	SBP2_INFO("Reconnected to SBP-2 device");
 
 	return(0);
 
@@ -1556,7 +1562,7 @@
 {      
 	quadlet_t data;
 
-	SBP2_DEBUG("sbp2: sbp2_set_busy_timeout");
+	SBP2_DEBUG("sbp2_set_busy_timeout");
 
 	/*
 	 * Ok, let's write to the target's busy timeout register
@@ -1564,7 +1570,7 @@
 	data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
 
 	if (hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
-		SBP2_ERR("sbp2: sbp2_set_busy_timeout error");
+		SBP2_ERR("sbp2_set_busy_timeout error");
 	}
 
 	return(0);
@@ -1580,7 +1586,7 @@
 	struct unit_directory *ud;
 	int i;
 
-	SBP2_DEBUG("sbp2: sbp2_parse_unit_directory");
+	SBP2_DEBUG("sbp2_parse_unit_directory");
 
 	ud = scsi_id->ud;
 
@@ -1593,21 +1599,21 @@
 				CONFIG_ROM_INITIAL_MEMORY_SPACE + 
 				(ud->arb_values[i] << 2);
 
-			SBP2_DEBUG("sbp2: sbp2_management_agent_addr = %x",
+			SBP2_DEBUG("sbp2_management_agent_addr = %x",
 				   (unsigned int) scsi_id->sbp2_management_agent_addr);
 			break;
 
 		case SBP2_COMMAND_SET_SPEC_ID_KEY:
 			/* Command spec organization */
 			scsi_id->sbp2_command_set_spec_id = ud->arb_values[i];
-			SBP2_DEBUG("sbp2: sbp2_command_set_spec_id = %x",
+			SBP2_DEBUG("sbp2_command_set_spec_id = %x",
 				   (unsigned int) scsi_id->sbp2_command_set_spec_id);
 			break;
 
 		case SBP2_COMMAND_SET_KEY:
 			/* Command set used by sbp2 device */
 			scsi_id->sbp2_command_set = ud->arb_values[i];
-			SBP2_DEBUG("sbp2: sbp2_command_set = %x",
+			SBP2_DEBUG("sbp2_command_set = %x",
 				   (unsigned int) scsi_id->sbp2_command_set);
 			break;
 
@@ -1617,7 +1623,7 @@
 			 * that I'm not yet paying attention to)
 			 */
 			scsi_id->sbp2_unit_characteristics = ud->arb_values[i];
-			SBP2_DEBUG("sbp2: sbp2_unit_characteristics = %x",
+			SBP2_DEBUG("sbp2_unit_characteristics = %x",
 				   (unsigned int) scsi_id->sbp2_unit_characteristics);
 			break;
 
@@ -1627,7 +1633,7 @@
 			 * detemining type of sbp2 device)
 			 */
 			scsi_id->sbp2_device_type_and_lun = ud->arb_values[i];
-			SBP2_DEBUG("sbp2: sbp2_device_type_and_lun = %x",
+			SBP2_DEBUG("sbp2_device_type_and_lun = %x",
 				   (unsigned int) scsi_id->sbp2_device_type_and_lun);
 			break;
 
@@ -1642,7 +1648,7 @@
 			scsi_id->sbp2_firmware_revision = ud->arb_values[i];
 			if (scsi_id->sbp2_firmware_revision ==
 			    SBP2_128KB_BROKEN_FIRMWARE) {
-				SBP2_WARN("sbp2: warning: Bridge chipset supports 128KB max transfer size");
+				SBP2_WARN("warning: Bridge chipset supports 128KB max transfer size");
 			}
 			break;
 
@@ -1654,39 +1660,36 @@
 
 /*
  * This function is called in order to determine the max speed and packet
- * size we can use in our ORBs. 
+ * size we can use in our ORBs. Note, that we (the driver and host) only
+ * initiate the transaction. The SBP-2 device actually transfers the data
+ * (by reading from the DMA area we tell it). This means that the SBP-2
+ * device decides the actual maximum data it can transfer. We just tell it
+ * the speed that it needs to use, and the max_rec the host supports, and
+ * it takes care of the rest.
  */
 static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
 {
-	u8 speed_code;
-	unsigned int max_rec;
-
-	SBP2_DEBUG("sbp2: sbp2_max_speed_and_size");
+	SBP2_DEBUG("sbp2_max_speed_and_size");
 
-	speed_code = scsi_id->ne->busopt.lnkspd;
-	max_rec = scsi_id->ne->busopt.max_rec;
-
-	/* Bump down our speed if there is a module parameter forcing us slower */
-	if (speed_code > max_speed) {
-		speed_code = max_speed;
-		SBP2_ERR("sbp2: Reducing SBP-2 max speed allowed (%x)", max_speed); 
-	}
-
-	/* Support the devices max_rec and max speed. We choose a setting
-	 * that fits both values, since they may differ.  */
-	if (speed_code >= SPEED_400 && max_rec >= MAX_REC_S400) {
-		HPSB_INFO("sbp2: SBP-2 device max speed S400 and payload 2KB");
-		scsi_id->speed_code = SPEED_400;
-		scsi_id->max_payload_size = MAX_PAYLOAD_S400;
-	} else if (speed_code >= SPEED_200 && max_rec >= MAX_REC_S200) {
-		HPSB_INFO("sbp2: SBP-2 device max speed S200 and payload 1KB");
-		scsi_id->speed_code = SPEED_200;
-		scsi_id->max_payload_size = MAX_PAYLOAD_S200;
-	} else {
-		HPSB_INFO("sbp2: SBP-2 device max speed S100 and payload 512 bytes");
-		scsi_id->speed_code = SPEED_100;
-		scsi_id->max_payload_size = MAX_PAYLOAD_S100;
-	}
+	/* Initial setting comes from the hosts speed map */
+	scsi_id->speed_code = hi->host->speed_map[(hi->host->node_id & NODE_MASK) * 64
+						  + (scsi_id->ne->nodeid & NODE_MASK)];
+
+	/* Bump down our speed if the user requested it */
+	if (scsi_id->speed_code > max_speed) {
+		scsi_id->speed_code = max_speed;
+		SBP2_ERR("Forcing SBP-2 max speed down to %s",
+			 hpsb_speedto_str[scsi_id->speed_code]);
+	}
+
+	/* Payload size is the lesser of what our speed supports and what
+	 * our host supports.  */
+	scsi_id->max_payload_size = min(sbp2_speedto_maxrec[scsi_id->speed_code],
+					(u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1));
+
+	SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [0x%02x/%u]",
+		 NODE_BUS_ARGS(scsi_id->ne->nodeid), hpsb_speedto_str[scsi_id->speed_code],
+		 scsi_id->max_payload_size, 1 << ((u32)scsi_id->max_payload_size + 2));
 
 	return(0);
 }
@@ -1698,7 +1701,7 @@
 {
 	struct sbp2_request_packet *agent_reset_request_packet;
 
-	SBP2_DEBUG("sbp2: sbp2_agent_reset");
+	SBP2_DEBUG("sbp2_agent_reset");
 
 	/*
 	 * Ok, let's write to the target's management agent register
@@ -1710,12 +1713,12 @@
 						       0, ntohl(SBP2_AGENT_RESET_DATA));
 
 	if (!agent_reset_request_packet) {
-		SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
+		SBP2_ERR("sbp2util_allocate_write_request_packet failed");
 		return(-EIO);
 	}
 
 	if (!hpsb_send_packet(agent_reset_request_packet->packet)) {
-		SBP2_ERR("sbp2: hpsb_send_packet failed");
+		SBP2_ERR("hpsb_send_packet failed");
 		sbp2util_free_request_packet(agent_reset_request_packet); 
 		return(-EIO);
 	}
@@ -1774,7 +1777,7 @@
 	 */
 	if (sbp2scsi_direction_table[*scsi_cmd] == ORB_DIRECTION_NO_DATA_TRANSFER) {
 
-		SBP2_DEBUG("sbp2: No data transfer");
+		SBP2_DEBUG("No data transfer");
 
 		/*
 		 * Handle no data transfer
@@ -1785,14 +1788,14 @@
 
 	} else if (scsi_use_sg) {
 
-		SBP2_DEBUG("sbp2: Use scatter/gather");
+		SBP2_DEBUG("Use scatter/gather");
 
 		/*
 		 * Special case if only one element (and less than 64KB in size)
 		 */
 		if ((scsi_use_sg == 1) && (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
 
-			SBP2_DEBUG("sbp2: Only one s/g element");
+			SBP2_DEBUG("Only one s/g element");
 			command->dma_dir = dma_dir;
 			command->dma_size = sgpnt[0].length;
 			command->cmd_dma = pci_map_single (hi->host->pdev, sgpnt[0].address,
@@ -1856,7 +1859,7 @@
 
 	} else {
 
-		SBP2_DEBUG("sbp2: No scatter/gather");
+		SBP2_DEBUG("No scatter/gather");
 
 		command->dma_dir = dma_dir;
 		command->dma_size = scsi_request_bufflen;
@@ -1977,7 +1980,7 @@
 								SBP2_ORB_POINTER_OFFSET, 8, 0);
 		
 			if (!command_request_packet) {
-				SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
+				SBP2_ERR("sbp2util_allocate_write_request_packet failed");
 				return(-EIO);
 			}
 		
@@ -1988,7 +1991,7 @@
 			SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb);
 
 			if (!hpsb_send_packet(command_request_packet->packet)) {
-				SBP2_ERR("sbp2: hpsb_send_packet failed");
+				SBP2_ERR("hpsb_send_packet failed");
 				sbp2util_free_request_packet(command_request_packet); 
 				return(-EIO);
 			}
@@ -2024,14 +2027,14 @@
 				0, cpu_to_be32(command->command_orb_dma));
 	
 			if (!command_request_packet) {
-				SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
+				SBP2_ERR("sbp2util_allocate_write_request_packet failed");
 				return(-EIO);
 			}
 
 			SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb);
 
 			if (!hpsb_send_packet(command_request_packet->packet)) {
-				SBP2_ERR("sbp2: hpsb_send_packet failed");
+				SBP2_ERR("hpsb_send_packet failed");
 				sbp2util_free_request_packet(command_request_packet);
 				return(-EIO);
 			}
@@ -2053,10 +2056,10 @@
 	u32 device_type = (scsi_id->sbp2_device_type_and_lun & 0x00ff0000) >> 16;
 	struct sbp2_command_info *command;
 
-	SBP2_DEBUG("sbp2: sbp2_send_command");
-	SBP2_DEBUG("sbp2: SCSI command = %02x", *cmd);
-	SBP2_DEBUG("sbp2: SCSI transfer size = %x", SCpnt->request_bufflen);
-	SBP2_DEBUG("sbp2: SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
+	SBP2_DEBUG("sbp2_send_command");
+	SBP2_DEBUG("SCSI command = %02x", *cmd);
+	SBP2_DEBUG("SCSI transfer size = %x", SCpnt->request_bufflen);
+	SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
 
 	/*
 	 * Check for broken devices that can't handle greater than 128K
@@ -2236,13 +2239,13 @@
 {
 	unchar new_cmd[16];
 
-	SBP2_DEBUG("sbp2: sbp2_check_sbp2_command");
+	SBP2_DEBUG("sbp2_check_sbp2_command");
 
 	switch (*cmd) {
 		
 		case READ_6:
 
-			SBP2_DEBUG("sbp2: Convert READ_6 to READ_10");
+			SBP2_DEBUG("Convert READ_6 to READ_10");
 
 			/*
 			 * Need to turn read_6 into read_10
@@ -2264,7 +2267,7 @@
 
 		case WRITE_6:
 
-			SBP2_DEBUG("sbp2: Convert WRITE_6 to WRITE_10");
+			SBP2_DEBUG("Convert WRITE_6 to WRITE_10");
 
 			/*
 			 * Need to turn write_6 into write_10
@@ -2286,7 +2289,7 @@
 
 		case MODE_SENSE:
 
-			SBP2_DEBUG("sbp2: Convert MODE_SENSE_6 to MOSE_SENSE_10");
+			SBP2_DEBUG("Convert MODE_SENSE_6 to MOSE_SENSE_10");
 
 			/*
 			 * Need to turn mode_sense_6 into mode_sense_10
@@ -2324,7 +2327,7 @@
  */
 static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data)
 {
-	SBP2_DEBUG("sbp2: sbp2_status_to_sense_data");
+	SBP2_DEBUG("sbp2_status_to_sense_data");
 
 	/*
 	 * Ok, it's pretty ugly...   ;-)
@@ -2360,19 +2363,19 @@
 	u8 *scsi_buf = SCpnt->request_buffer;
 	u32 device_type = (scsi_id->sbp2_device_type_and_lun & 0x00ff0000) >> 16;
         
-	SBP2_DEBUG("sbp2: sbp2_check_sbp2_response");
+	SBP2_DEBUG("sbp2_check_sbp2_response");
 
 	switch (SCpnt->cmnd[0]) {
 		
 		case INQUIRY:
 
-			SBP2_DEBUG("sbp2: Check Inquiry data");
+			SBP2_DEBUG("Check Inquiry data");
 
 			/*
 			 * Check for Simple Direct Access Device and change it to TYPE_DISK
 			 */
 			if ((scsi_buf[0] & 0x1f) == TYPE_SDAD) {
-				SBP2_DEBUG("sbp2: Changing TYPE_SDAD to TYPE_DISK");
+				SBP2_DEBUG("Changing TYPE_SDAD to TYPE_DISK");
 				scsi_buf[0] &= 0xe0;
 			}
 
@@ -2390,7 +2393,7 @@
 			    (device_type == TYPE_SDAD) ||
 			    (device_type == TYPE_ROM)) {
 
-				SBP2_DEBUG("sbp2: Modify mode sense response (10 byte version)");
+				SBP2_DEBUG("Modify mode sense response (10 byte version)");
 	
 				scsi_buf[0] = scsi_buf[1];	/* Mode data length */
 				scsi_buf[1] = scsi_buf[2];	/* Medium type */
@@ -2428,10 +2431,10 @@
 	u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
 	struct sbp2_command_info *command;
 
-	SBP2_DEBUG("sbp2: sbp2_handle_status_write");
+	SBP2_DEBUG("sbp2_handle_status_write");
 
 	if (!host) {
-		SBP2_ERR("sbp2: host is NULL - this is bad!");
+		SBP2_ERR("host is NULL - this is bad!");
 		return(RCODE_ADDRESS_ERROR);
 	}
 
@@ -2440,7 +2443,7 @@
 	sbp2_spin_unlock(&sbp2_host_info_lock, flags);
 
 	if (!hi) {
-		SBP2_ERR("sbp2: host info is NULL - this is bad!");
+		SBP2_ERR("host info is NULL - this is bad!");
 		return(RCODE_ADDRESS_ERROR);
 	}
 
@@ -2453,14 +2456,14 @@
 		if (hi->scsi_id[i]) {
 			if ((hi->scsi_id[i]->ne->nodeid & NODE_MASK) == (nodeid & NODE_MASK)) {
 				scsi_id = hi->scsi_id[i];
-				SBP2_DEBUG("sbp2: SBP-2 status write from node %x", scsi_id->ne->nodeid);
+				SBP2_DEBUG("SBP-2 status write from node %x", scsi_id->ne->nodeid);
 				break;
 			}
 		}
 	}
 
 	if (!scsi_id) {
-		SBP2_ERR("sbp2: scsi_id is NULL - device is gone?");
+		SBP2_ERR("scsi_id is NULL - device is gone?");
 		sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
 		return(RCODE_ADDRESS_ERROR);
 	}
@@ -2481,7 +2484,7 @@
 	command = sbp2util_find_command_for_orb(scsi_id, scsi_id->status_block.ORB_offset_lo);
 	if (command) {
 
-		SBP2_DEBUG("sbp2: Found status for command ORB");
+		SBP2_DEBUG("Found status for command ORB");
 
 		SBP2_ORB_DEBUG("matched command orb %p", &command->command_orb);
 		outstanding_orb_decr;
@@ -2499,7 +2502,7 @@
 			 */
 			if (STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
 
-				SBP2_DEBUG("sbp2: CHECK CONDITION");
+				SBP2_DEBUG("CHECK CONDITION");
 
 				/*
 				 * Translate SBP-2 status to SCSI sense data
@@ -2518,7 +2521,7 @@
 			/*
 			 * Complete the SCSI command
 			 */
-			SBP2_DEBUG("sbp2: Completing SCSI command");
+			SBP2_DEBUG("Completing SCSI command");
 			sbp2scsi_complete_command(hi, scsi_id, scsi_status, SCpnt, command->Current_done);
 			SBP2_ORB_DEBUG("command orb completed");
 		}
@@ -2555,7 +2558,7 @@
 	struct scsi_id_instance_data *scsi_id = NULL;
 	unsigned long flags;
 
-	SBP2_DEBUG("sbp2: sbp2scsi_queuecommand");
+	SBP2_DEBUG("sbp2scsi_queuecommand");
 
 	/*
 	 * Pull our host info and scsi id instance data from the scsi command
@@ -2563,7 +2566,7 @@
 	hi = (struct sbp2scsi_host_info *) SCpnt->host->hostdata[0];
 
 	if (!hi) {
-		SBP2_ERR("sbp2: sbp2scsi_host_info is NULL - this is bad!");
+		SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done (SCpnt);
 		return(0);
@@ -2596,7 +2599,7 @@
 	 * (autorequest sense)
 	 */
 	if (SCpnt->cmnd[0] == REQUEST_SENSE) {
-		SBP2_DEBUG("sbp2: REQUEST_SENSE");
+		SBP2_DEBUG("REQUEST_SENSE");
 		memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen);
 		memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
 		sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done);
@@ -2608,7 +2611,7 @@
 	 * busy (to be queued later)
 	 */
 	if (!hpsb_node_entry_valid(scsi_id->ne)) {
-		SBP2_ERR("sbp2: Bus reset in progress - rejecting command");
+		SBP2_ERR("Bus reset in progress - rejecting command");
 		SCpnt->result = DID_BUS_BUSY << 16;
 		done (SCpnt);
 		return(0);
@@ -2619,7 +2622,7 @@
 	 */
 	sbp2_spin_lock(&hi->sbp2_command_lock, flags);
 	if (sbp2_send_command(hi, scsi_id, SCpnt, done)) {
-		SBP2_ERR("sbp2: Error sending SCSI command");
+		SBP2_ERR("Error sending SCSI command");
 		sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, SCpnt, done);
 	}
 	sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
@@ -2638,10 +2641,10 @@
 	struct list_head *lh;
 	struct sbp2_command_info *command;
 
-	SBP2_DEBUG("sbp2: sbp2_complete_all_commands");
+	SBP2_DEBUG("sbp2_complete_all_commands");
 
 	while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
-		SBP2_DEBUG("sbp2: Found pending command to complete");
+		SBP2_DEBUG("Found pending command to complete");
 		lh = scsi_id->sbp2_command_orb_inuse.next;
 		command = list_entry(lh, struct sbp2_command_info, list);
 		sbp2util_mark_command_completed(scsi_id, command);
@@ -2661,13 +2664,13 @@
 static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status,
 				      Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
-	SBP2_DEBUG("sbp2: sbp2scsi_complete_command");
+	SBP2_DEBUG("sbp2scsi_complete_command");
 
 	/*
 	 * Sanity
 	 */
 	if (!SCpnt) {
-		SBP2_ERR("sbp2: SCpnt is NULL");
+		SBP2_ERR("SCpnt is NULL");
 		return;
 	}
 
@@ -2677,7 +2680,7 @@
 	 * bus reset.
 	 */
 	if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
-		SBP2_ERR("sbp2: Bus reset in progress - retry command later");
+		SBP2_ERR("Bus reset in progress - retry command later");
 		return;
 	}
         
@@ -2690,12 +2693,12 @@
 			break;
 
 		case SBP2_SCSI_STATUS_BUSY:
-			SBP2_ERR("sbp2: SBP2_SCSI_STATUS_BUSY");
+			SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
 			SCpnt->result = DID_BUS_BUSY << 16;
 			break;
 
 		case SBP2_SCSI_STATUS_CHECK_CONDITION:
-			SBP2_DEBUG("sbp2: SBP2_SCSI_STATUS_CHECK_CONDITION");
+			SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
 			SCpnt->result = CHECK_CONDITION << 1;
 
 			/*
@@ -2706,19 +2709,19 @@
 			break;
 
 		case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
-			SBP2_ERR("sbp2: SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
+			SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
 			SCpnt->result = DID_NO_CONNECT << 16;
 			break;
 
 		case SBP2_SCSI_STATUS_CONDITION_MET:
 		case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
 		case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
-			SBP2_ERR("sbp2: Bad SCSI status = %x", scsi_status);
+			SBP2_ERR("Bad SCSI status = %x", scsi_status);
 			SCpnt->result = DID_ERROR << 16;
 			break;
 
 		default:
-			SBP2_ERR("sbp2: Unsupported SCSI status = %x", scsi_status);
+			SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
 			SCpnt->result = DID_ERROR << 16;
 	}
 
@@ -2736,7 +2739,7 @@
 	 * can mount the device rw).
 	 */
 	if (mode_sense_hack && SCpnt->result != DID_OK && SCpnt->cmnd[0] == MODE_SENSE) {
-		SBP2_INFO("sbp2: Returning success to mode sense command");
+		SBP2_INFO("Returning success to mode sense command");
 		SCpnt->result = DID_OK;
 		SCpnt->sense_buffer[0] = 0;
 		memset (SCpnt->request_buffer, 0, 8);
@@ -2747,7 +2750,7 @@
 	 * the command as busy so that it will get retried.
 	 */
 	if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
-		SBP2_ERR("sbp2: Completing command with busy (bus reset)");
+		SBP2_ERR("Completing command with busy (bus reset)");
 		SCpnt->result = DID_BUS_BUSY << 16;
 	}
 
@@ -2757,7 +2760,7 @@
 	 * or hot-plug...
 	 */
 	if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) && (SCpnt->sense_buffer[2] == UNIT_ATTENTION)) {
-		SBP2_INFO("sbp2: UNIT ATTENTION - return busy");
+		SBP2_INFO("UNIT ATTENTION - return busy");
 		SCpnt->result = DID_BUS_BUSY << 16;
 	}
 
@@ -2780,7 +2783,7 @@
 	struct sbp2_command_info *command;
 	unsigned long flags;
 
-	SBP2_ERR("sbp2: aborting sbp2 command");
+	SBP2_ERR("aborting sbp2 command");
 
 	if (scsi_id) {
 
@@ -2793,7 +2796,7 @@
 		do {
 			command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
 			if (command) {
-				SBP2_DEBUG("sbp2: Found command to abort");
+				SBP2_DEBUG("Found command to abort");
 				sbp2util_mark_command_completed(scsi_id, command);
 				if (command->Current_SCpnt && !command->linked) {
 					void (*done)(Scsi_Cmnd *) = command->Current_done;
@@ -2821,10 +2824,10 @@
 {
 	struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->host->hostdata[0];
 
-	SBP2_ERR("sbp2: reset requested");
+	SBP2_ERR("reset requested");
 
 	if (hi) {
-		SBP2_ERR("sbp2: generating IEEE-1394 bus reset");
+		SBP2_ERR("Generating IEEE-1394 bus reset");
 		hpsb_reset_bus(hi->host, LONG_RESET);
 	}
 
@@ -2838,7 +2841,7 @@
 {
 	int heads, sectors, cylinders;
 
-	SBP2_DEBUG("sbp2: request for bios parameters");
+	SBP2_DEBUG("Request for bios parameters");
 
 	heads = 64;
 	sectors = 32;
@@ -2862,7 +2865,7 @@
  */
 void sbp2scsi_setup( char *str, int *ints) 
 {
-	SBP2_DEBUG("sbp2: sbp2scsi_setup");
+	SBP2_DEBUG("sbp2scsi_setup");
 	return;
 }
 
@@ -2871,7 +2874,7 @@
  */
 static int sbp2scsi_detect (Scsi_Host_Template *tpnt) 
 {
-	SBP2_DEBUG("sbp2: sbp2scsi_detect");
+	SBP2_DEBUG("sbp2scsi_detect");
 
 	global_scsi_tpnt = tpnt;
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,26)
@@ -2881,7 +2884,7 @@
 	 * Module load option for force one command at a time
 	 */
 	if (serialize_io) {
-		SBP2_ERR("sbp2: Driver forced to serialize I/O (serialize_io = 1)");
+		SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)");
 		global_scsi_tpnt->can_queue = 1;
 		global_scsi_tpnt->cmd_per_lun = 1;
 	}
@@ -2890,19 +2893,19 @@
 	 * Module load option to limit max size of requests from the scsi drivers
 	 */
 	if (no_large_packets) {
-		SBP2_ERR("sbp2: Driver forced to limit max transfer size (no_large_packets = 1)");
+		SBP2_ERR("Driver forced to limit max transfer size (no_large_packets = 1)");
 		global_scsi_tpnt->sg_tablesize = 0x1f;
 		global_scsi_tpnt->use_clustering = DISABLE_CLUSTERING;
 	}
 
 	if (mode_sense_hack) {
-		SBP2_ERR("sbp2: Mode sense emulation enabled (mode_sense_hack = 1)");
+		SBP2_ERR("Mode sense emulation enabled (mode_sense_hack = 1)");
 	}
 
 	sbp2_init();
 
 	if (!sbp2_host_count) {
-		SBP2_ERR("sbp2: Please load the lower level IEEE-1394 driver (e.g. ohci1394) before sbp2...");
+		SBP2_ERR("Please load the lower level IEEE-1394 driver (e.g. ohci1394) before sbp2...");
 		sbp2_cleanup();
 	}
 
@@ -2921,8 +2924,8 @@
 {
 	struct Scsi_Host *shpnt = NULL;
 
-	SBP2_DEBUG("sbp2: sbp2scsi_register_scsi_host");
-	SBP2_DEBUG("sbp2: sbp2scsi_host_info = %p", hi);
+	SBP2_DEBUG("sbp2scsi_register_scsi_host");
+	SBP2_DEBUG("sbp2scsi_host_info = %p", hi);
 
 	/*
 	 * Let's register with the scsi stack
@@ -2946,7 +2949,7 @@
 /* Called when our module is released */
 static int sbp2scsi_release(struct Scsi_Host *host)
 {
-	SBP2_DEBUG("sbp2: sbp2scsi_release");
+	SBP2_DEBUG("sbp2scsi_release");
 	sbp2_cleanup();
 	return(0);
 }
@@ -2960,6 +2963,7 @@
 MODULE_AUTHOR("James Goodwin <jamesg@filanet.com>");
 MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
 MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
+MODULE_LICENSE("GPL");
 
 /* SCSI host template */
 static Scsi_Host_Template driver_template = {
diff -urN linux-2.4.13-pre3/drivers/ieee1394/sbp2.h linux/drivers/ieee1394/sbp2.h
--- linux-2.4.13-pre3/drivers/ieee1394/sbp2.h	Mon Oct  1 21:24:25 2001
+++ linux/drivers/ieee1394/sbp2.h	Mon Dec  3 23:18:27 2001
@@ -36,16 +36,6 @@
 #define ORB_DIRECTION_READ_FROM_MEDIA   0x1
 #define ORB_DIRECTION_NO_DATA_TRANSFER  0x2
 
-/* 2^(MAX_PAYLOAD+1) = Maximum data transfer length */
-#define MAX_PAYLOAD_S100		0x7
-#define MAX_PAYLOAD_S200		0x8
-#define MAX_PAYLOAD_S400		0x9
-
-/* Max rec matches node_entry values */
-#define MAX_REC_S100			512
-#define MAX_REC_S200			1024
-#define MAX_REC_S400			2048
-
 #define ORB_SET_NOTIFY(value)                   ((value & 0x1) << 31)
 #define ORB_SET_RQ_FMT(value)                   ((value & 0x3) << 29)
 #define ORB_SET_NODE_ID(value)			((value & 0xffff) << 16)
@@ -268,6 +258,9 @@
  * DOU = OUT data direction
  * DNO = No data transfer
  * DUN = Unknown data direction
+ *
+ * Opcode 0xec (Teac specific "opc execute") possibly should be DNO,
+ * but we'll change it when somebody reports a problem with this.
  */
 #define DIN				ORB_DIRECTION_READ_FROM_MEDIA
 #define DOU				ORB_DIRECTION_WRITE_TO_MEDIA
@@ -280,7 +273,7 @@
 	DIN,DUN,DIN,DIN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
 	DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
 	DOU,DOU,DIN,DIN,DIN,DNO,DIN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DNO,DUN,
-	DUN,DIN,DIN,DNO,DOU,DOU,DUN,DUN,DNO,DIN,DIN,DNO,DIN,DOU,DUN,DUN,
+	DUN,DIN,DIN,DNO,DNO,DOU,DUN,DUN,DNO,DIN,DIN,DNO,DIN,DOU,DUN,DUN,
 	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
 	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
 	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
diff -urN linux-2.4.13-pre3/drivers/md/md.c linux/drivers/md/md.c
--- linux-2.4.13-pre3/drivers/md/md.c	Mon Dec  3 23:18:18 2001
+++ linux/drivers/md/md.c	Mon Dec  3 23:18:27 2001
@@ -542,8 +542,10 @@
 		goto abort;
 	}
 
-	if (calc_sb_csum(sb) != sb->sb_csum)
+	if (calc_sb_csum(sb) != sb->sb_csum) {
 		printk(BAD_CSUM, partition_name(rdev->dev));
+		goto abort;
+	}
 	ret = 0;
 abort:
 	return ret;
diff -urN linux-2.4.13-pre3/drivers/md/raid1.c linux/drivers/md/raid1.c
--- linux-2.4.13-pre3/drivers/md/raid1.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/md/raid1.c	Mon Dec  3 23:18:27 2001
@@ -1690,7 +1690,8 @@
 		}
 	}
 
-	if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN))) {
+	if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN)) &&
+	    (conf->working_disks > 1)) {
 		const char * name = "raid1syncd";
 
 		conf->resync_thread = md_register_thread(raid1syncd, conf,name);
diff -urN linux-2.4.13-pre3/drivers/md/raid5.c linux/drivers/md/raid5.c
--- linux-2.4.13-pre3/drivers/md/raid5.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/md/raid5.c	Mon Dec  3 23:18:27 2001
@@ -487,22 +487,24 @@
 	PRINTK("raid5_error called\n");
 
 	for (i = 0, disk = conf->disks; i < conf->raid_disks; i++, disk++) {
-		if (disk->dev == dev && disk->operational) {
-			disk->operational = 0;
-			mark_disk_faulty(sb->disks+disk->number);
-			mark_disk_nonsync(sb->disks+disk->number);
-			mark_disk_inactive(sb->disks+disk->number);
-			sb->active_disks--;
-			sb->working_disks--;
-			sb->failed_disks++;
-			mddev->sb_dirty = 1;
-			conf->working_disks--;
-			conf->failed_disks++;
-			md_wakeup_thread(conf->thread);
-			printk (KERN_ALERT
-				"raid5: Disk failure on %s, disabling device."
-				" Operation continuing on %d devices\n",
-				partition_name (dev), conf->working_disks);
+		if (disk->dev == dev) {
+			if (disk->operational) {
+				disk->operational = 0;
+				mark_disk_faulty(sb->disks+disk->number);
+				mark_disk_nonsync(sb->disks+disk->number);
+				mark_disk_inactive(sb->disks+disk->number);
+				sb->active_disks--;
+				sb->working_disks--;
+				sb->failed_disks++;
+				mddev->sb_dirty = 1;
+				conf->working_disks--;
+				conf->failed_disks++;
+				md_wakeup_thread(conf->thread);
+				printk (KERN_ALERT
+					"raid5: Disk failure on %s, disabling device."
+					" Operation continuing on %d devices\n",
+					partition_name (dev), conf->working_disks);
+			}
 			return 0;
 		}
 	}
diff -urN linux-2.4.13-pre3/drivers/media/video/bttv-cards.c linux/drivers/media/video/bttv-cards.c
--- linux-2.4.13-pre3/drivers/media/video/bttv-cards.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/bttv-cards.c	Mon Dec  3 23:18:27 2001
@@ -40,6 +40,8 @@
 
 /* fwd decl */
 static void hauppauge_eeprom(struct bttv *btv);
+static void avermedia_eeprom(struct bttv *btv);
+
 static void init_PXC200(struct bttv *btv);
 #if 0
 static void init_tea5757(struct bttv *btv);
@@ -52,6 +54,7 @@
 static void terratv_audio(struct bttv *btv, struct video_audio *v, int set);
 static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set);
 static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set);
+static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set);
 
 /* config variables */
 static int triton1=0;
@@ -71,6 +74,10 @@
 
 /* insmod options */
 MODULE_PARM(triton1,"i");
+MODULE_PARM_DESC(triton1,"set ETBF pci config bit "
+		 "[enable bug compatibility for triton1 + others]");
+MODULE_PARM(vsfx,"i");
+MODULE_PARM_DESC(vsfx,"set VSFX pci config bit [yet another chipset flaw workaround]");
 MODULE_PARM(no_overlay,"i");
 MODULE_PARM(card,"1-4i");
 MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list");
@@ -83,7 +90,6 @@
 MODULE_PARM(gpiomask,"i");
 MODULE_PARM(audioall,"i");
 MODULE_PARM(audiomux,"1-5i");
-MODULE_LICENSE("GPL");
 
 /* kernel args */
 #ifndef MODULE
@@ -127,13 +133,18 @@
 	{ 0x6606107d, BTTV_WINFAST2000,   "Leadtek WinFast TV 2000" },
 	{ 0x263610b4, BTTV_STB2,          "STB TV PCI FM, P/N 6000704" },
  	{ 0x402010fc, BTTV_GVBCTV3PCI,    "I-O Data Co. GV-BCV3/PCI" },
-	{ 0x405010fc, BTTV_GVBCTV3PCI,    "I-O Data Co. GV-BCV4/PCI" },
-	{ 0x001211bd, BTTV_PINNACLE,      "Pinnacle PCTV" },
-	{ 0x3000121a, 0/* no entry yet */,"VoodooTV 200" },
+	{ 0x405010fc, BTTV_GVBCTV4PCI,    "I-O Data Co. GV-BCV4/PCI" },
 
-	{ 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" },
-	{ 0x3002144f, BTTV_MAGICTVIEW061, "Askey Magic TView" },
+	{ 0x1200bd11, BTTV_PINNACLE,      "Pinnacle PCTV" },
+	{ 0x001211bd, BTTV_PINNACLE,      "Pinnacle PCTV" },
+	{ 0x001c11bd, BTTV_PINNACLE,      "Pinnacle PCTV Sat" },
 
+	{ 0x3000121a, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
+	
+	{ 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
+	{ 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
+	{ 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
+	
 	{ 0x00011461, BTTV_AVPHONE98,     "AVerMedia TVPhone98" },
 	{ 0x00021461, BTTV_AVERMEDIA98,   "AVermedia TVCapture 98" },
 	{ 0x00031461, BTTV_AVPHONE98,     "AVerMedia TVPhone98" },
@@ -154,15 +165,15 @@
 	{ 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
 	{ 0x400d15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
 	{ 0x401015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
+	{ 0x401615b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
 
     	{ 0x010115cb, BTTV_GMV1,          "AG GMV1" },
-	{ 0x010114c7, 16 /* FIXME */,     "Modular Technology PCTV" },
-	{ 0x18501851, BTTV_CHRONOS_VS2,   "Chronos Video Shuttle II" },
-	{ 0x18511851, 0 /* FIXME */,      "CyberMail AV" },
-	{ 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" },
+	{ 0x010114c7, BTTV_MODTEC_205,    "Modular Technology PCTV" },
+	{ 0x18501851, BTTV_CHRONOS_VS2,   "Flyvideo 98 (LR50)/ Chronos Video Shuttle II" },
+	{ 0x18511851, BTTV_FLYVIDEO98EZ,  "Flyvideo 98EZ (LR51)/ CyberMail AV" },
+	{ 0x18521852, BTTV_TYPHOON_TVIEW, "Flyvideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
 	{ 0x10b42636, BTTV_HAUPPAUGE878,  "STB ???" },
 	{ 0x217d6606, BTTV_WINFAST2000,   "Leadtek WinFast TV 2000" },
-	{ 0x1200bd11, BTTV_PINNACLE,      "Pinnacle PCTV" },
 
 	{ 0, -1, NULL }
 };
@@ -173,7 +184,7 @@
 struct tvcard bttv_tvcards[] = {
 {
 /* ---- card 0x00 ---------------------------------- */
-	name:		" *** UNKNOWN *** ",
+	name:		" *** UNKNOWN/GENERIC *** ",
 	video_inputs:	4,
 	audio_inputs:	1,
 	tuner:		0,
@@ -192,7 +203,7 @@
 	needs_tvaudio:	1,
 	tuner_type:	-1,
 },{
-	name:		"Hauppauge old",
+	name:		"Hauppauge (bt848)",
 	video_inputs:	4,
 	audio_inputs:	1,
 	tuner:		0,
@@ -265,7 +276,7 @@
 },{
 
 /* ---- card 0x08 ---------------------------------- */
-	name:		"Fly Video II",
+	name:		"Fly Video II (Bt848)",
 	video_inputs:	3,
 	audio_inputs:	1,
 	tuner:		0,
@@ -287,12 +298,12 @@
 	needs_tvaudio:	1,
 	tuner_type:	-1,
 },{
-	name:		"Hauppauge new (bt878)",
+	name:		"Hauppauge (bt878)",
 	video_inputs:	4,
 	audio_inputs:	1,
 	tuner:		0,
 	svhs:		2,
-	gpiomask:	7,
+	gpiomask:	0x0f, /* old: 7 */
 	muxsel:		{ 2, 0, 1, 1},
 	audiomux:	{ 0, 1, 2, 3, 4},
 	needs_tvaudio:	1,
@@ -333,7 +344,7 @@
 	audiomux:	{ 13, 14, 11, 7, 0, 0},
 	needs_tvaudio:	1,
 	pll:		PLL_28,
-	tuner_type:	5,
+	tuner_type:	-1,
 },{
 	name:		"Aimslab VHX",
 	video_inputs:	3,
@@ -452,14 +463,14 @@
 },{
 
 /* ---- card 0x18 ---------------------------------- */
-	name:		"Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)",
+	name:		"[many vendors] CPH05X/06X (bt878)",
 	video_inputs:	3,
 	audio_inputs:	1,
 	tuner:		0,
 	svhs:		2,
 	gpiomask:	0xe00,
 	muxsel:		{ 2, 3, 1, 1},
-	audiomux:	{0x400, 0x400, 0x400, 0x400, 0},
+	audiomux:	{0x400, 0x400, 0x400, 0x400, 0xc00},
 	needs_tvaudio:	1,
 	pll:		PLL_28,
 	tuner_type:	-1,
@@ -528,9 +539,9 @@
 	audio_inputs:	1,
 	tuner:		0,
 	svhs:		2,
-	gpiomask:	0x8dfe00,
+	gpiomask:	0x1800,  //0x8dfe00
 	muxsel:		{2, 3, 1, 1},
-	audiomux:	{ 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 },
+	audiomux:	{ 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 },
 	needs_tvaudio:	1,
 	tuner_type:	-1,
 },{
@@ -582,31 +593,32 @@
 	tuner_type:	-1,
 	audio_hook:	winfast2000_audio,
 },{
-	name:		"Chronos Video Shuttle II",
+	name:		"Flyvideo 98 (LR50Q) / Chronos Video Shuttle II",
 	video_inputs:	3,
 	audio_inputs:	3,
 	tuner:		0,
 	svhs:		2,
 	gpiomask:	0x1800,
 	muxsel:		{ 2, 3, 1, 1},
-	audiomux:	{ 0, 0, 0x1000, 0x1000, 0x0800},
+	audiomux:	{ 0, 0x800, 0x1000, 0x1000, 0x1800},
 	needs_tvaudio:	1,
 	pll:		PLL_28,
 	tuner_type:	-1,
 },{
 
 /* ---- card 0x24 ---------------------------------- */
-	name:		"Typhoon TView TV/FM Tuner",
+	name:		"Flyvideo 98FM (LR50Q) / Typhoon TView TV/FM Tuner",
 	video_inputs:	3,
 	audio_inputs:	3,
 	tuner:		0,
 	svhs:		2,
 	gpiomask:	0x1800,
 	muxsel:		{ 2, 3, 1, 1},
-	audiomux:	{ 0, 0x800, 0, 0, 0x1800, 0 },
+	audiomux:	{ 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
 	needs_tvaudio:	1,
 	pll:		PLL_28,
 	tuner_type:	-1,
+	has_radio:	1,
 },{
 	name:		"PixelView PlayTV pro",
 	video_inputs:	3,
@@ -620,14 +632,14 @@
 	pll:		PLL_28,
 	tuner_type:	-1,
 },{
-	name:		"TView99 CPH063",
+	name:		"TView99 CPH06X",
 	video_inputs:	4,
 	audio_inputs:	1,
 	tuner:		0,
 	svhs:		2,
 	gpiomask:	0x551e00,
 	muxsel:		{ 2, 3, 1, 0},
-	audiomux:	{ 0x551400, 0x551200, 0, 0, 0, 0x551200 },
+	audiomux:	{ 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 },
 	needs_tvaudio:	1,
 	pll:		PLL_28,
 	tuner_type:	-1,
@@ -668,7 +680,8 @@
 	audiomux:	{ 13, 4, 11, 7, 0, 0},
 	needs_tvaudio:	1,
 	pll:		PLL_28,
-	tuner_type:	5,
+	tuner_type:	-1,
+	has_radio:	1,
 },{
 	name:		"ProVideo PV951", /* pic16c54 */
 	video_inputs:	3,
@@ -742,6 +755,7 @@
 	no_msp34xx:	1,
 	pll:		PLL_35,
 	tuner_type:	1,
+	has_radio:	1,
 },{
 
 /* ---- card 0x30 ---------------------------------- */
@@ -770,7 +784,7 @@
 	tuner_type:	TUNER_ALPS_TSHC6_NTSC,
 	audio_hook:	gvbctv3pci_audio,
 },{
-	name:		"Prolink PV-BT878P+4E (PixelView PlayTV PAK)",
+	name:		"Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
 	video_inputs:	4,
 	audio_inputs:	1,
 	tuner:		0,
@@ -810,7 +824,7 @@
 },{
 	/* Claas Langbehn <claas@bigfoot.com>,
 	   Sven Grothklags <sven@upb.de> */
-	name:		"Typhoon TView RDS / FM Stereo",
+	name:		"Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS",
 	video_inputs:	3,
 	audio_inputs:	3,
 	tuner:		0,
@@ -821,13 +835,14 @@
 	needs_tvaudio:	1,
 	pll:		PLL_28,
 	tuner_type:	TUNER_PHILIPS_PAL_I,
+	has_radio:	1,
 },{
 	/* Tim Röstermundt <rosterm@uni-muenster.de>
 	   in de.comp.os.unix.linux.hardware:
 		options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
 		audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
 		options tuner type=5 */
-	name:		"Lifetec LT 9415 TV",
+	name:		"Lifetec LT 9415 TV (LR90 Rev.F)",
 	video_inputs:	4,
 	audio_inputs:	1,
 	tuner:		0,
@@ -841,6 +856,7 @@
 	pll:		PLL_28,
 	tuner_type:	TUNER_PHILIPS_PAL,
 	audio_hook:	lt9415_audio,
+	has_radio:	1,
 },{
 	/* Miguel Angel Alvarez <maacruz@navegalia.com>
 	   old Easy TV BT848 version (model CPH031) */
@@ -866,7 +882,7 @@
 	svhs:           2,
 	gpiomask:       0x1800,
 	muxsel:         { 2, 3, 0, 1},
-	audiomux:       { 0, 0x800, 0, 0, 0x1800, 0 },
+	audiomux:       { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
 	needs_tvaudio:  1,
 	pll:            PLL_28,
 	tuner_type:     5,
@@ -893,7 +909,7 @@
         audio_inputs:   1,
         tuner:          0,
         svhs:           2,
-        gpiomask:       0x0e00,
+        gpiomask:       0xe00,
         muxsel:         { 2, 3, 1, 1},
         audiomux:       { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
         needs_tvaudio:  1,
@@ -1005,7 +1021,93 @@
 	needs_tvaudio:	1,
 	pll:		PLL_28,
 	tuner_type:	TUNER_PHILIPS_PAL,
-}};
+	has_radio:	1,
+},{
+	/* TANAKA Kei <peg00625@nifty.com> */
+	name:           "GV-BCTV4/PCI",
+	video_inputs:   3,
+	audio_inputs:   1,
+	tuner:          0,
+	svhs:           2,
+	gpiomask:       0x010f00,
+	muxsel:         {2, 3, 0, 0},
+	audiomux:       {0x10000, 0, 0x10000, 0, 0, 0},
+	no_msp34xx:     1,
+	pll:            PLL_28,
+	tuner_type:     TUNER_SHARP_2U5JF5540_NTSC,
+	audio_hook:     gvbctv3pci_audio,
+},{
+
+/* ---- card 0x44 ---------------------------------- */
+        name:           "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
+	// try "insmod msp3400 simple=0" if you have
+	// sound problems with this card.
+        video_inputs:   4,
+        audio_inputs:   1,
+        tuner:          0,
+        svhs:           -1,
+        gpiomask:       0x4f8a00,
+	                // 0x100000: 1=MSP enabled (0=disable again)
+			// 0x010000: somehow influences tuner picture quality (?)
+        audiomux:       {0x947fff, 0x987fff,0x947fff,0x947fff},
+                        //tvtuner, radio,   external,internal,mute,stereo
+        muxsel:         { 2, 3 ,0 ,1}, /* tuner, Composit, SVid, Composit-on-Svid-adapter*/
+        tuner_type:     TUNER_MT2032,
+	pll:		PLL_28,
+	has_radio:	1,
+},{
+	/* Philip Blundell <pb@nexus.co.uk> */
+	name:           "Active Imaging AIMMS",
+	video_inputs:   1,
+	audio_inputs:   0,
+	tuner:          -1,
+	tuner_type:     -1,
+	pll:            PLL_28,
+	muxsel:         { 2 },
+	gpiomask:       0
+},{
+        /* Tomasz Pyra <hellfire@sedez.iq.pl> */
+        name:           "PV-BT878P+",
+        video_inputs:   3,
+        audio_inputs:   4,
+        tuner:          0,
+        svhs:           2,
+        gpiomask:       15,
+        muxsel:         { 2, 3, 1, 1},
+        audiomux:       { 0, 0, 11, 7, 13, 0},
+        needs_tvaudio:  1,
+        pll:            PLL_28,
+        tuner_type:     25,
+},{
+	name:		"Flyvideo 98EZ (capture only)",
+	video_inputs:	4,
+	audio_inputs:   0,
+	tuner:		-1,
+	svhs:		2,
+	muxsel:		{ 2, 3, 1, 1}, // AV1, AV2, SVHS, CVid adapter on SVHS
+	pll:		PLL_28,
+	no_msp34xx:	1,
+},{
+
+/* ---- card 0x48 ---------------------------------- */
+	/* Dariusz Kowalewski <darekk@automex.pl> */
+	name:		"Prolink PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)",
+	video_inputs:	3,
+	audio_inputs:	1,
+	tuner:		0,
+	svhs:		2,
+	gpiomask:	0x3f,
+	muxsel:		{ 2, 3, 0, 1 },
+	audiomux:	{ 0x01, 0x00, 0x03, 0x03, 0x09, 0x02 },
+	needs_tvaudio:  1,
+	no_msp34xx:	1,
+	no_tda9875:	1,
+	pll:		PLL_28,
+	tuner_type:	-1,
+	audio_hook:	pvbt878p9b_audio,
+	has_radio:	1,
+}
+};
 
 const int bttv_num_tvcards = (sizeof(bttv_tvcards)/sizeof(struct tvcard));
 
@@ -1036,17 +1138,17 @@
 		
 		if (type != -1) {
 			/* found it */
-			printk(KERN_INFO "bttv%d: subsystem: %04x:%04x  =>  %s  =>  card=%d\n",
-			       btv->nr, btv->cardid & 0xffff, btv->cardid >> 16,
-			       cards[type].name,cards[type].cardnr);
+			printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
+			       "PCI subsystem ID is %04x:%04x\n",
+			       btv->nr,cards[type].name,cards[type].cardnr,
+			       btv->cardid & 0xffff, btv->cardid >> 16);
 			btv->type = cards[type].cardnr;
 		} else {
 			/* 404 */
 			printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n",
 			       btv->nr, btv->cardid&0xffff, btv->cardid>>16);
 			printk(KERN_DEBUG "please mail id, board name and "
-			       "the correct card= insmod option to "
-			       "kraxel@goldbach.in-berlin.de\n");
+			       "the correct card= insmod option to kraxel@bytesex.org\n");
 		}
 	}
 
@@ -1059,7 +1161,8 @@
 		btv->id,
 		(btv->id==848 && btv->revision==0x12) ? "A" : "",
 		bttv_tvcards[btv->type].name);
-	printk(KERN_INFO "bttv%d: model: %s [%s]\n",btv->nr,btv->video_dev.name,
+	printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->nr,
+	       btv->video_dev.name,btv->type,
 	       (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) ?
 	       "insmod option" : "autodetected");
 
@@ -1128,7 +1231,8 @@
 				btv->type = BTTV_PINNACLEPRO;
 		}
 		if (bttv_verbose)
-			printk("bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+			printk(KERN_INFO "bttv%d: miro: id=%d tuner=%d "
+			       "radio=%s stereo=%s\n",
 			       btv->nr, id+1, btv->tuner_type,
 			       !btv->has_radio ? "no" :
 				   (btv->has_matchbox ? "matchbox" : "fmtuner"),
@@ -1148,6 +1252,11 @@
                 hauppauge_eeprom(btv);
         }
 
+	if (btv->type == BTTV_AVERMEDIA98 || btv->type == BTTV_AVPHONE98) {
+		bttv_readee(btv,eeprom_data,0xa0);
+		avermedia_eeprom(btv);
+	}
+
  	if (btv->type == BTTV_PXC200)
 		init_PXC200(btv);
 
@@ -1166,7 +1275,13 @@
 			printk("bttv%d: lifetec: tv mono/fm stereo card\n", btv->nr);
 		else
 			printk("bttv%d: lifetec: stereo(TDA9821) card\n",btv->nr);
-		btv->has_radio=1;
+	}
+
+	if (btv->type == BTTV_MAGICTVIEW061) {
+		if(btv->cardid == 0x4002144f) {
+			btv->has_radio=1;
+			printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->nr);
+		}
 	}
 
 	/* pll configuration */
@@ -1210,6 +1325,9 @@
 	if (btv->tuner_type != -1)
 		bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
 
+	if (bttv_tvcards[btv->type].has_radio)
+		btv->has_radio=1;
+
 	/* try to detect audio/fader chips */
 	if (!bttv_tvcards[btv->type].no_msp34xx &&
 	    bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) {
@@ -1217,7 +1335,8 @@
 			request_module("msp3400");
 	}
 
-	if (bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) {
+	if (!bttv_tvcards[btv->type].no_tda9875 &&
+	    bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) {
 		if (autoload)
 			request_module("tda9875");
 	}
@@ -1307,7 +1426,8 @@
 	int blk2,tuner,radio,model;
 
 	if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0)
-		printk("bttv%d: Hauppauge eeprom: invalid\n",btv->nr);
+		printk(KERN_WARNING "bttv%d: Hauppauge eeprom: invalid\n",
+		       btv->nr);
 
 	/* Block 2 starts after len+3 bytes header */
 	blk2 = eeprom_data[1] + 3;
@@ -1323,24 +1443,83 @@
 		btv->has_radio = 1;
 	
 	if (bttv_verbose)
-		printk("bttv%d: Hauppauge eeprom: model=%d, tuner=%s (%d), radio=%s\n",
+		printk(KERN_INFO "bttv%d: Hauppauge eeprom: model=%d, "
+		       "tuner=%s (%d), radio=%s\n",
 		       btv->nr, model, hauppauge_tuner[tuner].name,
 		       btv->tuner_type, radio ? "yes" : "no");
 }
 
-void __devinit bttv_hauppauge_boot_msp34xx(struct bttv *btv)
+// AVermedia specific stuff...
+// from  bktr_card.c
+int tuner_0_table[] = {
+        TUNER_PHILIPS_NTSC,  TUNER_PHILIPS_PAL,
+        TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL,
+        TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL,
+        TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM,
+        TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL};
+/*
+int tuner_0_fm_table[] = {
+        PHILIPS_FR1236_NTSC,  PHILIPS_FR1216_PAL,
+        PHILIPS_FR1216_PAL,   PHILIPS_FR1216_PAL,
+        PHILIPS_FR1216_PAL,   PHILIPS_FR1216_PAL,
+        PHILIPS_FR1236_SECAM, PHILIPS_FR1236_SECAM,
+        PHILIPS_FR1236_SECAM, PHILIPS_FR1216_PAL};
+*/
+
+int tuner_1_table[] = {
+        TUNER_TEMIC_NTSC,  TUNER_TEMIC_PAL,
+	TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
+	TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
+        TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, //TUNER_TEMIC_SECAM
+        TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
+
+static void __devinit avermedia_eeprom(struct bttv *btv)
 {
-        /* reset/enable the MSP on some Hauppauge cards */
-        /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */
-        btaor(32, ~32, BT848_GPIO_OUT_EN);
-        btaor(0, ~32, BT848_GPIO_DATA);
+        int tuner_make,tuner_tv_fm,tuner_format,tuner=0;
+
+	tuner_make   = (eeprom_data[0x41] & 0x7);
+        tuner_tv_fm  = (eeprom_data[0x41] & 0x18) >> 3;
+        tuner_format = (eeprom_data[0x42] & 0xf0) >> 4;
+
+	if (tuner_make == 0 || tuner_make == 2)
+		if(tuner_format <=9)
+			tuner = tuner_0_table[tuner_format];
+	if (tuner_make == 1)
+		if(tuner_format <=9)
+			tuner = tuner_1_table[tuner_format];
+	
+	printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
+		btv->nr,eeprom_data[0x41],eeprom_data[0x42]);
+	if(tuner) {
+		btv->tuner_type=tuner;
+		printk("%d\n",tuner);
+	} else
+		printk("Unknown type\n");
+}
+
+
+
+/*
+ * reset/enable the MSP on some Hauppauge cards
+ * Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)!
+ *
+ * Hauppauge:  pin  5
+ * Voodoo:     pin 20
+ */
+void __devinit bttv_boot_msp34xx(struct bttv *btv, int pin)
+{
+	int mask = (1 << pin);
+
+        btaor(mask, ~mask, BT848_GPIO_OUT_EN);
+        btaor(0, ~mask, BT848_GPIO_DATA);
         udelay(2500);
-        btaor(32, ~32, BT848_GPIO_DATA);
+        btaor(mask, ~mask, BT848_GPIO_DATA);
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv,"msp34xx");
 
 	if (bttv_verbose)
-		printk("bttv%d: Hauppauge msp34xx: reset line init\n",btv->nr);
+		printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line "
+		       "init [%d]\n", btv->nr, pin);
 }
 
 
@@ -1352,9 +1531,9 @@
 
 static void __devinit init_PXC200(struct bttv *btv)
 {
-	static const int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
-				    0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-				    0x00 };
+	static int vals[] __devinitdata = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
+					    0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+					    0x00 };
 	int i,tmp;
 
 	/* Initialise GPIO-connevted stuff */
@@ -1465,7 +1644,7 @@
 	    BUS_IN(btv->mbox_data) && time_before(jiffies, timeout);
 	    schedule());	/* 10 s */
 	if (BUS_IN(btv->mbox_data)) {
-		printk("bttv%d: tea5757: read timeout\n",btv->nr);
+		printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->nr);
 		return -1;
 	}
 	for(timeout = jiffies + HZ/5;
@@ -1706,6 +1885,43 @@
 	}
 }
 
+/*
+ * Dariusz Kowalewski <darekk@automex.pl>
+ * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
+ * revision 9B has on-board TDA9874A sound decoder).
+ */
+static void
+pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+	unsigned int val = 0;
+
+#if BTTV_VERSION_CODE > KERNEL_VERSION(0,8,0)
+	if (btv->radio_user)
+		return;
+#else
+	if (btv->radio)
+		return;
+#endif
+
+	if (set) {
+		if (v->mode & VIDEO_SOUND_MONO)	{
+			val = 0x01;
+		}
+		if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
+		    || (v->mode & VIDEO_SOUND_STEREO)) {
+			val = 0x02;
+		}
+		if (val) {
+			btaor(val, ~0x03, BT848_GPIO_DATA);
+			if (bttv_gpio)
+				bttv_gpio_tracking(btv,"pvbt878p9b");
+		}
+	} else {
+		v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+			  VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+	}
+}
+
 /* ----------------------------------------------------------------------- */
 /* motherboard chipset specific stuff                                      */
 
@@ -1717,13 +1933,16 @@
 	/* for 2.4.x we'll use the pci quirks (drivers/pci/quirks.c) */
 	if (pci_pci_problems & PCIPCI_FAIL)
 		pcipci_fail = 1;
-
 	if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF))
 		triton1 = 1;
-	while ((dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, dev)))
+	if (pci_pci_problems & PCIPCI_VSFX)
 		vsfx = 1;
 
-	/* print warnings about quirks found */
+	/* print which chipset we have */
+	while ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8,dev)))
+		printk(KERN_INFO "bttv: Host bridge is %s\n",dev->name);
+
+	/* print warnings about any quirks found */
 	if (triton1)
 		printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n");
 	if (vsfx)
diff -urN linux-2.4.13-pre3/drivers/media/video/bttv-driver.c linux/drivers/media/video/bttv-driver.c
--- linux-2.4.13-pre3/drivers/media/video/bttv-driver.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/bttv-driver.c	Mon Dec  3 23:18:27 2001
@@ -104,7 +104,7 @@
 MODULE_PARM(vbi_nr,"i");
 
 MODULE_DESCRIPTION("bttv - v4l driver module for bt848/878 based cards");
-MODULE_AUTHOR("Ralph  Metzler & Marcus Metzler & Gerd Knorr");
+MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
 MODULE_LICENSE("GPL");
 
 /* kernel args */
@@ -209,9 +209,11 @@
 	unsigned long adr, page;
 
 	mem=vmalloc_32(size);
-	if (mem) 
-	{
-		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	if (NULL == mem)
+		printk(KERN_INFO "bttv: vmalloc_32(%ld) failed\n",size);
+	else {
+		/* Clear the ram out, no junk to the user */
+		memset(mem, 0, size);
 	        adr=(unsigned long) mem;
 		while (size > 0) 
                 {
@@ -475,7 +477,13 @@
  	/* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
         { 35468950,
           924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
-          1135, 186, 924, 0x20, 255},
+          1135, 186, 924,
+#ifdef VIDEODAT_HACK
+	  VBI_MAXLINES*2,
+#else
+	  0x20,
+#endif
+	  255},
 
 	/* NTSC */
 	{ 28636363,
@@ -526,7 +534,7 @@
 		       btv->nr,virt_to_bus(po), virt_to_bus(pe));
         
 	*(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0;
-	for (i=0; i<16; i++) 
+	for (i=0; i<VBI_MAXLINES; i++) 
 	{
 		*(po++)=cpu_to_le32(VBI_RISC);
 		*(po++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048));
@@ -535,7 +543,7 @@
 	*(po++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+4));
 
 	*(pe++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(pe++)=0;
-	for (i=16; i<32; i++) 
+	for (i=VBI_MAXLINES; i<VBI_MAXLINES*2; i++) 
 	{
 		*(pe++)=cpu_to_le32(VBI_RISC);
 		*(pe++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048));
@@ -553,23 +561,23 @@
 };
 
 static int palette2fmt[] = {
-       0,
-       BT848_COLOR_FMT_Y8,
-       BT848_COLOR_FMT_RGB8,
-       BT848_COLOR_FMT_RGB16,
-       BT848_COLOR_FMT_RGB24,
-       BT848_COLOR_FMT_RGB32,
-       BT848_COLOR_FMT_RGB15,
-       BT848_COLOR_FMT_YUY2,
-       BT848_COLOR_FMT_BtYUV,
-       -1,
-       -1,
-       -1,
-       BT848_COLOR_FMT_RAW,
-       BT848_COLOR_FMT_YCrCb422,
-       BT848_COLOR_FMT_YCrCb411,
-       BT848_COLOR_FMT_YCrCb422,
-       BT848_COLOR_FMT_YCrCb411,
+	0,
+	BT848_COLOR_FMT_Y8,
+	BT848_COLOR_FMT_RGB8,
+	BT848_COLOR_FMT_RGB16,
+	BT848_COLOR_FMT_RGB24,
+	BT848_COLOR_FMT_RGB32,
+	BT848_COLOR_FMT_RGB15,
+	BT848_COLOR_FMT_YUY2,
+	BT848_COLOR_FMT_YUY2,
+	-1,
+	-1,
+	-1,
+	BT848_COLOR_FMT_RAW,
+	BT848_COLOR_FMT_YCrCb422,
+	BT848_COLOR_FMT_YCrCb411,
+	BT848_COLOR_FMT_YCrCb422,
+	BT848_COLOR_FMT_YCrCb411,
 };
 #define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(int))
 
@@ -2626,7 +2634,9 @@
 
 	/* needs to be done before i2c is registered */
         if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878)
-                bttv_hauppauge_boot_msp34xx(btv);
+                bttv_boot_msp34xx(btv,5);
+	if (btv->type == BTTV_VOODOOTV_FM)
+		bttv_boot_msp34xx(btv,20);
 
 	/* register i2c */
         btv->tuner_type=-1;
diff -urN linux-2.4.13-pre3/drivers/media/video/bttv-if.c linux/drivers/media/video/bttv-if.c
--- linux-2.4.13-pre3/drivers/media/video/bttv-if.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/bttv-if.c	Mon Dec  3 23:18:27 2001
@@ -209,7 +209,8 @@
 	if (btv->tuner_type != -1)
 		bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
         if (bttv_verbose)
-		printk("bttv%d: i2c attach [%s]\n",btv->nr,client->name);
+		printk("bttv%d: i2c attach [client=%s,%s]\n",btv->nr,
+		       client->name, (i < I2C_CLIENTS_MAX) ?  "ok" : "failed");
         return 0;
 }
 
@@ -218,14 +219,15 @@
         struct bttv *btv = (struct bttv*)client->adapter->data;
 	int i;
 
-        if (bttv_verbose)
-		printk("bttv%d: i2c detach [%s]\n",btv->nr,client->name);
 	for (i = 0; i < I2C_CLIENTS_MAX; i++) {
 		if (btv->i2c_clients[i] == client) {
 			btv->i2c_clients[i] = NULL;
 			break;
 		}
 	}
+        if (bttv_verbose)
+		printk("bttv%d: i2c detach [client=%s,%s]\n",btv->nr,
+		       client->name, (i < I2C_CLIENTS_MAX) ?  "ok" : "failed");
         return 0;
 }
 
@@ -351,7 +353,6 @@
 	btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap);
 	return btv->i2c_rc;
 }
-MODULE_LICENSE("GPL");
 
 /*
  * Local variables:
diff -urN linux-2.4.13-pre3/drivers/media/video/bttv.h linux/drivers/media/video/bttv.h
--- linux-2.4.13-pre3/drivers/media/video/bttv.h	Sun Aug  5 13:15:05 2001
+++ linux/drivers/media/video/bttv.h	Mon Dec  3 23:18:27 2001
@@ -81,6 +81,13 @@
 #define BTTV_ATI_TVWONDERVE 0x40
 #define BTTV_FLYVIDEO2000   0x41
 #define BTTV_TERRATVALUER   0x42
+#define BTTV_GVBCTV4PCI     0x43
+#define BTTV_VOODOOTV_FM    0x44
+#define BTTV_AIMMS          0x45
+#define BTTV_PV_BT878P_PLUS 0x46
+#define BTTV_FLYVIDEO98EZ   0x47
+#define BTTV_PV_BT878P_9B   0x48
+
 
 /* i2c address list */
 #define I2C_TSA5522        0xc2
@@ -88,6 +95,7 @@
 #define I2C_TDA8425        0x82
 #define I2C_TDA9840        0x84
 #define I2C_TDA9850        0xb6 /* also used by 9855,9873 */
+#define I2C_TDA9874A       0xb0 /* also used by 9875 */
 #define I2C_TDA9875        0xb0
 #define I2C_HAUPEE         0xa0
 #define I2C_STBEE          0xae
@@ -121,6 +129,7 @@
 
 	/* i2c audio flags */
 	int no_msp34xx:1;
+	int no_tda9875:1;
 	int needs_tvaudio:1;
 
 	/* other settings */
@@ -130,6 +139,7 @@
 #define PLL_35   2
 
 	int tuner_type;
+	int has_radio;
 	void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
 };
 
@@ -142,7 +152,7 @@
 
 /* card-specific funtions */
 extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
-extern void bttv_hauppauge_boot_msp34xx(struct bttv *btv);
+extern void bttv_boot_msp34xx(struct bttv *btv, int pin);
 
 /* kernel cmd line parse helper */
 extern int bttv_parse(char *str, int max, int *vals);
@@ -195,7 +205,7 @@
 extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card);
 
 /* i2c */
-#define I2C_CLIENTS_MAX 8
+#define I2C_CLIENTS_MAX 16
 extern void bttv_bit_setscl(void *data, int state);
 extern void bttv_bit_setsda(void *data, int state);
 extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg);
@@ -205,3 +215,8 @@
 extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
 
 #endif /* _BTTV_H_ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -urN linux-2.4.13-pre3/drivers/media/video/bttvp.h linux/drivers/media/video/bttvp.h
--- linux-2.4.13-pre3/drivers/media/video/bttvp.h	Sun Aug  5 13:15:05 2001
+++ linux/drivers/media/video/bttvp.h	Mon Dec  3 23:18:27 2001
@@ -25,7 +25,7 @@
 #ifndef _BTTVP_H_
 #define _BTTVP_H_
 
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,72)
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,83)
 
 
 #include <linux/types.h>
@@ -62,10 +62,14 @@
 #define O_NONCAP	O_TRUNC
 #endif
 
+#ifdef VIDEODAT_HACK
+# define VBI_MAXLINES   19
+#else
+# define VBI_MAXLINES   16
+#endif
+#define VBIBUF_SIZE     (2048*VBI_MAXLINES*2)
 #define MAX_GBUFFERS	64
 #define RISCMEM_LEN	(32744*2)
-#define VBI_MAXLINES    16
-#define VBIBUF_SIZE     (2048*VBI_MAXLINES*2)
 
 #define BTTV_MAX_FBUF	0x208000
 
diff -urN linux-2.4.13-pre3/drivers/media/video/id.h linux/drivers/media/video/id.h
--- linux-2.4.13-pre3/drivers/media/video/id.h	Sun Nov 12 20:47:19 2000
+++ linux/drivers/media/video/id.h	Mon Dec  3 23:18:27 2001
@@ -24,3 +24,6 @@
 #ifndef  I2C_DRIVERID_TDA7432
 # define I2C_DRIVERID_TDA7432 I2C_DRIVERID_EXP0+6
 #endif
+#ifndef  I2C_DRIVERID_TDA9874A
+# define I2C_DRIVERID_TDA9874A I2C_DRIVERID_EXP0+7
+#endif
diff -urN linux-2.4.13-pre3/drivers/media/video/msp3400.c linux/drivers/media/video/msp3400.c
--- linux-2.4.13-pre3/drivers/media/video/msp3400.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/msp3400.c	Mon Dec  3 23:18:27 2001
@@ -1,7 +1,7 @@
 /*
  * programming the msp34* sound processor family
  *
- * (c) 1997-2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
  *
  * what works and what doesn't:
  *
@@ -97,7 +97,6 @@
 	int nicam_on;
 	int acb;
 	int main, second;	/* sound carrier */
-	int scart;              /* input is scart (extern) */
 
 	int muted;
 	int left, right;	/* volume */
@@ -131,8 +130,10 @@
 MODULE_PARM(simple,"i");
 MODULE_PARM(amsound,"i");
 MODULE_PARM(dolby,"i");
-MODULE_LICENSE("GPL");
 
+MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
 
 /* ---------------------------------------------------------------------- */
 
@@ -231,6 +232,7 @@
 #define MSP_MODE_FM_NICAM2   6
 #define MSP_MODE_AM_NICAM    7
 #define MSP_MODE_BTSC        8
+#define MSP_MODE_EXTERN      9
 
 static struct MSP_INIT_DATA_DEM {
 	int fir1[6];
@@ -443,6 +445,8 @@
 			       msp_init_data[type].dfp_src);
 		msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,
 			       msp_init_data[type].dfp_src);
+		msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,
+			       msp_init_data[type].dfp_src);
 	}
 	msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,
 		       msp_init_data[type].dfp_src);
@@ -507,6 +511,13 @@
 		dprintk("msp3400: BTSC setstereo: %d\n",mode);
 		nicam=0x0300;
 		break;
+	case MSP_MODE_EXTERN:
+		dprintk("msp3400: extern setstereo: %d\n", mode);
+		nicam = 0x0200;
+		break;
+	case MSP_MODE_FM_RADIO:
+		dprintk("msp3400: FM-Radio setstereo: %d\n", mode);
+		break;
 	default:
 		dprintk("msp3400: mono setstereo\n");
 		return;
@@ -537,8 +548,8 @@
 		src = 0x0010 | nicam;
 		break;
 	}
-	if (msp->scart)
-		src |= 0x0200;
+	dprintk("msp3400: setstereo final source/matrix = 0x%x\n", src);
+
 	if (dolby) {
 		msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,0x0520);
 		msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,0x0620);
@@ -727,14 +738,14 @@
 {
 	struct i2c_client *client = data;
 	struct msp3400c *msp = client->data;
-    
+	
 	struct CARRIER_DETECT *cd;
-	int                   count, max1,max2,val1,val2, val,this;
-    
+	int count, max1,max2,val1,val2, val,this;
+	
 #ifdef CONFIG_SMP
 	lock_kernel();
 #endif
-    
+	
 	daemonize();
 	sigfillset(&current->blocked);
 	strcpy(current->comm,"msp3400");
@@ -748,7 +759,7 @@
 	printk("msp3400: daemon started\n");
 	if(msp->notify != NULL)
 		up(msp->notify);
-		
+
 	for (;;) {
 		if (msp->rmmod)
 			goto done;
@@ -760,9 +771,8 @@
 		if (msp->rmmod || signal_pending(current))
 			goto done;
 
-		if (VIDEO_MODE_RADIO == msp->norm)
-			continue;  /* nothing to do */
-		if (msp->scart)
+		if (VIDEO_MODE_RADIO == msp->norm ||
+		    MSP_MODE_EXTERN  == msp->mode)
 			continue;  /* nothing to do */
 	
 		msp->active = 1;
@@ -780,10 +790,9 @@
 			goto done;
 		
 	restart:
-		if (msp->scart)
-			continue;
-		if (VIDEO_MODE_RADIO == msp->norm)
-			continue;
+		if (VIDEO_MODE_RADIO == msp->norm ||
+		    MSP_MODE_EXTERN  == msp->mode)
+			continue;  /* nothing to do */
 		msp->restart = 0;
 		msp3400c_setvolume(client, msp->muted, 0, 0);
 		msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
@@ -1018,7 +1027,7 @@
 		if (msp->rmmod || signal_pending(current))
 			goto done;
 
-		if (msp->scart)
+		if (msp->mode == MSP_MODE_EXTERN)
 			continue;
 		
 		msp->active = 1;
@@ -1036,7 +1045,7 @@
 			goto done;
 
 	restart:
-		if (msp->scart)
+		if (msp->mode == MSP_MODE_EXTERN)
 			continue;
 		msp->restart = 0;
 		del_timer(&msp->wake_stereo);
@@ -1159,6 +1168,8 @@
 			/* scart routing */
 			msp3400c_set_scart(client,SCART_IN2,0);
 			msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0220);
+			msp3400c_write(client,I2C_MSP3400C_DFP, 0x09, 0x0220);
+			msp3400c_write(client,I2C_MSP3400C_DFP, 0x0b, 0x0220);
 			break;
 		case 0x0003:
 			msp->mode   = MSP_MODE_FM_TERRA;
@@ -1353,7 +1364,19 @@
 	return 0;
 }
 
-static int msp_command(struct i2c_client *client,unsigned int cmd, void *arg)
+static void msp_wake_thread(struct i2c_client *client)
+{
+	struct msp3400c *msp  = (struct msp3400c*)client->data;
+
+	msp3400c_setvolume(client,msp->muted,0,0);
+	msp->watch_stereo=0;
+	del_timer(&msp->wake_stereo);
+	if (msp->active)
+		msp->restart = 1;
+	wake_up_interruptible(&msp->wq);
+}
+
+static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
 	struct msp3400c *msp  = (struct msp3400c*)client->data;
         __u16           *sarg = arg;
@@ -1368,21 +1391,24 @@
 		     - IN1 is often used for external input
 		     - Hauppauge uses IN2 for the radio */
 		dprintk(KERN_DEBUG "msp34xx: AUDC_SET_INPUT(%d)\n",*sarg);
-		msp->scart = 0;
 		switch (*sarg) {
 		case AUDIO_RADIO:
+			msp->mode   = MSP_MODE_FM_RADIO;
+			msp->stereo = VIDEO_SOUND_STEREO;
 			msp3400c_set_scart(client,SCART_IN2,0);
 			msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
 			msp3400c_setstereo(client,msp->stereo);
 			break;
 		case AUDIO_EXTERN:
-			msp->scart = 1;
+			msp->mode   = MSP_MODE_EXTERN;
+			msp->stereo = VIDEO_SOUND_STEREO;
 			msp3400c_set_scart(client,SCART_IN1,0);
 			msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
 			msp3400c_setstereo(client,msp->stereo);
 			break;
 		case AUDIO_TUNER:
-			msp3400c_setstereo(client,msp->stereo);
+			msp->mode   = -1;
+			msp_wake_thread(client);
 			break;
 		default:
 			if (*sarg & AUDIO_MUTE)
@@ -1400,8 +1426,7 @@
 		dprintk("msp34xx: switching to radio mode\n");
 		if (msp->simple) {
 			/* the thread will do for us */
-			msp3400c_setvolume(client,msp->muted,0,0);
-			wake_up_interruptible(&msp->wq);
+			msp_wake_thread(client);
 		} else {
 			/* set msp3400 to FM radio mode */
 			msp3400c_setmode(client,MSP_MODE_FM_RADIO);
@@ -1457,6 +1482,8 @@
 			(va->volume ? va->volume : 1);
 		va->balance=(msp->left<msp->right)?
 			(65535-va->balance) : va->balance;
+		if (0 == va->volume)
+			va->balance = 32768;
 		va->bass = msp->bass;
 		va->treble = msp->treble;
 
@@ -1500,12 +1527,7 @@
 	case VIDIOCSFREQ:
 	{
 		/* new channel -- kick audio carrier scan */
-		msp3400c_setvolume(client,msp->muted,0,0);
-		msp->watch_stereo=0;
-		del_timer(&msp->wake_stereo);
-		if (msp->active)
-			msp->restart = 1;
-		wake_up_interruptible(&msp->wq);
+		msp_wake_thread(client);
 		break;
 	}
 
diff -urN linux-2.4.13-pre3/drivers/media/video/tda7432.c linux/drivers/media/video/tda7432.c
--- linux-2.4.13-pre3/drivers/media/video/tda7432.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/tda7432.c	Mon Dec  3 23:18:27 2001
@@ -52,7 +52,6 @@
 MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip");
 MODULE_LICENSE("GPL");
 
-
 MODULE_PARM(debug,"i");
 MODULE_PARM(loudness,"i");
 static int loudness = 0; /* disable loudness by default */
diff -urN linux-2.4.13-pre3/drivers/media/video/tda9875.c linux/drivers/media/video/tda9875.c
--- linux-2.4.13-pre3/drivers/media/video/tda9875.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/tda9875.c	Mon Dec  3 23:18:27 2001
@@ -36,7 +36,6 @@
 MODULE_PARM(debug,"i");
 MODULE_LICENSE("GPL");
 
-
 static int debug = 0;	/* insmod parameter */
 
 /* Addresses to scan */
diff -urN linux-2.4.13-pre3/drivers/media/video/tuner.c linux/drivers/media/video/tuner.c
--- linux-2.4.13-pre3/drivers/media/video/tuner.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/tuner.c	Mon Dec  3 23:18:27 2001
@@ -30,25 +30,29 @@
 	force
 };
 
-static int debug =  0; /* insmod parameter */
-static int type  = -1; /* insmod parameter */
-
+/* insmod options */
+static int debug =  0;
+static int type  = -1;
 static int addr  =  0;
 static char *pal =  "b";
-static int this_adap;
 static int tv_range[2]    = { 44, 958 };
 static int radio_range[2] = { 65, 108 };
-
-#define dprintk     if (debug) printk
-
 MODULE_PARM(debug,"i");
 MODULE_PARM(type,"i");
 MODULE_PARM(addr,"i");
 MODULE_PARM(tv_range,"2i");
 MODULE_PARM(radio_range,"2i");
 MODULE_PARM(pal,"s");
+
+#define optimize_vco 1
+
+MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
 MODULE_LICENSE("GPL");
 
+static int this_adap;
+#define dprintk     if (debug) printk
+
 struct tuner
 {
 	int type;            /* chip type */
@@ -56,12 +60,15 @@
 	int std;
 
 	int radio;
-	int mode;            /* PAL(0)/SECAM(1) mode (PHILIPS_SECAM only) */
+	int mode;            /* current norm for multi-norm tuners */
+	int xogc;	     // only for MT2032
 };
 
 static struct i2c_driver driver;
 static struct i2c_client client_template;
 
+/* ---------------------------------------------------------------------- */
+
 /* tv standard selection for Temic 4046 FM5
    this value takes the low bits of control byte 2
    from datasheet Rev.01, Feb.00 
@@ -154,13 +161,13 @@
 	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
         { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
 	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
-	{ "Temic PAL_I (4006FH5)", TEMIC, PAL_I,
+	{ "Temic PAL_BG (4006FH5)", TEMIC, PAL,
 	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, 
   	{ "Alps TSCH6",Alps,NTSC,
   	  16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
 
   	{ "Temic PAL_DK (4016 FY5)",TEMIC,PAL,
-  	  16*136.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
+  	  16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
   	{ "Philips NTSC_M (MK2)",Philips,NTSC,
   	  16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
         { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I,
@@ -191,7 +198,24 @@
 	{ "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL,
 	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
 	{ "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
-	  16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}
+	  16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
+	{ "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */
+	  16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940},
+
+	{ "Samsung PAL TCPM9091PD27", Samsung, PAL,  /* from sourceforge v3tv */
+          16*169,16*464,0xA0,0x90,0x30,0x8e,623},
+	{ "MT2032 universal", Microtune,PAL|NTSC,
+               0,0,0,0,0,0,0},
+	{ "Temic PAL_BG (4106 FH5)", TEMIC, PAL,
+          16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
+	{ "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL,
+          16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623},
+
+	{ "Temic NTSC (4136 FY5)", TEMIC, NTSC,
+          16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
+        { "LG PAL (newer TAPC series)", LGINNOTEK, PAL,
+          16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623},
+	
 };
 #define TUNERS (sizeof(tuners)/sizeof(struct tunertype))
 
@@ -201,6 +225,11 @@
 {
 	unsigned char byte;
 
+	struct tuner *t = (struct tuner*)c->data;
+
+        if (t->type == TUNER_MT2032)
+		return 0;
+
 	if (1 != i2c_master_recv(c,&byte,1))
 		return 0;
 	return byte;
@@ -241,6 +270,315 @@
         return (tuner_getstatus (c) & TUNER_MODE) >> 3;
 }
 #endif
+// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
+int mt2032_init(struct i2c_client *c)
+{
+        unsigned char buf[21];
+        int ret,xogc,xok=0;
+	struct tuner *t = (struct tuner*)c->data;
+
+        buf[0]=0;
+        ret=i2c_master_send(c,buf,1);
+        i2c_master_recv(c,buf,21);
+
+        printk("MT2032: Companycode=%02x%02x Part=%02x Revision=%02x\n",
+                buf[0x11],buf[0x12],buf[0x13],buf[0x14]);
+
+        if(debug) {
+                int i;
+                printk("MT2032 hexdump:\n");
+                for(i=0;i<21;i++) {
+                        printk(" %02x",buf[i]);
+                        if(((i+1)%8)==0) printk(" ");
+                        if(((i+1)%16)==0) printk("\n ");
+                }
+                printk("\n ");
+        }
+
+        // Initialize Registers per spec.
+        buf[1]=2; // Index to register 2
+        buf[2]=0xff;
+        buf[3]=0x0f;
+        buf[4]=0x1f;
+        ret=i2c_master_send(c,buf+1,4);
+
+        buf[5]=6; // Index register 6
+        buf[6]=0xe4;
+        buf[7]=0x8f;
+        buf[8]=0xc3;
+        buf[9]=0x4e;
+        buf[10]=0xec;
+        ret=i2c_master_send(c,buf+5,6);
+
+        buf[12]=13;  // Index register 13
+        buf[13]=0x32;
+        ret=i2c_master_send(c,buf+12,2);
+
+        // Adjust XOGC (register 7), wait for XOK
+        xogc=7;
+        do {
+		dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07);
+                mdelay(10);
+                buf[0]=0x0e;
+                i2c_master_send(c,buf,1);
+                i2c_master_recv(c,buf,1);
+                xok=buf[0]&0x01;
+                dprintk("mt2032: xok = 0x%02x\n",xok);
+                if (xok == 1) break;
+
+                xogc--;
+                dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07);
+                if (xogc == 3) {
+                        xogc=4; // min. 4 per spec
+                        break;
+                }
+                buf[0]=0x07;
+                buf[1]=0x88 + xogc;
+                ret=i2c_master_send(c,buf,2);
+                if (ret!=2)
+                        printk("mt2032_init failed with %d\n",ret);
+        } while (xok != 1 );
+	t->xogc=xogc;
+
+        return(1);
+}
+
+
+// IsSpurInBand()?
+int mt2032_spurcheck(int f1, int f2, int spectrum_from,int spectrum_to)
+{
+	int n1=1,n2,f;
+
+	f1=f1/1000; //scale to kHz to avoid 32bit overflows
+	f2=f2/1000;
+	spectrum_from/=1000;
+	spectrum_to/=1000;
+
+	dprintk("spurcheck f1=%d f2=%d  from=%d to=%d\n",f1,f2,spectrum_from,spectrum_to);
+
+	do {
+	    n2=-n1;
+	    f=n1*(f1-f2);
+	    do {
+		n2--;
+		f=f-f2;
+		dprintk(" spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
+
+		if( (f>spectrum_from) && (f<spectrum_to))
+			printk("mt2032 spurcheck triggered: %d\n",n1);
+	    } while ( (f>(f2-spectrum_to)) || (n2>-5));
+	    n1++;
+	} while (n1<5);
+
+	return 1;
+}
+
+int mt2032_compute_freq(int rfin, int if1, int if2, int spectrum_from,
+	int spectrum_to, unsigned char *buf, int *ret_sel, int xogc) //all in Hz
+{
+        int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
+		desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
+
+        fref= 5250 *1000; //5.25MHz
+	desired_lo1=rfin+if1;
+
+	lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
+        lo1n=lo1/8;
+        lo1a=lo1-(lo1n*8);
+
+        s=rfin/1000/1000+1090;
+
+	if(optimize_vco) {
+		if(s>1890) sel=0;
+		else if(s>1720) sel=1;
+		else if(s>1530) sel=2;
+		else if(s>1370) sel=3;
+		else sel=4; // >1090
+	}
+	else {
+        	if(s>1790) sel=0; // <1958
+        	else if(s>1617) sel=1;
+        	else if(s>1449) sel=2;
+        	else if(s>1291) sel=3;
+        	else sel=4; // >1090
+	}
+	*ret_sel=sel;
+
+        lo1freq=(lo1a+8*lo1n)*fref;
+
+        dprintk("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
+		rfin,lo1,lo1n,lo1a,sel,lo1freq);
+
+        desired_lo2=lo1freq-rfin-if2;
+        lo2=(desired_lo2)/fref;
+        lo2n=lo2/8;
+        lo2a=lo2-(lo2n*8);
+        lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
+        lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
+
+        dprintk("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
+		rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
+
+        if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
+                printk("mt2032: frequency parameters out of range: %d %d %d %d\n",
+		       lo1a, lo1n, lo2a,lo2n);
+                return(-1);
+        }
+
+	mt2032_spurcheck(lo1freq, desired_lo2,  spectrum_from, spectrum_to);
+	// should recalculate lo1 (one step up/down)
+
+	// set up MT2032 register map for transfer over i2c
+	buf[0]=lo1n-1;
+	buf[1]=lo1a | (sel<<4);
+	buf[2]=0x86; // LOGC
+	buf[3]=0x0f; //reserved
+	buf[4]=0x1f;
+	buf[5]=(lo2n-1) | (lo2a<<5);
+ 	if(rfin >400*1000*1000)
+                buf[6]=0xe4;
+        else
+                buf[6]=0xf4; // set PKEN per rev 1.2 
+	buf[7]=8+xogc;
+	buf[8]=0xc3; //reserved
+	buf[9]=0x4e; //reserved
+	buf[10]=0xec; //reserved
+	buf[11]=(lo2num&0xff);
+	buf[12]=(lo2num>>8) |0x80; // Lo2RST
+
+	return 0;
+}
+
+int mt2032_check_lo_lock(struct i2c_client *c)
+{
+	int try,lock=0;
+	unsigned char buf[2];
+	for(try=0;try<10;try++) {
+		buf[0]=0x0e;
+		i2c_master_send(c,buf,1);
+		i2c_master_recv(c,buf,1);
+		dprintk("mt2032 Reg.E=0x%02x\n",buf[0]);
+		lock=buf[0] &0x06;
+		
+		if (lock==6)
+			break;
+		
+		dprintk("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
+		udelay(1000);
+	}
+        return lock;
+}
+
+int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
+{
+	unsigned char buf[2];
+	int tad1;
+
+	buf[0]=0x0f;
+	i2c_master_send(c,buf,1);
+	i2c_master_recv(c,buf,1);
+	dprintk("mt2032 Reg.F=0x%02x\n",buf[0]);
+	tad1=buf[0]&0x07;
+
+	if(tad1 ==0) return lock;
+	if(tad1 ==1) return lock;
+
+	if(tad1==2) {
+		if(sel==0) 
+			return lock;
+		else sel--;
+	}
+	else {
+		if(sel<4)
+			sel++;
+		else
+			return lock;
+	}
+
+	dprintk("mt2032 optimize_vco: sel=%d\n",sel);
+
+	buf[0]=0x0f;
+	buf[1]=sel;
+        i2c_master_send(c,buf,2);
+	lock=mt2032_check_lo_lock(c);
+	return lock;
+}
+
+
+void mt2032_set_if_freq(struct i2c_client *c,int rfin, int if1, int if2, int from, int to)
+{
+	unsigned char buf[21];
+	int lint_try,ret,sel,lock=0;
+	struct tuner *t = (struct tuner*)c->data;
+
+	dprintk("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",rfin,if1,if2,from,to);
+
+        buf[0]=0;
+        ret=i2c_master_send(c,buf,1);
+        i2c_master_recv(c,buf,21);
+
+	buf[0]=0;
+	ret=mt2032_compute_freq(rfin,if1,if2,from,to,&buf[1],&sel,t->xogc);
+	if (ret<0)
+		return;
+
+        // send only the relevant registers per Rev. 1.2
+        buf[0]=0;
+        ret=i2c_master_send(c,buf,4);
+        buf[5]=5;
+        ret=i2c_master_send(c,buf+5,4);
+        buf[11]=11;
+        ret=i2c_master_send(c,buf+11,3);
+        if(ret!=3)
+                printk("mt2032_set_if_freq failed with %d\n",ret);
+
+	// wait for PLLs to lock (per manual), retry LINT if not.
+	for(lint_try=0; lint_try<2; lint_try++) {
+		lock=mt2032_check_lo_lock(c);
+		
+		if(optimize_vco)
+			lock=mt2032_optimize_vco(c,sel,lock);
+		if(lock==6) break;
+		
+		printk("mt2032: re-init PLLs by LINT\n"); 
+		buf[0]=7; 
+		buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs
+		i2c_master_send(c,buf,2);
+		mdelay(10);
+		buf[1]=8+t->xogc;
+		i2c_master_send(c,buf,2);
+        }
+
+	if (lock!=6)
+		printk("MT2032 Fatal Error: PLLs didn't lock.\n");
+
+	buf[0]=2;
+	buf[1]=0x20; // LOGC for optimal phase noise
+	ret=i2c_master_send(c,buf,2);
+	if (ret!=2)
+		printk("mt2032_set_if_freq2 failed with %d\n",ret);
+}
+
+
+void mt2032_set_tv_freq(struct i2c_client *c, int freq, int norm)
+{
+	int if2,from,to;
+
+	// signal bandwidth and picture carrier
+	if(norm==VIDEO_MODE_NTSC) {
+		from=40750*1000;
+		to=46750*1000;
+		if2=45750*1000; 
+	}
+	else {  // Pal 
+		from=32900*1000;
+		to=39900*1000;
+		if2=38900*1000;
+	}
+
+        mt2032_set_if_freq(c,freq* 1000*1000/16, 1090*1000*1000, if2, from, to);
+}
+
 
 // Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz
 static void set_tv_freq(struct i2c_client *c, int freq)
@@ -252,6 +590,15 @@
         unsigned char buffer[4];
 	int rc;
 
+	if (t->type == -1) {
+		printk("tuner: tuner type not set\n");
+		return;
+	}
+	if (t->type == TUNER_MT2032) {
+		mt2032_set_tv_freq(c,freq,t->mode);
+		return;
+	}
+
 	if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
 		/* FIXME: better do that chip-specific, but
 		   right now we don't have that in the config
@@ -259,10 +606,6 @@
 		   check at all */
 		printk("tuner: TV freq (%d.%02d) out of range (%d-%d)\n",
 		       freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
-	}
-
-	if (t->type == -1) {
-		printk("tuner: tuner type not set\n");
 		return;
 	}
 
@@ -282,7 +625,7 @@
 		/* 0x02 -> PAL BDGHI / SECAM L */
 		/* 0x04 -> ??? PAL others / SECAM others ??? */
 		config &= ~0x02;
-		if (t->mode)
+		if (t->mode == VIDEO_MODE_SECAM)
 			config |= 0x02;
 		break;
 
@@ -366,6 +709,15 @@
 
 }
 
+static void mt2032_set_radio_freq(struct i2c_client *c,int freq)
+{               
+        int if2;
+
+        if2=10700*1000; //  10.7MHz FM intermediate frequency
+
+        mt2032_set_if_freq(c,freq* 1000*1000/16, 1085*1000*1000,if2,if2,if2);
+}
+
 static void set_radio_freq(struct i2c_client *c, int freq)
 {
 	u8 config;
@@ -386,6 +738,11 @@
 		return;
 	}
 
+        if (t->type == TUNER_MT2032) {
+                mt2032_set_radio_freq(c,freq);
+		return;
+	}
+
 	tun=&tuners[t->type];
 	config = 0xa4 /* 0xa5 */; /* bit 0 is AFC (set) vs. RF-Signal (clear) */
 	div=freq + (int)(16*10.7);
@@ -448,6 +805,9 @@
 		t->type = -1;
 	}
         i2c_attach_client(client);
+        if (t->type == TUNER_MT2032)
+                 mt2032_init(client);
+
 	MOD_INC_USE_COUNT;
 
 	return 0;
@@ -497,6 +857,8 @@
 		dprintk("tuner: type set to %d (%s)\n",
                         t->type,tuners[t->type].name);
 		strncpy(client->name, tuners[t->type].name, sizeof(client->name));
+		if (t->type == TUNER_MT2032)
+                        mt2032_init(client);
 		break;
 	case AUDC_SET_RADIO:
 		t->radio = 1;
@@ -508,12 +870,11 @@
 	case VIDIOCSCHAN:
 	{
 		struct video_channel *vc = arg;
-		
+
 		t->radio = 0;
-		if (t->type == TUNER_PHILIPS_SECAM) {
-			t->mode = (vc->norm == VIDEO_MODE_SECAM) ? 1 : 0;
+		t->mode = vc->norm;
+		if (t->freq)
 			set_tv_freq(client,t->freq);
-		}
 		return 0;
 	}
 	case VIDIOCSFREQ:
diff -urN linux-2.4.13-pre3/drivers/media/video/tuner.h linux/drivers/media/video/tuner.h
--- linux-2.4.13-pre3/drivers/media/video/tuner.h	Sun Aug  5 13:15:05 2001
+++ linux/drivers/media/video/tuner.h	Mon Dec  3 23:18:27 2001
@@ -22,29 +22,29 @@
 #ifndef _TUNER_H
 #define _TUNER_H
 
-#define TUNER_TEMIC_PAL     0        /* 4002 FH5_9483 */
+#define TUNER_TEMIC_PAL     0        /* 4002 FH5 (3X 7756, 9483) */
 #define TUNER_PHILIPS_PAL_I 1
 #define TUNER_PHILIPS_NTSC  2
 #define TUNER_PHILIPS_SECAM 3		/* you must actively select B/G, L, L` */
 #define TUNER_ABSENT        4
 #define TUNER_PHILIPS_PAL   5
-#define TUNER_TEMIC_NTSC    6        /* 4032 FY5_7004 */
-#define TUNER_TEMIC_PAL_I   7        /* 4062 FY5_9957 */
-#define TUNER_TEMIC_4036FY5_NTSC 8   /* 4036 FY5      */
+#define TUNER_TEMIC_NTSC    6        /* 4032 FY5 (3X 7004, 9498, 9789)  */
+#define TUNER_TEMIC_PAL_I   7        /* 4062 FY5 (3X 8501, 9957)        */
+#define TUNER_TEMIC_4036FY5_NTSC 8   /* 4036 FY5 (3X 1223, 1981, 7686)  */
 #define TUNER_ALPS_TSBH1_NTSC 	 9
 #define TUNER_ALPS_TSBE1_PAL 	10
 #define TUNER_ALPS_TSBB5_PAL_I 	11
 #define TUNER_ALPS_TSBE5_PAL 	12
 #define TUNER_ALPS_TSBC5_PAL 	13
-#define TUNER_TEMIC_4006FH5_PAL	14   /* 4006 FH5      */
+#define TUNER_TEMIC_4006FH5_PAL	14   /* 4006 FH5 (3X 9500, 9501, 7291)     */
 #define TUNER_ALPS_TSHC6_NTSC 	15
-#define TUNER_TEMIC_PAL_DK	16   /* 4016 FY5      */
+#define TUNER_TEMIC_PAL_DK	16   /* 4016 FY5 (3X 1392, 1393)     */
 #define TUNER_PHILIPS_NTSC_M	17
-#define TUNER_TEMIC_4066FY5_PAL_I       18
-#define TUNER_TEMIC_4006FN5_MULTI_PAL   19  /* B/G, I and D/K autodetected */
-#define TUNER_TEMIC_4009FR5_PAL         20  /* incl. FM radio */
-#define TUNER_TEMIC_4039FR5_NTSC        21  /* incl. FM radio */
-#define TUNER_TEMIC_4046FM5             22  /* you must actively select B/G, D/K, I, L, L` !  */
+#define TUNER_TEMIC_4066FY5_PAL_I       18  /* 4066 FY5 (3X 7032, 7035) */
+#define TUNER_TEMIC_4006FN5_MULTI_PAL   19  /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/
+#define TUNER_TEMIC_4009FR5_PAL         20  /* incl. FM radio (3X 7607, 7488, 7711)*/
+#define TUNER_TEMIC_4039FR5_NTSC        21  /* incl. FM radio (3X 7246, 7578, 7732)*/
+#define TUNER_TEMIC_4046FM5             22  /* you must actively select B/G, D/K, I, L, L` !  (3X 7804, 7806, 8103, 8104)*/
 #define TUNER_PHILIPS_PAL_DK		23
 #define TUNER_PHILIPS_FQ1216ME		24  /* you must actively select B/G/D/K, I, L, L` */
 #define TUNER_LG_PAL_I_FM	25
@@ -52,7 +52,15 @@
 #define TUNER_LG_NTSC_FM	27
 #define TUNER_LG_PAL_FM		28
 #define TUNER_LG_PAL		29
-#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM	30  /* B/G, I and D/K autodetected */
+#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM	30  /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/
+#define TUNER_SHARP_2U5JF5540_NTSC  31
+#define TUNER_Samsung_PAL_TCPM9091PD27 32
+#define TUNER_MT2032 33
+#define TUNER_TEMIC_4106FH5 	34	/* 4106 FH5 (3X 7808, 7865)*/
+#define TUNER_TEMIC_4012FY5	35	/* 4012 FY5 (3X 0971, 1099)*/
+#define TUNER_TEMIC_4136FY5	36	/* 4136 FY5 (3X 7708, 7746)*/
+#define TUNER_LG_PAL_NEW_TAPC   37
+
 
 
 #define NOTUNER 0
@@ -67,6 +75,9 @@
 #define Sony    3
 #define Alps    4
 #define LGINNOTEK 5
+#define SHARP   6
+#define Samsung 7
+#define Microtune 8
 
 #define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
 #define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
diff -urN linux-2.4.13-pre3/drivers/media/video/tvaudio.c linux/drivers/media/video/tvaudio.c
--- linux-2.4.13-pre3/drivers/media/video/tvaudio.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/tvaudio.c	Mon Dec  3 23:18:27 2001
@@ -42,6 +42,9 @@
 
 #define dprintk  if (debug) printk
 
+MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
+MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr");
+MODULE_LICENSE("GPL");
 
 /* ---------------------------------------------------------------------- */
 /* our structs                                                            */
@@ -51,6 +54,7 @@
 struct CHIPSTATE;
 typedef int  (*getvalue)(int);
 typedef int  (*checkit)(struct CHIPSTATE*);
+typedef int  (*initialize)(struct CHIPSTATE*);
 typedef int  (*getmode)(struct CHIPSTATE*);
 typedef void (*setmode)(struct CHIPSTATE*, int mode);
 typedef void (*checkmode)(struct CHIPSTATE*);
@@ -70,6 +74,7 @@
 
 	int        *insmodopt;
 	checkit    checkit;
+	initialize initialize;
 	int        flags;
 #define CHIP_HAS_VOLUME      1
 #define CHIP_HAS_BASSTREBLE  2
@@ -134,6 +139,7 @@
 	I2C_TDA9840   >> 1,
 	I2C_TDA985x_L >> 1,
 	I2C_TDA985x_H >> 1,
+	I2C_TDA9874A  >> 1,
 	I2C_PIC16C54  >> 1,
 	I2C_CLIENT_END };
 static unsigned short normal_i2c_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
@@ -216,7 +222,7 @@
                 { chip->c.addr, 0,        1, write },
                 { chip->c.addr, I2C_M_RD, 1, read  }
         };
-        write[1] = subaddr;
+        write[0] = subaddr;
 
 	if (2 != i2c_transfer(chip->c.adapter,msgs,2)) {
 		printk(KERN_WARNING "%s: I/O error (read2)\n",
@@ -323,6 +329,8 @@
 
 	if (mode & VIDEO_SOUND_LANG1)
 		desc->setmode(chip,VIDEO_SOUND_LANG1);
+	else if (mode & VIDEO_SOUND_LANG2)
+		desc->setmode(chip,VIDEO_SOUND_LANG2);
 	else if (mode & VIDEO_SOUND_STEREO)
 		desc->setmode(chip,VIDEO_SOUND_STEREO);
 	else
@@ -695,6 +703,7 @@
 		return;
 	}
 
+	chip_write(chip, TDA9873_SW, sw_data);
 	dprintk("tda9873_setmode(): req. mode %d; chip_write: %d\n",
 		mode, sw_data);
 }
@@ -710,6 +719,181 @@
 
 
 /* ---------------------------------------------------------------------- */
+/* audio chip description - defines+functions for tda9874a                */
+/* Dariusz Kowalewski <darekk@automex.pl>                                 */
+
+/* Subaddresses for TDA9874A (slave rx) */
+#define TDA9874A_AGCGR		0x00	/* AGC gain */
+#define TDA9874A_GCONR		0x01	/* general config */
+#define TDA9874A_MSR		0x02	/* monitor select */
+#define TDA9874A_C1FRA		0x03	/* carrier 1 freq. */
+#define TDA9874A_C1FRB		0x04	/* carrier 1 freq. */
+#define TDA9874A_C1FRC		0x05	/* carrier 1 freq. */
+#define TDA9874A_C2FRA		0x06	/* carrier 2 freq. */
+#define TDA9874A_C2FRB		0x07	/* carrier 2 freq. */
+#define TDA9874A_C2FRC		0x08	/* carrier 2 freq. */
+#define TDA9874A_DCR		0x09	/* demodulator config */
+#define TDA9874A_FMER		0x0a	/* FM de-emphasis */
+#define TDA9874A_FMMR		0x0b	/* FM dematrix */
+#define TDA9874A_C1OLAR		0x0c	/* ch.1 output level adj. */
+#define TDA9874A_C2OLAR		0x0d	/* ch.2 output level adj. */
+#define TDA9874A_NCONR		0x0e	/* NICAM config */
+#define TDA9874A_NOLAR		0x0f	/* NICAM output level adj. */
+#define TDA9874A_NLELR		0x10	/* NICAM lower error limit */
+#define TDA9874A_NUELR		0x11	/* NICAM upper error limit */
+#define TDA9874A_AMCONR		0x12	/* audio mute control */
+#define TDA9874A_SDACOSR	0x13	/* stereo DAC output select */
+#define TDA9874A_AOSR		0x14	/* analog output select */
+#define TDA9874A_DAICONR	0x15	/* digital audio interface config */
+#define TDA9874A_I2SOSR		0x16	/* I2S-bus output select */
+#define TDA9874A_I2SOLAR	0x17	/* I2S-bus output level adj. */
+#define TDA9874A_MDACOSR	0x18	/* mono DAC output select */
+#define TDA9874A_ESP		0xFF	/* easy standard progr. */
+
+/* Subaddresses for TDA9874A (slave tx) */
+#define TDA9874A_DSR		0x00	/* device status */
+#define TDA9874A_NSR		0x01	/* NICAM status */
+#define TDA9874A_NECR		0x02	/* NICAM error count */
+#define TDA9874A_DR1		0x03	/* add. data LSB */
+#define TDA9874A_DR2		0x04	/* add. data MSB */
+#define TDA9874A_LLRA		0x05	/* monitor level read-out LSB */
+#define TDA9874A_LLRB		0x06	/* monitor level read-out MSB */
+#define TDA9874A_SIFLR		0x07	/* SIF level */
+#define TDA9874A_TR2		252	/* test reg. 2 */
+#define TDA9874A_TR1		253	/* test reg. 1 */
+#define TDA9874A_DIC		254	/* device id. code */
+#define TDA9874A_SIC		255	/* software id. code */
+
+
+static int tda9874a_mode = 1;		/* 0: A2, 1: NICAM */
+static int tda9874a_GCONR = 0xc0;	/* default config. input pin: SIFSEL=0 */
+static int tda9874a_ESP = 0x07;		/* default standard: NICAM D/K */
+
+/* insmod options for tda9874a */
+static int tda9874a_SIF = -1;
+static int tda9874a_STD = -1;
+MODULE_PARM(tda9874a_SIF,"i");
+MODULE_PARM(tda9874a_STD,"i");
+
+
+static int tda9874a_setup(struct CHIPSTATE *chip)
+{
+	chip_write(chip, TDA9874A_AGCGR, 0x00); /* 0 dB */
+	chip_write(chip, TDA9874A_GCONR, tda9874a_GCONR);
+	chip_write(chip, TDA9874A_MSR, (tda9874a_mode) ? 0x03:0x02);
+	chip_write(chip, TDA9874A_FMMR, 0x80);
+	chip_write(chip, TDA9874A_C1OLAR, 0x00); /* 0 dB */
+	chip_write(chip, TDA9874A_C2OLAR, 0x00); /* 0 dB */
+	chip_write(chip, TDA9874A_NCONR, 0x00); /* not 0x04 as doc. table 10 says! */
+	chip_write(chip, TDA9874A_NOLAR, 0x00); /* 0 dB */
+	chip_write(chip, TDA9874A_AMCONR, 0xf9);
+	chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80); /* 0x81 */
+	chip_write(chip, TDA9874A_AOSR, 0x80);
+	chip_write(chip, TDA9874A_MDACOSR, (tda9874a_mode) ? 0x82:0x80);
+	chip_write(chip, TDA9874A_ESP, tda9874a_ESP);
+
+	return 1;
+}
+
+int tda9874a_getmode(struct CHIPSTATE *chip)
+{
+	int dsr,nsr,mode;
+
+	mode = VIDEO_SOUND_MONO;
+
+	if(-1 == (dsr = chip_read2(chip,TDA9874A_DSR)))
+		return mode;
+	if(-1 == (nsr = chip_read2(chip,TDA9874A_NSR)))
+		return mode;
+
+	if(tda9874a_mode) {
+		/* check also DSR.RSSF and DSR.AMSTAT bits? */
+		if(nsr & 0x02) /* NSR.S/MB */
+			mode |= VIDEO_SOUND_STEREO;
+		if(nsr & 0x01) /* NSR.D/SB */ 
+			mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+	} else {
+		if(dsr & 0x02) /* DSR.IDSTE */
+			mode |= VIDEO_SOUND_STEREO;
+		if(dsr & 0x04) /* DSR.IDDUA */
+			mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+	}
+
+	dprintk("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, return: %d.\n",
+		 dsr, nsr, mode);
+	return mode;
+}
+
+void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
+{
+	int aosr=0x80,mdacosr=0x82;
+
+	/* note: TDA9874A has auto-select function for audio output */
+	switch(mode) {
+	case VIDEO_SOUND_MONO:
+	case VIDEO_SOUND_STEREO:
+		break;
+	case VIDEO_SOUND_LANG1:
+		aosr = 0x80; /* dual A/A */
+		mdacosr = (tda9874a_mode) ? 0x82:0x80;
+		break;
+	case VIDEO_SOUND_LANG2:
+		aosr = 0xa0; /* dual B/B */
+		mdacosr = (tda9874a_mode) ? 0x83:0x81;
+		break;
+	default:
+		chip->mode = 0;
+		return;
+	}
+
+	chip_write(chip, TDA9874A_AOSR, aosr);
+	chip_write(chip, TDA9874A_MDACOSR, mdacosr);
+
+	dprintk("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
+		mode, aosr, mdacosr);
+}
+
+int tda9874a_checkit(struct CHIPSTATE *chip)
+{
+	int dic,sic;	/* device id. and software id. codes */
+
+	if(-1 == (dic = chip_read2(chip,TDA9874A_DIC)))
+		return 0;
+	if(-1 == (sic = chip_read2(chip,TDA9874A_SIC)))
+		return 0;
+
+	dprintk("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
+
+	return((dic & 0xff) == 0x11);
+}
+
+int tda9874a_initialize(struct CHIPSTATE *chip)
+{
+	if(tda9874a_SIF != -1) {
+		if(tda9874a_SIF == 1)
+			tda9874a_GCONR = 0xc0;	/* sound IF input 1 */
+		else if(tda9874a_SIF == 2)
+			tda9874a_GCONR = 0xc1;	/* sound IF input 2 */
+		else
+			printk(KERN_WARNING "tda9874a: SIF parameter must be 1 or 2.\n");
+	}
+
+	if(tda9874a_STD != -1) {
+		if((tda9874a_STD >= 0)&&(tda9874a_STD <= 8)) {
+			tda9874a_ESP = tda9874a_STD;
+			tda9874a_mode = (tda9874a_STD < 5) ? 0 : 1;
+		} else {
+			printk(KERN_WARNING "tda9874a: STD parameter must be between 0 and 8.\n");
+		}
+	}
+
+	tda9874a_setup(chip);
+
+	return 0;
+}
+
+
+/* ---------------------------------------------------------------------- */
 /* audio chip descriptions - defines+functions for tea6420                */
 
 #define TEA6300_VL         0x00  /* volume left */
@@ -779,6 +963,7 @@
 int tda9850  = 1;
 int tda9855  = 1;
 int tda9873  = 1;
+int tda9874a = 1;
 int tea6300  = 0;
 int tea6420  = 1;
 int pic16c54 = 1;
@@ -787,6 +972,7 @@
 MODULE_PARM(tda9850,"i");
 MODULE_PARM(tda9855,"i");
 MODULE_PARM(tda9873,"i");
+MODULE_PARM(tda9874a,"i");
 MODULE_PARM(tea6300,"i");
 MODULE_PARM(tea6420,"i");
 MODULE_PARM(pic16c54,"i");
@@ -829,6 +1015,19 @@
 		
 	},
 	{
+		name:       "tda9874a",
+		id:         I2C_DRIVERID_TDA9874A,
+		checkit:    tda9874a_checkit,
+		initialize: tda9874a_initialize,
+		insmodopt:  &tda9874a,
+		addr_lo:    I2C_TDA9874A >> 1,
+		addr_hi:    I2C_TDA9874A >> 1,
+
+		getmode:    tda9874a_getmode,
+		setmode:    tda9874a_setmode,
+		checkmode:  generic_checkmode,
+	},
+	{
 		name:       "tda9850",
 		id:         I2C_DRIVERID_TDA9850,
 		insmodopt:  &tda9850,
@@ -991,7 +1190,11 @@
 	i2c_attach_client(&chip->c);
 
 	/* initialization  */
-	chip_cmd(chip,"init",&desc->init);
+	if (desc->initialize != NULL)
+		desc->initialize(chip);
+	else
+		chip_cmd(chip,"init",&desc->init);
+
 	if (desc->flags & CHIP_HAS_VOLUME) {
 		chip->left   = desc->leftinit   ? desc->leftinit   : 65536;
 		chip->right  = desc->rightinit  ? desc->rightinit  : 65536;
@@ -1168,7 +1371,6 @@
 
 module_init(audiochip_init_module);
 module_exit(audiochip_cleanup_module);
-MODULE_LICENSE("GPL");
 
 /*
  * Local variables:
diff -urN linux-2.4.13-pre3/drivers/media/video/tvaudio.h linux/drivers/media/video/tvaudio.h
--- linux-2.4.13-pre3/drivers/media/video/tvaudio.h	Sun Nov 12 20:47:19 2000
+++ linux/drivers/media/video/tvaudio.h	Mon Dec  3 23:18:27 2001
@@ -6,6 +6,7 @@
 #define I2C_TDA9840        0x84
 #define I2C_TDA985x_L      0xb4 /* also used by 9873 */
 #define I2C_TDA985x_H      0xb6
+#define I2C_TDA9874A       0xb0 /* also used by 9875 */
 
 #define I2C_TEA6300        0x80
 #define I2C_TEA6420	   0x98
diff -urN linux-2.4.13-pre3/drivers/media/video/tvmixer.c linux/drivers/media/video/tvmixer.c
--- linux-2.4.13-pre3/drivers/media/video/tvmixer.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/tvmixer.c	Mon Dec  3 23:18:27 2001
@@ -26,6 +26,9 @@
 MODULE_PARM(debug,"i");
 MODULE_PARM(devnr,"i");
 
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
 /* ----------------------------------------------------------------------- */
 
 struct TVMIXER {
@@ -39,27 +42,6 @@
 static int tvmixer_adapters(struct i2c_adapter *adap);
 static int tvmixer_clients(struct i2c_client *client);
 
-static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int tvmixer_open(struct inode *inode, struct file *file);
-static int tvmixer_release(struct inode *inode, struct file *file);
-
-
-static struct i2c_driver driver = {
-	name:            "tv card mixer driver",
-        id:              I2C_DRIVERID_TVMIXER,
-	flags:           I2C_DF_DUMMY,
-        attach_adapter:  tvmixer_adapters,
-        detach_client:   tvmixer_clients,
-};
-
-static struct file_operations tvmixer_fops = {
-	owner:		THIS_MODULE,
-	llseek:         no_llseek,
-	ioctl:          tvmixer_ioctl,
-	open:           tvmixer_open,
-	release:        tvmixer_release,
-};
-
 /* ----------------------------------------------------------------------- */
 
 static int mix_to_v4l(int i)
@@ -232,6 +214,23 @@
 	return 0;
 }
 
+
+static struct i2c_driver driver = {
+	name:            "tv card mixer driver",
+        id:              I2C_DRIVERID_TVMIXER,
+	flags:           I2C_DF_DUMMY,
+        attach_adapter:  tvmixer_adapters,
+        detach_client:   tvmixer_clients,
+};
+
+static struct file_operations tvmixer_fops = {
+	owner:		THIS_MODULE,
+	llseek:         no_llseek,
+	ioctl:          tvmixer_ioctl,
+	open:           tvmixer_open,
+	release:        tvmixer_release,
+};
+
 /* ----------------------------------------------------------------------- */
 
 static int tvmixer_adapters(struct i2c_adapter *adap)
@@ -355,4 +354,3 @@
  * c-basic-offset: 8
  * End:
  */
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.13-pre3/drivers/net/a2065.c linux/drivers/net/a2065.c
--- linux-2.4.13-pre3/drivers/net/a2065.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/a2065.c	Mon Dec  3 23:18:27 2001
@@ -837,3 +837,4 @@
 
 module_init(a2065_probe);
 module_exit(a2065_cleanup);
+MODULE_LICENSE("GPL");
diff -urN linux-2.4.13-pre3/drivers/net/atari_bionet.c linux/drivers/net/atari_bionet.c
--- linux-2.4.13-pre3/drivers/net/atari_bionet.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/atari_bionet.c	Mon Dec  3 23:18:27 2001
@@ -128,6 +128,7 @@
 unsigned int bionet_debug = NET_DEBUG;
 MODULE_PARM(bionet_debug, "i");
 MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)");
+MODULE_LICENSE("GPL");
 
 static unsigned int bionet_min_poll_time = 2;
 
diff -urN linux-2.4.13-pre3/drivers/net/atari_pamsnet.c linux/drivers/net/atari_pamsnet.c
--- linux-2.4.13-pre3/drivers/net/atari_pamsnet.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/atari_pamsnet.c	Mon Dec  3 23:18:27 2001
@@ -124,6 +124,7 @@
 unsigned int pamsnet_debug = NET_DEBUG;
 MODULE_PARM(pamsnet_debug, "i");
 MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)");
+MODULE_LICENSE("GPL");
 
 static unsigned int pamsnet_min_poll_time = 2;
 
diff -urN linux-2.4.13-pre3/drivers/net/atarilance.c linux/drivers/net/atarilance.c
--- linux-2.4.13-pre3/drivers/net/atarilance.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/atarilance.c	Mon Dec  3 23:18:27 2001
@@ -84,6 +84,7 @@
 #endif
 MODULE_PARM(lance_debug, "i");
 MODULE_PARM_DESC(lance_debug, "atarilance debug level (0-3)");
+MODULE_LICENSE("GPL");
 
 /* Print debug messages on probing? */
 #undef LANCE_DEBUG_PROBE
diff -urN linux-2.4.13-pre3/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c
--- linux-2.4.13-pre3/drivers/net/bagetlance.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/bagetlance.c	Mon Dec  3 23:18:27 2001
@@ -60,6 +60,7 @@
 #endif
 MODULE_PARM(lance_debug, "i");
 MODULE_PARM_DESC(lance_debug, "Lance debug level (0-3)");
+MODULE_LICENSE("GPL");
 
 /* Print debug messages on probing? */
 #undef LANCE_DEBUG_PROBE
diff -urN linux-2.4.13-pre3/drivers/net/bmac.c linux/drivers/net/bmac.c
--- linux-2.4.13-pre3/drivers/net/bmac.c	Tue Sep 18 14:23:14 2001
+++ linux/drivers/net/bmac.c	Mon Dec  3 23:18:27 2001
@@ -1658,6 +1658,7 @@
 
 MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
 MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
+MODULE_LICENSE("GPL");
 
 
 static void __exit bmac_cleanup (void)
diff -urN linux-2.4.13-pre3/drivers/net/fealnx.c linux/drivers/net/fealnx.c
--- linux-2.4.13-pre3/drivers/net/fealnx.c	Fri Sep 14 14:40:00 2001
+++ linux/drivers/net/fealnx.c	Mon Dec  3 23:18:27 2001
@@ -109,6 +109,7 @@
 
 MODULE_AUTHOR("Myson or whoever");
 MODULE_DESCRIPTION("Myson MTD-8xx 100/10M Ethernet PCI Adapter Driver");
+MODULE_LICENSE("GPL");
 MODULE_PARM(max_interrupt_work, "i");
 //MODULE_PARM(min_pci_latency, "i");
 MODULE_PARM(debug, "i");
diff -urN linux-2.4.13-pre3/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c
--- linux-2.4.13-pre3/drivers/net/fmv18x.c	Tue Jul 17 18:53:55 2001
+++ linux/drivers/net/fmv18x.c	Mon Dec  3 23:18:27 2001
@@ -632,6 +632,7 @@
 MODULE_PARM_DESC(io, "FMV-18X I/O address");
 MODULE_PARM_DESC(irq, "FMV-18X IRQ number");
 MODULE_PARM_DESC(net_debug, "FMV-18X debug level (0-1,5-6)");
+MODULE_LICENSE("GPL");
 
 int init_module(void)
 {
diff -urN linux-2.4.13-pre3/drivers/net/gmac.c linux/drivers/net/gmac.c
--- linux-2.4.13-pre3/drivers/net/gmac.c	Tue Sep 18 14:23:14 2001
+++ linux/drivers/net/gmac.c	Mon Dec  3 23:18:27 2001
@@ -1676,6 +1676,7 @@
 
 MODULE_AUTHOR("Paul Mackerras/Ben Herrenschmidt");
 MODULE_DESCRIPTION("PowerMac GMAC driver.");
+MODULE_LICENSE("GPL");
 
 static void __exit gmac_cleanup_module(void)
 {
diff -urN linux-2.4.13-pre3/drivers/net/gt96100eth.c linux/drivers/net/gt96100eth.c
--- linux-2.4.13-pre3/drivers/net/gt96100eth.c	Sun Sep  9 10:45:43 2001
+++ linux/drivers/net/gt96100eth.c	Mon Dec  3 23:18:27 2001
@@ -1250,3 +1250,4 @@
 }
 
 module_init(gt96100_probe);
+MODULE_LICENSE("GPL");
diff -urN linux-2.4.13-pre3/drivers/net/hplance.c linux/drivers/net/hplance.c
--- linux-2.4.13-pre3/drivers/net/hplance.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/hplance.c	Mon Dec  3 23:18:27 2001
@@ -226,6 +226,7 @@
 }
 
 #ifdef MODULE
+MODULE_LICENSE("GPL");
 int init_module(void)
 {
         root_lance_dev = NULL;
diff -urN linux-2.4.13-pre3/drivers/net/hydra.c linux/drivers/net/hydra.c
--- linux-2.4.13-pre3/drivers/net/hydra.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/hydra.c	Mon Dec  3 23:18:27 2001
@@ -254,3 +254,4 @@
 
 module_init(hydra_probe);
 module_exit(hydra_cleanup);
+MODULE_LICENSE("GPL");
diff -urN linux-2.4.13-pre3/drivers/net/ibmlana.c linux/drivers/net/ibmlana.c
--- linux-2.4.13-pre3/drivers/net/ibmlana.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/ibmlana.c	Mon Dec  3 23:18:27 2001
@@ -1199,6 +1199,7 @@
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(irq, "IBM LAN/A IRQ number");
 MODULE_PARM_DESC(io, "IBM LAN/A I/O base address");
+MODULE_LICENSE("GPL");
 
 int init_module(void)
 {
diff -urN linux-2.4.13-pre3/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c
--- linux-2.4.13-pre3/drivers/net/ioc3-eth.c	Thu Sep 13 16:04:43 2001
+++ linux/drivers/net/ioc3-eth.c	Mon Dec  3 23:18:27 2001
@@ -1817,6 +1817,7 @@
 
 MODULE_AUTHOR("Ralf Baechle <ralf@oss.sgi.com>");
 MODULE_DESCRIPTION("SGI IOC3 Ethernet driver");
+MODULE_LICENSE("GPL");
 
 module_init(ioc3_init_module);
 module_exit(ioc3_cleanup_module);
diff -urN linux-2.4.13-pre3/drivers/net/isa-skeleton.c linux/drivers/net/isa-skeleton.c
--- linux-2.4.13-pre3/drivers/net/isa-skeleton.c	Tue Jul 17 18:53:55 2001
+++ linux/drivers/net/isa-skeleton.c	Mon Dec  3 23:18:27 2001
@@ -636,6 +636,7 @@
 static int irq;
 static int dma;
 static int mem;
+MODULE_LICENSE("GPL");
 
 int init_module(void)
 {
diff -urN linux-2.4.13-pre3/drivers/net/lasi_82596.c linux/drivers/net/lasi_82596.c
--- linux-2.4.13-pre3/drivers/net/lasi_82596.c	Sun Aug 12 10:51:42 2001
+++ linux/drivers/net/lasi_82596.c	Mon Dec  3 23:18:27 2001
@@ -180,6 +180,7 @@
 
 MODULE_AUTHOR("Richard Hirst");
 MODULE_DESCRIPTION("i82596 driver");
+MODULE_LICENSE("GPL");
 MODULE_PARM(i596_debug, "i");
 MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask");
 
diff -urN linux-2.4.13-pre3/drivers/net/mac89x0.c linux/drivers/net/mac89x0.c
--- linux-2.4.13-pre3/drivers/net/mac89x0.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/net/mac89x0.c	Mon Dec  3 23:18:27 2001
@@ -627,6 +627,7 @@
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)");
+MODULE_LICENSE("GPL");
 
 EXPORT_NO_SYMBOLS;
 
diff -urN linux-2.4.13-pre3/drivers/net/mace.c linux/drivers/net/mace.c
--- linux-2.4.13-pre3/drivers/net/mace.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/mace.c	Mon Dec  3 23:18:27 2001
@@ -913,6 +913,7 @@
 
 MODULE_AUTHOR("Paul Mackerras");
 MODULE_DESCRIPTION("PowerMac MACE driver.");
+MODULE_LICENSE("GPL");
 
 static void __exit mace_cleanup (void)
 {
diff -urN linux-2.4.13-pre3/drivers/net/macsonic.c linux/drivers/net/macsonic.c
--- linux-2.4.13-pre3/drivers/net/macsonic.c	Wed Oct 10 23:23:24 2001
+++ linux/drivers/net/macsonic.c	Mon Dec  3 23:18:27 2001
@@ -584,6 +584,7 @@
 
 MODULE_PARM(sonic_debug, "i");
 MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
+MODULE_LICENSE("GPL");
 
 EXPORT_NO_SYMBOLS;
 
diff -urN linux-2.4.13-pre3/drivers/net/mvme147.c linux/drivers/net/mvme147.c
--- linux-2.4.13-pre3/drivers/net/mvme147.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/mvme147.c	Mon Dec  3 23:18:27 2001
@@ -188,6 +188,8 @@
 }
 
 #ifdef MODULE
+MODULE_LICENSE("GPL");
+
 int init_module(void)
 {
 	root_lance_dev = NULL;
diff -urN linux-2.4.13-pre3/drivers/net/ne2.c linux/drivers/net/ne2.c
--- linux-2.4.13-pre3/drivers/net/ne2.c	Sun Aug  5 13:12:40 2001
+++ linux/drivers/net/ne2.c	Mon Dec  3 23:18:27 2001
@@ -744,6 +744,7 @@
 static int io[MAX_NE_CARDS];
 static int irq[MAX_NE_CARDS];
 static int bad[MAX_NE_CARDS];	/* 0xbad = bad sig or no reset ack */
+MODULE_LICENSE("GPL");
 
 #ifdef MODULE_PARM
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
diff -urN linux-2.4.13-pre3/drivers/net/oaknet.c linux/drivers/net/oaknet.c
--- linux-2.4.13-pre3/drivers/net/oaknet.c	Sat Mar  3 10:55:47 2001
+++ linux/drivers/net/oaknet.c	Mon Dec  3 23:18:27 2001
@@ -696,3 +696,4 @@
 
 module_init(oaknet_init_module);
 module_exit(oaknet_cleanup_module);
+MODULE_LICENSE("GPL");
diff -urN linux-2.4.13-pre3/drivers/net/pci-skeleton.c linux/drivers/net/pci-skeleton.c
--- linux-2.4.13-pre3/drivers/net/pci-skeleton.c	Tue Aug  7 08:30:50 2001
+++ linux/drivers/net/pci-skeleton.c	Mon Dec  3 23:18:27 2001
@@ -484,6 +484,7 @@
 
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
 MODULE_DESCRIPTION ("Skeleton for a PCI Fast Ethernet driver");
+MODULE_LICENSE("GPL");
 MODULE_PARM (multicast_filter_limit, "i");
 MODULE_PARM (max_interrupt_work, "i");
 MODULE_PARM (debug, "i");
diff -urN linux-2.4.13-pre3/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c
--- linux-2.4.13-pre3/drivers/net/pcmcia/xircom_tulip_cb.c	Tue Oct  9 15:59:03 2001
+++ linux/drivers/net/pcmcia/xircom_tulip_cb.c	Mon Dec  3 23:18:27 2001
@@ -9,11 +9,25 @@
 	Scyld Computing Corporation
 	410 Severn Ave., Suite 210
 	Annapolis MD 21403
+
+	-----------------------------------------------------------
+
+	Linux kernel-specific changes:
+
+	LK1.0 (Ion Badulescu)
+	- Major cleanup
+	- Use 2.4 PCI API
+	- Support ethtool
+	- Rewrite perfect filter/hash code
+	- Use interrupts for media changes
+
+	LK1.1 (Ion Badulescu)
+	- Disallow negotiation of unsupported full-duplex modes
 */
 
 #define DRV_NAME	"xircom_tulip_cb"
-#define DRV_VERSION	"0.91+LK"
-#define DRV_RELDATE	"July 19, 2001"
+#define DRV_VERSION	"0.91+LK1.1"
+#define DRV_RELDATE	"October 11, 2001"
 
 #define CARDBUS 1
 
@@ -94,7 +108,6 @@
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
 KERN_INFO DRV_NAME ".c derived from tulip.c:v0.91 4/14/99 becker@scyld.com\n"
-KERN_INFO " modified by danilo@cs.uni-magdeburg.de for XIRCOM CBE, fixed by Doug Ledford\n"
 KERN_INFO " unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE "\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
@@ -238,7 +251,7 @@
 	int valid_intrs;			/* CSR7 interrupt enable settings */
 	int flags;
 } xircom_tbl[] = {
-  { "Xircom Cardbus Adapter (DEC 21143 compatible mode)",
+  { "Xircom Cardbus Adapter",
 	LinkChange | NormalIntr | AbnormalIntr | BusErrorIntr |
 	RxDied | RxNoBuf | RxIntr | TxFIFOUnderflow | TxNoBuf | TxDied | TxIntr,
 	HAS_MII | HAS_ACPI, },
@@ -425,12 +438,22 @@
 
 /*
  * locate the MII interfaces and initialize them.
+ * we disable full-duplex modes here,
+ * because we don't know how to handle them.
  */
 static void find_mii_transceivers(struct net_device *dev)
 {
 	struct xircom_private *tp = dev->priv;
 	int phy, phy_idx;
 
+	if (media_cap[tp->default_port] & MediaIsMII) {
+		u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
+		tp->to_advertise = media2advert[tp->default_port - 9];
+	} else
+		tp->to_advertise =
+			/*ADVERTISE_100BASE4 | ADVERTISE_100FULL |*/ ADVERTISE_100HALF |
+			/*ADVERTISE_10FULL |*/ ADVERTISE_10HALF | ADVERTISE_CSMA;
+
 	/* Find the connected MII xcvrs.
 	   Doing this in open() would allow detecting external xcvrs later,
 	   but takes much time. */
@@ -447,17 +470,6 @@
 			printk(KERN_INFO "%s:  MII transceiver #%d "
 				   "config %4.4x status %4.4x advertising %4.4x.\n",
 				   dev->name, phy, mii_reg0, mii_status, mii_advert);
-			/* Fixup for DLink with miswired PHY. */
-			if (mii_advert != reg4) {
-				printk(KERN_DEBUG "%s:  Advertising %4.4x on PHY %d,"
-					   " previously advertising %4.4x.\n",
-					   dev->name, reg4, phy, mii_advert);
-				mdio_write(dev, phy, MII_ADVERTISE, reg4);
-			}
-			/* Enable autonegotiation: some boards default to off. */
-			mdio_write(dev, phy, MII_BMCR, mii_reg0 | BMCR_ANENABLE |
-					   (tp->full_duplex ? BMCR_FULLDPLX : 0) |
-					   (media_cap[tp->default_port]&MediaIs100 ? BMCR_SPEED100 : 0));
 		}
 	}
 	tp->mii_cnt = phy_idx;
@@ -529,7 +541,7 @@
 		printk(version);
 #endif
 
-	printk(KERN_INFO "xircom_init_one(%s)\n", pdev->slot_name);
+	//printk(KERN_INFO "xircom_init_one(%s)\n", pdev->slot_name);
 
 	board_idx++;
 
@@ -1696,7 +1708,6 @@
 }
 
 
-/* XXX: resume isn't able to power up the MII/PHY! */
 static int xircom_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pdev->driver_data;
diff -urN linux-2.4.13-pre3/drivers/net/saa9730.c linux/drivers/net/saa9730.c
--- linux-2.4.13-pre3/drivers/net/saa9730.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/saa9730.c	Mon Dec  3 23:18:27 2001
@@ -1080,3 +1080,4 @@
 }
 
 module_init(saa9730_probe);
+MODULE_LICENSE("GPL");
diff -urN linux-2.4.13-pre3/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c
--- linux-2.4.13-pre3/drivers/net/seeq8005.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/seeq8005.c	Mon Dec  3 23:18:27 2001
@@ -711,6 +711,7 @@
 static struct net_device dev_seeq = { init: seeq8005_probe };
 static int io = 0x320;
 static int irq = 10;
+MODULE_LICENSE("GPL");
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
 MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address");
diff -urN linux-2.4.13-pre3/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- linux-2.4.13-pre3/drivers/net/sk_g16.c	Wed Jul  4 11:50:39 2001
+++ linux/drivers/net/sk_g16.c	Mon Dec  3 23:18:27 2001
@@ -616,6 +616,7 @@
 
 MODULE_AUTHOR("Patrick J.D. Weichmann");
 MODULE_DESCRIPTION("Schneider & Koch G16 Ethernet Device Driver");
+MODULE_LICENSE("GPL");
 MODULE_PARM(io, "i");
 MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the board");
 
diff -urN linux-2.4.13-pre3/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c
--- linux-2.4.13-pre3/drivers/net/sk_mca.c	Wed Jul  4 11:50:39 2001
+++ linux/drivers/net/sk_mca.c	Mon Dec  3 23:18:27 2001
@@ -1229,6 +1229,7 @@
  * ------------------------------------------------------------------------ */
 
 #ifdef MODULE
+MODULE_LICENSE("GPL");
 
 #define DEVMAX 5
 
diff -urN linux-2.4.13-pre3/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c
--- linux-2.4.13-pre3/drivers/net/smc-mca.c	Sun Aug 12 10:51:42 2001
+++ linux/drivers/net/smc-mca.c	Mon Dec  3 23:18:27 2001
@@ -437,6 +437,7 @@
 static struct net_device dev_ultra[MAX_ULTRAMCA_CARDS];
 static int io[MAX_ULTRAMCA_CARDS];
 static int irq[MAX_ULTRAMCA_CARDS];
+MODULE_LICENSE("GPL");
 
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i");
diff -urN linux-2.4.13-pre3/drivers/net/smc9194.c linux/drivers/net/smc9194.c
--- linux-2.4.13-pre3/drivers/net/smc9194.c	Sat Sep  8 12:14:25 2001
+++ linux/drivers/net/smc9194.c	Mon Dec  3 23:18:27 2001
@@ -1558,6 +1558,7 @@
 static int io;
 static int irq;
 static int ifport;
+MODULE_LICENSE("GPL");
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
diff -urN linux-2.4.13-pre3/drivers/net/stnic.c linux/drivers/net/stnic.c
--- linux-2.4.13-pre3/drivers/net/stnic.c	Tue Jul 10 20:16:30 2001
+++ linux/drivers/net/stnic.c	Mon Dec  3 23:18:27 2001
@@ -316,3 +316,4 @@
 
 module_init(stnic_probe);
 /* No cleanup routine. */
+MODULE_LICENSE("GPL");
diff -urN linux-2.4.13-pre3/drivers/net/sun3lance.c linux/drivers/net/sun3lance.c
--- linux-2.4.13-pre3/drivers/net/sun3lance.c	Wed Jul  4 11:50:39 2001
+++ linux/drivers/net/sun3lance.c	Mon Dec  3 23:18:27 2001
@@ -71,6 +71,7 @@
 #endif
 MODULE_PARM(lance_debug, "i");
 MODULE_PARM_DESC(lance_debug, "SUN3 Lance debug level (0-3)");
+MODULE_LICENSE("GPL");
 
 #define	DPRINTK(n,a) \
 	do {  \
diff -urN linux-2.4.13-pre3/drivers/net/sunqe.c linux/drivers/net/sunqe.c
--- linux-2.4.13-pre3/drivers/net/sunqe.c	Thu Apr 26 22:17:26 2001
+++ linux/drivers/net/sunqe.c	Mon Dec  3 23:18:27 2001
@@ -1041,3 +1041,4 @@
 
 module_init(qec_probe);
 module_exit(qec_cleanup);
+MODULE_LICENSE("GPL");
diff -urN linux-2.4.13-pre3/drivers/net/tulip/interrupt.c linux/drivers/net/tulip/interrupt.c
--- linux-2.4.13-pre3/drivers/net/tulip/interrupt.c	Tue Oct  2 09:00:58 2001
+++ linux/drivers/net/tulip/interrupt.c	Mon Dec  3 23:18:27 2001
@@ -301,7 +301,7 @@
 	long ioaddr = dev->base_addr;
 	int csr5;
 	int entry;
-	int csr8;
+	int missed;
 	int rx = 0;
 	int tx = 0;
 	int oi = 0;
@@ -434,6 +434,7 @@
 				}
 			}
 			if (csr5 & RxDied) {		/* Missed a Rx frame. */
+                                tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
 #ifdef CONFIG_NET_HW_FLOWCONTROL
 				if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) {
 					tp->stats.rx_errors++;
@@ -547,8 +548,9 @@
 		}
 	}
 
-	csr8 = inl(ioaddr + CSR8);
-	tp->stats.rx_dropped += (csr8 & 0x1ffff) + ((csr8 >> 17) & 0xfff);
+	if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) {
+		tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
+	}
 
 	if (tulip_debug > 4)
 		printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
diff -urN linux-2.4.13-pre3/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- linux-2.4.13-pre3/drivers/net/tulip/tulip_core.c	Tue Oct  2 09:00:58 2001
+++ linux/drivers/net/tulip/tulip_core.c	Mon Dec  3 23:18:27 2001
@@ -15,8 +15,8 @@
 */
 
 #define DRV_NAME	"tulip"
-#define DRV_VERSION	"0.9.15-pre7"
-#define DRV_RELDATE	"Oct 2, 2001"
+#define DRV_VERSION	"0.9.15-pre8"
+#define DRV_RELDATE	"Oct 11, 2001"
 
 #include <linux/config.h>
 #include <linux/module.h>
diff -urN linux-2.4.13-pre3/drivers/net/wireless/airport.c linux/drivers/net/wireless/airport.c
--- linux-2.4.13-pre3/drivers/net/wireless/airport.c	Thu Sep 13 16:04:43 2001
+++ linux/drivers/net/wireless/airport.c	Mon Dec  3 23:18:27 2001
@@ -43,6 +43,7 @@
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
 MODULE_LICENSE("Dual MPL/GPL");
+EXPORT_NO_SYMBOLS;
 
 typedef struct dldwd_card {
 	struct device_node* node;
diff -urN linux-2.4.13-pre3/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c
--- linux-2.4.13-pre3/drivers/sbus/audio/amd7930.c	Mon Dec  3 23:18:18 2001
+++ linux/drivers/sbus/audio/amd7930.c	Mon Dec  3 23:18:27 2001
@@ -1,4 +1,4 @@
-/* $Id: amd7930.c,v 1.27 2001/05/21 01:25:22 davem Exp $
+/* $Id: amd7930.c,v 1.28 2001/10/13 01:47:29 davem Exp $
  * drivers/sbus/audio/amd7930.c
  *
  * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
diff -urN linux-2.4.13-pre3/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c
--- linux-2.4.13-pre3/drivers/sbus/char/aurora.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/sbus/char/aurora.c	Mon Dec  3 23:18:27 2001
@@ -1,4 +1,4 @@
-/*	$Id: aurora.c,v 1.16 2001/10/08 22:19:51 davem Exp $
+/*	$Id: aurora.c,v 1.17 2001/10/13 08:27:50 davem Exp $
  *	linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
  *
  *	Copyright (c) 1999 by Oliver Aldulea (oli at bv dot ro)
@@ -33,6 +33,14 @@
  *	read that file before reading this one.
  *
  *	Several parts of the code do not have comments yet.
+ * 
+ * n.b.  The board can support 115.2 bit rates, but only on a few
+ * ports. The total badwidth of one chip (ports 0-7 or 8-15) is equal
+ * to OSC_FREQ div 16. In case of my board, each chip can take 6
+ * channels of 115.2 kbaud.  This information is not well-tested.
+ * 
+ * Fixed to use tty_get_baud_rate().
+ *   Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
  */
 
 #include <linux/module.h>
@@ -100,16 +108,6 @@
 
 DECLARE_TASK_QUEUE(tq_aurora);
 
-/* Yes, the board can support 115.2 bit rates, but only on a few ports. The
- * total badwidth of one chip (ports 0-7 or 8-15) is equal to OSC_FREQ div
- * 16. In case of my board, each chip can take 6 channels of 115.2 kbaud.
- * This information is not well-tested.
- */
-static unsigned long baud_table[] =  {
-        0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-        9600, 19200, 38400, 57600, 115200, 0,
-};
-
 static inline int aurora_paranoia_check(struct Aurora_port const * port,
 				    kdev_t device, const char *routine)
 {
@@ -1030,28 +1028,14 @@
 	port->COR2 = 0;
 	port->MSVR = MSVR_RTS|MSVR_DTR;
 	
-	baud = C_BAUD(tty);
-	
-	if (baud & CBAUDEX) {
-		baud &= ~CBAUDEX;
-		if (baud < 1 || baud > 2) 
-			port->tty->termios->c_cflag &= ~CBAUDEX;
-		else
-			baud += 15;
-	}
-	if (baud == 15)  {
-		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baud ++;
-		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baud += 2;
-	}
+	baud = tty_get_baud_rate(tty);
 	
 	/* Select port on the board */
 	sbus_writeb(port_No(port) & 7,
 		    &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
 	
-	if (!baud_table[baud])  {
+	if (!baud)  {
 		/* Drop DTR & exit */
 		port->MSVR &= ~(bp->DTR|bp->RTS);
 		sbus_writeb(port->MSVR,
@@ -1067,10 +1051,10 @@
 	/* Now we must calculate some speed dependant things. */
 	
 	/* Set baud rate for port. */
-	tmp = (((bp->oscfreq + baud_table[baud]/2) / baud_table[baud] +
+	tmp = (((bp->oscfreq + baud/2) / baud +
 		CD180_TPC/2) / CD180_TPC);
 
-/*	tmp = (bp->oscfreq/7)/baud_table[baud];
+/*	tmp = (bp->oscfreq/7)/baud;
 	if((tmp%10)>4)tmp=tmp/10+1;else tmp=tmp/10;*/
 /*	printk("Prescaler period: %d\n",tmp);*/
 
@@ -1081,7 +1065,7 @@
 	sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_RBPRL]);
 	sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_TBPRL]);
 	
-	baud = (baud_table[baud] + 5) / 10;   /* Estimated CPS */
+	baud = (baud + 5) / 10;   /* Estimated CPS */
 	
 	/* Two timer ticks seems enough to wakeup something like SLIP driver */
 	tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;		
diff -urN linux-2.4.13-pre3/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c
--- linux-2.4.13-pre3/drivers/sbus/char/sab82532.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/sbus/char/sab82532.c	Mon Dec  3 23:18:27 2001
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.64 2001/10/08 22:19:51 davem Exp $
+/* $Id: sab82532.c,v 1.65 2001/10/13 08:27:50 davem Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -6,6 +6,10 @@
  * Rewrote buffer handling to use CIRC(Circular Buffer) macros.
  *   Maxim Krasnyanskiy <maxk@qualcomm.com>
  *
+ * Fixed to use tty_get_baud_rate, and to allow for arbitrary baud
+ * rates to be programmed into the UART.  Also eliminated a lot of
+ * duplicated code in the console setup.
+ *   Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
  */
 
 #include <linux/config.h>
@@ -147,45 +151,47 @@
  * The formula is:    Baud = BASE_BAUD / ((N + 1) * (1 << M)),
  *
  * with               0 <= N < 64 and 0 <= M < 16
- *
- * XXX:	Speeds with M = 0 might not work properly for XTAL frequencies
- *      above 10 MHz.
+ * 
+ * 12-Oct-2001 - Replaced table driven approach with code written by
+ * Theodore Ts'o <tytso@alum.mit.edu> which exactly replicates the
+ * table.  (Modulo bugs for the 307200 and 61440 baud rates, which
+ * were clearly incorrectly calculated in the original table.  This is
+ * why tables filled with magic constants are evil.)
  */
-struct ebrg_struct {
-	int	baud;
-	int	n;
-	int	m;
-};
 
-static struct ebrg_struct ebrg_table[] = {
-	{       0,	0,	 0 },
-	{      50,	35,	10 },
-	{      75,	47,	 9 },
-	{     110,	32,	 9 },
-	{     134,	53,	 8 },
-	{     150,	47,	 8 },
-	{     200,	35,	 8 },
-	{     300,	47,	 7 },
-	{     600,	47,	 6 },
-	{    1200,	47,	 5 },
-	{    1800,	31,	 5 },
-	{    2400,	47,	 4 },
-	{    4800,	47,	 3 },
-	{    9600,	47,	 2 },
-	{   19200,	47,	 1 },
-	{   38400,	23,	 1 },
-	{   57600,	15,	 1 },
-	{  115200,	 7,	 1 },
-	{  230400,	 3,	 1 },
-	{  460800,	 1,	 1 },
-	{   76800,	11,	 1 },
-	{  153600,	 5,	 1 },
-	{  307200,	 3,	 1 },
-	{  614400,	 3,	 0 },
-	{  921600,	 0,	 1 },
-};
+static void calc_ebrg(int baud, int *n_ret, int *m_ret)
+{
+	int	n, m;
 
-#define NR_EBRG_VALUES	(sizeof(ebrg_table)/sizeof(struct ebrg_struct))
+	if (baud == 0) {
+		*n_ret = 0;
+		*m_ret = 0;
+		return;
+	}
+     
+	/*
+	 * We scale numbers by 10 so that we get better accuracy
+	 * without having to use floating point.  Here we increment m
+	 * until n is within the valid range.
+	 */
+	n = (BASE_BAUD*10) / baud;
+	m = 0;
+	while (n >= 640) {
+		n = n / 2;
+		m++;
+	}
+	n = (n+5) / 10;
+	/*
+	 * We try very hard to avoid speeds with M == 0 since they may
+	 * not work correctly for XTAL frequences above 10 MHz.
+	 */
+	if ((m == 0) && ((n & 1) == 0)) {
+		n = n / 2;
+		m++;
+	}
+	*n_ret = n - 1;
+	*m_ret = m;
+}
 
 #define SAB82532_MAX_TEC_TIMEOUT 200000	/* 1 character time (at 50 baud) */
 #define SAB82532_MAX_CEC_TIMEOUT  50000	/* 2.5 TX CLKs (at 50 baud) */
@@ -939,7 +945,7 @@
 	unsigned int	ebrg;
 	tcflag_t	cflag;
 	unsigned char	dafo;
-	int		i, bits;
+	int		bits, n, m;
 
 	if (!info->tty || !info->tty->termios)
 		return;
@@ -982,18 +988,11 @@
 	}
 
 	/* Determine EBRG values based on baud rate */
-	i = cflag & CBAUD;
-	if (i & CBAUDEX) {
-		i &= ~(CBAUDEX);
-		if ((i < 1) || ((i + 15) >= NR_EBRG_VALUES))
-			info->tty->termios->c_cflag &= ~CBAUDEX;
-		else
-			i += 15;
-	}
-	ebrg = ebrg_table[i].n;
-	ebrg |= (ebrg_table[i].m << 6);
+	info->baud = tty_get_baud_rate(info->tty);
+	calc_ebrg(info->baud, &n, &m);
+	
+	ebrg = n | (m << 6);
 
-	info->baud = ebrg_table[i].baud;
 	if (info->baud) {
 		info->timeout = (info->xmit_fifo_size * HZ * bits) / info->baud;
 		info->tec_timeout = (10 * 1000000) / info->baud;
@@ -2205,7 +2204,7 @@
 
 static inline void __init show_serial_version(void)
 {
-	char *revision = "$Revision: 1.64 $";
+	char *revision = "$Revision: 1.65 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2558,12 +2557,11 @@
 static int
 sab82532_console_setup(struct console *con, char *options)
 {
+	static struct tty_struct c_tty;
+	static struct termios c_termios;
 	struct sab82532 *info;
-	unsigned int	ebrg;
 	tcflag_t	cflag;
-	unsigned char	dafo;
-	int		i, bits;
-	unsigned long	flags;
+	int		i;
 
 	info = sab82532_chain;
 	for (i = con->index; i; i--) {
@@ -2595,92 +2593,28 @@
 	sunserial_console_termios(con);
 	cflag = con->cflag;
 
-	/* Byte size and parity */
-	switch (cflag & CSIZE) {
-	      case CS5: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
-	      case CS6: dafo = SAB82532_DAFO_CHL6; bits = 8; break;
-	      case CS7: dafo = SAB82532_DAFO_CHL7; bits = 9; break;
-	      case CS8: dafo = SAB82532_DAFO_CHL8; bits = 10; break;
-	      /* Never happens, but GCC is too dumb to figure it out */
-	      default:  dafo = SAB82532_DAFO_CHL5; bits = 7; break;
-	}
-
-	if (cflag & CSTOPB) {
-		dafo |= SAB82532_DAFO_STOP;
-		bits++;
-	}
-
-	if (cflag & PARENB) {
-		dafo |= SAB82532_DAFO_PARE;
-		bits++;
-	}
-
-	if (cflag & PARODD) {
-#ifdef CMSPAR
-		if (cflag & CMSPAR)
-			dafo |= SAB82532_DAFO_PAR_MARK;
-		else
-#endif
-			dafo |= SAB82532_DAFO_PAR_ODD;
-	} else {
-#ifdef CMSPAR
-		if (cflag & CMSPAR)
-			dafo |= SAB82532_DAFO_PAR_SPACE;
-		else
-#endif
-			dafo |= SAB82532_DAFO_PAR_EVEN;
+	/*
+	 * Fake up the tty and tty->termios structures so we can use
+	 * change_speed (and eliminate a lot of duplicate code).
+	 */
+	if (!info->tty) {
+		memset(&c_tty, 0, sizeof(c_tty));
+		info->tty = &c_tty;
 	}
-
-	/* Determine EBRG values based on baud rate */
-	i = cflag & CBAUD;
-	if (i & CBAUDEX) {
-		i &= ~(CBAUDEX);
-		if ((i < 1) || ((i + 15) >= NR_EBRG_VALUES))
-			cflag &= ~CBAUDEX;
-		else
-			i += 15;
+	if (!info->tty->termios) {
+		memset(&c_termios, 0, sizeof(c_termios));
+		info->tty->termios = &c_termios;
 	}
-	ebrg = ebrg_table[i].n;
-	ebrg |= (ebrg_table[i].m << 6);
-
-	info->baud = ebrg_table[i].baud;
-	if (info->baud)
-		info->timeout = (info->xmit_fifo_size * HZ * bits) / info->baud;
-	else
-		info->timeout = 0;
-	info->timeout += HZ / 50;		/* Add .02 seconds of slop */
-
-	/* CTS flow control flags */
-	if (cflag & CRTSCTS)
-		info->flags |= ASYNC_CTS_FLOW;
-	else
-		info->flags &= ~(ASYNC_CTS_FLOW);
-
-	if (cflag & CLOCAL)
-		info->flags &= ~(ASYNC_CHECK_CD);
-	else
-		info->flags |= ASYNC_CHECK_CD;
+	info->tty->termios->c_cflag = con->cflag;
 
-	save_flags(flags); cli();
-	sab82532_cec_wait(info);
-	sab82532_tec_wait(info);
-	writeb(dafo, &info->regs->w.dafo);
-	writeb(ebrg & 0xff, &info->regs->w.bgr);
-	writeb(readb(&info->regs->rw.ccr2) & ~(0xc0), &info->regs->rw.ccr2);
-	writeb(readb(&info->regs->rw.ccr2) | ((ebrg >> 2) & 0xc0), &info->regs->rw.ccr2);
-	if (info->flags & ASYNC_CTS_FLOW) {
-		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);
-		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
-		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FCTS), &info->regs->rw.mode);
-	} else {
-		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
-		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);
-		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FCTS, &info->regs->rw.mode);
-	}
-	writeb(~(info->pvr_dtr_bit), &info->regs->rw.pvr);
-	writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RAC, &info->regs->rw.mode);
-	restore_flags(flags);
+	change_speed(info);
 
+	/* Now take out the pointers to static structures if necessary */
+	if (info->tty->termios == &c_termios)
+		info->tty->termios = 0;
+	if (info->tty == &c_tty)
+		info->tty = 0;
+	
 	return 0;
 }
 
diff -urN linux-2.4.13-pre3/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- linux-2.4.13-pre3/drivers/sbus/char/su.c	Fri Jun 29 19:38:26 2001
+++ linux/drivers/sbus/char/su.c	Mon Dec  3 23:18:27 2001
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.52 2001/06/29 21:54:32 davem Exp $
+/* $Id: su.c,v 1.53 2001/10/13 08:27:50 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -6,6 +6,9 @@
  *
  * This is mainly a variation of drivers/char/serial.c,
  * credits go to authors mentioned therein.
+ *
+ * Fixed to use tty_get_baud_rate().
+ *   Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
  */
 
 /*
@@ -935,24 +938,18 @@
 static int
 su_get_baud_rate(struct su_struct *info)
 {
-	static int baud_table[] = {
-		0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
-		4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0
-	};
-	int i;
+	static struct tty_struct c_tty;
+	static struct termios c_termios;
 
 	if (info->tty)
 		return tty_get_baud_rate(info->tty);
 
-	i = info->cflag & CBAUD;
-	if (i & CBAUDEX) {
-		i &= ~(CBAUDEX);
-		if (i < 1 || i > 4)
-			info->cflag &= ~(CBAUDEX);
-		else
-			i += 15;
-	}
-	return baud_table[i];
+	memset(&c_tty, 0, sizeof(c_tty));
+	memset(&c_termios, 0, sizeof(c_termios));
+	c_tty.termios = &c_termios;
+	c_termios.c_cflag = info->cflag;
+
+	return tty_get_baud_rate(&c_tty);
 }
 
 /*
@@ -1168,7 +1165,7 @@
 	if (info->port_type != SU_PORT_MS)
 		return;
 
-	info->cflag &= ~(CBAUDEX | CBAUD);
+	info->cflag &= ~CBAUD;
 	switch (baud) {
 		case 1200:
 			info->cflag |= B1200;
@@ -2255,7 +2252,7 @@
  */
 static __inline__ void __init show_su_version(void)
 {
-	char *revision = "$Revision: 1.52 $";
+	char *revision = "$Revision: 1.53 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -urN linux-2.4.13-pre3/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- linux-2.4.13-pre3/drivers/sbus/char/zs.c	Fri Jun 29 19:38:26 2001
+++ linux/drivers/sbus/char/zs.c	Mon Dec  3 23:18:27 2001
@@ -1,9 +1,12 @@
-/* $Id: zs.c,v 1.66 2001/06/29 21:33:22 davem Exp $
+/* $Id: zs.c,v 1.67 2001/10/13 08:27:50 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1996 Eddie C. Dost   (ecd@skynet.be)
  * Fixes by Pete A. Zaitcev <zaitcev@yahoo.com>.
+ *
+ * Fixed to use tty_get_baud_rate().
+ *   Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
  */
 
 #include <linux/errno.h>
@@ -241,12 +244,6 @@
 	return 0;
 }
 
-/* This is used to figure out the divisor speeds and the timeouts. */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 76800, 0
-};
-
 /* Reading and writing Zilog8530 registers.  The delays are to make this
  * driver work on the Sun4 which needs a settling delay after each chip
  * register access, other machines handle this in hardware via auxiliary
@@ -944,8 +941,7 @@
 static void change_speed(struct sun_serial *info)
 {
 	unsigned cflag;
-	int	quot = 0;
-	int	i;
+	int	baud, quot = 0;
 	int	brg;
 
 	if (!info->tty || !info->tty->termios)
@@ -953,20 +949,12 @@
 	cflag = info->tty->termios->c_cflag;
 	if (!info->port)
 		return;
-	i = cflag & CBAUD;
-	if (cflag & CBAUDEX) {
-		i &= ~CBAUDEX;
-		if (i != 5)
-			info->tty->termios->c_cflag &= ~CBAUDEX;
-		else
-			i = 16;
-	}
-	if (i == 15) {
-		if ((info->flags & ZILOG_SPD_MASK) == ZILOG_SPD_HI)
-			i += 1;
-		if ((info->flags & ZILOG_SPD_MASK) == ZILOG_SPD_CUST)
-			quot = info->custom_divisor;
-	}
+	baud = tty_get_baud_rate(info->tty);
+	
+	if ((baud == 38400) && 
+	    ((info->flags & ZILOG_SPD_MASK) == ZILOG_SPD_CUST))
+		quot = info->custom_divisor;
+
 	if (quot) {
 		info->zs_baud = info->baud_base / quot;
 		info->clk_divisor = 16;
@@ -978,8 +966,8 @@
 		info->curregs[13] = ((brg >> 8) & 255);
 		info->curregs[14] = BRSRC | BRENAB;
 		zs_rtsdtr(info, 1);
-	} else if (baud_table[i]) {
-		info->zs_baud = baud_table[i];
+	} else if (baud) {
+		info->zs_baud = baud;
 		info->clk_divisor = 16;
 
 		info->curregs[4] = X16CLK;
@@ -1945,7 +1933,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.66 $";
+	char *revision = "$Revision: 1.67 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2796,22 +2784,23 @@
 
 static int __init zs_console_setup(struct console *con, char *options)
 {
+	static struct tty_struct c_tty;
+	static struct termios c_termios;
 	struct sun_serial *info;
-	int i, brg, baud;
+	int brg, baud;
 
 	info = zs_soft + con->index;
 	info->is_cons = 1;
 
 	printk("Console: ttyS%d (Zilog8530)\n", info->line);
-
+	
 	sunserial_console_termios(con);
+	memset(&c_tty, 0, sizeof(c_tty));
+	memset(&c_termios, 0, sizeof(c_termios));
+	c_tty.termios = &c_termios;
+	c_termios.c_cflag = con->cflag;
+	baud = tty_get_baud_rate(&c_tty);
 
-	i = con->cflag & CBAUD;
-	if (con->cflag & CBAUDEX) {
-		i &= ~CBAUDEX;
-		con->cflag &= ~CBAUDEX;
-	}
-	baud = baud_table[i];
 	info->zs_baud = baud;
 
 	switch (con->cflag & CSIZE) {
diff -urN linux-2.4.13-pre3/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- linux-2.4.13-pre3/drivers/scsi/scsi.c	Fri Oct  5 11:19:50 2001
+++ linux/drivers/scsi/scsi.c	Mon Dec  3 23:18:28 2001
@@ -1837,6 +1837,8 @@
 
 	pcount = next_scsi_host;
 
+	MOD_INC_USE_COUNT;
+
 	/* The detect routine must carefully spinunlock/spinlock if 
 	   it enables interrupts, since all interrupt handlers do 
 	   spinlock as well.
@@ -1966,8 +1968,6 @@
 	       (scsi_init_memory_start - scsi_memory_lower_value) / 1024,
 	       (scsi_memory_upper_value - scsi_init_memory_start) / 1024);
 #endif
-
-	MOD_INC_USE_COUNT;
 
 	if (out_of_space) {
 		scsi_unregister_host(tpnt);	/* easiest way to clean up?? */
diff -urN linux-2.4.13-pre3/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- linux-2.4.13-pre3/drivers/scsi/sd.c	Mon Dec  3 23:18:18 2001
+++ linux/drivers/scsi/sd.c	Mon Dec  3 23:18:28 2001
@@ -152,6 +152,9 @@
 	int diskinfo[4];
     
 	SDev = rscsi_disks[DEVICE_NR(dev)].device;
+	if (!SDev)
+		return -ENODEV;
+
 	/*
 	 * If we are in the middle of error recovery, don't let anyone
 	 * else try and use this device.  Also, if error recovery fails, it
@@ -533,6 +536,8 @@
 
 	target = DEVICE_NR(inode->i_rdev);
 	SDev = rscsi_disks[target].device;
+	if (!SDev)
+		return -ENODEV;
 
 	SDev->access_count--;
 
diff -urN linux-2.4.13-pre3/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c
--- linux-2.4.13-pre3/drivers/scsi/sym53c8xx.c	Mon Dec  3 23:18:18 2001
+++ linux/drivers/scsi/sym53c8xx.c	Mon Dec  3 23:18:28 2001
@@ -13168,14 +13168,14 @@
 	** in the size field.  We use normal 32-bit PCI addresses for
 	** descriptors.
 	*/
-	if (chip->features & FE_DAC) {
+	if (chip && (chip->features & FE_DAC)) {
 		if (pci_set_dma_mask(pdev, (u64) 0xffffffffff))
 			chip->features &= ~FE_DAC_IN_USE;
 		else
 			chip->features |= FE_DAC_IN_USE;
 	}
 
-	if (!(chip->features & FE_DAC_IN_USE)) {
+	if (chip && !(chip->features & FE_DAC_IN_USE)) {
 		if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
 			printk(KERN_WARNING NAME53C8XX
 			       "32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
diff -urN linux-2.4.13-pre3/drivers/sound/btaudio.c linux/drivers/sound/btaudio.c
--- linux-2.4.13-pre3/drivers/sound/btaudio.c	Thu Sep 20 14:20:14 2001
+++ linux/drivers/sound/btaudio.c	Mon Dec  3 23:18:28 2001
@@ -748,6 +748,24 @@
         case SNDCTL_DSP_SYNC:
 		/* NOP */
 		return 0;
+	case SNDCTL_DSP_GETISPACE:
+	{
+		audio_buf_info info;
+		if (!bta->recording)
+			return -EINVAL;
+		info.fragsize = bta->block_bytes>>bta->sampleshift;
+		info.fragstotal = bta->block_count;
+		info.bytes = bta->read_count;
+		info.fragments = info.bytes / info.fragsize;
+		if (debug)
+			printk(KERN_DEBUG "btaudio: SNDCTL_DSP_GETISPACE "
+			       "returns %d/%d/%d/%d\n",
+			       info.fragsize, info.fragstotal,
+			       info.bytes, info.fragments);
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
 #if 0 /* TODO */
         case SNDCTL_DSP_GETTRIGGER:
         case SNDCTL_DSP_SETTRIGGER:
diff -urN linux-2.4.13-pre3/drivers/usb/Config.in linux/drivers/usb/Config.in
--- linux-2.4.13-pre3/drivers/usb/Config.in	Fri Oct  5 12:04:51 2001
+++ linux/drivers/usb/Config.in	Mon Dec  3 23:18:28 2001
@@ -4,8 +4,8 @@
 mainmenu_option next_comment
 comment 'USB support'
 
-tristate 'Support for USB' CONFIG_USB
-if [ ! "$CONFIG_USB" = "n" ]; then
+dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
+if [ "$CONFIG_USB" = "y" -o  "$CONFIG_USB" = "m" ]; then
    bool '  USB verbose debug messages' CONFIG_USB_DEBUG
 
 comment 'Miscellaneous USB options'
@@ -15,73 +15,84 @@
    else
       define_bool CONFIG_USB_BANDWIDTH n
    fi
+   bool '  Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
+   bool '  Large report fetching for "broken" devices (some APC UPSes)' CONFIG_USB_LARGE_CONFIG
+fi
 
 comment 'USB Controllers'
-   if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
-      dep_tristate '  UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
-   fi
-   if [ "$CONFIG_USB_UHCI" != "y" ]; then
-      dep_tristate '  UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
-   fi
-   dep_tristate '  OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
+if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
+   dep_tristate '  UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
+fi
+if [ "$CONFIG_USB_UHCI" != "y" ]; then
+   dep_tristate '  UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
+else
+   define_bool CONFIG_USB_UHCI_ALT n
+fi
+dep_tristate '  OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
 
-   comment 'USB Device Class drivers'
-   dep_tristate '  USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
-   dep_tristate '  USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
-   dep_tristate '  USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
-   if [ "$CONFIG_USB_STORAGE" != "n" ]; then
-      bool '    USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG
-      bool '    Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM
-      bool '    ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200
-      bool '    Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM
-      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-         bool '    HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e
-         bool '    SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09
-      fi
+comment 'USB Device Class drivers'
+dep_tristate '  USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
+dep_tristate '  USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
+   dep_mbool '    USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE
+   dep_mbool '    Datafab MDCFE-B Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+   dep_mbool '    Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM  $CONFIG_USB_STORAGE
+   dep_mbool '    ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE
+   dep_mbool '    Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE
+   dep_mbool '    HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+   dep_mbool '    SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+   dep_mbool '    Lexar Jumpshot Compact Flash Reader' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
+dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
+
+comment 'USB Human Interface Devices (HID)'
+if [ "$CONFIG_INPUT" = "n" ]; then
+   comment '  Input core support is needed for USB HID'
+else
+   dep_tristate '  USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB $CONFIG_INPUT
+      dep_mbool '    /dev/hiddev raw HID device support (EXPERIMENTAL)' CONFIG_USB_HIDDEV $CONFIG_USB_HID
+   if [ "$CONFIG_USB_HID" != "y" ]; then
+      dep_tristate '  USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
+      dep_tristate '  USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
    fi
-   dep_tristate '  USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
-   dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
-
-   comment 'USB Human Interface Devices (HID)'
-   if [ "$CONFIG_INPUT" = "n" ]; then
-      comment '  Input core support is needed for USB HID'
-   else
-      dep_tristate '  USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB $CONFIG_INPUT
-      if [ "$CONFIG_USB_HID" != "y" ]; then
-         dep_tristate '  USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
-         dep_tristate '  USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
-      fi
-      dep_tristate '  Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
-   fi
-
-   comment 'USB Imaging devices'
-   dep_tristate '  USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
-   dep_tristate '  USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
-   dep_tristate '  USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
-   dep_tristate '  Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
-   dep_tristate '  HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL
+   dep_tristate '  Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
+fi
 
-   comment 'USB Multimedia devices'
+comment 'USB Imaging devices'
+dep_tristate '  USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
+dep_tristate '  USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
+dep_tristate '  Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
+dep_tristate '  HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL
+
+comment 'USB Multimedia devices'
+if [ "$CONFIG_VIDEO_DEV" = "n" ]; then
+   comment '  Video4Linux support is needed for USB Multimedia device support'
+else
    dep_tristate '  USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV
    dep_tristate '  D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
    dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
+fi
 
-   comment 'USB Network adaptors'
+comment 'USB Network adaptors'
+if [ "$CONFIG_NET" = "n" ]; then
+   comment '  Networking support is needed for USB Networking device support'
+else
    dep_tristate '  USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
-   dep_tristate '  USB CATC NetMate-based Ethernet driver (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
-   dep_tristate '  USB CDC Ethernet class (USB cable modem) support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
    dep_tristate '  USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
-   dep_tristate '  USB-to-USB Networking (NetChip, Prolific, ...) (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB Communication Class Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB-to-USB Networking cable device support (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+fi
 
-   comment 'USB port drivers'
-   dep_tristate '  USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
-   source drivers/usb/serial/Config.in
+comment 'USB port drivers'
+dep_tristate '  USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
+source drivers/usb/serial/Config.in
 
-   comment 'USB misc drivers'
-   dep_tristate '  USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
-fi
+comment 'USB Miscellaneous drivers'
+dep_tristate '  USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
 
 endmenu
diff -urN linux-2.4.13-pre3/drivers/usb/pegasus.h linux/drivers/usb/pegasus.h
--- linux-2.4.13-pre3/drivers/usb/pegasus.h	Mon Oct  1 13:45:47 2001
+++ linux/drivers/usb/pegasus.h	Mon Dec  3 23:18:28 2001
@@ -131,6 +131,8 @@
 #define	VENDOR_ABOCOM		0x07b8
 #define	VENDOR_ACCTON		0x083a
 #define	VENDOR_ADMTEK		0x07a6
+#define	VENDOR_ALLIEDTEL	0x07c9
+#define	VENDOR_BELKIN		0x050d
 #define	VENDOR_BILLIONTON	0x08dd
 #define	VENDOR_COREGA		0x07aa
 #define	VENDOR_DLINK		0x2001
@@ -142,7 +144,7 @@
 #define	VENDOR_SMARTBRIDGES	0x08d1
 #define	VENDOR_SMC		0x0707
 #define	VENDOR_SOHOWARE		0x15e8
-#define	VENDOR_BELKIN		0x050d
+
 
 #else	/* PEGASUS_DEV */
 
@@ -176,6 +178,10 @@
 PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)",
 		VENDOR_ADMTEK, 0x0986,
 		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
+PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986,
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987,
@@ -236,8 +242,6 @@
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
 		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "Belkin F5D5050 USB Ethernet",
-		VENDOR_BELKIN, 0x0121,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
+
 
 #endif	/* PEGASUS_DEV */
diff -urN linux-2.4.13-pre3/drivers/usb/pwc-ctrl.c linux/drivers/usb/pwc-ctrl.c
--- linux-2.4.13-pre3/drivers/usb/pwc-ctrl.c	Sat Sep 15 22:21:43 2001
+++ linux/drivers/usb/pwc-ctrl.c	Mon Dec  3 23:18:28 2001
@@ -495,7 +495,7 @@
 }
 
 
-#ifdef __KERNEL__
+
 /* BRIGHTNESS */
 
 int pwc_get_brightness(struct pwc_device *pdev)
@@ -983,6 +983,7 @@
 	
 	return (buf << 8);
 }
+
 static inline int pwc_read_blue_gain(struct pwc_device *pdev)
 {
 	unsigned char buf;
@@ -1001,43 +1002,55 @@
 	return (buf << 8);
 }
 
-/* still unused (it doesn't work yet...) */
-static inline int pwc_set_led(struct pwc_device *pdev, int value)
+int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
 {
-	unsigned char buf;
+	unsigned char buf[2];
 
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
+	if (pdev->type < 730)
+		return 0;
+	if (on_value < 0)
+		on_value = 0;
+	if (on_value > 0xff)
+		on_value = 0xff;
+	if (off_value < 0)
+		off_value = 0;
+	if (off_value > 0xff)
+		off_value = 0xff;
 
-	buf = (value >> 8);
+	buf[0] = on_value;
+	buf[1] = off_value;
 
 	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
 		SET_STATUS_CTL,
 		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 		LED_FORMATTER,
 		pdev->vcinterface,
-		&buf, 1, HZ / 2);
+		&buf, 2, HZ / 2);
 }
 
-/* still unused (it doesn't work yet...) */
-static inline int pwc_get_led(struct pwc_device *pdev)
+int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
 {
-	unsigned char buf;
+	unsigned char buf[2];
 	int ret;
 	
+	if (pdev->type < 730) {
+		*on_value = -1;
+		*off_value = -1;
+		return 0;
+	}
+
 	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
    	        GET_STATUS_CTL,
 		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 		LED_FORMATTER,
 		pdev->vcinterface,
-		&buf, 1, HZ / 2);
+		&buf, 2, HZ / 2);
 
 	if (ret < 0)
-	    return ret;
-	
-	return (buf << 8);
+		return ret;
+	*on_value = buf[0];
+	*off_value = buf[1];
+	return 0;
 }
 
  /* End of Add-Ons                                    */
@@ -1167,15 +1180,15 @@
 
         case VIDIOCPWCSLED:
 	{
-	    int led, ret;
-	    if (copy_from_user(&led,arg,sizeof(led)))
-		return -EFAULT;
-	    else {
-		/* ret = pwc_set_led(pdev, led); */
-		ret = 0;
+		int ret;
+		struct pwc_leds leds;
+
+		if (copy_from_user(&leds, arg, sizeof(leds)))
+			return -EFAULT;
+
+		ret = pwc_set_leds(pdev, leds.led_on, leds.led_off);
 		if (ret<0)
 		    return ret;
-	    }
 	    break;
 	}
 
@@ -1184,11 +1197,12 @@
 	case VIDIOCPWCGLED:
 	{
 		int led;
+		struct pwc_leds leds;
 		
-		led = pwc_get_led(pdev); 
+		led = pwc_get_leds(pdev, &leds.led_on, &leds.led_off); 
 		if (led < 0)
 			return -EINVAL;
-		if (copy_to_user(arg, &led, sizeof(led)))
+		if (copy_to_user(arg, &leds, sizeof(leds)))
 			return -EFAULT;
 		break;
 	}
@@ -1202,9 +1216,6 @@
 	}
 	return 0;
 }
-
-#endif
-
 
 
 
diff -urN linux-2.4.13-pre3/drivers/usb/pwc-if.c linux/drivers/usb/pwc-if.c
--- linux-2.4.13-pre3/drivers/usb/pwc-if.c	Sat Sep 15 22:21:43 2001
+++ linux/drivers/usb/pwc-if.c	Mon Dec  3 23:18:28 2001
@@ -73,7 +73,9 @@
 	{ USB_DEVICE(0x0471, 0x0311) },
 	{ USB_DEVICE(0x0471, 0x0312) },
 	{ USB_DEVICE(0x069A, 0x0001) },
-	{ USB_DEVICE(0x046D, 0x0b80) },
+	{ USB_DEVICE(0x046D, 0x08b0) },
+	{ USB_DEVICE(0x055D, 0x9000) },
+	{ USB_DEVICE(0x055D, 0x9001) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, pwc_device_table);
@@ -96,6 +98,7 @@
 static int default_mbufs = 2;	/* Default number of mmap() buffers */
        int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
 static int power_save = 0;
+static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */
 int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
 
 static struct semaphore mem_lock;
@@ -592,7 +595,8 @@
 	pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
 }
 
-/* XXX: 2001-06-17: The YUV420 palette will be phased out soon */
+/* 2001-10-14: The YUV420 is still there, but you can only set it from within 
+   a program (YUV420P being the default) */
 static int pwc_set_palette(struct pwc_device *pdev, int pal)
 {
 	if (   pal == VIDEO_PALETTE_YUV420
@@ -947,14 +951,16 @@
 			Info("Failed to set alternate interface to 0.\n");
 		pdev->usb_init = 1;
 	}
-	else {
-		/* Turn on camera */
-		if (power_save) {
-			i = pwc_camera_power(pdev, 1);
-			if (i < 0)
-				Info("Failed to restore power to the camera! (%d)\n", i);
-		}
+
+	/* Turn on camera */
+	if (power_save) {
+		i = pwc_camera_power(pdev, 1);
+		if (i < 0)
+			Info("Failed to restore power to the camera! (%d)\n", i);
 	}
+	/* Set LED on/off time */
+	if (pwc_set_leds(pdev, led_on, led_off) < 0)
+		Info("Failed to set LED on/off time.\n");
 
 	/* Find our decompressor, if any */
 	pdev->decompressor = pwc_find_decompressor(pdev->type);
@@ -1007,6 +1013,7 @@
 		up(&pdev->modlock);
 		return i;
 	}
+	
 	i = usb_set_interface(pdev->udev, 0, pdev->valternate);
 	if (i) {
 		Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i);
@@ -1066,7 +1073,10 @@
 		Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n");
 		usb_set_interface(pdev->udev, 0, 0);
 
-		/* Turn off LED by powering down camera */
+		/* Turn LEDs off */
+		if (pwc_set_leds(pdev, 0, 0) < 0)
+			Info("Failed to set LED on/off time..\n");
+		/* Power down camere to save energy */
 		if (power_save) {
 			i = pwc_camera_power(pdev, 0);
 			if (i < 0) 
@@ -1121,19 +1131,19 @@
 		while (pdev->full_frames == NULL) {
 	                if (noblock) {
 	                	remove_wait_queue(&pdev->frameq, &wait);
-	                	current->state = TASK_RUNNING;
+	                	set_current_state(TASK_RUNNING);
 	                	return -EWOULDBLOCK;
 	                }
 	                if (signal_pending(current)) {
 	                	remove_wait_queue(&pdev->frameq, &wait);
-	                	current->state = TASK_RUNNING;
+	                	set_current_state(TASK_RUNNING);
 	                	return -ERESTARTSYS;
 	                }
 	                schedule();
-	                current->state = TASK_INTERRUPTIBLE;
+	                set_current_state(TASK_INTERRUPTIBLE);
 		}
 		remove_wait_queue(&pdev->frameq, &wait);
-		current->state = TASK_RUNNING;
+		set_current_state(TASK_RUNNING);
 	                                                                                                                                                                                
 		/* Decompress [, convert] and release frame */
 		if (pwc_handle_frame(pdev))
@@ -1473,14 +1483,14 @@
 			while (pdev->full_frames == NULL) {
 	                	if (signal_pending(current)) {
 	                		remove_wait_queue(&pdev->frameq, &wait);
-		                	current->state = TASK_RUNNING;
+		                	set_current_state(TASK_RUNNING);
 		                	return -ERESTARTSYS;
 	        	        }
 	                	schedule();
-		                current->state = TASK_INTERRUPTIBLE;
+		                set_current_state(TASK_INTERRUPTIBLE);
 			}
 			remove_wait_queue(&pdev->frameq, &wait);
-			current->state = TASK_RUNNING;
+			set_current_state(TASK_RUNNING);
 				
 			/* The frame is ready. Expand in the image buffer 
 			   requested by the user. I don't care if you 
@@ -1656,18 +1666,37 @@
 			break;
 		}
 	}
-        else if (vendor_id == 0x046d) {
-        	switch(product_id) {
-        	case 0x08b0:
-        		Info("Logitech QuickCam 3000 Pro detected.\n");
-        		type_id = 730;
+	else if (vendor_id == 0x046d) {
+		switch(product_id) {
+		case 0x08b0:
+			Info("Logitech QuickCam 3000 Pro detected.\n");
+			type_id = 730;
         		break;
         	default:
         		return NULL;
         		break;
         	}
         }
-        else return NULL; /* Not Philips or Askey, for sure. */
+	else if (vendor_id == 0x055d) {
+		/* I don't know the difference between the C10 and the C30;
+		   I suppose the difference is the sensor, but both cameras
+		   work equally well with a type_id of 675
+		 */
+		switch(product_id) {
+		case 0x9000:
+			Info("Samsung MPC-C10 USB webcam detected.\n");
+			type_id = 675;
+			break;
+		case 0x9001:
+			Info("Samsung MPC-C30 USB webcam detected.\n");
+			type_id = 675;
+			break;
+		default:
+			return NULL;
+			break;
+		}
+	}
+	else return NULL; /* Not Philips, Askey, Logitech or Samsung, for sure. */
 
 	if (udev->descriptor.bNumConfigurations > 1)
 		Info("Warning: more than 1 configuration available.\n");
@@ -1799,19 +1828,17 @@
 
 static char *size = NULL;
 static int fps = 0;
-static char *palette = NULL;
 static int fbufs = 0;
 static int mbufs = 0;
 static int trace = -1;
 static int compression = -1;
+static int leds[2] = { -1, -1 };
 
 MODULE_PARM(video_nr, "i");
 MODULE_PARM(size, "s");
 MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
 MODULE_PARM(fps, "i");
 MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
-MODULE_PARM(palette, "s");
-MODULE_PARM_DESC(palette, "Initial colour format of images. One of yuv420, yuv420p");
 MODULE_PARM(fbufs, "i");
 MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
 MODULE_PARM(mbufs, "i");
@@ -1822,7 +1849,8 @@
 MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
 MODULE_PARM(compression, "i");
 MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
-
+MODULE_PARM(leds, "2i");
+MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
 MODULE_DESCRIPTION("Philips USB webcam driver");
 MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
 MODULE_LICENSE("GPL");
@@ -1833,7 +1861,7 @@
 	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
 
 	Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
-	Info("Also supports Askey VC010 cam.\n");
+	Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro and the Samsung MPC-C10 and MPC-C30.\n");
 
 	if (fps) {
 		if (fps < 5 || fps > 30) {
@@ -1858,18 +1886,6 @@
 		}
 		Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
 	}
-	if (palette) {
-		/* Determine default palette */
-		if (!strcmp(palette, "yuv420"))
-			default_palette = VIDEO_PALETTE_YUV420;
-		else if (!strcmp(palette, "yuv420p"))
-			default_palette = VIDEO_PALETTE_YUV420P;
-		else {
-			Err("Palette not recognized: try palette=yuv420 or yuv420p.\n");
-			return -EINVAL;
-		}
-		Info("Default palette set to %d.\n", default_palette);
-	}
 	if (mbufs) {
 		if (mbufs < 1 || mbufs > MAX_IMAGES) {
 			Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
@@ -1900,6 +1916,10 @@
 	}
 	if (power_save)
 		Info("Enabling power save on open/close.\n");
+	if (leds[0] >= 0)
+		led_on = leds[0] / 100;
+	if (leds[1] >= 0)
+		led_off = leds[1] / 100;
 
 	init_MUTEX(&mem_lock);
  	Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
diff -urN linux-2.4.13-pre3/drivers/usb/pwc-ioctl.h linux/drivers/usb/pwc-ioctl.h
--- linux-2.4.13-pre3/drivers/usb/pwc-ioctl.h	Sat Sep 15 22:21:43 2001
+++ linux/drivers/usb/pwc-ioctl.h	Mon Dec  3 23:18:28 2001
@@ -76,6 +76,15 @@
 };
 
 
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+	int led_on;			/* Led on-time; range = 0..255 */
+	int led_off;			/*  */
+};
+
+
+
  /* Restore user settings */
 #define VIDIOCPWCRUSER		_IO('v', 192)
  /* Save user settings */
@@ -107,9 +116,8 @@
 #define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
 
  /* Turn LED on/off ; int range 0..65535 */
-#define VIDIOCPWCSLED           _IOW('v', 205, int)
-
+#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
  /* Get state of LED; int range 0..65535 */
-#define VIDIOCPWCGLED           _IOR('v', 205, int)
+#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
 
 #endif
diff -urN linux-2.4.13-pre3/drivers/usb/pwc.h linux/drivers/usb/pwc.h
--- linux-2.4.13-pre3/drivers/usb/pwc.h	Sat Sep 15 22:21:43 2001
+++ linux/drivers/usb/pwc.h	Mon Dec  3 23:18:28 2001
@@ -60,8 +60,8 @@
 
 /* Version block */
 #define PWC_MAJOR	8
-#define PWC_MINOR	2
-#define PWC_VERSION 	"8.2"
+#define PWC_MINOR	3
+#define PWC_VERSION 	"8.3"
 #define PWC_NAME 	"pwc"
 
 /* Turn certain features on/off */
@@ -245,6 +245,8 @@
 extern int pwc_set_gamma(struct pwc_device *pdev, int value);
 extern int pwc_get_saturation(struct pwc_device *pdev);
 extern int pwc_set_saturation(struct pwc_device *pdev, int value);
+extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
+extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
 
 /* Power down or up the camera; not supported by all models */
 extern int pwc_camera_power(struct pwc_device *pdev, int power);
diff -urN linux-2.4.13-pre3/drivers/usb/serial/Config.in linux/drivers/usb/serial/Config.in
--- linux-2.4.13-pre3/drivers/usb/serial/Config.in	Tue Oct  9 15:15:02 2001
+++ linux/drivers/usb/serial/Config.in	Mon Dec  3 23:18:28 2001
@@ -5,36 +5,32 @@
 comment 'USB Serial Converter support'
 
 dep_tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
-if [ "$CONFIG_USB_SERIAL" != "n" ]; then
-  if [ "$CONFIG_USB_SERIAL" = "y" ]; then
-     bool '  USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG
-  fi
-  bool '  USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC
-  dep_tristate '  USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL
-  dep_tristate '  USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
-  dep_tristate '  USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  if [ "$CONFIG_USB_SERIAL_KEYSPAN" != "n" ]; then
-     bool '    USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28
-     bool '    USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X
-     bool '    USB Keyspan USA-28XA Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XA
-     bool '    USB Keyspan USA-28XB Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XB
-     bool '    USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19
-     bool '    USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X
-     bool '    USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W
-     bool '    USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W
-  fi
-  dep_tristate '  USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-  dep_tristate '  USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+if [ "$CONFIG_USB_SERIAL" = "y" ]; then
+  dep_mbool '  USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG $CONFIG_USB_SERIAL
 fi
+dep_mbool '  USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC $CONFIG_USB_SERIAL
+dep_tristate '  USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL
+dep_tristate '  USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
+dep_tristate '  USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+   dep_mbool '    USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28 $CONFIG_USB_SERIAL_KEYSPAN
+   dep_mbool '    USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X $CONFIG_USB_SERIAL_KEYSPAN
+   dep_mbool '    USB Keyspan USA-28XA Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XA $CONFIG_USB_SERIAL_KEYSPAN
+   dep_mbool '    USB Keyspan USA-28XB Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XB $CONFIG_USB_SERIAL_KEYSPAN
+   dep_mbool '    USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19 $CONFIG_USB_SERIAL_KEYSPAN
+   dep_mbool '    USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X $CONFIG_USB_SERIAL_KEYSPAN
+   dep_mbool '    USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W $CONFIG_USB_SERIAL_KEYSPAN
+   dep_mbool '    USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W $CONFIG_USB_SERIAL_KEYSPAN
+dep_tristate '  USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 
 endmenu
diff -urN linux-2.4.13-pre3/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- linux-2.4.13-pre3/drivers/usb/uhci.c	Mon Dec  3 23:18:18 2001
+++ linux/drivers/usb/uhci.c	Mon Dec  3 23:18:28 2001
@@ -159,7 +159,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	uhci->skel_term_td->status |= TD_CTRL_IOC;
+	set_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
 	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 }
 
@@ -168,7 +168,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	uhci->skel_term_td->status &= ~TD_CTRL_IOC;
+	clear_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
 	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 }
 
@@ -796,7 +796,7 @@
 	if (status & TD_CTRL_NAK)			/* NAK */
 		return -ETIMEDOUT;
 	if (status & TD_CTRL_BABBLE)			/* Babble */
-		return -EPIPE;
+		return -EOVERFLOW;
 	if (status & TD_CTRL_DBUFERR)			/* Buffer error */
 		return -ENOSR;
 	if (status & TD_CTRL_STALLED)			/* Stalled */
@@ -961,7 +961,7 @@
 		    !(td->status & TD_CTRL_ACTIVE)) {
 			uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
 			urbp->fsbr_timeout = 0;
-			td->status &= ~TD_CTRL_IOC;
+			clear_bit(TD_CTRL_IOC_BIT, &td->status);
 		}
 
 		status = uhci_status_bits(td->status);
@@ -1134,7 +1134,7 @@
 		    !(td->status & TD_CTRL_ACTIVE)) {
 			uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
 			urbp->fsbr_timeout = 0;
-			td->status &= ~TD_CTRL_IOC;
+			clear_bit(TD_CTRL_IOC_BIT, &td->status);
 		}
 
 		status = uhci_status_bits(td->status);
@@ -1796,7 +1796,7 @@
 		tmp = tmp->next;
 
 		if (td->status & TD_CTRL_ACTIVE) {
-			td->status |= TD_CTRL_IOC;
+			set_bit(TD_CTRL_IOC_BIT, &td->status);
 			break;
 		}
 	}
diff -urN linux-2.4.13-pre3/drivers/usb/uhci.h linux/drivers/usb/uhci.h
--- linux-2.4.13-pre3/drivers/usb/uhci.h	Wed Oct 10 23:47:51 2001
+++ linux/drivers/usb/uhci.h	Mon Dec  3 23:18:28 2001
@@ -100,6 +100,7 @@
 #define TD_CTRL_C_ERR_SHIFT	27
 #define TD_CTRL_LS		(1 << 26)	/* Low Speed Device */
 #define TD_CTRL_IOS		(1 << 25)	/* Isochronous Select */
+#define TD_CTRL_IOC_BIT		24
 #define TD_CTRL_IOC		(1 << 24)	/* Interrupt on Complete */
 #define TD_CTRL_ACTIVE		(1 << 23)	/* TD Active */
 #define TD_CTRL_STALLED		(1 << 22)	/* TD Stalled */
diff -urN linux-2.4.13-pre3/drivers/usb/ultracam.c linux/drivers/usb/ultracam.c
--- linux-2.4.13-pre3/drivers/usb/ultracam.c	Fri Oct  5 12:04:51 2001
+++ linux/drivers/usb/ultracam.c	Mon Dec  3 23:18:28 2001
@@ -537,11 +537,7 @@
  * 12-Nov-2000 Reworked to comply with new probe() signature.
  * 23-Jan-2001 Added compatibility with 2.2.x kernels.
  */
-static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum
-#if defined(usb_device_id_ver)
-	,const struct usb_device_id *devid
-#endif
-	)
+static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum ,const struct usb_device_id *devid)
 {
 	uvd_t *uvd = NULL;
 	int i, nas;
diff -urN linux-2.4.13-pre3/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- linux-2.4.13-pre3/drivers/usb/usb-uhci.c	Tue Oct  9 15:15:02 2001
+++ linux/drivers/usb/usb-uhci.c	Mon Dec  3 23:18:28 2001
@@ -2193,7 +2193,7 @@
 	if (status & TD_CTRL_NAK)	/* NAK */
 		return -ETIMEDOUT;
 	if (status & TD_CTRL_BABBLE)	/* Babble */
-		return -EPIPE;
+		return -EOVERFLOW;
 	if (status & TD_CTRL_DBUFERR)	/* Buffer error */
 		return -ENOSR;
 	if (status & TD_CTRL_STALLED)	/* Stalled */
diff -urN linux-2.4.13-pre3/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c
--- linux-2.4.13-pre3/drivers/video/cgsixfb.c	Mon Dec  3 23:18:18 2001
+++ linux/drivers/video/cgsixfb.c	Mon Dec  3 23:18:28 2001
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.25 2001/09/19 00:04:33 davem Exp $
+/* $Id: cgsixfb.c,v 1.26 2001/10/16 05:44:44 davem Exp $
  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
diff -urN linux-2.4.13-pre3/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
--- linux-2.4.13-pre3/drivers/video/creatorfb.c	Mon Dec  3 23:18:18 2001
+++ linux/drivers/video/creatorfb.c	Mon Dec  3 23:18:28 2001
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.36 2001/09/19 00:04:33 davem Exp $
+/* $Id: creatorfb.c,v 1.37 2001/10/16 05:44:44 davem Exp $
  * creatorfb.c: Creator/Creator3D frame buffer driver
  *
  * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
diff -urN linux-2.4.13-pre3/drivers/video/leofb.c linux/drivers/video/leofb.c
--- linux-2.4.13-pre3/drivers/video/leofb.c	Mon Dec  3 23:18:18 2001
+++ linux/drivers/video/leofb.c	Mon Dec  3 23:18:28 2001
@@ -1,4 +1,4 @@
-/* $Id: leofb.c,v 1.13 2001/09/19 00:04:33 davem Exp $
+/* $Id: leofb.c,v 1.14 2001/10/16 05:44:44 davem Exp $
  * leofb.c: Leo (ZX) 24/8bit frame buffer driver
  *
  * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
diff -urN linux-2.4.13-pre3/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.13-pre3/fs/buffer.c	Mon Dec  3 23:18:18 2001
+++ linux/fs/buffer.c	Mon Dec  3 23:18:28 2001
@@ -508,11 +508,13 @@
 	size_buffers_type[blist] += bh->b_size;
 }
 
-static void __remove_from_lru_list(struct buffer_head * bh, int blist)
+static void __remove_from_lru_list(struct buffer_head * bh)
 {
 	struct buffer_head *next = bh->b_next_free;
 	if (next) {
 		struct buffer_head *prev = bh->b_prev_free;
+		int blist = bh->b_list;
+
 		prev->b_next_free = next;
 		next->b_prev_free = prev;
 		if (lru_list[blist] == bh) {
@@ -532,7 +534,7 @@
 static void __remove_from_queues(struct buffer_head *bh)
 {
 	__hash_unlink(bh);
-	__remove_from_lru_list(bh, bh->b_list);
+	__remove_from_lru_list(bh);
 }
 
 struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
@@ -1101,7 +1103,7 @@
 	if (buffer_dirty(bh))
 		dispose = BUF_DIRTY;
 	if (dispose != bh->b_list) {
-		__remove_from_lru_list(bh, bh->b_list);
+		__remove_from_lru_list(bh);
 		bh->b_list = dispose;
 		if (dispose == BUF_CLEAN)
 			remove_inode_queue(bh);
@@ -1134,8 +1136,26 @@
  */
 void __bforget(struct buffer_head * buf)
 {
-	/* mark_buffer_clean(bh); */
-	__brelse(buf);
+	/* grab the lru lock here so that "b_count" is stable */
+	spin_lock(&lru_list_lock);
+	write_lock(&hash_table_lock);
+	if (!atomic_dec_and_test(&buf->b_count) || buffer_locked(buf))
+		goto in_use;
+
+	/* Mark it clean */
+	clear_bit(BH_Dirty, &buf->b_state);
+	write_unlock(&hash_table_lock);
+
+	/* After which we can remove it from all queues */
+	remove_inode_queue(buf);
+	__remove_from_lru_list(buf);
+	buf->b_list = BUF_CLEAN;
+	spin_unlock(&lru_list_lock);
+	return;
+
+in_use:
+	write_unlock(&hash_table_lock);
+	spin_unlock(&lru_list_lock);
 }
 
 /**
diff -urN linux-2.4.13-pre3/fs/hfs/catalog.c linux/fs/hfs/catalog.c
--- linux-2.4.13-pre3/fs/hfs/catalog.c	Tue Feb 13 14:13:45 2001
+++ linux/fs/hfs/catalog.c	Mon Dec  3 23:18:28 2001
@@ -100,7 +100,7 @@
 static LIST_HEAD(entry_unused);
 static struct list_head hash_table[C_HASHSIZE];
 
-spinlock_t entry_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t entry_lock = SPIN_LOCK_UNLOCKED;
 
 static struct {
         int nr_entries;
diff -urN linux-2.4.13-pre3/fs/namei.c linux/fs/namei.c
--- linux-2.4.13-pre3/fs/namei.c	Wed Oct 10 23:15:49 2001
+++ linux/fs/namei.c	Mon Dec  3 23:18:28 2001
@@ -646,10 +646,14 @@
 static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
 {
 	if (path_walk(name, nd))
-		return 0;
+		return 0;		/* something went wrong... */
 
-	if (!nd->dentry->d_inode) {
+	if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) {
 		struct nameidata nd_root;
+		/*
+		 * NAME was not found in alternate root or it's a directory.  Try to find
+		 * it in the normal root:
+		 */
 		nd_root.last_type = LAST_ROOT;
 		nd_root.flags = nd->flags;
 		read_lock(&current->fs->lock);
diff -urN linux-2.4.13-pre3/fs/namespace.c linux/fs/namespace.c
--- linux-2.4.13-pre3/fs/namespace.c	Wed Oct 10 15:39:04 2001
+++ linux/fs/namespace.c	Mon Dec  3 23:18:28 2001
@@ -153,6 +153,8 @@
 		atomic_inc(&sb->s_active);
 		mnt->mnt_sb = sb;
 		mnt->mnt_root = dget(root);
+		mnt->mnt_mountpoint = mnt->mnt_root;
+		mnt->mnt_parent = mnt;
 	}
 	return mnt;
 }
@@ -1086,7 +1088,7 @@
 		printk(KERN_NOTICE "Trying to unmount old root ... ");
 		if (!blivet) {
 			spin_lock(&dcache_lock);
-			list_del(&old_rootmnt->mnt_list);
+			list_del_init(&old_rootmnt->mnt_list);
  			spin_unlock(&dcache_lock);
  			mntput(old_rootmnt);
 			mntput(old_rootmnt);
diff -urN linux-2.4.13-pre3/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- linux-2.4.13-pre3/fs/nfsd/nfsproc.c	Fri Sep 14 14:16:08 2001
+++ linux/fs/nfsd/nfsproc.c	Mon Dec  3 23:18:28 2001
@@ -86,8 +86,8 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: LOOKUP   %s %s\n",
-		SVCFH_fmt(&argp->fh), argp->name);
+	dprintk("nfsd: LOOKUP   %s %.*s\n",
+		SVCFH_fmt(&argp->fh), argp->len, argp->name);
 
 	fh_init(&resp->fh, NFS_FHSIZE);
 	nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
@@ -199,8 +199,8 @@
 	int		nfserr, type, mode;
 	dev_t		rdev = NODEV;
 
-	dprintk("nfsd: CREATE   %s %s\n",
-		SVCFH_fmt(dirfhp), argp->name);
+	dprintk("nfsd: CREATE   %s %*.s\n",
+		SVCFH_fmt(dirfhp), argp->len, argp->name);
 
 	/* First verify the parent file handle */
 	nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC);
@@ -349,7 +349,8 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: REMOVE   %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
+	dprintk("nfsd: REMOVE   %s %.*s\n", SVCFH_fmt(&argp->fh),
+		argp->len, argp->name);
 
 	/* Unlink. -SIFDIR means file must not be a directory */
 	nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
@@ -363,10 +364,10 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: RENAME   %s %s -> \n",
-		SVCFH_fmt(&argp->ffh), argp->fname);
-	dprintk("nfsd:        ->  %s %s\n",
-		SVCFH_fmt(&argp->tfh), argp->tname);
+	dprintk("nfsd: RENAME   %s %.*s -> \n",
+		SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
+	dprintk("nfsd:        ->  %s %.*s\n",
+		SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
 
 	nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
 				    &argp->tfh, argp->tname, argp->tlen);
@@ -383,8 +384,9 @@
 
 	dprintk("nfsd: LINK     %s ->\n",
 		SVCFH_fmt(&argp->ffh));
-	dprintk("nfsd:    %s %s\n",
+	dprintk("nfsd:    %s %.*s\n",
 		SVCFH_fmt(&argp->tfh),
+		argp->tlen,
 		argp->tname);
 
 	nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
@@ -401,8 +403,9 @@
 	struct svc_fh	newfh;
 	int		nfserr;
 
-	dprintk("nfsd: SYMLINK  %s %s -> %s\n",
-		SVCFH_fmt(&argp->ffh), argp->fname, argp->tname);
+	dprintk("nfsd: SYMLINK  %s %.*s -> %.*s\n",
+		SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
+		argp->tlen, argp->tname);
 
 	fh_init(&newfh, NFS_FHSIZE);
 	/*
@@ -428,7 +431,7 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: MKDIR    %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
+	dprintk("nfsd: MKDIR    %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
 
 	if (resp->fh.fh_dentry) {
 		printk(KERN_WARNING
@@ -452,7 +455,7 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: RMDIR    %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
+	dprintk("nfsd: RMDIR    %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
 
 	nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
 	fh_put(&argp->fh);
diff -urN linux-2.4.13-pre3/fs/nfsd/nfssvc.c linux/fs/nfsd/nfssvc.c
--- linux-2.4.13-pre3/fs/nfsd/nfssvc.c	Thu Sep 20 21:02:01 2001
+++ linux/fs/nfsd/nfssvc.c	Mon Dec  3 23:18:28 2001
@@ -162,7 +162,7 @@
 	lock_kernel();
 	daemonize();
 	sprintf(current->comm, "nfsd");
-	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 
+	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
 
 	nfsdstats.th_cnt++;
 	/* Let svc_process check client's authentication. */
diff -urN linux-2.4.13-pre3/fs/nfsd/nfsxdr.c linux/fs/nfsd/nfsxdr.c
--- linux-2.4.13-pre3/fs/nfsd/nfsxdr.c	Mon Dec  3 23:18:18 2001
+++ linux/fs/nfsd/nfsxdr.c	Mon Dec  3 23:18:28 2001
@@ -86,7 +86,6 @@
 			if (*name == '\0')
 				return NULL;
 		}
-		*name = '\0';
 	}
 
 	return p;
diff -urN linux-2.4.13-pre3/fs/udf/udfdecl.h linux/fs/udf/udfdecl.h
--- linux-2.4.13-pre3/fs/udf/udfdecl.h	Mon Dec  3 23:18:18 2001
+++ linux/fs/udf/udfdecl.h	Mon Dec  3 23:18:28 2001
@@ -150,7 +150,7 @@
 
 /* lowlevel.c */
 extern unsigned int udf_get_last_session(struct super_block *);
-extern unsigned int udf_get_last_block(struct super_block *);
+extern unsigned long udf_get_last_block(struct super_block *);
 
 /* partition.c */
 extern Uint32 udf_get_pblock(struct super_block *, Uint32, Uint16, Uint32);
diff -urN linux-2.4.13-pre3/include/asm-i386/system.h linux/include/asm-i386/system.h
--- linux-2.4.13-pre3/include/asm-i386/system.h	Mon Dec  3 23:18:18 2001
+++ linux/include/asm-i386/system.h	Mon Dec  3 23:18:28 2001
@@ -349,4 +349,6 @@
 void disable_hlt(void);
 void enable_hlt(void);
 
+extern int is_sony_vaio_laptop;
+
 #endif
diff -urN linux-2.4.13-pre3/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- linux-2.4.13-pre3/include/asm-i386/unistd.h	Mon Oct  8 10:40:16 2001
+++ linux/include/asm-i386/unistd.h	Mon Dec  3 23:18:28 2001
@@ -229,6 +229,7 @@
 #define __NR_fcntl64		221
 #define __NR_security		223	/* syscall for security modules */
 #define __NR_gettid		224
+#define __NR_readahead		225
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff -urN linux-2.4.13-pre3/include/asm-sparc/highmem.h linux/include/asm-sparc/highmem.h
--- linux-2.4.13-pre3/include/asm-sparc/highmem.h	Sun Feb 18 19:49:55 2001
+++ linux/include/asm-sparc/highmem.h	Mon Dec  3 23:18:28 2001
@@ -111,14 +111,11 @@
 
 static inline void kunmap_atomic(void *kvaddr, enum km_type type)
 {
-#if HIGHMEM_DEBUG
 	unsigned long vaddr = (unsigned long) kvaddr;
 	unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
 
-#if 0
-	if (vaddr < FIXADDR_START) // FIXME
+	if (vaddr < FIX_KMAP_BEGIN) // FIXME
 		return;
-#endif
 
 	if (vaddr != FIX_KMAP_BEGIN + idx * PAGE_SIZE)
 		BUG();
@@ -130,6 +127,7 @@
 	flush_cache_all();
 #endif
 
+#ifdef HIGHMEM_DEBUG
 	/*
 	 * force other mappings to Oops if they'll try to access
 	 * this pte without first remap it
diff -urN linux-2.4.13-pre3/include/asm-sparc64/cache.h linux/include/asm-sparc64/cache.h
--- linux-2.4.13-pre3/include/asm-sparc64/cache.h	Fri Aug  6 11:58:00 1999
+++ linux/include/asm-sparc64/cache.h	Mon Dec  3 23:18:28 2001
@@ -9,7 +9,8 @@
 
 #define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 
-#define        SMP_CACHE_BYTES		64 /* L2 cache line size. */
+#define        SMP_CACHE_BYTES_SHIFT	6
+#define        SMP_CACHE_BYTES		(1 << SMP_CACHE_BYTES_SHIFT) /* L2 cache line size. */
 
 #ifdef MODULE
 #define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
diff -urN linux-2.4.13-pre3/include/asm-sparc64/hardirq.h linux/include/asm-sparc64/hardirq.h
--- linux-2.4.13-pre3/include/asm-sparc64/hardirq.h	Mon Jul  9 14:47:39 2001
+++ linux/include/asm-sparc64/hardirq.h	Mon Dec  3 23:18:28 2001
@@ -12,6 +12,7 @@
 #include <linux/spinlock.h>
 
 /* entry.S is sensitive to the offsets of these fields */
+/* rtrap.S is sensitive to the size of this structure */
 typedef struct {
 	unsigned int __softirq_pending;
 	unsigned int __unused_1;
diff -urN linux-2.4.13-pre3/include/linux/ethtool.h linux/include/linux/ethtool.h
--- linux-2.4.13-pre3/include/linux/ethtool.h	Tue Aug 14 10:14:12 2001
+++ linux/include/linux/ethtool.h	Mon Dec  3 23:18:28 2001
@@ -53,7 +53,10 @@
 #define ETHTOOL_GDRVINFO	0x00000003 /* Get driver info. */
 #define ETHTOOL_GREGS		0x00000004 /* Get NIC registers, privileged. */
 #define ETHTOOL_GWOL		0x00000005 /* Get wake-on-lan options. */
-#define ETHTOOL_SWOL		0x00000006 /* Set wake-on-lan options. */
+#define ETHTOOL_SWOL		0x00000006 /* Set wake-on-lan options, priv. */
+#define ETHTOOL_GMSGLVL		0x00000007 /* Get driver message level */
+#define ETHTOOL_SMSGLVL		0x00000008 /* Set driver msg level, priv. */
+#define ETHTOOL_NWAY_RST	0X00000009 /* Restart autonegotiation, priv. */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
@@ -71,6 +74,7 @@
 #define SUPPORTED_AUI			(1 << 8)
 #define SUPPORTED_MII			(1 << 9)
 #define SUPPORTED_FIBRE			(1 << 10)
+#define SUPPORTED_10base2		(1 << 11)
 
 /* Indicates what features are advertised by the interface. */
 #define ADVERTISED_10baseT_Half		(1 << 0)
@@ -84,6 +88,7 @@
 #define ADVERTISED_AUI			(1 << 8)
 #define ADVERTISED_MII			(1 << 9)
 #define ADVERTISED_FIBRE		(1 << 10)
+#define ADVERTISED_10base2		(1 << 11)
 
 /* The following are all involved in forcing a particular link
  * mode for the device for setting things.  When getting the
diff -urN linux-2.4.13-pre3/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- linux-2.4.13-pre3/include/linux/pci_ids.h	Mon Dec  3 23:18:18 2001
+++ linux/include/linux/pci_ids.h	Mon Dec  3 23:18:28 2001
@@ -1604,6 +1604,7 @@
 #define PCI_DEVICE_ID_INTEL_82801CA_10	0x248a
 #define PCI_DEVICE_ID_INTEL_82801CA_11	0x248b
 #define PCI_DEVICE_ID_INTEL_82801CA_12	0x248c
+#define PCI_DEVICE_ID_INTEL_80310	0x530d
 #define PCI_DEVICE_ID_INTEL_82810_MC1	0x7120
 #define PCI_DEVICE_ID_INTEL_82810_IG1	0x7121
 #define PCI_DEVICE_ID_INTEL_82810_MC3	0x7122
diff -urN linux-2.4.13-pre3/include/linux/swap.h linux/include/linux/swap.h
--- linux-2.4.13-pre3/include/linux/swap.h	Wed Oct 10 23:44:34 2001
+++ linux/include/linux/swap.h	Mon Dec  3 23:18:28 2001
@@ -110,7 +110,7 @@
 
 /* linux/mm/vmscan.c */
 extern wait_queue_head_t kswapd_wait;
-extern int FASTCALL(try_to_free_pages(zone_t *, unsigned int, unsigned int));
+extern int FASTCALL(try_to_free_pages(unsigned int, unsigned int));
 
 /* linux/mm/page_io.c */
 extern void rw_swap_page(int, struct page *);
diff -urN linux-2.4.13-pre3/include/net/route.h linux/include/net/route.h
--- linux-2.4.13-pre3/include/net/route.h	Wed Oct 10 23:44:57 2001
+++ linux/include/net/route.h	Mon Dec  3 23:18:28 2001
@@ -37,9 +37,12 @@
 #endif
 
 #define RTO_ONLINK	0x01
-#define RTO_TPROXY	0x80000000
 
 #define RTO_CONN	0
+/* RTO_CONN is not used (being alias for 0), but preserved not to break
+ * some modules referring to it. */
+
+#define RT_CONN_FLAGS(sk)   (RT_TOS(sk->protinfo.af_inet.tos) | sk->localroute)
 
 struct rt_key
 {
diff -urN linux-2.4.13-pre3/ipc/shm.c linux/ipc/shm.c
--- linux-2.4.13-pre3/ipc/shm.c	Fri Sep 14 14:17:38 2001
+++ linux/ipc/shm.c	Mon Dec  3 23:18:28 2001
@@ -348,6 +348,7 @@
 
 static void shm_get_stat (unsigned long *rss, unsigned long *swp) 
 {
+	struct shmem_inode_info *info;
 	int i;
 
 	*rss = 0;
@@ -361,10 +362,11 @@
 		if(shp == NULL)
 			continue;
 		inode = shp->shm_file->f_dentry->d_inode;
-		spin_lock (&inode->u.shmem_i.lock);
+		info = SHMEM_I(inode);
+		spin_lock (&info->lock);
 		*rss += inode->i_mapping->nrpages;
-		*swp += inode->u.shmem_i.swapped;
-		spin_unlock (&inode->u.shmem_i.lock);
+		*swp += info->swapped;
+		spin_unlock (&info->lock);
 	}
 }
 
diff -urN linux-2.4.13-pre3/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.4.13-pre3/kernel/ksyms.c	Mon Dec  3 23:18:18 2001
+++ linux/kernel/ksyms.c	Mon Dec  3 23:18:28 2001
@@ -59,7 +59,7 @@
 
 extern void *sys_call_table;
 
-extern int sys_tz;
+extern struct timezone sys_tz;
 extern int request_dma(unsigned int dmanr, char * deviceID);
 extern void free_dma(unsigned int dmanr);
 extern spinlock_t dma_spin_lock;
diff -urN linux-2.4.13-pre3/kernel/sched.c linux/kernel/sched.c
--- linux-2.4.13-pre3/kernel/sched.c	Fri Oct  5 12:11:05 2001
+++ linux/kernel/sched.c	Mon Dec  3 23:18:28 2001
@@ -1297,6 +1297,7 @@
 
 	current->session = 1;
 	current->pgrp = 1;
+	current->tty = NULL;
 
 	/* Become as one with the init task */
 
diff -urN linux-2.4.13-pre3/mm/filemap.c linux/mm/filemap.c
--- linux-2.4.13-pre3/mm/filemap.c	Mon Dec  3 23:18:18 2001
+++ linux/mm/filemap.c	Mon Dec  3 23:18:28 2001
@@ -1520,6 +1520,53 @@
 	return retval;
 }
 
+static ssize_t do_readahead(struct file *file, unsigned long index, unsigned long nr)
+{
+	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+	unsigned long max;
+
+	if (!mapping || !mapping->a_ops || !mapping->a_ops->readpage)
+		return -EINVAL;
+
+	/* Limit it to the size of the file.. */
+	max = (mapping->host->i_size + ~PAGE_CACHE_MASK) >> PAGE_CACHE_SHIFT;
+	if (index > max)
+		return 0;
+	max -= index;
+	if (nr > max)
+		nr = max;
+
+	/* And limit it to a sane percentage of the inactive list.. */
+	max = nr_inactive_pages / 2;
+	if (nr > max)
+		nr = max;
+
+	while (nr) {
+		page_cache_read(file, index);
+		index++;
+		nr--;
+	}
+	return 0;
+}
+
+asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count)
+{
+	ssize_t ret;
+	struct file *file;
+
+	ret = -EBADF;
+	file = fget(fd);
+	if (file) {
+		if (file->f_mode & FMODE_READ) {
+			unsigned long start = offset >> PAGE_CACHE_SHIFT;
+			unsigned long len = (count + ((long)offset & ~PAGE_CACHE_MASK)) >> PAGE_CACHE_SHIFT;
+			ret = do_readahead(file, start, len);
+		}
+		fput(file);
+	}
+	return ret;
+}
+
 /*
  * Read-ahead and flush behind for MADV_SEQUENTIAL areas.  Since we are
  * sure this is sequential access, we don't need a flexible read-ahead
@@ -2312,7 +2359,7 @@
 	unsigned long pgoff)
 {
 	unsigned char present = 0;
-	struct address_space * as = &vma->vm_file->f_dentry->d_inode->i_mapping;
+	struct address_space * as = vma->vm_file->f_dentry->d_inode->i_mapping;
 	struct page * page, ** hash = page_hash(as, pgoff);
 
 	spin_lock(&pagecache_lock);
diff -urN linux-2.4.13-pre3/mm/page_alloc.c linux/mm/page_alloc.c
--- linux-2.4.13-pre3/mm/page_alloc.c	Mon Oct  8 12:23:51 2001
+++ linux/mm/page_alloc.c	Mon Dec  3 23:18:28 2001
@@ -242,7 +242,7 @@
 	current->allocation_order = order;
 	current->flags |= PF_MEMALLOC | PF_FREE_PAGES;
 
-	__freed = try_to_free_pages(classzone, gfp_mask, order);
+	__freed = try_to_free_pages(gfp_mask, order);
 
 	current->flags &= ~(PF_MEMALLOC | PF_FREE_PAGES);
 
diff -urN linux-2.4.13-pre3/mm/shmem.c linux/mm/shmem.c
--- linux-2.4.13-pre3/mm/shmem.c	Mon Dec  3 23:18:18 2001
+++ linux/mm/shmem.c	Mon Dec  3 23:18:28 2001
@@ -1235,45 +1235,54 @@
 
 static int shmem_parse_options(char *options, int *mode, unsigned long * blocks, unsigned long *inodes)
 {
-	char *this_char, *value;
+	char *this_char, *value, *rest;
 
 	this_char = NULL;
 	if ( options )
 		this_char = strtok(options,",");
 	for ( ; this_char; this_char = strtok(NULL,",")) {
-		if ((value = strchr(this_char,'=')) != NULL)
+		if ((value = strchr(this_char,'=')) != NULL) {
 			*value++ = 0;
+		} else {
+			printk(KERN_ERR 
+			    "shmem_parse_options: No value for option '%s'\n", 
+			    this_char);
+			return 1;
+		}
+
 		if (!strcmp(this_char,"size")) {
 			unsigned long long size;
-			if (!value || !*value || !blocks)
-				return 1;
-			size = memparse(value,&value);
-			if (*value)
-				return 1;
+			size = memparse(value,&rest);
+			if (*rest)
+				goto bad_val;
 			*blocks = size >> PAGE_CACHE_SHIFT;
 		} else if (!strcmp(this_char,"nr_blocks")) {
-			if (!value || !*value || !blocks)
-				return 1;
-			*blocks = memparse(value,&value);
-			if (*value)
-				return 1;
+			*blocks = memparse(value,&rest);
+			if (*rest)
+				goto bad_val;
 		} else if (!strcmp(this_char,"nr_inodes")) {
-			if (!value || !*value || !inodes)
-				return 1;
-			*inodes = memparse(value,&value);
-			if (*value)
-				return 1;
+			*inodes = memparse(value,&rest);
+			if (*rest)
+				goto bad_val;
 		} else if (!strcmp(this_char,"mode")) {
-			if (!value || !*value || !mode)
-				return 1;
-			*mode = simple_strtoul(value,&value,8);
-			if (*value)
-				return 1;
-		}
-		else
+			if (!mode)
+				continue;
+			*mode = simple_strtoul(value,&rest,8);
+			if (*rest)
+				goto bad_val;
+		} else {
+			printk(KERN_ERR "shmem_parse_options: Bad option %s\n",
+			       this_char);
 			return 1;
+		}
 	}
 	return 0;
+
+bad_val:
+	printk(KERN_ERR "shmem_parse_options: Bad value '%s' for option '%s'\n", 
+	       value, this_char);
+	return 1;
+
 }
 
 static int shmem_remount_fs (struct super_block *sb, int *flags, char *data)
diff -urN linux-2.4.13-pre3/mm/swap.c linux/mm/swap.c
--- linux-2.4.13-pre3/mm/swap.c	Mon Dec  3 23:18:18 2001
+++ linux/mm/swap.c	Mon Dec  3 23:18:28 2001
@@ -135,12 +135,10 @@
 	/* Use a smaller cluster for small-memory machines */
 	if (megs < 16)
 		page_cluster = 2;
-	else if (megs < 32)
-		page_cluster = 3;
-	else if (megs < 64)
-		page_cluster = 4;
-	else if (megs < 128)
-		page_cluster = 5;
 	else
-		page_cluster = 6;
+		page_cluster = 3;
+	/*
+	 * Right now other parts of the system means that we
+	 * _really_ don't want to cluster much more
+	 */
 }
diff -urN linux-2.4.13-pre3/mm/vmscan.c linux/mm/vmscan.c
--- linux-2.4.13-pre3/mm/vmscan.c	Sun Oct  7 17:18:31 2001
+++ linux/mm/vmscan.c	Mon Dec  3 23:18:28 2001
@@ -33,6 +33,8 @@
  */
 #define DEF_PRIORITY (6)
 
+#define page_zone_plenty(page) ((page)->zone->free_pages > (page)->zone->pages_high)
+
 /*
  * The swap-out function returns 1 if it successfully
  * scanned all the pages it was asked to (`count').
@@ -43,11 +45,10 @@
  */
 
 /* mm->page_table_lock is held. mmap_sem is not held */
-static inline int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, unsigned long address, pte_t * page_table, struct page *page, zone_t * classzone)
+static inline int try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, unsigned long address, pte_t * page_table, struct page *page)
 {
 	pte_t pte;
 	swp_entry_t entry;
-	int right_classzone;
 
 	/* Don't look at this pte if it's been accessed recently. */
 	if (ptep_test_and_clear_young(page_table)) {
@@ -55,12 +56,12 @@
 		return 0;
 	}
 
-	if (TryLockPage(page))
+	/* Don't bother replenishing zones that have tons of memory */
+	if (page_zone_plenty(page))
 		return 0;
 
-	right_classzone = 1;
-	if (!memclass(page->zone, classzone))
-		right_classzone = 0;
+	if (TryLockPage(page))
+		return 0;
 
 	/* From this point on, the odds are that we're going to
 	 * nuke this pte, so read and clear the pte.  This hook
@@ -89,7 +90,7 @@
 		{
 			int freeable = page_count(page) - !!page->buffers <= 2;
 			page_cache_release(page);
-			return freeable & right_classzone;
+			return freeable;
 		}
 	}
 
@@ -145,7 +146,7 @@
 }
 
 /* mm->page_table_lock is held. mmap_sem is not held */
-static inline int swap_out_pmd(struct mm_struct * mm, struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int count, zone_t * classzone)
+static inline int swap_out_pmd(struct mm_struct * mm, struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int count)
 {
 	pte_t * pte;
 	unsigned long pmd_end;
@@ -169,7 +170,7 @@
 			struct page *page = pte_page(*pte);
 
 			if (VALID_PAGE(page) && !PageReserved(page)) {
-				count -= try_to_swap_out(mm, vma, address, pte, page, classzone);
+				count -= try_to_swap_out(mm, vma, address, pte, page);
 				if (!count) {
 					address += PAGE_SIZE;
 					break;
@@ -184,7 +185,7 @@
 }
 
 /* mm->page_table_lock is held. mmap_sem is not held */
-static inline int swap_out_pgd(struct mm_struct * mm, struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int count, zone_t * classzone)
+static inline int swap_out_pgd(struct mm_struct * mm, struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int count)
 {
 	pmd_t * pmd;
 	unsigned long pgd_end;
@@ -204,7 +205,7 @@
 		end = pgd_end;
 	
 	do {
-		count = swap_out_pmd(mm, vma, pmd, address, end, count, classzone);
+		count = swap_out_pmd(mm, vma, pmd, address, end, count);
 		if (!count)
 			break;
 		address = (address + PMD_SIZE) & PMD_MASK;
@@ -214,7 +215,7 @@
 }
 
 /* mm->page_table_lock is held. mmap_sem is not held */
-static inline int swap_out_vma(struct mm_struct * mm, struct vm_area_struct * vma, unsigned long address, int count, zone_t * classzone)
+static inline int swap_out_vma(struct mm_struct * mm, struct vm_area_struct * vma, unsigned long address, int count)
 {
 	pgd_t *pgdir;
 	unsigned long end;
@@ -229,7 +230,7 @@
 	if (address >= end)
 		BUG();
 	do {
-		count = swap_out_pgd(mm, vma, pgdir, address, end, count, classzone);
+		count = swap_out_pgd(mm, vma, pgdir, address, end, count);
 		if (!count)
 			break;
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
@@ -244,7 +245,7 @@
 /*
  * Returns remaining count of pages to be swapped out by followup call.
  */
-static inline int swap_out_mm(struct mm_struct * mm, int count, int * mmcounter, zone_t * classzone)
+static inline int swap_out_mm(struct mm_struct * mm, int count, int * mmcounter)
 {
 	unsigned long address;
 	struct vm_area_struct* vma;
@@ -266,7 +267,7 @@
 			address = vma->vm_start;
 
 		for (;;) {
-			count = swap_out_vma(mm, vma, address, count, classzone);
+			count = swap_out_vma(mm, vma, address, count);
 			vma = vma->vm_next;
 			if (!vma)
 				break;
@@ -283,8 +284,8 @@
 	return count;
 }
 
-static int FASTCALL(swap_out(unsigned int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages));
-static int swap_out(unsigned int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages)
+static int FASTCALL(swap_out(unsigned int priority, unsigned int gfp_mask, int nr_pages));
+static int swap_out(unsigned int priority, unsigned int gfp_mask, int nr_pages)
 {
 	int counter;
 	struct mm_struct *mm;
@@ -311,7 +312,7 @@
 		atomic_inc(&mm->mm_users);
 		spin_unlock(&mmlist_lock);
 
-		nr_pages = swap_out_mm(mm, nr_pages, &counter, classzone);
+		nr_pages = swap_out_mm(mm, nr_pages, &counter);
 
 		mmput(mm);
 
@@ -326,8 +327,8 @@
 	return 0;
 }
 
-static int FASTCALL(shrink_cache(int nr_pages, int max_scan, zone_t * classzone, unsigned int gfp_mask));
-static int shrink_cache(int nr_pages, int max_scan, zone_t * classzone, unsigned int gfp_mask)
+static int FASTCALL(shrink_cache(int nr_pages, int max_scan, unsigned int gfp_mask));
+static int shrink_cache(int nr_pages, int max_scan, unsigned int gfp_mask)
 {
 	struct list_head * entry;
 
@@ -348,28 +349,45 @@
 		if (unlikely(!PageInactive(page) && !PageActive(page)))
 			BUG();
 
+		/* Mapping-less page on LRU-list? */
+		if (unlikely(!page->mapping))
+			BUG();
+
 		list_del(entry);
 		list_add(entry, &inactive_list);
 		if (PageTestandClearReferenced(page))
 			continue;
 
 		max_scan--;
-
-		if (unlikely(!memclass(page->zone, classzone)))
+		if (unlikely(page_zone_plenty(page)))
 			continue;
 
 		/* Racy check to avoid trylocking when not worthwhile */
-		if (!page->buffers && page_count(page) != 1)
+		if (!is_page_cache_freeable(page))
+			continue;
+
+		if (unlikely(TryLockPage(page))) {
+			if (gfp_mask & __GFP_FS) {
+				page_cache_get(page);
+				spin_unlock(&pagemap_lru_lock);
+				wait_on_page(page);
+				page_cache_release(page);
+				spin_lock(&pagemap_lru_lock);
+			}
 			continue;
+		}
 
 		/*
-		 * The page is locked. IO in progress?
-		 * Move it to the back of the list.
+		 * Still strictly racy - we don't own the pagecache lock,
+		 * so somebody might look up the page while we do this.
+		 * It's just a heuristic, though.
 		 */
-		if (unlikely(TryLockPage(page)))
+		if (!is_page_cache_freeable(page)) {
+			UnlockPage(page);
 			continue;
+		}
 
-		if (PageDirty(page) && is_page_cache_freeable(page)) {
+		if (PageDirty(page)) {
 			/*
 			 * It is not critical here to write it only if
 			 * the page is unmapped beause any direct writer
@@ -443,9 +461,6 @@
 			}
 		}
 
-		if (unlikely(!page->mapping))
-			BUG();
-
 		if (unlikely(!spin_trylock(&pagecache_lock))) {
 			/* we hold the page lock so the page cannot go away from under us */
 			spin_unlock(&pagemap_lru_lock);
@@ -522,8 +537,8 @@
 	spin_unlock(&pagemap_lru_lock);
 }
 
-static int FASTCALL(shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages));
-static int shrink_caches(int priority, zone_t * classzone, unsigned int gfp_mask, int nr_pages)
+static int FASTCALL(shrink_caches(int priority, unsigned int gfp_mask, int nr_pages));
+static int shrink_caches(int priority, unsigned int gfp_mask, int nr_pages)
 {
 	int max_scan;
 	int chunk_size = nr_pages;
@@ -537,9 +552,9 @@
 	/* try to keep the active list 2/3 of the size of the cache */
 	ratio = (unsigned long) nr_pages * nr_active_pages / ((nr_inactive_pages + 1) * 2);
 	refill_inactive(ratio);
-  
+
 	max_scan = nr_inactive_pages / priority;
-	nr_pages = shrink_cache(nr_pages, max_scan, classzone, gfp_mask);
+	nr_pages = shrink_cache(nr_pages, max_scan, gfp_mask);
 	if (nr_pages <= 0)
 		return 0;
 
@@ -552,18 +567,18 @@
 	return nr_pages;
 }
 
-int try_to_free_pages(zone_t * classzone, unsigned int gfp_mask, unsigned int order)
+int try_to_free_pages(unsigned int gfp_mask, unsigned int order)
 {
 	int ret = 0;
 	int priority = DEF_PRIORITY;
 	int nr_pages = SWAP_CLUSTER_MAX;
 
 	do {
-		nr_pages = shrink_caches(priority, classzone, gfp_mask, nr_pages);
+		nr_pages = shrink_caches(priority, gfp_mask, nr_pages);
 		if (nr_pages <= 0)
 			return 1;
 
-		ret |= swap_out(priority, classzone, gfp_mask, SWAP_CLUSTER_MAX << 2);
+		ret |= swap_out(priority, gfp_mask, SWAP_CLUSTER_MAX << 2);
 	} while (--priority);
 
 	return ret;
@@ -595,7 +610,7 @@
 			schedule();
 		if (!zone->need_balance)
 			continue;
-		if (!try_to_free_pages(zone, GFP_KSWAPD, 0)) {
+		if (!try_to_free_pages(GFP_KSWAPD, 0)) {
 			zone->need_balance = 0;
 			__set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(HZ);
diff -urN linux-2.4.13-pre3/net/bridge/br.c linux/net/bridge/br.c
--- linux-2.4.13-pre3/net/bridge/br.c	Sun Sep 30 12:26:08 2001
+++ linux/net/bridge/br.c	Mon Dec  3 23:18:28 2001
@@ -5,7 +5,7 @@
  *	Authors:
  *	Lennert Buytenhek		<buytenh@gnu.org>
  *
- *	$Id: br.c,v 1.45 2000/10/22 18:26:07 davem Exp $
+ *	$Id: br.c,v 1.46 2001/10/02 02:22:36 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
diff -urN linux-2.4.13-pre3/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- linux-2.4.13-pre3/net/ipv4/ip_output.c	Fri Sep  7 11:01:21 2001
+++ linux/net/ipv4/ip_output.c	Mon Dec  3 23:18:28 2001
@@ -5,7 +5,7 @@
  *
  *		The Internet Protocol (IP) output module.
  *
- * Version:	$Id: ip_output.c,v 1.98 2001/09/01 00:31:50 davem Exp $
+ * Version:	$Id: ip_output.c,v 1.99 2001/10/15 12:34:50 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -367,7 +367,7 @@
 		 * out.
 		 */
 		if (ip_route_output(&rt, daddr, sk->saddr,
-				    RT_TOS(sk->protinfo.af_inet.tos) | RTO_CONN | sk->localroute,
+				    RT_CONN_FLAGS(sk),
 				    sk->bound_dev_if))
 			goto no_route;
 		__sk_dst_set(sk, &rt->u.dst);
diff -urN linux-2.4.13-pre3/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- linux-2.4.13-pre3/net/ipv4/ipconfig.c	Mon Dec  3 23:18:18 2001
+++ linux/net/ipv4/ipconfig.c	Mon Dec  3 23:18:28 2001
@@ -1,5 +1,5 @@
 /*
- *  $Id: ipconfig.c,v 1.38 2001/09/25 23:23:07 davem Exp $
+ *  $Id: ipconfig.c,v 1.39 2001/10/13 01:47:31 davem Exp $
  *
  *  Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or
  *  user-supplied information to configure own IP address and routes.
diff -urN linux-2.4.13-pre3/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- linux-2.4.13-pre3/net/ipv4/ipip.c	Mon Oct  1 09:19:56 2001
+++ linux/net/ipv4/ipip.c	Mon Dec  3 23:18:28 2001
@@ -1,7 +1,7 @@
 /*
  *	Linux NET3:	IP/IP protocol decoder. 
  *
- *	Version: $Id: ipip.c,v 1.49 2001/09/25 22:35:47 davem Exp $
+ *	Version: $Id: ipip.c,v 1.50 2001/10/02 02:22:36 davem Exp $
  *
  *	Authors:
  *		Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
diff -urN linux-2.4.13-pre3/net/ipv4/route.c linux/net/ipv4/route.c
--- linux-2.4.13-pre3/net/ipv4/route.c	Thu Sep 20 14:12:56 2001
+++ linux/net/ipv4/route.c	Mon Dec  3 23:18:28 2001
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.99 2001/09/18 22:29:09 davem Exp $
+ * Version:	$Id: route.c,v 1.100 2001/10/15 12:34:50 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -2002,9 +2002,7 @@
 		    rth->key.fwmark == key->fwmark &&
 #endif
 		    !((rth->key.tos ^ key->tos) &
-			    (IPTOS_RT_MASK | RTO_ONLINK)) &&
-		    ((key->tos & RTO_TPROXY) ||
-		     !(rth->rt_flags & RTCF_TPROXY))) {
+			    (IPTOS_RT_MASK | RTO_ONLINK))) {
 			rth->u.dst.lastuse = jiffies;
 			dst_hold(&rth->u.dst);
 			rth->u.dst.__use++;
diff -urN linux-2.4.13-pre3/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c
--- linux-2.4.13-pre3/net/ipv4/syncookies.c	Wed May 16 10:31:27 2001
+++ linux/net/ipv4/syncookies.c	Mon Dec  3 23:18:28 2001
@@ -9,7 +9,7 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  * 
- *  $Id: syncookies.c,v 1.14 2001/05/05 01:01:55 davem Exp $
+ *  $Id: syncookies.c,v 1.15 2001/10/15 12:34:50 davem Exp $
  *
  *  Missing: IPv6 support. 
  */
@@ -178,7 +178,7 @@
 			    opt && 
 			    opt->srr ? opt->faddr : req->af.v4_req.rmt_addr,
 			    req->af.v4_req.loc_addr,
-			    sk->protinfo.af_inet.tos | RTO_CONN,
+			    RT_CONN_FLAGS(sk),
 			    0)) { 
 		tcp_openreq_free(req);
 		goto out; 
diff -urN linux-2.4.13-pre3/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- linux-2.4.13-pre3/net/ipv4/tcp_ipv4.c	Mon Oct  1 09:19:56 2001
+++ linux/net/ipv4/tcp_ipv4.c	Mon Dec  3 23:18:28 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.231 2001/09/26 23:38:47 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.232 2001/10/15 12:34:50 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -660,7 +660,7 @@
 	}
 
 	tmp = ip_route_connect(&rt, nexthop, sk->saddr,
-			       RT_TOS(sk->protinfo.af_inet.tos)|RTO_CONN|sk->localroute, sk->bound_dev_if);
+			       RT_CONN_FLAGS(sk), sk->bound_dev_if);
 	if (tmp < 0)
 		return tmp;
 
@@ -676,7 +676,7 @@
 		daddr = rt->rt_dst;
 
 	err = -ENOBUFS;
-	buff = alloc_skb(MAX_TCP_HEADER + 15, GFP_KERNEL);
+	buff = alloc_skb(MAX_TCP_HEADER + 15, sk->allocation);
 
 	if (buff == NULL)
 		goto failure;
@@ -1147,8 +1147,7 @@
 				 opt->faddr :
 				 req->af.v4_req.rmt_addr),
 			   req->af.v4_req.loc_addr,
-			   RT_TOS(sk->protinfo.af_inet.tos) | RTO_CONN | sk->localroute,
-			   sk->bound_dev_if)) {
+			   RT_CONN_FLAGS(sk), sk->bound_dev_if)) {
 		IP_INC_STATS_BH(IpOutNoRoutes);
 		return NULL;
 	}
@@ -1776,8 +1775,7 @@
 		daddr = sk->protinfo.af_inet.opt->faddr;
 
 	err = ip_route_output(&rt, daddr, sk->saddr,
-			      RT_TOS(sk->protinfo.af_inet.tos) | RTO_CONN | sk->localroute,
-			      sk->bound_dev_if);
+			      RT_CONN_FLAGS(sk), sk->bound_dev_if);
 	if (!err) {
 		__sk_dst_set(sk, &rt->u.dst);
 		sk->route_caps = rt->u.dst.dev->features;
diff -urN linux-2.4.13-pre3/net/ipv4/udp.c linux/net/ipv4/udp.c
--- linux-2.4.13-pre3/net/ipv4/udp.c	Fri Sep  7 11:01:21 2001
+++ linux/net/ipv4/udp.c	Mon Dec  3 23:18:28 2001
@@ -5,7 +5,7 @@
  *
  *		The User Datagram Protocol (UDP).
  *
- * Version:	$Id: udp.c,v 1.99 2001/09/01 00:31:50 davem Exp $
+ * Version:	$Id: udp.c,v 1.100 2001/10/15 12:34:50 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -724,7 +724,7 @@
 	sk_dst_reset(sk);
 
 	err = ip_route_connect(&rt, usin->sin_addr.s_addr, sk->saddr,
-			       sk->protinfo.af_inet.tos|sk->localroute, sk->bound_dev_if);
+			       RT_CONN_FLAGS(sk), sk->bound_dev_if);
 	if (err)
 		return err;
 	if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) {
diff -urN linux-2.4.13-pre3/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- linux-2.4.13-pre3/net/ipv6/af_inet6.c	Sun Sep 30 12:26:08 2001
+++ linux/net/ipv6/af_inet6.c	Mon Dec  3 23:18:28 2001
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.64 2001/06/13 16:25:03 davem Exp $
+ *	$Id: af_inet6.c,v 1.65 2001/10/02 02:22:36 davem Exp $
  *
  * 	Fixes:
  *	piggy, Karl Knutson	:	Socket protocol table
diff -urN linux-2.4.13-pre3/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- linux-2.4.13-pre3/net/ipv6/tcp_ipv6.c	Mon Oct  1 09:19:56 2001
+++ linux/net/ipv6/tcp_ipv6.c	Mon Dec  3 23:18:28 2001
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.139 2001/09/26 23:38:47 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.140 2001/10/15 12:34:50 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -339,13 +339,18 @@
 	return tcp_v6_lookup_listener(daddr, hnum, dif);
 }
 
-#define tcp_v6_lookup(sa, sp, da, dp, dif) \
-({	struct sock *___sk; \
-	local_bh_disable(); \
-	___sk = __tcp_v6_lookup((sa),(sp),(da),ntohs(dp),(dif)); \
-	local_bh_enable(); \
-	___sk; \
-})
+__inline__ struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
+				      struct in6_addr *daddr, u16 dport,
+				      int dif)
+{
+	struct sock *sk;
+
+	local_bh_disable();
+	sk = __tcp_v6_lookup(saddr, sport, daddr, ntohs(dport), dif);
+	local_bh_enable();
+
+	return sk;
+}
 
 
 /*
@@ -656,7 +661,7 @@
 	tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
 
 	err = -ENOBUFS;
-	buff = alloc_skb(MAX_TCP_HEADER + 15, GFP_KERNEL);
+	buff = alloc_skb(MAX_TCP_HEADER + 15, sk->allocation);
 
 	if (buff == NULL)
 		goto failure;
diff -urN linux-2.4.13-pre3/net/socket.c linux/net/socket.c
--- linux-2.4.13-pre3/net/socket.c	Fri Sep 28 18:03:48 2001
+++ linux/net/socket.c	Mon Dec  3 23:18:28 2001
@@ -440,10 +440,11 @@
 	struct inode * inode;
 	struct socket * sock;
 
-	inode = new_inode(sock_mnt->mnt_sb);
+	inode = get_empty_inode();
 	if (!inode)
 		return NULL;
 
+	inode->i_sb = sock_mnt->mnt_sb;
 	sock = socki_lookup(inode);
 
 	inode->i_mode = S_IFSOCK|S_IRWXUGO;
