## Automatically generated incremental diff
## From:   linux-2.2.18-pre9
## To:     linux-2.2.18-pre10
## Robot:  $Id: make-incremental-diff,v 1.5 2001/12/01 08:32:36 hpa Exp $

diff -urN linux-2.2.18-pre9/CREDITS linux/CREDITS
--- linux-2.2.18-pre9/CREDITS	Mon Sep  4 10:39:15 2000
+++ linux/CREDITS	Mon Dec  3 20:27:05 2001
@@ -202,6 +202,14 @@
 S: 6369 BG Simpelveld
 S: The Netherlands
 
+N: Peter Berger
+E: pberger@brimson.com
+W: http://www.brimson.com
+D: Author/maintainer of Digi AccelePort USB driver
+S: 1549 Hiironen Rd.
+S: Brimson, MN  55602
+S: USA
+
 N: Hennus Bergman
 E: hennus@cybercomm.nl
 W: http://www.cybercomm.nl/~hennus/
@@ -222,6 +230,14 @@
 S: Marrickville NSW 2204
 S: Australia
 
+N: Hugh Blemings
+E: hugh@linuxcare.com
+W: http://www.linuxcare.com.au/hugh/
+D: Author and maintainer of the Keyspan USB to Serial drivers
+S: Po Box 234
+S: Belconnen ACT 2616
+S: Australia
+
 N: Philip Blundell
 E: philb@gnu.org
 D: Linux/ARM hacker
@@ -253,6 +269,13 @@
 D: Configuration help text support
 D: Linux CD and Support Giveaway List
 
+N: Al Borchers
+E: alborchers@steinerpoint.com
+D: Author/maintainer of Digi AccelePort USB driver
+S: 4912 Zenith Ave. S.
+S: Minneapolis, MN  55410
+S: USA
+
 N: Zoltán Böszörményi
 E: zboszor@mail.externet.hu
 D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support
@@ -393,6 +416,13 @@
 D: Assorted sched/mm titbits
 S: Oxfordshire, UK.
 
+N: Mark Corner
+E: mcorner@umich.edu
+W: http://www.eecs.umich.edu/~mcorner/
+D: USB Bluetooth Driver
+S: University of Michigan
+S: Ann Arbor, MI
+
 N: Alan Cox
 W: http://roadrunner.swansea.linux.org.uk/alan.shtml
 E: alan@lxorguk.ukuu.org.uk
@@ -500,6 +530,15 @@
 S: Blacksburg, Virginia 24061
 S: USA
 
+N: Randy Dunlap
+E: randy.dunlap@intel.com
+W: http://home.att.net/~randy.dunlap/
+W: http://www.linux-usb.org
+D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
+S: 5200 NE Elam Young Pkwy., M/S HF3-77
+S: Hillsboro, Oregon 97124
+S: USA
+
 N: Cyrus Durgin
 E: cider@speakeasy.org
 W: http://www.speakeasy.org/~cider/
@@ -554,6 +593,13 @@
 S: Huntington Beach, California 92649
 S: USA
 
+N: Johannes Erdfelt
+E: jerdfelt@valinux.com
+D: USB
+S: 6350 Stoneridge Mall Road
+S: Pleasanton, CA 94588
+S: USA
+
 N: Doug Evans
 E: dje@cygnus.com
 D: Wrote Xenix FS (part of standard kernel since 0.99.15)
@@ -1128,6 +1174,14 @@
 S: L3R 8B2
 S: Canada
 
+N: Greg Kroah-Hartman
+E: greg@kroah.com
+W: http://www.kroah.com/linux-usb/
+D: USB Serial Converter driver framework, USB Handspring Visor driver
+D: ConnectTech WHITEHeat USB driver, Generic USB Serial driver
+D: USB Bluetooth driver,
+D: bits and pieces of USB core code.
+
 N: Russell Kroll
 E: rkroll@exploits.org
 W: http://www.exploits.org/
@@ -1287,7 +1341,7 @@
 N: Pavel Machek
 E: pavel@atrey.karlin.mff.cuni.cz
 D: Softcursor for vga, hypertech cdrom support, vcsa bugfix
-D: Network block device, sun4/330 port 
+D: Network block device, sun4/330 port, USB
 S: Volkova 1131
 S: 198 00 Praha 9
 S: Czech Republic
@@ -1317,6 +1371,15 @@
 S: Halifax, Nova Scotia
 S: Canada B3J 3C8
 
+N: Petko Manolov
+E: petkan@dce.bg
+D: USB ethernet (pegasus) driver
+D: optimizing i[45]86 string routines
+D: i386 task swithing hacks
+S: 5, Vrah Mancho str.
+S: 1324 Sofia
+S: Bulgaria
+
 N: Martin Mares
 E: mj@atrey.karlin.mff.cuni.cz
 W: http://atrey.karlin.mff.cuni.cz/~mj/
@@ -1382,6 +1445,7 @@
 E: acme@conectiva.com.br
 D: wanrouter hacking
 D: cyclades 2X sync card driver (still in early devel stage)
+D: USB hacking
 S: R. Prof. Rubens Elke Braga, 558 - Parolin
 S: 80220-320 Curitiba - Parana
 S: Brazil
@@ -1473,6 +1537,13 @@
 S: Fremont, California 94536
 S: USA
 
+N: Sam Mosel
+E: sam.mosel@computer.org
+D: Wacom Intuos USB Support
+S: 22 Seaview St
+S: Fullarton 5063
+S: South Australia
+
 N: Ian A. Murdock
 E: imurdock@gnu.ai.mit.edu
 D: Creator of Debian distribution
@@ -1576,7 +1647,7 @@
 D: Joystick driver
 D: arcnet-hardware readme
 D: Minor ARCnet hacking
-D: USB development
+D: USB (HID, ACM, Printer ...)
 S: Ucitelska 1576
 S: Prague 8
 S: 182 00 Czech Republic
@@ -1799,6 +1870,14 @@
 W: http://netfilter.kernelnotes.org/ipchains
 D: Ruggedly handsome.
 D: Developed Generic IP Firewalling Chains with Michael Neuling.
+
+N: Bill Ryder
+E: bryder@sgi.com
+D: FTDI_SIO usb/serial converter driver
+W: http://reality.sgi.com/bryder_wellington/ftdi_sio
+S: I/3 Walter St
+S: Wellington
+S: New Zealand
 
 N: Thomas Sailer
 E: sailer@ife.ee.ethz.ch
diff -urN linux-2.2.18-pre9/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.2.18-pre9/Documentation/Configure.help	Mon Dec  3 20:26:34 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 20:27:06 2001
@@ -3545,6 +3545,29 @@
   in ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. The Bridging code is
   still in test. If unsure, say N.
 
+Frame Diverter (EXPERIMENTAL)
+CONFIG_NET_DIVERT
+  The Frame Diverter allows you to divert packets from the
+  network, that are not aimed at the interface receiving it (in 
+  promisc. mode). Typically, a Linux box setup as an ethernet bridge
+  with the Frames Diverter on, can do some *really* transparent www 
+  caching using a Squid proxy for example.
+
+  This is very useful when you don't want to change your router's
+  config (or if you simply don't have access to it).
+
+  The other possible usages of diverting Ethernet Frames are numberous:
+   - reroute smtp traffic to another interface
+   - traffic-shape certain network streams
+   - transparently proxy smtp connections
+   - etc...
+
+  For more informations, please refer to:
+    http://www.freshmeat.net/projects/etherdivert
+    http://perso.wanadoo.fr/magpie/EtherDivert.html
+
+  If unsure, say N
+
 Packet socket
 CONFIG_PACKET
   The Packet protocol is used by applications which communicate
@@ -7339,6 +7362,635 @@
   only driver for hard disks.  These should be the first partition
   (eg. /dev/[sh]d?1) on each of your drives.  If unsure, say N.
 
+Support for USB
+CONFIG_USB
+  Universal Serial Bus (USB) is a specification for a serial bus
+  subsystem which offers higher speeds and more features than the
+  traditional PC serial port. The bus supplies power to peripherals
+  and allows for hot swapping. Up to 127 USB peripherals can be
+  connected to a single USB port in a tree structure. The USB port is
+  the root of the tree, the peripherals are the leaves and the inner
+  nodes are special USB devices called hubs. Many newer PC's have USB
+  ports and newer peripherals such as scanners, keyboards, mice,
+  modems, and printers support the USB protocol and can be connected
+  to the PC via those ports.
+
+  Say Y here if your computer has a USB port and you want to use USB
+  devices. You then need to say Y to at least one of "UHCI support" or
+  "OHCI support" below (the type of interface that the USB hardware in
+  your computer provides to the operating system) and then choose from
+  among the drivers for USB peripherals. You may want to check out the
+  information provided in Documentation/usb/ and especially the links
+  given in Documentation/usb/usb-help.txt.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usbcore.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB verbose debug messages
+CONFIG_USB_DEBUG
+  Say Y here if you want the USB core & hub drivers to produce a bunch
+  of debug messages to the system log. Select this if you are having a
+  problem with USB support and want to see more of what is going on.
+
+UHCI (intel PIIX4, VIA, ...) support?
+CONFIG_USB_UHCI
+  The Universal Host Controller Interface is a standard by Intel for
+  accessing the USB hardware in the PC (which is also called the USB
+  host controller). If your USB host controller conforms to this
+  standard, you may want to say Y, but see below. All recent boards
+  with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
+  i810, i820) conform to this standard. Also all VIA PCI chipsets
+  (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
+  133).
+
+  Currently there exist two drivers for UHCI host controllers: this
+  one and the so-called JE driver, which you can get from 
+  "UHCI alternate (JE) support", below. You need only one.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usb-uhci.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+UHCI (intel PIIX4, VIA, ...) alternate (JE) support?
+CONFIG_USB_UHCI_ALT
+  The Universal Host Controller Interface is a standard by Intel for
+  accessing the USB hardware in the PC (which is also called the USB
+  host controller). If your USB host controller conforms to this
+  standard, you may want to say Y, but see below. All recent boards
+  with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
+  i810, i820) conform to this standard. Also all VIA PCI chipsets
+  (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
+  133). If unsure, say Y.
+
+  Currently there exist two drivers for UHCI host controllers: this
+  so-called JE driver, and the one you get from "UHCI support", above.
+  You need only one.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called uhci.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+UHCI unlink optimizations (EXPERIMENTAL)
+CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
+  This option currently does nothing. You may say Y or N.
+
+OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support
+CONFIG_USB_OHCI
+  The Open Host Controller Interface is a standard by
+  Compaq/Microsoft/National for accessing the USB PC hardware (also
+  called USB host controller). If your USB host controller conforms to
+  this standard, say Y. The USB host controllers on most non-Intel
+  architectures and on several x86 compatibles with non-Intel chipsets
+  -- like SiS (aktual 610, 610 and so on) or ALi (ALi IV, ALi V,
+  Aladdin Pro..) -- conform to this standard.
+
+  You may want to read the file Documentation/usb/ohci.txt.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usb-ohci.o. If you want to compile it
+  as a module, say M here and read Documentation/modules.txt.
+
+USB Human Interface Device (HID) support
+CONFIG_USB_HID
+  Say Y here if you want to connect keyboards, mice, joysticks,
+  graphic tablets, or any other HID based devices to your
+  computer via USB. More information is available:
+  Documentation/usb/input.txt.
+
+  If unsure, say Y.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called hid.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB HIDBP Keyboard support
+CONFIG_USB_KBD
+  Say Y here if you don't want to use the generic HID driver for your
+  USB keyboard and prefer to use the keyboard in its limited Boot
+  Protocol mode. This driver is much smaller than the HID one.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usbkbd.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+  If unsure, say N.
+
+USB HIDBP Mouse support
+CONFIG_USB_MOUSE
+  Say Y here if you don't want to use the generic HID driver for your
+  USB mouse and prefer to use the mouse in its limited Boot Protocol
+  mode. This driver is much smaller than the HID one.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usbmouse.o. If you want to compile it as
+  a module, say M here and read Documentation/modules.txt.
+
+  If unsure, say N.
+
+Wacom Intuos/Graphire tablet support
+CONFIG_USB_WACOM
+  Say Y here if you want to use the USB version of the Wacom Intuos
+  or Graphire tablet. Make sure to say Y to "Mouse support"
+  (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+  (CONFIG_INPUT_EVDEV) as well.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called wacom.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+Logitech WingMan Force joystick support
+CONFIG_USB_WMFORCE
+  Say Y here if you want to use the Logitech WingMan Force with Linux
+  on the USB port. No force-feedback support yet, but other than that
+  it should work like a normal joystick.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called wmforce.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+Keyboard support
+CONFIG_INPUT_KEYBDEV
+  Say Y here if you want your USB HID keyboard to be able to serve 
+  as a system keyboard.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called keybdev.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+Mouse support
+CONFIG_INPUT_MOUSEDEV
+  Say Y here if you want your USB HID mouse (or ADB mouse handled by
+  the input layer) to be accessible as char devices 13:32+ -
+  /dev/input/mouseX and 13:63 - /dev/input/mice as an emulated ImPS/2
+  mouse.  That way, all user space programs will be able to use your
+  mouse.
+  
+  If unsure, say Y.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called mousedev.o. If you want to compile it as
+  a module, say M here and read Documentation/modules.txt.
+
+Horizontal screen resolution
+CONFIG_INPUT_MOUSEDEV_SCREEN_X
+  If you're using a digitizer, or a graphic tablet, and want to use
+  it as a mouse then the mousedev driver needs to know the X window
+  screen resolution you are using to correctly scale the data. If
+  you're not using a digitizer, this value is ignored.
+
+Vertical screen resolution
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y
+  If you're using a digitizer, or a graphic tablet, and want to use
+  it as a mouse then the mousedev driver needs to know the X window
+  screen resolution you are using to correctly scale the data. If
+  you're not using a digitizer, this value is ignored.
+
+Joystick support
+CONFIG_INPUT_JOYDEV
+  Say Y here if you want your USB HID joystick or gamepad to be
+  accessible as char device 13:0+ - /dev/input/jsX device. 
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called joydev.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+Event interface support
+CONFIG_INPUT_EVDEV
+  Say Y here if you want your USB or ADB HID device events be accessible
+  under char device 13:64+ - /dev/input/eventX in a generic way.
+  This is the future ...
+
+USB Scanner support
+CONFIG_USB_SCANNER
+  Say Y here if you want to connect a USB scanner to your computer's
+  USB port. Please read Documentation/usb/scanner.txt and
+  Documentation/usb/scanner-hp-sane.txt for more information.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called scanner.o. If you want to compile it as
+  a module, say M here and read Documentation/modules.txt.
+
+USB Audio support
+CONFIG_USB_AUDIO
+  Say Y here if you want to connect UAB audio equipment such as
+  speakers to your computer's USB port.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called audio.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB Modem (CDC ACM) support
+CONFIG_USB_ACM
+  This driver supports USB modems and ISDN adapters which support the
+  Communication Device Class Abstract Control Model interface.
+  Please read Documentation/usb/acm.txt for details.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called acm.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB Serial converter support
+CONFIG_USB_SERIAL
+  Say Y here if you have a USB device that provides normal serial
+  ports, and you want to connect it to your USB bus. Supported devices
+  are the Tech WhiteHEAT multi-port USB to serial converter, and the
+  FTDI or Keyspan single port USB to serial converter Handspring
+  Visor. In addition to saying Y here, you need to say Y to the driver
+  for your specific hardware below. Some other devices may also be
+  used if you say Y to "USB Generic Serial Driver", below.
+
+  Please read Documentation/usb/usb-serial.txt for more information.
+  
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usbserial.o. If you want to compile it 
+  as a module, say M here and read Documentation/modules.txt.
+
+USB Generic Serial Driver
+CONFIG_USB_SERIAL_GENERIC
+  Say Y here if you want to use the generic USB serial driver. Please
+  read Documentation/usb/usb-serial.txt for more information on using
+  this driver. It is recommended that the "USB Serial converter
+  support" be compiled as a module for this driver to be used
+  properly.
+
+USB ConnectTech WhiteHEAT Serial Driver
+CONFIG_USB_SERIAL_WHITEHEAT
+  Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
+  USB to serial converter device.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called whiteheat.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB Handspring Visor Driver
+CONFIG_USB_SERIAL_VISOR
+  Say Y here if you want to connect to your HandSpring Visor through
+  its USB docking station. See http://usbvisor.sourceforge.net for
+  more information on using this driver.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called visor.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB FTDI Single Port Serial Driver
+CONFIG_USB_SERIAL_FTDI_SIO
+  Say Y here if you want to use a FTDI SIO single port USB to serial
+  converter device. The implementation I have is called the USC-1000.
+
+  See http://reality.sgi.com/bryder_wellington/ftdi_sio for more
+  information on this driver and the device.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ftdi_sio.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB Keyspan PDA Single Port Serial Driver
+CONFIG_USB_SERIAL_KEYSPAN_PDA
+  Say Y here if you want to use a Keyspan PDA single port USB to
+  serial converter device.  This driver makes use of firmware
+  developed from scratch by Brian Warner.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called keyspan_pda.o. If you want to compile it 
+  as a module, say M here and read Documentation/modules.txt.
+
+USB Keyspan USA-xxx Serial Driver
+CONFIG_USB_SERIAL_KEYSPAN
+  Say Y here if you want to use Keyspan USB to serial converter
+  devices.  This driver makes use of Keyspan's official firmware
+  and was developed with their support.  You must also include
+  firmware to support your particular device(s). 
+
+  See http://www.linuxcare.com.au/hugh/keyspan.html for 
+  more information.
+ 
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called keyspan.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB Keyspan USA-28 Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA28
+  Say Y here to include firmware for the USA-28 converter.
+
+USB Keyspan USA-28X Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA28X
+  Say Y here to include firmware for the USA-28X converter.
+
+USB Keyspan USA-19 Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA19
+  Say Y here to include firmware for the USA-19 converter.
+
+USB Keyspan USA-18X Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA18X
+  Say Y here to include firmware for the USA-18X converter.
+
+USB Keyspan USA-19W Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA19W
+  Say Y here to include firmware for the USA-19W converter.
+
+USB ZyXEL omni.net LCD Plus Driver
+CONFIG_USB_SERIAL_OMNINET
+  Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called omninet.o. If you want to compile it as a 
+  module, say M here and read Documentation/modules.txt.
+
+USB Digi International AccelePort USB Serial Driver
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT
+  Say Y here if you want to use Digi AccelePort USB 2 or 4 devices,
+  2 port (plus parallel port) and 4 port USB serial converters.  The
+  parallel port on the USB 2 appears as a third serial port on Linux.
+  The Digi Acceleport USB 8 is not yet supported by this driver.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called digi_acceleport.o. If you want to compile 
+  it as a module, say M here and read Documentation/modules.txt.
+
+USB Serial Converter verbose debug
+CONFIG_USB_SERIAL_DEBUG
+  Say Y here if you want verbose debug messages from the USB Serial
+  Converter. 
+
+USB Printer support
+CONFIG_USB_PRINTER
+  Say Y here if you want to connect a USB printer to your computer's
+  USB port.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called printer.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB IBM (Xirlink) C-It Camera support
+CONFIG_USB_IBMCAM
+  Say Y here if you want to connect a IBM "C-It" camera, also known as
+  "Xirlink PC Camera" to your computer's USB port. For more
+  information, read Documentation/usb/ibmcam.txt.
+
+  This driver uses the Video For Linux API.  You must enable
+  (Y or M in config) Video For Linux (under Character Devices)
+  to use this driver.  Information on this API and pointers to
+  "v4l" programs may be found on the WWW at
+  http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ibmcam.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt. This camera
+  has several configuration options which can be specified when you
+  load the module. Read Documentation/usb/ibmcam.txt to learn more.
+
+USB OV511 Camera support
+CONFIG_USB_OV511
+  Say Y here if you want to connect this type of camera to your
+  computer's USB port. See Documentation/usb/ov511.txt for more
+  information and for a list of supported cameras.
+  
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Character Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ov511.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
+CONFIG_USB_PEGASUS
+  Say Y if you want to use your USB ethernet device. Supported
+  cards until now are:
+    ADMtek AN986 (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
+  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.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called pegasus.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB Kodak DC-2xx Camera support
+CONFIG_USB_DC2XX
+  Say Y here if you want to connect this type of still camera to
+  your computer's USB port.  See Documentation/usb/dc2xx.txt for more
+  information; some non-Kodak cameras may also work with this
+  driver, given application support (such as www.gPhoto.org).
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called dc2xx.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB Mustek MDC800 Digital Camera Support
+CONFIG_USB_MDC800
+  Say Y here if you want to connect this type of still camera to
+  your computer's USB port. This driver can be used with gphoto 0.4.3
+  and higher (look at http://www.gphoto.org ).
+  To use it create a device node with "mknod /dev/mustek c 180 32" and
+  configure it in your software.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called mdc800.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB Mass Storage support
+CONFIG_USB_STORAGE
+  Say Y here if you want to connect USB mass storage devices to your
+  computer's USB port.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usb-storage.o. If you want to compile it
+  as a module, say M here and read Documentation/modules.txt.
+
+USB Mass Storage verbose debug
+CONFIG_USB_STORAGE_DEBUG
+  Say Y here in order to have the USB Mass Storage code generate
+  verbose debugging messages.
+
+USS720 parport driver
+CONFIG_USB_USS720
+  This driver is for USB parallel port adapters that use the Lucent
+  Technologies USS-720 chip. These cables are plugged into your USB
+  port and provide USB compatibility to peripherals designed with
+  parallel port interfaces.
+  
+  The chip has two modes: automatic mode and manual mode. In automatic
+  mode, it looks to the computer like a standard USB printer. Only
+  printers may be connected to the USS-720 in this mode. The generic
+  USB printer driver ("USB Printer support", above) may be used in
+  that mode, and you can say N here if you want to use the chip only
+  in this mode.
+
+  Manual mode is not limited to printers, any parallel port
+  device should work. This driver utilizes manual mode.
+  Note however that some operations are three orders of magnitude
+  slower than on a PCI/ISA Parallel Port, so timing critical
+  applications might not work.
+
+  Say Y here if you own an USS-720 USB->Parport cable and intend to
+  connect anything other than a printer to it.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called uss720.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+  
+USB device file system
+CONFIG_USB_DEVICEFS
+  If you say Y here (and to "/proc file system support" below), you
+  will get a file /proc/usb/devices which lists the devices currently
+  connected to your USB busses, a file /proc/usb/drivers which lists
+  the USB kernel client drivers currently loaded, and for every
+  connected device a file named "/proc/usb/xxx/yyy", where xxx is the
+  bus number and yyy the device number; the latter files can be used
+  by user space programs to talk directly to the device. These files
+  are "virtual", meaning they are generated on the fly and not stored
+  on the hard drive.
+  
+  For the format of the /proc/usb/ files, please read
+  Documentation/usb/proc_usb_info.txt. 
+
+  Please note that this code is completely unrelated to devfs, the
+  "/dev file system support".
+
+  Most users want to say Y here.
+
+USB Bandwidth allocation
+CONFIG_USB_BANDWIDTH
+  If you say Y here, the USB subsystem enforces USB bandwidth
+  allocation and will prevent some device opens from succeeding
+  if they would cause USB bandwidth usage to go above 90% of
+  the bus bandwidth.
+
+  If you say N here, these conditions will cause warning messages
+  about USB bandwidth usage to be logged and some devices or
+  drivers may not work correctly.
+
+DABUSB driver
+CONFIG_USB_DABUSB
+  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+  brought to you by the DAB-Team (http://dab.in.tum.de). This driver
+  can be taken as an example for URB-based bulk, control, and
+  isochronous transactions. URB's are explained in
+  Documentation/usb/URB.txt.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called dabusb.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+PLUSB driver
+CONFIG_USB_PLUSB
+  A driver for the Prolific PL-2302 USB-to-USB network device. This
+  'USB cable' connects two hosts via a point-to-point network with
+  bandwidth of 5 Mbit/s. Configure this driver after connecting the
+  USB cable via ifconfig plusb0 10.0.0.1 pointopoint 10.0.0.2 (and
+  vice versa on the other host).
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called plusb.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+USB Diamond Rio500 support
+CONFIG_USB_RIO500
+  Say Y here if you want to connect a USB Rio500 mp3 player to your
+  computer's USB port. Please read Documentation/usb/rio.txt
+  for more information.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called rio500.o. If you want to compile it as
+  a module, say M here and read Documentation/modules.txt.
+
+D-Link DSB-R100 FM radio support
+CONFIG_USB_DSBR
+  Say Y here if you want to connect this type of radio to your
+  computer's USB port. Note that the audio is not digital, and
+  you must connect the line out connector to a sound card or a
+  set of speakers.
+
+  This driver uses the Video For Linux API.  You must enable
+  (Y or M in config) Video For Linux (under Character Devices)
+  to use this driver.  Information on this API and pointers to
+  "v4l" programs may be found on the WWW at
+  http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called dsbr100.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+Microtek USB scanner support
+CONFIG_USB_MICROTEK
+  Say Y here if you want support for the Microtek X6USB and possibly
+  some other scanners by that vendor. The scanner will appear as a
+  scsi generic device to the rest of the system.
+  A patched version of SANE is necessary to use the
+  scanner. It's available at 
+  http://fachschaft.cup.uni-muenchen.de/~neukum/scanner.html
+  This driver can be compiled as a module.
+
+USB Bluetooth support
+CONFIG_USB_BLUETOOTH
+  Say Y here if you want to connect a USB Bluetooth device to your
+  computer's USB port. You will need the Bluetooth stack (available
+  at http://developer.axis.com/software/index.shtml) to fully use
+  the device.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called bluetooth.o. If you want to compile it as 
+  a module, say M here and read Documentation/modules.txt.
+  
+Kawasaki USB ethernet controller support
+CONFIG_USB_KAWETH
+  Say Y here if you want support for devices based on the Kawasaki
+  LSI KL5KUSB100 USB to Ethernet 1-Chip Controller, such as the
+  NetGear EA101 USB to Ethernet Adapter.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called kaweth.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+ 
 Minix fs support
 CONFIG_MINIX_FS
   Minix is a simple operating system used in many classes about OS's.
@@ -9611,6 +10263,21 @@
   The module will be called microcode.o. If you want to compile it as
   a module, say M here and read Documentation/modules.txt.
 
+/dev/cpu/*/msr - Model-specific register support
+CONFIG_X86_MSR
+  This device gives privileged processes access to the x86
+  Model-Specific Registers (MSRs).  It is a character device with
+  major 202 and minors 0 to 31 for /dev/cpu/0/msr to /dev/cpu/31/msr.
+  MSR accesses are directed to a specific CPU on multi-processor
+  systems.
+
+/dev/cpu/*/cpuid - CPU information support
+CONFIG_X86_CPUID
+  This device gives processes access to the x86 CPUID instruction to
+  be executed on a specific processor.  It is a character device
+  with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
+  /dev/cpu/31/cpuid.
+
 Enhanced Real Time Clock Support
 CONFIG_RTC
   If you say Y here and create a character special file /dev/rtc with
@@ -12482,17 +13149,6 @@
   If you do not have any Quicknet telephony cards, you can safely
   ignore this option.
 
-Kawasaki USB ethernet controller support
-CONFIG_USB_KAWETH
-  Say Y here if you want support for devices based on the Kawasaki
-  LSI KL5KUSB100 USB to Ethernet 1-Chip Controller, such as the
-  NetGear EA101 USB to Ethernet Adapter.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called kaweth.o. If you want to compile it as a
-  module, say M here and read Documentation/modules.txt.
- 
 Toshiba Laptop support
 CONFIG_TOSHIBA	
   If you intend to run this the kernel on a Toshiba portable say yes
diff -urN linux-2.2.18-pre9/Documentation/isdn/README.act2000 linux/Documentation/isdn/README.act2000
--- linux-2.2.18-pre9/Documentation/isdn/README.act2000	Mon Aug  9 12:04:38 1999
+++ linux/Documentation/isdn/README.act2000	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-$Id: README.act2000,v 1.2 1998/04/29 19:49:06 he Exp $
+$Id: README.act2000,v 1.3 2000/08/06 09:22:51 armin Exp $
 
 This document describes the ACT2000 driver for the
 IBM Active 2000 ISDN card.
@@ -7,7 +7,7 @@
 Version. Currently, only the ISA-Bus version of the card is supported.
 However MCA and PCMCIA will follow soon.
 
-The ISA-Bus Version uses 8 IO-ports. The base port adress has to be set
+The ISA-Bus Version uses 8 IO-ports. The base port address has to be set
 manually using the DIP switches.
 
 Setting up the DIP switches for the IBM Active 2000 ISDN card:
diff -urN linux-2.2.18-pre9/Documentation/isdn/README.avmb1 linux/Documentation/isdn/README.avmb1
--- linux-2.2.18-pre9/Documentation/isdn/README.avmb1	Tue Jan  4 10:12:10 2000
+++ linux/Documentation/isdn/README.avmb1	Mon Dec  3 20:27:06 2001
@@ -175,7 +175,7 @@
 subscribe linux-avmb1
 in the body.
 
-German documentaion and several scripts can be found at
+German documentation and several scripts can be found at
 ftp://ftp.avm.de/cardware/b1/linux/
 
 Bugs 
diff -urN linux-2.2.18-pre9/Documentation/isdn/README.concap linux/Documentation/isdn/README.concap
--- linux-2.2.18-pre9/Documentation/isdn/README.concap	Tue Oct 26 17:53:39 1999
+++ linux/Documentation/isdn/README.concap	Mon Dec  3 20:27:06 2001
@@ -68,7 +68,7 @@
 Likewise, a similar encapsulation protocol will frequently be needed by
 several different interfaces of even different hardware type, e.g. the
 synchronous ppp implementation used by the isdn driver and the
-asyncronous ppp implementation used by the ppp driver have a lot of
+asynchronous ppp implementation used by the ppp driver have a lot of
 similar code in them. By cleanly separating the encapsulation protocol
 from the hardware specific interface stuff such code could be shared
 better in future.
diff -urN linux-2.2.18-pre9/Documentation/isdn/README.diversion linux/Documentation/isdn/README.diversion
--- linux-2.2.18-pre9/Documentation/isdn/README.diversion	Wed Aug 25 17:29:45 1999
+++ linux/Documentation/isdn/README.diversion	Mon Dec  3 20:27:06 2001
@@ -57,7 +57,7 @@
    compared to the mechanism of ipfwadm or ipchains. If a given rule matches
    the checking process is finished and the rule matching will be applied
    to the call.
-   The rules include primary and secondary service indentifiers, called 
+   The rules include primary and secondary service identifiers, called 
    number and subaddress, callers number and subaddress and whether the rule
    matches to all filtered calls or only those when all B-channel resources
    are exhausted.
@@ -82,7 +82,7 @@
    available in some countries (for example germany). Countries requiring the 
    keypad protocol for activating static diversions (like the netherlands) are
    not supported but may use the tty devices for this purpose.
-   The dynamic diversion servives may be used in all countries if the provider
+   The dynamic diversion services may be used in all countries if the provider
    enables the feature CF (call forwarding). This should work on both MSN- and
    point-to-point lines.
    To add and delete rules the additional divertctrl program is needed. This
diff -urN linux-2.2.18-pre9/Documentation/isdn/README.icn linux/Documentation/isdn/README.icn
--- linux-2.2.18-pre9/Documentation/isdn/README.icn	Mon Aug  9 12:04:38 1999
+++ linux/Documentation/isdn/README.icn	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-$Id: README.icn,v 1.6 1998/04/29 19:49:08 he Exp $
+$Id: README.icn,v 1.7 2000/08/06 09:22:51 armin Exp $
 
 You can get the ICN-ISDN-card from:
 
@@ -139,7 +139,7 @@
   To load a 4B-card, the same command is used, except a second firmware
   file is appended to the commandline of icnctrl.
 
-  -> After dowloading firmware, the two LEDs at the back cover of the card
+  -> After downloading firmware, the two LEDs at the back cover of the card
      (ICN-4B: 4 LEDs) must be blinking intermittently now. If a connection
      is up, the corresponding led is lit continuously.
 
diff -urN linux-2.2.18-pre9/Makefile linux/Makefile
--- linux-2.2.18-pre9/Makefile	Mon Dec  3 20:26:35 2001
+++ linux/Makefile	Mon Dec  3 20:27:06 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 18
-EXTRAVERSION = pre9
+EXTRAVERSION = pre10
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -urN linux-2.2.18-pre9/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c
--- linux-2.2.18-pre9/arch/i386/kernel/bluesmoke.c	Mon Dec  3 20:26:35 2001
+++ linux/arch/i386/kernel/bluesmoke.c	Mon Dec  3 20:27:06 2001
@@ -37,7 +37,7 @@
 			high&=~(1<<31);
 			if(high&(1<<27))
 			{
-				rdmsr(0x402+i*4, alow, ahigh);
+				rdmsr(0x403+i*4, alow, ahigh);
 				printk("[%08x%08x]", alow, ahigh);
 			}
 			if(high&(1<<26))
@@ -49,7 +49,7 @@
 			/* Clear it */
 			wrmsr(0x401+i*4, 0UL, 0UL);
 			/* Serialize */
-			wmb();
+			mb();
 		}
 	}
 	
diff -urN linux-2.2.18-pre9/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- linux-2.2.18-pre9/arch/sparc/kernel/sparc_ksyms.c	Mon Dec  3 20:26:35 2001
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.77.2.5 2000/07/17 18:44:26 jj Exp $
+/* $Id: sparc_ksyms.c,v 1.77.2.6 2000/09/16 14:15:15 davem Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.18-pre9/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- linux-2.2.18-pre9/arch/sparc/kernel/sys_sunos.c	Mon Dec  3 20:26:35 2001
+++ linux/arch/sparc/kernel/sys_sunos.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.94.2.4 2000/01/17 21:28:27 davem Exp $
+/* $Id: sys_sunos.c,v 1.94.2.5 2000/09/16 14:15:15 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.18-pre9/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile
--- linux-2.2.18-pre9/arch/sparc/lib/Makefile	Mon Dec  3 20:26:35 2001
+++ linux/arch/sparc/lib/Makefile	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.28.2.1 1999/09/28 16:47:36 davem Exp $
+# $Id: Makefile,v 1.28.2.2 2000/09/16 14:15:15 davem Exp $
 # Makefile for Sparc library files..
 #
 
diff -urN linux-2.2.18-pre9/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux-2.2.18-pre9/arch/sparc64/defconfig	Mon Dec  3 20:26:35 2001
+++ linux/arch/sparc64/defconfig	Mon Dec  3 20:27:06 2001
@@ -318,7 +318,9 @@
 # CONFIG_NFSD_SUN is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
+CONFIG_NFS_V3=y
 CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
 CONFIG_NCP_FS=m
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
diff -urN linux-2.2.18-pre9/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- linux-2.2.18-pre9/arch/sparc64/kernel/setup.c	Wed May  3 17:16:32 2000
+++ linux/arch/sparc64/kernel/setup.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.43.2.3 2000/03/03 23:50:37 davem Exp $
+/*  $Id: setup.c,v 1.43.2.4 2000/09/16 16:56:08 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -550,7 +550,7 @@
 	init_task.tss.kregs = &fake_swapper_regs;
 
 #ifdef CONFIG_IP_PNP
-	if (!ic_set_manually) {
+	if (ic_myaddr == INADDR_NONE) {
 		int chosen = prom_finddevice ("/chosen");
 		u32 cl, sv, gw;
 		
diff -urN linux-2.2.18-pre9/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.2.18-pre9/arch/sparc64/kernel/sys_sunos32.c	Mon Dec  3 20:26:35 2001
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.22.2.3 2000/01/17 21:28:31 davem Exp $
+/* $Id: sys_sunos32.c,v 1.22.2.4 2000/09/16 14:15:15 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.18-pre9/drivers/block/floppy.c linux/drivers/block/floppy.c
--- linux-2.2.18-pre9/drivers/block/floppy.c	Mon Dec  3 20:26:35 2001
+++ linux/drivers/block/floppy.c	Mon Dec  3 20:27:06 2001
@@ -2257,6 +2257,7 @@
 static void request_done(int uptodate)
 {
 	int block;
+	unsigned long flags;
 
 	probing = 0;
 	reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
@@ -2275,6 +2276,7 @@
 			DRS->maxtrack = 1;
 
 		/* unlock chained buffers */
+		spin_lock_irqsave(&io_request_lock, flags);
 		while (current_count_sectors && CURRENT &&
 		       current_count_sectors >= CURRENT->current_nr_sectors){
 			current_count_sectors -= CURRENT->current_nr_sectors;
@@ -2282,6 +2284,7 @@
 			CURRENT->sector += CURRENT->current_nr_sectors;
 			end_request(1);
 		}
+		spin_unlock_irqrestore(&io_request_lock, flags);
 		if (current_count_sectors && CURRENT){
 			/* "unlock" last subsector */
 			CURRENT->buffer += current_count_sectors <<9;
@@ -2305,7 +2308,9 @@
 			DRWE->last_error_sector = CURRENT->sector;
 			DRWE->last_error_generation = DRS->generation;
 		}
+		spin_lock_irqsave(&io_request_lock, flags);
 		end_request(0);
+		spin_unlock_irqrestore(&io_request_lock, flags);
 	}
 }
 
diff -urN linux-2.2.18-pre9/drivers/block/genhd.c linux/drivers/block/genhd.c
--- linux-2.2.18-pre9/drivers/block/genhd.c	Mon Dec  3 20:26:35 2001
+++ linux/drivers/block/genhd.c	Mon Dec  3 20:27:06 2001
@@ -1516,7 +1516,7 @@
 	char buf[MAX_DISKNAME_LEN];
 
 	if (first_time)
-		printk("Partition check:\n");
+		printk(KERN_INFO "Partition check:\n");
 	first_time = 0;
 	first_sector = hd->part[MINOR(dev)].start_sect;
 
@@ -1529,7 +1529,7 @@
 		return;
 	}
 
-	printk(" %s:", disk_name(hd, MINOR(dev), buf));
+	printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
 #ifdef CONFIG_MSDOS_PARTITION
 	if (msdos_partition(hd, dev, first_sector))
 		return;
diff -urN linux-2.2.18-pre9/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- linux-2.2.18-pre9/drivers/cdrom/cdrom.c	Mon Dec  3 20:26:35 2001
+++ linux/drivers/cdrom/cdrom.c	Mon Dec  3 20:27:06 2001
@@ -1106,6 +1106,7 @@
 		cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
 		setup_report_key(&cgc, 0, 8);
 		memset(&rpc_state, 0, sizeof(rpc_state_t));
+		cgc.buffer = (char *) &rpc_state;
 
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
 			return ret;
diff -urN linux-2.2.18-pre9/drivers/char/Config.in linux/drivers/char/Config.in
--- linux-2.2.18-pre9/drivers/char/Config.in	Mon Dec  3 20:26:35 2001
+++ linux/drivers/char/Config.in	Mon Dec  3 20:27:06 2001
@@ -189,7 +189,7 @@
     fi
   fi
   dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_PMAC" = "y" ]; then
+  if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
     dep_tristate 'PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV
   fi
   dep_tristate 'SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
diff -urN linux-2.2.18-pre9/drivers/char/isicom.c linux/drivers/char/isicom.c
--- linux-2.2.18-pre9/drivers/char/isicom.c	Wed May  3 17:16:37 2000
+++ linux/drivers/char/isicom.c	Mon Dec  3 20:27:06 2001
@@ -16,6 +16,31 @@
  *
  *	10/6/99 sameer			Merged the ISA and PCI drivers to
  *					a new unified driver.
+ *
+ *	3/9/99	sameer			Added support for ISI4616 cards.
+ *
+ *	16/9/99	sameer			We do not force RTS low anymore.
+ *					This is to prevent the firmware 
+ *					from getting confused.
+ *
+ *	26/10/99 sameer			Cosmetic changes:The driver now
+ *					dumps the Port Count information
+ *					along with I/O address and IRQ.
+ *
+ *	13/12/99 sameer			Fixed the problem with IRQ sharing.
+ *
+ *	10/5/00  sameer			Fixed isicom_shutdown_board()
+ *					to not lower DTR on all the ports
+ *					when the last port on the card is 
+ *					closed.
+ *
+ *	10/5/00  sameer			Signal mask setup command added
+ *					to  isicom_setup_port and 
+ *					isicom_shutdown_port.
+ *
+ *	24/5/00 sameer			The driver is now SMP aware.
+ *					
+ *
  *	***********************************************************
  *
  *	To use this driver you also need the support package. You 
@@ -51,6 +76,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/spinlock.h>
 
 #include <linux/pci.h>
 
@@ -67,9 +93,11 @@
 				0x2058
 			};
 
+#define	DEVID_COUNT	(sizeof(device_id) / sizeof(device_id[0]))
+
 static int isicom_refcount = 0;
 static int prev_card = 3;	/*	start servicing isi_card[0]	*/
-static struct isi_board * irq_to_board[16] = { NULL, };
+/*static struct isi_board * irq_to_board[16] = { NULL, };*/
 static struct tty_driver isicom_normal, isicom_callout;
 static struct tty_struct * isicom_table[PORT_COUNT] = { NULL, };
 static struct termios * isicom_termios[PORT_COUNT] = { NULL, };
@@ -84,6 +112,7 @@
 static char re_schedule = 1;
 #ifdef ISICOM_DEBUG
 static unsigned long tx_count = 0;
+static unsigned long intr_count = 0;
 #endif
 
 static int ISILoad_open(struct inode *inode, struct file *filp);
@@ -140,6 +169,70 @@
 		return 1;
 }
 
+
+extern inline unsigned char valid_irq(int irq)
+{
+	if	((irq != 2) &&
+		(irq != 3) &&
+		(irq != 4) &&
+		(irq != 5) &&
+		(irq != 7) &&
+		(irq != 10) &&
+		(irq != 11) &&
+		(irq != 12) &&
+		(irq != 15))
+		return 0;
+	else
+		return 1;
+}
+
+static unsigned short reset_card(int base_addr, unsigned char read_portcount)
+{
+	unsigned int	i;
+	unsigned short	sig, portcount;
+
+	inw(base_addr + 0x8);
+			
+	for(i = jiffies+HZ/100; time_before(jiffies, i););
+				
+	outw(0, base_addr + 0x8); /* Reset */
+
+	for(i = jiffies+HZ; time_before(jiffies, i););
+
+	sig = (inw(base_addr + 0x4)) & 0xff;
+
+	if ((sig!= 0xa5) &&
+		(sig != 0xbb) &&
+		(sig != 0xcc) &&
+		(sig != 0xdd)) 
+		return 0;
+
+	if (read_portcount) {
+
+		for(i = jiffies+HZ/100; time_before(jiffies, i););
+
+		portcount = inw(base_addr + 0x2);
+		if ((portcount != 0) && 
+			(portcount != 4) && 
+			(portcount != 8) &&
+			(portcount != 16))
+			return 0;
+		else
+			sig |= (portcount << 8);
+	}
+
+	if (!(inw(base_addr + 0xe) & 0x1)) {
+#ifdef ISICOM_DEBUG				
+		printk("\nbase+0xe=0x%x", inw(base_addr + 0xe));
+#endif				
+		printk("\nISILoad:ISA Card reset failure"
+			"(Possible bad I/O Port Address 0x%x).\n",
+			base_addr);
+		return 0;
+	}
+	return sig;	
+}
+
 static int ISILoad_open(struct inode *inode, struct file *filp)
 {
 #ifdef ISICOM_DEBUG	
@@ -152,7 +245,7 @@
 static int ISILoad_release(struct inode *inode, struct file *filp)
 {
 #ifdef ISICOM_DEBUG
-	printk(KERN_DEBUG "ISILoad:Firmware loader Close(Release)d\n",);
+	printk(KERN_DEBUG "ISILoad:Firmware loader Close(Release)d\n");
 #endif	
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -161,7 +254,7 @@
 static int ISILoad_ioctl(struct inode *inode, struct file *filp,
 		         unsigned int cmd, unsigned long arg)
 {
-	unsigned int card, i, j, signature, status, portcount = 0;
+	unsigned int card, i, signature, status;
 	unsigned short word_count, base;
 	bin_frame frame;
 	/* exec_record exec_rec; */
@@ -182,46 +275,18 @@
 			if (!capable(CAP_SYS_ADMIN))
 				return -EPERM;
 			printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%x ",card+1,base);
-								
-			inw(base+0x8);
-			
-			for(i=jiffies+HZ/100;time_before(jiffies, i););
-				
-			outw(0,base+0x8); /* Reset */
-			
-			for(j=1;j<=3;j++) {
-				for(i=jiffies+HZ;time_before(jiffies, i););
-				printk(".");
-			}	
-			signature=(inw(base+0x4)) & 0xff;	
-			if (isi_card[card].isa) {
-					
-				if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
-#ifdef ISICOM_DEBUG				
-					printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
-#endif				
-					printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
-					return -EIO;					
-				}
-			}	
-			else {
-				portcount = inw(base+0x2);
-				if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) {	
-#ifdef ISICOM_DEBUG
-					printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
-#endif
-					printk("\nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
-					return -EIO;
-				}
-			}	
-			switch(signature) {
+							
+			signature = reset_card(base, 
+					(isi_card[card].isa ? 0 : 1));
+
+			switch(signature & 0xff) {
 			case	0xa5:
 			case	0xbb:
 			case	0xdd:	
 					if (isi_card[card].isa) 
 						isi_card[card].port_count = 8;
 					else {
-						if (portcount == 4)
+						if ((signature & 0xff00) == 0x0400)
 							isi_card[card].port_count = 4;
 						else
 							isi_card[card].port_count = 8;
@@ -229,17 +294,20 @@
 				     	isi_card[card].shift_count = 12;
 				     	break;
 				        
-			case	0xcc:	isi_card[card].port_count = 16;
+			case	0xcc:	/*	ISI616EM	*/
+			case	0xee:	/*	ISI4616		*/
+					isi_card[card].port_count = 16;
 					isi_card[card].shift_count = 11;
 					break;  			
 					
-			default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
+			default: printk("\nISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
 #ifdef ISICOM_DEBUG			
-				 printk("Sig=0x%x\n",signature);
+				 printk("Sig=0x%x\n", signature);
 #endif				 
 				 return -EIO;
 			}
 			printk("-Done\n");
+			signature &= 0xff;
 			return put_user(signature,(unsigned int*)arg);
 						
 	case	MIOCTL_LOAD_FIRMWARE:
@@ -266,8 +334,14 @@
 				return -EIO;
 				
 			if ((status=inw(base+0x4))!=0) {
-				printk(KERN_WARNING "ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n", 
-				card+1, frame.addr, frame.count, status);
+				printk(KERN_WARNING "ISILoad:"
+					"Card%d rejected load header:"
+					"\nAddress:0x%x \nCount:0x%x"
+					" \nStatus:0x%x \n", 
+					card+1, 
+					frame.addr, 
+					frame.count, 
+					status);
 				return -EIO;
 			}
 			outsw(base, (void *) frame.bin_data, word_count);
@@ -280,7 +354,10 @@
 				return -EIO;
 				
 			if ((status=inw(base+0x4))!=0) {
-				printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%x\n",card+1, status);
+				printk(KERN_ERR "ISILoad:Card%d"
+				" got out of sync.Card Status:0x%x\n",
+				card+1, 
+				status);
 				return -EIO;
 			}	
 			return 0;
@@ -346,6 +423,9 @@
 			outw(0x0, base+0x4);    /* for ISI4608 cards */
 							
 			isi_card[card].status |= FIRMWARE_LOADED;
+			printk(KERN_INFO "ISICOM: Card%d with %d ports at 0x%x using irq %d.\n", 
+				card+1,isi_card[card].port_count, 
+				isi_card[card].base, isi_card[card].irq); 
 			return 0;	
 			
 	default:
@@ -363,8 +443,10 @@
  *	ISICOM Driver specific routines ...
  *
  */
- 
-static inline int isicom_paranoia_check(struct isi_port const * port, kdev_t dev, 
+#ifndef ISIOCM_DEBUG 
+static 
+#endif
+inline int isicom_paranoia_check(struct isi_port const * port, kdev_t dev, 
 					const char * routine)
 {
 #ifdef ISICOM_DEBUG 
@@ -391,14 +473,15 @@
 } 
 
 /*	Transmitter	*/
-
-static void isicom_tx(unsigned long _data)
+#ifndef ISICOM_DEBUG
+static 
+#endif
+void isicom_tx(unsigned long _data)
 {
 	short count = (BOARD_COUNT-1), card, base;
-	short txcount, wait, wrd, residue, word_count, cnt;
+	short txcount, wrd, residue, word_count, cnt;
 	struct isi_port * port;
 	struct tty_struct * tty;
-	unsigned long flags;
 	
 #ifdef ISICOM_DEBUG
 	++tx_count;
@@ -416,54 +499,64 @@
 		
 	prev_card = card;
 	
-	count = isi_card[card].port_count;
+	
 	port = isi_card[card].ports;
 	base = isi_card[card].base;
-	for (;count > 0;count--, port++) {
+	for (count = isi_card[card].port_count; count > 0; count--, port++) {
+		
+		if (!lock_card_at_interrupt(&isi_card[card])) {
+#ifdef ISICOM_DEBUG
+			printk(KERN_DEBUG "ISICOM: isicom_tx:"
+				"Card(0x%x) found busy.\n",
+				card);
+#endif
+			continue;
+		}
+
 		/* port not active or tx disabled to force flow control */
-		if (!(port->status & ISI_TXOK))
+		if (!(port->flags & ASYNC_INITIALIZED) ||
+			!(port->status & ISI_TXOK)) {
+			unlock_card(&isi_card[card]);
 			continue;
+		}
 		
 		tty = port->tty;
-		save_flags(flags); cli();
+
 		txcount = MIN(TX_SIZE, port->xmit_cnt);
 		if ((txcount <= 0) || tty->stopped || tty->hw_stopped) {
-			restore_flags(flags);
-			continue;
-		}
-		wait = 200;	
-		while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
-		if (wait <= 0) {
-			restore_flags(flags);
-#ifdef ISICOM_DEBUG
-			printk(KERN_DEBUG "ISICOM: isicom_tx:Card(0x%x) found busy.\n",
-				card);
-#endif
+			unlock_card(&isi_card[card]);
 			continue;
 		}
+
 		if (!(inw(base + 0x02) & (1 << port->channel))) {
-			restore_flags(flags);
+			unlock_card(&isi_card[card]);
 #ifdef ISICOM_DEBUG					
-			printk(KERN_DEBUG "ISICOM: isicom_tx: cannot tx to 0x%x:%d.\n",
-					base, port->channel + 1);
+			printk(KERN_DEBUG "ISICOM: isicom_tx:"
+					"Card(0x%x) cannot accept data"
+					" for channel %d!\n",
+					base,
+					port->channel + 1);
 #endif					
 			continue;		
 		}
 #ifdef ISICOM_DEBUG
 		printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n", 
-				txcount, port->channel+1); 
+				txcount,
+				port->channel+1); 
 #endif	
-		outw((port->channel << isi_card[card].shift_count) | txcount
-					, base);
+		outw((port->channel << isi_card[card].shift_count) | txcount,
+			base);
 		residue = NO;
-		wrd = 0;			
+		wrd = 0;
 		while (1) {
 			cnt = MIN(txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
 			if (residue == YES) {
 				residue = NO;
 				if (cnt > 0) {
-					wrd |= (port->xmit_buf[port->xmit_tail] << 8);
-					port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+					wrd |= (port->xmit_buf[port->xmit_tail]
+						 << 8);
+					port->xmit_tail = (port->xmit_tail + 1)
+						 & (SERIAL_XMIT_SIZE - 1);
 					port->xmit_cnt--;
 					txcount--;
 					cnt--;
@@ -477,14 +570,15 @@
 			if (cnt <= 0) break;
 			word_count = cnt >> 1;
 			outsw(base, port->xmit_buf+port->xmit_tail, word_count);
-			port->xmit_tail = (port->xmit_tail + (word_count << 1)) &
-						(SERIAL_XMIT_SIZE - 1);
+			port->xmit_tail = (port->xmit_tail + (word_count << 1))
+				& (SERIAL_XMIT_SIZE - 1);
 			txcount -= (word_count << 1);
 			port->xmit_cnt -= (word_count << 1);
 			if (cnt & 0x0001) {
 				residue = YES;
 				wrd = port->xmit_buf[port->xmit_tail];
-				port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+				port->xmit_tail = (port->xmit_tail + 1) &
+						(SERIAL_XMIT_SIZE - 1);
 				port->xmit_cnt--;
 				txcount--;
 			}
@@ -495,7 +589,7 @@
 			port->status &= ~ISI_TXOK;
 		if (port->xmit_cnt <= WAKEUP_CHARS)
 			schedule_bh(port);
-		restore_flags(flags);
+		unlock_card(&isi_card[card]);
 	}	
 
 		/*	schedule another tx for hopefully in about 10ms	*/	
@@ -532,11 +626,13 @@
 	    tty->ldisc.write_wakeup)
 		(tty->ldisc.write_wakeup)(tty);
 	wake_up_interruptible(&tty->write_wait);
-	wake_up_interruptible(&tty->poll_wait);
 } 		
  		
 /* main interrupt handler routine */ 		
-static void isicom_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+#ifndef	ISICOM_DEBUG
+static 
+#endif
+void isicom_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
 	struct isi_board * card;
 	struct isi_port * port;
@@ -545,26 +641,34 @@
 	unsigned char channel;
 	short byte_count;
 	
-	/*
-	 *      find the source of interrupt
-	 */
-	 
-	for(count = 0; count < BOARD_COUNT; count++) { 
-		card = &isi_card[count];
-		if (card->base != 0) {
-			if (((card->isa == YES) && (card->irq == irq)) || 
-				((card->isa == NO) && (card->irq == irq) && (inw(card->base+0x0e) & 0x02)))
-				break;
-		}
-		card = NULL;
-	}
+#ifdef	ISICOM_DEBUG
+	++intr_count;
+#endif
+	
+	card = (struct isi_board *) dev_id;
 
 	if (!card || !(card->status & FIRMWARE_LOADED)) {
-/*		printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);*/
+#ifdef ISICOM_DEBUG 
+		printk(KERN_DEBUG "ISICOM: interrupt:"
+				" not handling irq%d!.\n", 
+				irq);
+#endif
 		return;
 	}
-	
+
 	base = card->base;
+
+	/*
+	 *	If this is a PCI card, did it really interrupt us ?
+	 */
+	if ((card->isa == NO) && (!inw(base+0x0e) & 0x02))
+		return;
+
+	spin_lock(&card->card_lock);
+#ifdef ISICOM_DEBUG 
+	printk(KERN_DEBUG "ISICOM: isicom_interrupt: acquired card spinlock\n");
+
+#endif	
 	if (card->isa == NO) {
 	/*
 	 *      disable any interrupts from the PCI card and lower the
@@ -582,12 +686,14 @@
 	printk(KERN_DEBUG "ISICOM:Intr:(0x%x:%d).\n", base, channel+1);
 #endif	
 	if ((channel+1) > card->port_count) {
-		printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
-				base, channel+1);
+		printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x):"
+					" %d(channel) > port_count.\n",
+					base, channel+1);
 		if (card->isa)
 			ClearInterrupt(base);
 		else
 			outw(0x0000, base+0x04); /* enable interrupts */		
+		spin_unlock(&card->card_lock);
 		return;			
 	}
 	port = card->ports + channel;
@@ -596,6 +702,7 @@
 			ClearInterrupt(base);
 		else
 			outw(0x0000, base+0x04); /* enable interrupts */
+		spin_unlock(&card->card_lock);
 		return;
 	}	
 		
@@ -606,6 +713,7 @@
 		switch(header & 0xff) {
 			case 0:	/* Change in EIA signals */
 				
+
 				if (port->flags & ASYNC_CHECK_CD) {
 					if (port->status & ISI_DCD) {
 						if (!(header & ISI_DCD)) {
@@ -613,7 +721,6 @@
 #ifdef ISICOM_DEBUG						
 							printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n");
 #endif							
-							port->status &= ~ISI_DCD;
 							if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
 								(port->flags & ASYNC_CALLOUT_NOHUP)))
 								queue_task(&port->hangup_tq,
@@ -626,42 +733,39 @@
 #ifdef ISICOM_DEBUG
 							printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n");
 #endif							
-							port->status |= ISI_DCD;
 							wake_up_interruptible(&port->open_wait);
 						}
 					}
 				}
-				else {
-					if (header & ISI_DCD) 
-						port->status |= ISI_DCD;
-					else
-						port->status &= ~ISI_DCD;
-				}	
 				
+				if (header & ISI_DCD) 
+					port->status |= ISI_DCD;
+				else
+					port->status &= ~ISI_DCD;
+
 				if (port->flags & ASYNC_CTS_FLOW) {
 					if (port->tty->hw_stopped) {
 						if (header & ISI_CTS) {
 							port->tty->hw_stopped = 0;
-							/* start tx ing */
-							port->status |= (ISI_TXOK | ISI_CTS);
+							/* start tx ing 
+							port->status |= (ISI_TXOK | ISI_CTS);*/
 							schedule_bh(port);
 						}
 					}
 					else {
 						if (!(header & ISI_CTS)) {
-							port->tty->hw_stopped = 1;
-							/* stop tx ing */
-							port->status &= ~(ISI_TXOK | ISI_CTS);
+						/*	port->tty->hw_stopped = 1;*/
+							/* stop tx ing 
+							port->status &= ~(ISI_TXOK | ISI_CTS);*/
 						}
 					}
 				}
-				else {
-					if (header & ISI_CTS) 
-						port->status |= ISI_CTS;
-					else
-						port->status &= ~ISI_CTS;
-				}
 				
+				if (header & ISI_CTS) 
+					port->status |= ISI_CTS;
+				else
+					port->status &= ~ISI_CTS;
+
 				if (header & ISI_DSR) 
 					port->status |= ISI_DSR;
 				else
@@ -687,7 +791,8 @@
 				break;
 				
 			case 2:	/* Statistics		 */
-				printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n");			
+				printk(KERN_DEBUG "ISICOM: isicom_interrupt:"
+					" stats!!!.\n");
 				break;
 				
 			default:
@@ -714,8 +819,9 @@
 		tty->flip.count += count;
 		
 		if (byte_count > 0) {
-			printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
-					base, channel+1);
+			printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d):"
+				" Flip buffer overflow! dropping bytes...\n",
+				base, channel+1);
 			while(byte_count > 0) { /* drain out unread xtra data */
 				inw(base);
 				byte_count -= 2;
@@ -726,20 +832,25 @@
 	if (card->isa == YES)
 		ClearInterrupt(base);
 	else
-		outw(0x0000, base+0x04); /* enable interrupts */	
+		outw(0x0000, base+0x04); /* enable interrupts */
+	spin_unlock(&card->card_lock);
 	return;
 } 
-
- /* called with interrupts disabled */ 
-static void isicom_config_port(struct isi_port * port)
+#ifndef ISICOM_DEBUG
+static 
+#endif
+void isicom_config_port(struct isi_port * port)
 {
 	struct isi_board * card = port->card;
 	struct tty_struct * tty;
 	unsigned long baud;
-	unsigned short channel_setup, wait, base = card->base;
+	unsigned short channel_setup, base = card->base;
 	unsigned short channel = port->channel, shift_count = card->shift_count;
 	unsigned char flow_ctrl;
 	
+#ifdef	ISICOM_DEBUG
+	printk(KERN_DEBUG "ISICOM:isicom_config_port:start\n");
+#endif
 	if (!(tty = port->tty) || !tty->termios)
 		return;
 	baud = C_BAUD(tty);
@@ -776,40 +887,47 @@
 	else  
 		raise_dtr(port);
 		
-	wait = 100;	
-	while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));	
-	if (!wait) {
-		printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at channel setup.\n");
-		return;
-	}			 
-	outw(0x8000 | (channel << shift_count) |0x03, base);
-	outw(linuxb_to_isib[baud] << 8 | 0x03, base);
-	channel_setup = 0;
-	switch(C_CSIZE(tty)) {
-		case CS5:
-			channel_setup |= ISICOM_CS5;
-			break;
-		case CS6:
-			channel_setup |= ISICOM_CS6;
-			break;
-		case CS7:
-			channel_setup |= ISICOM_CS7;
-			break;
-		case CS8:
-			channel_setup |= ISICOM_CS8;
-			break;
-	}
+	if (lock_card(card)) {
+		outw(0x8000 | (channel << shift_count) |0x03, base);
+		outw(linuxb_to_isib[baud] << 8 | 0x03, base);
+		channel_setup = 0;
+		switch(C_CSIZE(tty)) {
+			case CS5:
+				channel_setup |= ISICOM_CS5;
+				break;
+			case CS6:
+				channel_setup |= ISICOM_CS6;
+				break;
+			case CS7:
+				channel_setup |= ISICOM_CS7;
+				break;
+			case CS8:
+				channel_setup |= ISICOM_CS8;
+				break;
+		}
 		
-	if (C_CSTOPB(tty))
-		channel_setup |= ISICOM_2SB;
-	
-	if (C_PARENB(tty))
-		channel_setup |= ISICOM_EVPAR;
-	if (C_PARODD(tty))
-		channel_setup |= ISICOM_ODPAR;	
-	outw(channel_setup, base);	
-	InterruptTheCard(base);
+		if (C_CSTOPB(tty))
+			channel_setup |= ISICOM_2SB;
 	
+		if (C_PARENB(tty)) {
+			if (C_PARODD(tty))
+				channel_setup |= ISICOM_ODPAR;
+			else
+				channel_setup |= ISICOM_EVPAR;
+		}
+		outw(channel_setup, base);	
+		InterruptTheCard(base);
+
+#ifdef	ISICOM_DEBUG
+		printk(KERN_DEBUG "ISICOM:isicom_config_port:channel setup\n");
+#endif
+		unlock_card(card);	
+	}
+	else 
+		printk(KERN_WARNING "ISICOM:isicom_config_port:"
+				"Card (0x%x) busy for Channel Setup\n",
+				card->base);
+
 	if (C_CLOCAL(tty))
 		port->flags &= ~ASYNC_CHECK_CD;
 	else
@@ -827,23 +945,33 @@
 	if (I_IXOFF(tty))
 		flow_ctrl |= ISICOM_INITIATE_XONXOFF;	
 		
-	wait = 100;	
-	while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));	
-	if (!wait) {
-		printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at flow setup.\n");
-		return;
-	}			 
-	outw(0x8000 | (channel << shift_count) |0x04, base);
-	outw(flow_ctrl << 8 | 0x05, base);
-	outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
-	InterruptTheCard(base);
+	if (lock_card(card)) {
+		outw(0x8000 | (channel << shift_count) |0x04, base);
+		outw(flow_ctrl << 8 | 0x05, base);
+		outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
+		InterruptTheCard(base);
+
+#ifdef	ISICOM_DEBUG
+		printk(KERN_DEBUG "ISICOM:isicom_config_port:flow setup\n");
+#endif
+
+		unlock_card(card);
+	}
+	else
+		printk(KERN_WARNING "ISICOM:isicom_config_port:"
+				"Card (0x%x) busy for Flow Ctrl Setup\n",
+				card->base);
 	
+			 
 	/*	rx enabled -> enable port for rx on the card	*/
 	if (C_CREAD(tty)) {
 		card->port_status |= (1 << channel);
 		outw(card->port_status, base + 0x02);
 	}
 		
+#ifdef	ISICOM_DEBUG
+	printk(KERN_DEBUG "ISICOM:isicom_config_port:stop\n");
+#endif
 }
  
 /* open et all */ 
@@ -854,74 +982,106 @@
 	struct isi_port * port;
 	unsigned long flags;
 	
-	if (bp->status & BOARD_ACTIVE) 
-		return;
-	port = bp->ports;
 #ifdef ISICOM_DEBUG	
-	printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts start, port_count %d...\n", bp->port_count);
+	printk(KERN_DEBUG "ISICOM: setup_board:start\n");
+#endif
+
+	spin_lock_irqsave(&bp->card_lock, flags);
+		if (bp->status & BOARD_ACTIVE) {
+#ifdef ISICOM_DEBUG	
+			printk(KERN_DEBUG "ISICOM: setup_board:"
+					" already active\n");
+#endif
+			spin_unlock_irqrestore(&bp->card_lock, flags);
+			return;
+		}
+		port = bp->ports;
+		bp->status |= BOARD_ACTIVE;
+		MOD_INC_USE_COUNT;
+	spin_unlock_irqrestore(&bp->card_lock, flags);
+
+	for(channel = 0; channel < bp->port_count; channel++, port++)
+		drop_dtr(port);
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: setup_board:stop\n");
 #endif
-	for(channel = 0; channel < bp->port_count; channel++, port++) {
-		save_flags(flags); cli();
-		drop_dtr_rts(port);
-		restore_flags(flags);
-	}
-#ifdef ISICOM_DEBUG		
-	printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts stop...\n");	
-#endif	
-	
-	bp->status |= BOARD_ACTIVE;
-	MOD_INC_USE_COUNT;
 	return;
 }
- 
-static int isicom_setup_port(struct isi_port * port)
+
+#ifndef	ISICOM_DEBUG 
+static 
+#endif
+int isicom_setup_port(struct isi_port * port)
 {
 	struct isi_board * card = port->card;
 	unsigned long flags;
 	
-	if (port->flags & ASYNC_INITIALIZED)
-		return 0;
-	if (!port->xmit_buf) {
-		unsigned long page;
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: setup_port:start\n");
+#endif
+	spin_lock_irqsave(&card->card_lock, flags);
+		if (port->flags & ASYNC_INITIALIZED) {
+			spin_unlock_irqrestore(&card->card_lock, flags);
+			return 0;
+		}
+
+		if (!port->xmit_buf) {
+			unsigned long page;
 		
-		if (!(page = get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
+			if (!(page = get_free_page(GFP_KERNEL))) {
+				spin_unlock_irqrestore(&card->card_lock, flags);
+				return -ENOMEM;
+			}
 		
-		if (port->xmit_buf) {
-			free_page(page);
-			return -ERESTARTSYS;
+			if (port->xmit_buf) {
+				free_page(page);
+				spin_unlock_irqrestore(&card->card_lock, flags);
+				return -ERESTARTSYS;
+			}
+			port->xmit_buf = (unsigned char *) page;	
 		}
-		port->xmit_buf = (unsigned char *) page;	
-	}	
-	save_flags(flags); cli();
-	if (port->tty)
-		clear_bit(TTY_IO_ERROR, &port->tty->flags);
-	if (port->count == 1)
-		card->count++;
+
+		if (port->tty)
+			clear_bit(TTY_IO_ERROR, &port->tty->flags);
+		if (port->count == 1)
+			card->count++;
 		
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+		port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+
+		port->flags |= ASYNC_INITIALIZED;
+	spin_unlock_irqrestore(&card->card_lock, flags);
 	
 	/*	discard any residual data	*/
 	kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
 	
+#ifdef ISICOM_DEBUG		
+	printk(KERN_DEBUG "ISICOM: setup_port: isicom_config_port...\n");	
+#endif	
 	isicom_config_port(port);
-	port->flags |= ASYNC_INITIALIZED;
 	
-	restore_flags(flags);
+	set_signal_mask(port, 0xff); /* enable EIA status interrupt reporting */
 	
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: setup_port:stop\n");
+#endif
 	return 0;		
-} 
- 
-static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port) 
+}
+#ifndef	ISICOM_DEBUG
+static 
+#endif
+int block_til_ready(struct tty_struct * tty, struct file * filp, 
+				struct isi_port * port)
 {
 	int do_clocal = 0, retval;
 	struct wait_queue wait = { current, NULL };
+	struct isi_board *card = port->card;
 
 	/* block if port is in the process of being closed */
 
 	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
 #ifdef ISICOM_DEBUG	
-		printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n");
+		printk(KERN_DEBUG "ISICOM: block_til_ready:"
+				" close in progress.\n");
 #endif		
 		interruptible_sleep_on(&port->close_wait);
 		if (port->flags & ASYNC_HUP_NOTIFY)
@@ -948,15 +1108,14 @@
 		    (port->pgrp != current->pgrp))
 			return -EBUSY;
 		port->flags |= ASYNC_CALLOUT_ACTIVE;
-		cli();
 		raise_dtr_rts(port);
-		sti();
 		return 0;
 	}
 	
 	/* if non-blocking mode is set ... */
 	
-	if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
+	if ((filp->f_flags & O_NONBLOCK) || 
+		(tty->flags & (1 << TTY_IO_ERROR))) {
 #ifdef ISICOM_DEBUG	
 		printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n");
 #endif		
@@ -982,20 +1141,20 @@
 						callout dev is busy */
 	retval = 0;
 	add_wait_queue(&port->open_wait, &wait);
-	cli();
+
+	spin_lock_irqsave(&card->card_lock, card->flags);
 		if (!tty_hung_up_p(filp))
 			port->count--;
-	sti();
+	spin_unlock_irqrestore(&card->card_lock, card->flags);
+
 	port->blocked_open++;
 #ifdef ISICOM_DEBUG	
 	printk(KERN_DEBUG "ISICOM: block_til_ready: waiting for DCD...\n");
 #endif	
 	while (1) {
-		cli();
 		if (!(port->flags & ASYNC_CALLOUT_ACTIVE)) 
 			raise_dtr_rts(port);
 		
-		sti();
 		current->state = TASK_INTERRUPTIBLE;
 		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { 	
 			if (port->flags & ASYNC_HUP_NOTIFY)
@@ -1003,7 +1162,8 @@
 			else
 				retval = -ERESTARTSYS;
 #ifdef ISICOM_DEBUG				
-			printk(KERN_DEBUG "ISICOM: block_til_ready: tty_hung_up_p || not init.\n"); 
+			printk(KERN_DEBUG "ISICOM: block_til_ready:"
+					" tty_hung_up_p || not init.\n"); 
 #endif			
 			break;
 		}	
@@ -1011,13 +1171,15 @@
 		    !(port->flags & ASYNC_CLOSING) &&
 		    (do_clocal || (port->status & ISI_DCD))) {
 #ifdef ISICOM_DEBUG		    
-		 	printk(KERN_DEBUG "ISICOM: block_til_ready: do_clocal || DCD.\n");   
+		 	printk(KERN_DEBUG "ISICOM: block_til_ready:"
+					" do_clocal || DCD.\n");   
 #endif		 	
 			break;
 		}	
 		if (signal_pending(current)) {
 #ifdef ISICOM_DEBUG		
-			printk(KERN_DEBUG "ISICOM: block_til_ready: sig blocked.\n");
+			printk(KERN_DEBUG "ISICOM: block_til_ready:"
+					" sig blocked.\n");
 #endif			
 			retval = -ERESTARTSYS;
 			break;
@@ -1034,13 +1196,15 @@
 	port->flags |= ASYNC_NORMAL_ACTIVE;
 	return 0;
 }
- 
-static int isicom_open(struct tty_struct * tty, struct file * filp)
+
+#ifndef	ISICOM_DEBUG 
+static 
+#endif
+int isicom_open(struct tty_struct * tty, struct file * filp)
 {
 	struct isi_port * port;
 	struct isi_board * card;
 	unsigned int line, board;
-	unsigned long flags;
 	int error;
 
 #ifdef ISICOM_DEBUG	
@@ -1063,14 +1227,16 @@
 	card = &isi_card[board];
 	if (!(card->status & FIRMWARE_LOADED)) {
 #ifdef ISICOM_DEBUG	
-		printk(KERN_DEBUG"ISICOM: Firmware not loaded to card%d.\n", board);
+		printk(KERN_DEBUG"ISICOM: Firmware not loaded"
+				" to card%d.\n", board);
 #endif		
 		return -ENODEV;
 	}
 	
 	/*  open on a port greater than the port count for the card !!! */
 	if (line > ((board * 16) + card->port_count - 1)) {
-		printk(KERN_ERR "ISICOM: Open on a port which exceeds the port_count of the card!\n");
+		printk(KERN_ERR "ISICOM: Open on a port which exceeds"
+				" the port_count of the card!\n");
 		return -ENODEV;
 	}	
 	port = &isi_ports[line];	
@@ -1080,16 +1246,18 @@
 #ifdef ISICOM_DEBUG		
 	printk(KERN_DEBUG "ISICOM: isicom_setup_board ...\n");		
 #endif	
-	isicom_setup_board(card);		
+	isicom_setup_board(card);
 	
 	port->count++;
 	tty->driver_data = port;
 	port->tty = tty;
+
 #ifdef ISICOM_DEBUG	
 	printk(KERN_DEBUG "ISICOM: isicom_setup_port ...\n");
 #endif	
 	if ((error = isicom_setup_port(port))!=0)
 		return error;
+
 #ifdef ISICOM_DEBUG		
 	printk(KERN_DEBUG "ISICOM: block_til_ready ...\n");	
 #endif	
@@ -1101,9 +1269,7 @@
 			*tty->termios = port->normal_termios;
 		else 
 			*tty->termios = port->callout_termios;
-		save_flags(flags); cli();
 		isicom_config_port(port);
-		restore_flags(flags);		
 	}	
 	
 	port->session = current->session;	
@@ -1118,30 +1284,40 @@
 
 extern inline void isicom_shutdown_board(struct isi_board * bp)
 {
-	int channel;
-	struct isi_port * port;
-	
-	if (!(bp->status & BOARD_ACTIVE))
-		return;
-	bp->status &= ~BOARD_ACTIVE;
-	port = bp->ports;
-	for(channel = 0; channel < bp->port_count; channel++, port++) {
-		drop_dtr_rts(port);
-	}	
-	MOD_DEC_USE_COUNT;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bp->card_lock, flags);
+		if (!(bp->status & BOARD_ACTIVE)) {
+			spin_unlock_irqrestore(&bp->card_lock, flags);
+			return;
+		}
+		bp->status &= ~BOARD_ACTIVE;
+		MOD_DEC_USE_COUNT;
+	spin_unlock_irqrestore(&bp->card_lock, flags);
 }
 
-static void isicom_shutdown_port(struct isi_port * port)
+#ifndef	ISICOM_DEBUG
+static 
+#endif
+void isicom_shutdown_port(struct isi_port * port)
 {
 	struct isi_board * card = port->card;
-	struct tty_struct * tty;	
-	
-	if (!(port->flags & ASYNC_INITIALIZED))
-		return;
-	if (port->xmit_buf) {
-		free_page((unsigned long) port->xmit_buf);
-		port->xmit_buf = NULL;
-	}	
+	struct tty_struct * tty;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->card_lock, flags);	
+		if (!(port->flags & ASYNC_INITIALIZED)){
+			spin_unlock_irqrestore(&card->card_lock, flags);
+			return;
+		}
+		if (port->xmit_buf) {
+			free_page((unsigned long) port->xmit_buf);
+			port->xmit_buf = NULL;
+		}	
+		port->flags &= ~ASYNC_INITIALIZED;
+	spin_unlock_irqrestore(&card->card_lock, flags);
+
+	tty = port->tty;
 	if (!(tty = port->tty) || C_HUPCL(tty)) 
 		/* drop dtr on this port */
 		drop_dtr(port);
@@ -1150,37 +1326,44 @@
 	
 	if (tty)
 		set_bit(TTY_IO_ERROR, &tty->flags);
-	port->flags &= ~ASYNC_INITIALIZED;
 	
 	if (--card->count < 0) {
-		printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
-			card->base, card->count);
+		printk(KERN_DEBUG "ISICOM: isicom_shutdown_port:"
+				" bad board(0x%x) count %d.\n",
+				card->base, card->count);
 		card->count = 0;	
 	}
 	
+	set_signal_mask(port, 0x00); /*disable EIA status interrupt reporting */
+
 	/* last port was closed , shutdown that boad too */
 	if (!card->count)
 		isicom_shutdown_board(card);
 }
 
-static void isicom_close(struct tty_struct * tty, struct file * filp)
+#ifndef	ISICOM_DEBUG
+static 
+#endif
+void isicom_close(struct tty_struct * tty, struct file * filp)
 {
 	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	struct isi_board * card = port->card;
+	struct isi_board * card;
 	unsigned long flags;
 	
+#ifdef ISICOM_DEBUG		
+	printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
+#endif	
 	if (!port)
 		return;
+
+	card = port->card;
+
 	if (isicom_paranoia_check(port, tty->device, "isicom_close"))
 		return;
 	
-#ifdef ISICOM_DEBUG		
-	printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
-#endif	
-	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&card->card_lock, flags);
 	if (tty_hung_up_p(filp)) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->card_lock, flags);
 		return;
 	}
 	
@@ -1191,14 +1374,16 @@
 		port->count = 1;
 	}
 	if (--port->count < 0) {
-		printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
-			"channel%d = %d", card->base, port->channel, 
+		printk(KERN_WARNING "ISICOM:(0x%x) isicom_close:"
+			" bad port count for channel%d = %d", 
+			card->base, 
+			port->channel, 
 			port->count);
 		port->count = 0;	
 	}
 	
 	if (port->count) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->card_lock, flags);
 		return;
 	} 	
 	port->flags |= ASYNC_CLOSING;
@@ -1212,22 +1397,35 @@
 		port->callout_termios = *tty->termios;
 	
 	tty->closing = 1;
+
+	spin_unlock_irqrestore(&card->card_lock, flags);
 	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		tty_wait_until_sent(tty, port->closing_wait);
-	/* indicate to the card that no more data can be received 
-	   on this port */
+	spin_lock_irqsave(&card->card_lock, flags);
+
+	/* 
+	 *	indicate to the card that no more data can be received 
+	 *	on this port
+	 */
 	if (port->flags & ASYNC_INITIALIZED) {   
 		card->port_status &= ~(1 << port->channel);
 		outw(card->port_status, card->base + 0x02);
-	}	
+	}
+
+	spin_unlock_irqrestore(&card->card_lock, flags);
+
 	isicom_shutdown_port(port);
 	if (tty->driver.flush_buffer)
 		tty->driver.flush_buffer(tty);
 	if (tty->ldisc.flush_buffer)
 		tty->ldisc.flush_buffer(tty);
+
+	spin_lock_irqsave(&card->card_lock, flags);
+
 	tty->closing = 0;
 	port->tty = 0;
 	if (port->blocked_open) {
+		spin_unlock_irqrestore(&card->card_lock, flags);
 		if (port->close_delay) {
 			current->state = TASK_INTERRUPTIBLE;
 #ifdef ISICOM_DEBUG			
@@ -1236,101 +1434,130 @@
 			schedule_timeout(port->close_delay);
 		}
 		wake_up_interruptible(&port->open_wait);
+		spin_lock_irqsave(&card->card_lock, flags);
 	}	
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE | 
 			ASYNC_CLOSING);
+	port->status &= ~ISI_TXOK;
 	wake_up_interruptible(&port->close_wait);
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&card->card_lock, flags);
+
 #ifdef ISICOM_DEBUG	
 	printk(KERN_DEBUG "ISICOM: Close end!!!.\n");
 #endif	
 }
 
 /* write et all */
-static int isicom_write(struct tty_struct * tty, int from_user,
+#ifndef	ISICOM_DEBUG
+static 
+#endif
+int isicom_write(struct tty_struct * tty, int from_user,
 			const unsigned char * buf, int count)
 {
 	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	unsigned long flags;
+	struct isi_board * card = port->card;
 	int cnt, total = 0;
 #ifdef ISICOM_DEBUG
-	printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.\n",
-			port->channel+1, count);
+/*	printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.\n",
+			port->channel+1, count);*/
 #endif	  	
 	if (isicom_paranoia_check(port, tty->device, "isicom_write"))
 		return 0;
 	
+	spin_lock_irqsave(&card->card_lock, card->flags);
+
 	if (!tty || !port->xmit_buf || !tmp_buf)
 		return 0;
 	if (from_user)
 		down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */
 		
-	save_flags(flags);
+	
 	while(1) {	
-		cli();
+
+/*		spin_lock_irqsave(&card->card_lock, card->flags);*/
 		cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 			SERIAL_XMIT_SIZE - port->xmit_head));
-		if (cnt <= 0) 
+		if (cnt <= 0)  {
+/*			spin_unlock_irqrestore(&card->card_lock, card->flags);*/
 			break;
+		}
 		
 		if (from_user) {
-			/* the following may block for paging... hence 
-			   enabling interrupts but tx routine may have 
-			   created more space in xmit_buf when the ctrl 
-			   gets back here  */
-			sti(); 
+			/*	
+			 *	the following may block for paging... hence 
+			 *	enabling interrupts but tx routine may have 
+			 *	created more space in xmit_buf when the ctrl 
+			 *	gets back here
+			 */
+
+			spin_unlock_irqrestore(&card->card_lock, card->flags);
+
 			copy_from_user(tmp_buf, buf, cnt);
-			cli();
-			cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-			SERIAL_XMIT_SIZE - port->xmit_head));
+
+			spin_lock_irqsave(&card->card_lock, card->flags);
+
+			cnt = MIN(cnt,
+				MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+				SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt);
 		}	
 		else
 			memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
-		port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
+		port->xmit_head = (port->xmit_head + cnt) &
+				(SERIAL_XMIT_SIZE - 1);
 		port->xmit_cnt += cnt;
-		restore_flags(flags);
+
+/*		spin_unlock_irqrestore(&card->card_lock, card->flags);*/
+		
 		buf += cnt;
 		count -= cnt;
 		total += cnt;
-	}		
+	}
 	if (from_user)
 		up(&tmp_buf_sem);
+
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
 		port->status |= ISI_TXOK;
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&card->card_lock, card->flags);
+
 #ifdef ISICOM_DEBUG
-	printk(KERN_DEBUG "ISICOM: isicom_write %d bytes written.\n", total);
+/*	printk(KERN_DEBUG "ISICOM: isicom_write %d bytes written.\n", total);*/
 #endif		
-	return total;	
+	return total;
 }
 
 /* put_char et all */
-static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
+#ifndef	ISICOM_DEBUG
+static 
+#endif
+void isicom_put_char(struct tty_struct * tty, unsigned char ch)
 {
 	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	unsigned long flags;
+	struct isi_board * card = port->card;
 	
+#ifdef ISICOM_DEBUG
+	printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.\n", port->channel+1, ch);
+#endif			
 	if (isicom_paranoia_check(port, tty->device, "isicom_put_char"))
 		return;
 	
 	if (!tty || !port->xmit_buf)
 		return;
-#ifdef ISICOM_DEBUG
-	printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.\n", port->channel+1, ch);
-#endif			
-		
-	save_flags(flags); cli();
+
+	spin_lock_irqsave(&card->card_lock, card->flags);
 	
-	if (port->xmit_cnt >= (SERIAL_XMIT_SIZE - 1)) {
-		restore_flags(flags);
-		return;
-	}
+		if (port->xmit_cnt >= (SERIAL_XMIT_SIZE - 1)) {
+			spin_unlock_irqrestore(&card->card_lock, card->flags);
+			return;
+		}
 	
-	port->xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
-	port->xmit_cnt++;
-	restore_flags(flags);
+		port->xmit_buf[port->xmit_head++] = ch;
+		port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
+		port->xmit_cnt++;
+
+	spin_unlock_irqrestore(&card->card_lock, card->flags);
 }
 
 /* flush_chars et all */
@@ -1377,21 +1604,20 @@
 extern inline void isicom_send_break(struct isi_port * port, unsigned long length)
 {
 	struct isi_board * card = port->card;
-	short wait = 10;
 	unsigned short base = card->base;	
-	unsigned long flags;
 	
-	save_flags(flags); cli();
-	while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));	
-	if (!wait) {
-		printk(KERN_DEBUG "ISICOM: Card found busy in isicom_send_break.\n");
+	if (!lock_card(card)) {
+		printk(KERN_DEBUG "ISICOM: Card found busy in"
+			" isicom_send_break.\n");
 		return;
-	}	
+	}
+
 	outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
 	outw((length & 0xff) << 8 | 0x00, base);
 	outw((length & 0xff00), base);
 	InterruptTheCard(base);
-	restore_flags(flags);
+
+	unlock_card(card);
 }
 
 static int isicom_get_modem_info(struct isi_port * port, unsigned int * value)
@@ -1414,12 +1640,10 @@
 					unsigned int * value)
 {
 	unsigned int arg;
-	unsigned long flags;
 	
 	if(get_user(arg, value))
 		return -EFAULT;
 	
-	save_flags(flags); cli();
 	
 	switch(cmd) {
 		case TIOCMBIS:
@@ -1449,10 +1673,8 @@
 			break;
 		
 		default:
-			restore_flags(flags);
 			return -EINVAL;		 	
 	}
-	restore_flags(flags);
 	return 0;
 }			
 
@@ -1460,7 +1682,6 @@
 					struct serial_struct * info)
 {
 	struct serial_struct newinfo;
-	unsigned long flags;
 	int reconfig_port;
 
 	if(copy_from_user(&newinfo, info, sizeof(newinfo)))
@@ -1485,9 +1706,7 @@
 				(newinfo.flags & ASYNC_FLAGS));
 	}
 	if (reconfig_port) {
-		save_flags(flags); cli();
 		isicom_config_port(port);
-		restore_flags(flags);
 	}
 	return 0;		 
 }		
@@ -1576,7 +1795,6 @@
 static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
 {
 	struct isi_port * port = (struct isi_port *) tty->driver_data;
-	unsigned long flags;
 	
 	if (isicom_paranoia_check(port, tty->device, "isicom_set_termios"))
 		return;
@@ -1585,9 +1803,7 @@
 	    tty->termios->c_iflag == old_termios->c_iflag)
 		return;
 		
-	save_flags(flags); cli();
 	isicom_config_port(port);
-	restore_flags(flags);
 	
 	if ((old_termios->c_cflag & CRTSCTS) &&
 	    !(tty->termios->c_cflag & CRTSCTS)) {	
@@ -1601,16 +1817,13 @@
 {
 	struct isi_port * port = (struct isi_port *) tty->driver_data;
 	struct isi_board * card = port->card;
-	unsigned long flags;
 	
 	if (isicom_paranoia_check(port, tty->device, "isicom_throttle"))
 		return;
 	
 	/* tell the card that this port cannot handle any more data for now */
-	save_flags(flags); cli();
 	card->port_status &= ~(1 << port->channel);
 	outw(card->port_status, card->base + 0x02);
-	restore_flags(flags);
 }
 
 /* unthrottle et all */
@@ -1618,16 +1831,13 @@
 {
 	struct isi_port * port = (struct isi_port *) tty->driver_data;
 	struct isi_board * card = port->card;
-	unsigned long flags;
 	
 	if (isicom_paranoia_check(port, tty->device, "isicom_unthrottle"))
 		return;
 	
 	/* tell the card that this port is ready to accept more data */
-	save_flags(flags); cli();
 	card->port_status |= (1 << port->channel);
 	outw(card->port_status, card->base + 0x02);
-	restore_flags(flags);
 }
 
 /* stop et all */
@@ -1688,16 +1898,20 @@
 {
 	struct isi_port * port = (struct isi_port *) tty->driver_data;
 	unsigned long flags;
+#ifdef	__SMP__
+	struct isi_board *card = port->card;
+#endif
 	
 	if (isicom_paranoia_check(port, tty->device, "isicom_flush_buffer"))
 		return;
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&card->card_lock, flags);
+
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&card->card_lock, flags);
 	
 	wake_up_interruptible(&tty->write_wait);
-	wake_up_interruptible(&tty->poll_wait);
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 	    tty->ldisc.write_wakeup)
 		(tty->ldisc.write_wakeup)(tty);
@@ -1710,14 +1924,23 @@
 	for (count=0; count < BOARD_COUNT; count++ ) {
 		if (isi_card[count].base) {
 			if (check_region(isi_card[count].base,16)) {
-				printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
-					isi_card[count].base,isi_card[count].base+15,count+1);
+				printk(KERN_DEBUG "ISICOM: I/O Region"
+					" 0x%x-0x%x is busy."
+					" Card%d will be disabled.\n",
+					isi_card[count].base,
+					isi_card[count].base+15,
+					count+1);
 				isi_card[count].base=0;
 			}
 			else {
-				request_region(isi_card[count].base,16,ISICOM_NAME);
+				request_region(isi_card[count].base,16,
+						ISICOM_NAME);
 #ifdef ISICOM_DEBUG				
-				printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x requested for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
+				printk(KERN_DEBUG "ISICOM: I/O Region"
+					" 0x%x-0x%x requested for Card%d.\n",
+					isi_card[count].base,
+					isi_card[count].base+15,
+					count+1);
 #endif				
 				done++;
 			}
@@ -1733,7 +1956,11 @@
 		if (isi_card[count].base) {
 			release_region(isi_card[count].base,16);
 #ifdef ISICOM_DEBUG			
-			printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x released for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
+			printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x"
+				" released for Card%d.\n",
+				isi_card[count].base,
+				isi_card[count].base+15,
+				count+1);
 #endif			
 		}
 }
@@ -1744,55 +1971,57 @@
 
 	/* tty driver structure initialization */
 	memset(&isicom_normal, 0, sizeof(struct tty_driver));
-	isicom_normal.magic	= TTY_DRIVER_MAGIC;
-	isicom_normal.name 	= "ttyM";
-	isicom_normal.major	= ISICOM_NMAJOR;
+	isicom_normal.magic		= TTY_DRIVER_MAGIC;
+	isicom_normal.name 		= "ttyM";
+	isicom_normal.major		= ISICOM_NMAJOR;
 	isicom_normal.minor_start	= 0;
-	isicom_normal.num	= PORT_COUNT;
-	isicom_normal.type	= TTY_DRIVER_TYPE_SERIAL;
-	isicom_normal.subtype	= SERIAL_TYPE_NORMAL;
+	isicom_normal.num		= PORT_COUNT;
+	isicom_normal.type		= TTY_DRIVER_TYPE_SERIAL;
+	isicom_normal.subtype		= SERIAL_TYPE_NORMAL;
 	isicom_normal.init_termios	= tty_std_termios;
 	isicom_normal.init_termios.c_cflag	= 
 				B9600 | CS8 | CREAD | HUPCL |CLOCAL;
-	isicom_normal.flags	= TTY_DRIVER_REAL_RAW;
-	isicom_normal.refcount	= &isicom_refcount;
+	isicom_normal.flags		= TTY_DRIVER_REAL_RAW;
+	isicom_normal.refcount		= &isicom_refcount;
 	
-	isicom_normal.table	= isicom_table;
-	isicom_normal.termios	= isicom_termios;
+	isicom_normal.table		= isicom_table;
+	isicom_normal.termios		= isicom_termios;
 	isicom_normal.termios_locked	= isicom_termios_locked;
 	
-	isicom_normal.open	= isicom_open;
-	isicom_normal.close	= isicom_close;
-	isicom_normal.write	= isicom_write;
-	isicom_normal.put_char	= isicom_put_char;
+	isicom_normal.open		= isicom_open;
+	isicom_normal.close		= isicom_close;
+	isicom_normal.write		= isicom_write;
+	isicom_normal.put_char		= isicom_put_char;
 	isicom_normal.flush_chars	= isicom_flush_chars;
 	isicom_normal.write_room	= isicom_write_room;
 	isicom_normal.chars_in_buffer	= isicom_chars_in_buffer;
-	isicom_normal.ioctl	= isicom_ioctl;
+	isicom_normal.ioctl		= isicom_ioctl;
 	isicom_normal.set_termios	= isicom_set_termios;
-	isicom_normal.throttle	= isicom_throttle;
+	isicom_normal.throttle		= isicom_throttle;
 	isicom_normal.unthrottle	= isicom_unthrottle;
-	isicom_normal.stop	= isicom_stop;
-	isicom_normal.start	= isicom_start;
-	isicom_normal.hangup	= isicom_hangup;
+	isicom_normal.stop		= isicom_stop;
+	isicom_normal.start		= isicom_start;
+	isicom_normal.hangup		= isicom_hangup;
 	isicom_normal.flush_buffer	= isicom_flush_buffer;
 	
 	/*	callout device	*/
 	
-	isicom_callout	= isicom_normal;
-	isicom_callout.name	= "cum"; 
-	isicom_callout.major	= ISICOM_CMAJOR;
-	isicom_callout.subtype	= SERIAL_TYPE_CALLOUT;
+	isicom_callout			= isicom_normal;
+	isicom_callout.name		= "cum"; 
+	isicom_callout.major		= ISICOM_CMAJOR;
+	isicom_callout.subtype		= SERIAL_TYPE_CALLOUT;
 	
 	if ((error=tty_register_driver(&isicom_normal))!=0) {
-		printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
-			error);
+		printk(KERN_DEBUG "ISICOM: Couldn't register the"
+				" dialin driver, error=%d\n",
+				error);
 		return error;
 	}
 	if ((error=tty_register_driver(&isicom_callout))!=0) {
 		tty_unregister_driver(&isicom_normal);
-		printk(KERN_DEBUG "ISICOM: Couldn't register the callout driver, error=%d\n",
-			error);
+		printk(KERN_DEBUG "ISICOM: Couldn't register the"
+				" callout driver, error=%d\n",
+				error);
 		return error;	
 	}
 	return 0;
@@ -1802,15 +2031,17 @@
 {
 	int error;
 	if ((error=tty_unregister_driver(&isicom_callout))!=0)
-		printk(KERN_DEBUG "ISICOM: couldn't unregister callout driver error=%d.\n",error);
+		printk(KERN_DEBUG "ISICOM: couldn't unregister"
+				" callout driver error=%d.\n",error);
 	if (tty_unregister_driver(&isicom_normal))
-		printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
+		printk(KERN_DEBUG "ISICOM: couldn't unregister"
+				" normal driver error=%d.\n",error);
 }
 
+#if 0
 static int register_isr(void)
 {
 	int count, done=0, card;
-	int flag;
 	unsigned char request;
 	for (count=0; count < BOARD_COUNT; count++ ) {
 		if (isi_card[count].base) {
@@ -1820,9 +2051,11 @@
 		 */
 			request = YES;
 			for(card = 0; card < count; card++)
-			if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) {
+			if ((isi_card[card].base) && 
+				(isi_card[card].irq == isi_card[count].irq)) {
 				request = NO;
-				if ((isi_card[count].isa == NO) && (isi_card[card].isa == NO))
+				if ((isi_card[count].isa == NO) 
+					&& (isi_card[card].isa == NO))
 					break;
 				/*
 				 * ISA cards cannot share interrupts with other
@@ -1832,22 +2065,24 @@
 				isi_card[count].base = 0;
 				break;
 			}
-			flag=0;
-			if(isi_card[count].isa == NO)
-				flag |= SA_SHIRQ;
-				
 			if (request == YES) { 
-				if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT|flag, ISICOM_NAME, NULL)) {
-					printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n",
+				if (request_irq(isi_card[count].irq, 
+						isicom_interrupt, 
+						SA_INTERRUPT | SA_SHIRQ, 
+						ISICOM_NAME, NULL)) {
+
+					printk(KERN_WARNING "ISICOM: Could not"
+						" install handler at Irq %d."
+						" Card%d will be disabled.\n",
 						isi_card[count].irq, count+1);
+
 					release_region(isi_card[count].base,16);
 					isi_card[count].base=0;
 				}
 				else {
-					printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n", 
-					count+1, isi_card[count].base, isi_card[count].irq); 
 					
-					irq_to_board[isi_card[count].irq]=&isi_card[count];
+/*					irq_to_board[isi_card[count].irq]=
+								&isi_card[count];*/
 					done++;
 				}
 			}
@@ -1855,7 +2090,41 @@
 	}
 	return done;
 }
+#endif
+
+static int register_isr(void)
+{
+	int count, done = 0;
+	unsigned long irqflags;
+
+	for (count=0; count < BOARD_COUNT; count++ ) {
+		if (isi_card[count].base) {
+
+			irqflags = (isi_card[count].isa == YES) ? 
+					SA_INTERRUPT : 
+					(SA_INTERRUPT | SA_SHIRQ);
+
+			if (request_irq(isi_card[count].irq, 
+					isicom_interrupt, 
+					irqflags, 
+					ISICOM_NAME, &isi_card[count])) {
+
+				printk(KERN_WARNING "ISICOM: Could not"
+					" install handler at Irq %d."
+					" Card%d will be disabled.\n",
+					isi_card[count].irq, count+1);
 
+				release_region(isi_card[count].base,16);
+				isi_card[count].base=0;
+			}
+			else
+				done++;
+		}
+	}
+	return done;
+}
+
+#if 0
 static void unregister_isr(void)
 {
 	int count, card;
@@ -1864,19 +2133,42 @@
 		if (isi_card[count].base) {
 			freeirq = YES;
 			for(card = 0; card < count; card++)
-				if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) {
+				if ((isi_card[card].base) && 
+					(isi_card[card].irq == 
+						isi_card[count].irq)) {
 					freeirq = NO;
 					break;
 				}
 			if (freeirq == YES) {
 				free_irq(isi_card[count].irq, NULL);
 #ifdef ISICOM_DEBUG			
-				printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1);
+				printk(KERN_DEBUG "ISICOM: Irq %d released"
+					" for Card%d.\n",
+					isi_card[count].irq, 
+					count+1);
 #endif	
 			}		
 		}
 	}
 }
+#endif
+
+static void unregister_isr(void)
+{
+	int count;
+
+	for (count=0; count < BOARD_COUNT; count++ ) {
+		if (isi_card[count].base) {
+			free_irq(isi_card[count].irq, &isi_card[count]);
+#ifdef ISICOM_DEBUG			
+			printk(KERN_DEBUG "ISICOM: Irq %d released"
+				" for Card%d.\n",
+				isi_card[count].irq, 
+				count+1);
+#endif	
+		}
+	}
+}
 
 static int isicom_init(void)
 {
@@ -1888,7 +2180,8 @@
 		page = get_free_page(GFP_KERNEL);
 	      	if (!page) {
 #ifdef ISICOM_DEBUG	      	
-	      		printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");
+	      		printk(KERN_DEBUG "ISICOM: Couldn't allocate page"
+				" for tmp_buf.\n");
 #else
 			printk(KERN_ERR "ISICOM: Not enough memory...\n");
 #endif	      
@@ -1909,6 +2202,7 @@
 		free_page((unsigned long)tmp_buf);
 		return 0;
 	}
+
 	if (!register_isr()) 
 	{
 		unregister_drivers();
@@ -1916,7 +2210,7 @@
 		free_page((unsigned long)tmp_buf);
 		return 0;		
 	}
-	
+
 	/* initialize bottom half  */
 	init_bh(ISICOM_BH, do_isicom_bh);
 
@@ -1925,6 +2219,9 @@
 	for (card = 0; card < BOARD_COUNT; card++) {
 		port = &isi_ports[card * 16];
 		isi_card[card].ports = port;
+		/* 11/5/00 -sameer SMPCHG*/
+		isi_card[card].card_lock = SPIN_LOCK_UNLOCKED;
+
 		base = isi_card[card].base;
 		for (channel = 0; channel < 16; channel++, port++) {
 			port->magic = ISICOM_MAGIC;
@@ -1967,54 +2264,45 @@
 	int retval, card, idx, count;
 	unsigned char pciirq;
 	unsigned int ioaddr;
-	                
+
+	for (idx = 0; idx < BOARD_COUNT; idx++) {
+		isi_card[idx].base = 0;
+		isi_card[idx].irq = 0;
+	}
+
 	card = 0;
 	for(idx=0; idx < BOARD_COUNT; idx++) {	
-		if (io[idx]) {
-			isi_card[idx].base=io[idx];
-			isi_card[idx].irq=irq[idx];
-			isi_card[idx].isa=YES;
+		if (io[idx] && reset_card(io[idx], 0) && valid_irq(irq[idx])) {
+			isi_card[card].base=io[idx];
+			isi_card[card].irq=irq[idx];
+			isi_card[card].isa=YES;
 			card++;
 		}
-		else {
-			isi_card[idx].base = 0;
-			isi_card[idx].irq = 0;
-		}
 	}
 	
-	for (idx=0 ;idx < card; idx++) {
-		if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)||
-		    (isi_card[idx].irq==4)||(isi_card[idx].irq==5)||
-		    (isi_card[idx].irq==7)||(isi_card[idx].irq==10)||
-		    (isi_card[idx].irq==11)||(isi_card[idx].irq==12)||
-		    (isi_card[idx].irq==15))) {
-			
-			if (isi_card[idx].base) {
-				printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
-					isi_card[idx].irq, idx+1);
-				isi_card[idx].base=0;
-				card--;
-			}	
-		}
-	}	
-	
 	if (pci_present() && (card < BOARD_COUNT)) {
 		for (idx=0; idx < DEVID_COUNT; idx++) {
 			dev = NULL;
 			for (;;){
-				if (!(dev = pci_find_device(VENDOR_ID, device_id[idx], dev)))
+				if (!(dev = pci_find_device(VENDOR_ID, 
+							device_id[idx], dev)))
 					break;
 				if (card >= BOARD_COUNT)
 					break;
 					
 				/* found a PCI ISI card! */
-				ioaddr = dev->base_address[3]; /* i.e at offset 0x1c in the
-								* PCI configuration register
-								* space.
-								*/
+
+				/*
+				 *	16 bytes address space base at 
+				 *	offset 0x1c in the PCI configuration 
+				 *	register space
+				 */
+				ioaddr = dev->base_address[3]; 
 				ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
 				pciirq = dev->irq;
-				printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", device_id[idx]);
+				printk(KERN_INFO "ISI PCI "
+					"Card(Device ID 0x%x)\n", 
+					device_id[idx]);
 				/*
 				 * allot the first empty slot in the array
 				 */				
@@ -2032,29 +2320,34 @@
 		}
 	}
 	
-	if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
-		printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n"); 
+	if (!(isi_card[0].base || isi_card[1].base ||
+		isi_card[2].base || isi_card[3].base)) {
+
+		printk(KERN_ERR "ISICOM: No valid card configuration."
+				" Driver cannot be initialized...\n"); 
 		return -EIO;
 	}		
 	retval=misc_register(&isiloader_device);
 	if (retval<0) {
-		printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");
+		printk(KERN_ERR "ISICOM: Unable to register"
+				" firmware loader driver.\n");
 		return -EIO;
 	}
 	
 	if (!isicom_init()) {
 		if (misc_deregister(&isiloader_device)) 
-			printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+			printk(KERN_ERR "ISICOM: Unable to unregister"
+					" Firmware Loader driver\n");
 		return -EIO;
 	}
-	
+
 	init_timer(&tx);
 	tx.expires = jiffies + 1;
 	tx.data = 0;
 	tx.function = isicom_tx;
 	re_schedule = 1;
 	add_timer(&tx);
-	
+
 	return 0;
 }
 
@@ -2067,10 +2360,11 @@
 	
 #ifdef ISICOM_DEBUG	
 	printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count);
+	printk("ISICOM: isicom_interrupt intr_count = %ld.\n", intr_count);
 #endif	
 
 #ifdef ISICOM_DEBUG
-	printk("ISICOM: uregistering isr ...\n");
+	printk("ISICOM: unregistering isr ...\n");
 #endif	
 	unregister_isr();
 
@@ -2093,5 +2387,6 @@
 	printk("ISICOM: unregistering firmware loader ...\n");	
 #endif
 	if (misc_deregister(&isiloader_device))
-		printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+		printk(KERN_ERR "ISICOM: Unable to unregister"
+				" Firmware Loader driver\n");
 }
diff -urN linux-2.2.18-pre9/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c
--- linux-2.2.18-pre9/drivers/isdn/divert/divert_procfs.c	Wed May  3 17:16:39 2000
+++ linux/drivers/isdn/divert/divert_procfs.c	Mon Dec  3 20:27:06 2001
@@ -1,5 +1,5 @@
 /*
- * $Id: divert_procfs.c,v 1.6 2000/02/14 19:23:03 werner Exp $
+ * $Id: divert_procfs.c,v 1.9 2000/08/20 07:40:14 keil Exp $
  *
  * Filesystem handling for the diversion supplementary services.
  *
@@ -20,6 +20,17 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: divert_procfs.c,v $
+ * Revision 1.9  2000/08/20 07:40:14  keil
+ * changes from 2.4
+ *
+ * Revision 1.8  2000/03/03 16:37:11  kai
+ * incorporated some cosmetic changes from the official kernel tree back
+ * into CVS
+ *
+ * Revision 1.7  2000/03/02 00:11:06  werner
+ *
+ * Changes related to procfs for 2.3.48
+ *
  * Revision 1.6  2000/02/14 19:23:03  werner
  *
  * Changed handling of proc filesystem tables to a more portable version
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_audio.c linux/drivers/isdn/isdn_audio.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_audio.c	Tue Oct 26 17:53:40 1999
+++ linux/drivers/isdn/isdn_audio.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_audio.c,v 1.17 1999/08/17 11:10:52 paul Exp $
+/* $Id: isdn_audio.c,v 1.21 2000/06/20 18:01:55 keil Exp $
 
  * Linux ISDN subsystem, audio conversion and compression (linklevel).
  *
@@ -20,73 +20,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Log: isdn_audio.c,v $
- * Revision 1.17  1999/08/17 11:10:52  paul
- * don't try to use x86 assembler on non-x86!
- *
- * Revision 1.16  1999/08/06 12:47:35  calle
- * Using __GNUC__ == 2 && __GNUC_MINOR__ < 95 how to define
- *   ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT
- *
- * Revision 1.15  1999/08/06 12:02:52  calle
- * egcs 2.95 complain about invalid asm statement:
- *    "fixed or forbidden register 2 (cx) was spilled for class CREG."
- * Using ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT and not
- * define it at the moment.
- *
- * Revision 1.14  1999/07/11 17:14:06  armin
- * Added new layer 2 and 3 protocols for Fax and DSP functions.
- * Moved "Add CPN to RING message" to new register S23,
- * "Display message" is now correct on register S13 bit 7.
- * New audio command AT+VDD implemented (deactivate DTMF decoder and
- * activate possible existing hardware/DSP decoder).
- * Moved some tty defines to .h file.
- * Made whitespace possible in AT command line.
- * Some AT-emulator output bugfixes.
- * First Fax G3 implementations.
- *
- * Revision 1.13  1999/04/12 12:33:09  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.12  1998/07/26 18:48:43  armin
- * Added silence detection in voice receive mode.
- *
- * Revision 1.11  1998/04/10 10:35:10  paul
- * fixed (silly?) warnings from egcs on Alpha.
- *
- * Revision 1.10  1998/02/20 17:09:40  fritz
- * Changes for recent kernels.
- *
- * Revision 1.9  1997/10/01 09:20:25  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.8  1997/03/02 14:29:16  fritz
- * More ttyI related cleanup.
- *
- * Revision 1.7  1997/02/03 22:44:11  fritz
- * Reformatted according CodingStyle
- *
- * Revision 1.6  1996/06/06 14:43:31  fritz
- * Changed to support DTMF decoding on audio playback also.
- *
- * Revision 1.5  1996/06/05 02:24:08  fritz
- * Added DTMF decoder for audio mode.
- *
- * Revision 1.4  1996/05/17 03:48:01  fritz
- * Removed some test statements.
- * Added revision string.
- *
- * Revision 1.3  1996/05/10 08:48:11  fritz
- * Corrected adpcm bugs.
- *
- * Revision 1.2  1996/04/30 09:31:17  fritz
- * General rewrite.
- *
- * Revision 1.1.1.1  1996/04/28 12:25:40  fritz
- * Taken under CVS control
- *
  */
 
 #define __NO_VERSION__
@@ -95,7 +28,7 @@
 #include "isdn_audio.h"
 #include "isdn_common.h"
 
-char *isdn_audio_revision = "$Revision: 1.17 $";
+char *isdn_audio_revision = "$Revision: 1.21 $";
 
 /*
  * Misc. lookup-tables.
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_audio.h linux/drivers/isdn/isdn_audio.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_audio.h	Mon Aug  9 12:04:39 1999
+++ linux/drivers/isdn/isdn_audio.h	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_audio.h,v 1.8 1999/07/11 17:14:07 armin Exp $
+/* $Id: isdn_audio.h,v 1.9 2000/05/11 22:29:20 kai Exp $
 
  * Linux ISDN subsystem, audio conversion and compression (linklevel).
  *
@@ -17,39 +17,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_audio.h,v $
- * Revision 1.8  1999/07/11 17:14:07  armin
- * Added new layer 2 and 3 protocols for Fax and DSP functions.
- * Moved "Add CPN to RING message" to new register S23,
- * "Display message" is now correct on register S13 bit 7.
- * New audio command AT+VDD implemented (deactivate DTMF decoder and
- * activate possible existing hardware/DSP decoder).
- * Moved some tty defines to .h file.
- * Made whitespace possible in AT command line.
- * Some AT-emulator output bugfixes.
- * First Fax G3 implementations.
- *
- * Revision 1.7  1999/04/12 12:33:11  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.6  1998/07/26 18:48:44  armin
- * Added silence detection in voice receive mode.
- *
- * Revision 1.5  1997/02/03 22:45:21  fritz
- * Reformatted according CodingStyle
- *
- * Revision 1.4  1996/06/06 14:43:32  fritz
- * Changed to support DTMF decoding on audio playback also.
- *
- * Revision 1.3  1996/06/05 02:24:09  fritz
- * Added DTMF decoder for audio mode.
- *
- * Revision 1.2  1996/05/10 08:48:32  fritz
- * Corrected adpcm bugs.
- *
- * Revision 1.1  1996/04/30 09:29:06  fritz
- * Taken under CVS control.
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_cards.c linux/drivers/isdn/isdn_cards.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_cards.c	Mon Sep  4 10:39:18 2000
+++ linux/drivers/isdn/isdn_cards.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_cards.c,v 1.10 1999/07/20 06:41:28 calle Exp $
+/* $Id: isdn_cards.c,v 1.11 2000/05/11 22:29:20 kai Exp $
 
  * Linux ISDN subsystem, initialization for non-modularized drivers.
  *
@@ -17,38 +17,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_cards.c,v $
- * Revision 1.10  1999/07/20 06:41:28  calle
- * Bugfix: After the redesign of the AVM B1 driver, the driver didn't even
- *         compile, if not selected as modules.
- *
- * Revision 1.9  1999/04/12 12:33:11  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.8  1999/03/29 11:13:23  armin
- * Added eicon driver init.
- *
- * Revision 1.7  1998/02/20 17:24:28  fritz
- * Added ACT2000 init.
- *
- * Revision 1.6  1997/04/23 18:56:03  fritz
- * Old Teles driver removed, Changed doc and scripts accordingly.
- *
- * Revision 1.5  1997/03/30 17:10:36  calle
- * added support for AVM-B1-PCI card.
- *
- * Revision 1.4  1997/03/04 21:59:44  calle
- * Added AVM-B1-CAPI2.0 driver
- *
- * Revision 1.3  1997/02/03 23:31:14  fritz
- * Reformatted according CodingStyle
- *
- * Revision 1.2  1996/10/13 19:52:17  keil
- * HiSax support
- *
- * Revision 1.1  1996/04/20 16:04:36  fritz
- * Initial revision
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_cards.h linux/drivers/isdn/isdn_cards.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_cards.h	Mon Aug  9 12:04:39 1999
+++ linux/drivers/isdn/isdn_cards.h	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_cards.h,v 1.3 1999/04/12 12:33:13 fritz Exp $
+/* $Id: isdn_cards.h,v 1.4 2000/05/11 22:29:20 kai Exp $
 
  * Linux ISDN subsystem, initialization for non-modularized drivers.
  *
@@ -17,16 +17,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_cards.h,v $
- * Revision 1.3  1999/04/12 12:33:13  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.2  1997/02/03 23:31:55  fritz
- * Reformatted according CodingStyle
- *
- * Revision 1.1  1996/04/20 16:04:03  fritz
- * Initial revision
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_common.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/isdn/isdn_common.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.100 2000/03/03 16:37:11 kai Exp $
+/* $Id: isdn_common.c,v 1.111 2000/08/20 07:40:14 keil Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -20,412 +20,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Log: isdn_common.c,v $
- * Revision 1.100  2000/03/03 16:37:11  kai
- * incorporated some cosmetic changes from the official kernel tree back
- * into CVS
- *
- * Revision 1.99  2000/02/26 01:00:52  keil
- * changes from 2.3.47
- *
- * Revision 1.98  2000/02/16 14:56:27  paul
- * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers
- *
- * Revision 1.97  2000/01/23 18:45:37  keil
- * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
- *
- * Revision 1.96  2000/01/20 19:55:33  keil
- * Add FAX Class 1 support
- *
- * Revision 1.95  2000/01/09 20:43:13  detabc
- * exand logical bind-group's for both call's (in and out).
- * add first part of kernel-config-help for abc-extension.
- *
- * Revision 1.94  1999/11/20 22:14:13  detabc
- * added channel dial-skip in case of external use
- * (isdn phone or another isdn device) on the same NTBA.
- * usefull with two or more card's connected the different NTBA's.
- * global switchable in kernel-config and also per netinterface.
- *
- * add auto disable of netinterface's in case of:
- * 	to many connection's in short time.
- * 	config mistakes (wrong encapsulation, B2-protokoll or so on) on local
- * 	or remote side.
- * 	wrong password's or something else to a ISP (syncppp).
- *
- * possible encapsulations for this future are:
- * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
- * and ISDN_NET_ENCAP_CISCOHDLCK.
- *
- * Revision 1.93  1999/11/04 13:11:36  keil
- * Reinit of v110 structs
- *
- * Revision 1.92  1999/10/31 15:59:50  he
- * more skb headroom checks
- *
- * Revision 1.91  1999/10/28 22:48:45  armin
- * Bugfix: isdn_free_channel() now frees the channel,
- * even when the usage of the ttyI has changed.
- *
- * Revision 1.90  1999/10/27 21:21:17  detabc
- * Added support for building logically-bind-group's per interface.
- * usefull for outgoing call's with more then one isdn-card.
- *
- * Switchable support to dont reset the hangup-timeout for
- * receive frames. Most part's of the timru-rules for receiving frames
- * are now obsolete. If the input- or forwarding-firewall deny
- * the frame, the line will be not hold open.
- *
- * Revision 1.89  1999/10/16 14:46:47  keil
- * replace kmalloc with vmalloc for the big dev struct
- *
- * Revision 1.88  1999/10/02 00:39:26  he
- * Fixed a 2.3.x wait queue initialization (was causing panics)
- *
- * Revision 1.87  1999/09/12 16:19:39  detabc
- * added abc features
- * low cost routing for net-interfaces (only the HL side).
- * need more implementation in the isdnlog-utility
- * udp info support (first part).
- * different EAZ on outgoing call's.
- * more checks on D-Channel callbacks (double use of channels).
- * tested and running with kernel 2.3.17
- *
- * Revision 1.86  1999/07/31 12:59:42  armin
- * Added tty fax capabilities.
- *
- * Revision 1.85  1999/07/29 16:58:35  armin
- * Bugfix: DLE handling in isdn_readbchan()
- *
- * Revision 1.84  1999/07/25 16:21:10  keil
- * fix number matching
- *
- * Revision 1.83  1999/07/13 21:02:05  werner
- * Added limit possibilty of driver b_channel resources (ISDN_STAT_DISCH)
- *
- * Revision 1.82  1999/07/12 21:06:50  werner
- * Fixed problem when loading more than one driver temporary
- *
- * Revision 1.81  1999/07/11 17:14:09  armin
- * Added new layer 2 and 3 protocols for Fax and DSP functions.
- * Moved "Add CPN to RING message" to new register S23,
- * "Display message" is now correct on register S13 bit 7.
- * New audio command AT+VDD implemented (deactivate DTMF decoder and
- * activate possible existing hardware/DSP decoder).
- * Moved some tty defines to .h file.
- * Made whitespace possible in AT command line.
- * Some AT-emulator output bugfixes.
- * First Fax G3 implementations.
- *
- * Revision 1.80  1999/07/07 10:14:00  detabc
- * remove unused messages
- *
- * Revision 1.79  1999/07/05 23:51:30  werner
- * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
- * hisaxctrl id 10 <nr. of chans 0-2>
- *
- * Revision 1.78  1999/07/05 20:21:15  werner
- * changes to use diversion sources for all kernel versions.
- * removed static device, only proc filesystem used
- *
- * Revision 1.77  1999/07/01 08:29:50  keil
- * compatibility to 2.3 kernel
- *
- * Revision 1.76  1999/06/29 16:16:44  calle
- * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
- * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
- * isdnlog should check returncode of read(2) calls.
- *
- * Revision 1.75  1999/04/18 14:06:47  fritz
- * Removed TIMRU stuff.
- *
- * Revision 1.74  1999/04/12 13:16:45  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.73  1999/04/12 12:33:15  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.72  1999/03/02 12:04:44  armin
- * -added ISDN_STAT_ADDCH to increase supported channels after
- *  register_isdn().
- * -ttyI now goes on-hook on ATZ when B-Ch is connected.
- * -added timer-function for register S7 (Wait for Carrier).
- * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
- * -on L2_MODEM a string will be appended to the CONNECT-Message,
- *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
- * -variable "dialing" used for ATA also, for interrupting call
- *  establishment and register S7.
- *
- * Revision 1.71  1999/01/28 09:10:43  armin
- * Fixed bad while-loop in isdn_readbch().
- *
- * Revision 1.70  1999/01/15 19:58:54  he
- * removed compatibiltity macro
- *
- * Revision 1.69  1998/09/07 21:59:58  he
- * flush method for 2.1.118 and above
- * updated IIOCTLNETGPN
- *
- * Revision 1.68  1998/08/31 21:09:45  he
- * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
- *     peer phone number)
- *
- * Revision 1.67  1998/06/26 15:12:21  fritz
- * Added handling of STAT_ICALL with incomplete CPN.
- * Added AT&L for ttyI emulator.
- * Added more locking stuff in tty_write.
- *
- * Revision 1.66  1998/06/17 19:50:41  he
- * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
- * brute force fix to avoid Ugh's in isdn_tty_write()
- * cleaned up some dead code
- *
- *
- * Revision 1.62  1998/04/14 16:28:43  he
- * Fixed user space access with interrupts off and remaining
- * copy_{to,from}_user() -> -EFAULT return codes
- *
- * Revision 1.61  1998/03/22 18:50:46  hipp
- * Added BSD Compression for syncPPP .. UNTESTED at the moment
- *
- * Revision 1.60  1998/03/19 13:18:18  keil
- * Start of a CAPI like interface for supplementary Service
- * first service: SUSPEND
- *
- * Revision 1.59  1998/03/09 17:46:23  he
- * merged in 2.1.89 changes
- *
- * Revision 1.58  1998/03/07 22:35:24  fritz
- * Starting generic module support (Nothing usable yet).
- *
- * Revision 1.57  1998/03/07 18:21:01  cal
- * Dynamic Timeout-Rule-Handling vs. 971110 included
- *
- * Revision 1.56  1998/02/25 17:49:38  he
- * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
- *
- * Revision 1.55  1998/02/23 23:35:32  fritz
- * Eliminated some compiler warnings.
- *
- * Revision 1.54  1998/02/22 19:44:19  fritz
- * Bugfixes and improvements regarding V.110, V.110 now running.
- *
- * Revision 1.53  1998/02/20 17:18:05  fritz
- * Changes for recent kernels.
- * Added common stub for sending commands to lowlevel.
- * Added V.110.
- *
- * Revision 1.52  1998/01/31 22:05:57  keil
- * Lots of changes for X.25 support:
- * Added generic support for connection-controlling encapsulation protocols
- * Added support of BHUP status message
- * Added support for additional p_encap X25IFACE
- * Added support for kernels >= 2.1.72
- *
- * Revision 1.51  1998/01/31 19:17:29  calle
- * merged changes from and for 2.1.82
- *
- * Revision 1.50  1997/12/12 06:12:11  calle
- * moved EXPORT_SYMBOL(register_isdn) from isdn_syms.c to isdn_common.c
- *
- * Revision 1.49  1997/11/06 17:16:52  keil
- * Sync to 2.1.62 changes
- *
- * Revision 1.48  1997/11/02 23:55:50  keil
- * Andi Kleen's changes for 2.1.60
- * without it the isdninfo and isdnctrl devices won't work
- *
- * Revision 1.47  1997/10/09 21:28:46  fritz
- * New HL<->LL interface:
- *   New BSENT callback with nr. of bytes included.
- *   Sending without ACK.
- *   New L1 error status (not yet in use).
- *   Cleaned up obsolete structures.
- * Implemented Cisco-SLARP.
- * Changed local net-interface data to be dynamically allocated.
- * Removed old 2.0 compatibility stuff.
- *
- * Revision 1.46  1997/10/01 09:20:27  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.45  1997/08/21 23:11:41  fritz
- * Added changes for kernels >= 2.1.45
- *
- * Revision 1.44  1997/05/27 15:17:23  fritz
- * Added changes for recent 2.1.x kernels:
- *   changed return type of isdn_close
- *   queue_task_* -> queue_task
- *   clear/set_bit -> test_and_... where apropriate.
- *   changed type of hard_header_cache parameter.
- *
- * Revision 1.43  1997/03/31 14:09:43  fritz
- * Fixed memory leak in isdn_close().
- *
- * Revision 1.42  1997/03/30 16:51:08  calle
- * changed calls to copy_from_user/copy_to_user and removed verify_area
- * were possible.
- *
- * Revision 1.41  1997/03/24 22:54:41  fritz
- * Some small fixes in debug code.
- *
- * Revision 1.40  1997/03/08 08:13:51  fritz
- * Bugfix: IIOCSETMAP (Set mapping) was broken.
- *
- * Revision 1.39  1997/03/07 01:32:54  fritz
- * Added proper ifdef's for CONFIG_ISDN_AUDIO
- *
- * Revision 1.38  1997/03/05 21:15:02  fritz
- * Fix: reduced stack usage of isdn_ioctl() and isdn_set_allcfg()
- *
- * Revision 1.37  1997/03/02 14:29:18  fritz
- * More ttyI related cleanup.
- *
- * Revision 1.36  1997/02/28 02:32:40  fritz
- * Cleanup: Moved some tty related stuff from isdn_common.c
- *          to isdn_tty.c
- * Bugfix:  Bisync protocol did not behave like documented.
- *
- * Revision 1.35  1997/02/21 13:01:19  fritz
- * Changes CAUSE message output in kernel log.
- *
- * Revision 1.34  1997/02/10 20:12:43  fritz
- * Changed interface for reporting incoming calls.
- *
- * Revision 1.33  1997/02/10 10:05:42  fritz
- * More changes for Kernel 2.1.X
- * Symbol information moved to isdn_syms.c
- *
- * Revision 1.32  1997/02/03 22:55:26  fritz
- * Reformatted according CodingStyle.
- * Changed isdn_writebuf_stub static.
- * Slow down tty-RING counter.
- * skb->free stuff replaced by macro.
- * Bugfix in audio-skb locking.
- * Bugfix in HL-driver locking.
- *
- * Revision 1.31  1997/01/17 01:19:18  fritz
- * Applied chargeint patch.
- *
- * Revision 1.30  1997/01/14 01:27:47  fritz
- * Changed audio receive not to rely on skb->users and skb->lock.
- * Added ATI2 and related variables.
- * Started adding full-duplex audio capability.
- *
- * Revision 1.29  1997/01/12 23:33:03  fritz
- * Made isdn_all_eaz foolproof.
- *
- * Revision 1.28  1996/11/13 02:33:19  fritz
- * Fixed a race condition.
- *
- * Revision 1.27  1996/10/27 22:02:41  keil
- * return codes for ISDN_STAT_ICALL
- *
- * Revision 1.26  1996/10/23 11:59:40  fritz
- * More compatibility changes.
- *
- * Revision 1.25  1996/10/22 23:13:54  fritz
- * Changes for compatibility to 2.0.X and 2.1.X kernels.
- *
- * Revision 1.24  1996/10/11 14:02:03  fritz
- * Bugfix: call to isdn_ppp_timer_timeout() never compiled, because of
- *         typo in #ifdef.
- *
- * Revision 1.23  1996/06/25 18:35:38  fritz
- * Fixed bogus memory access in isdn_set_allcfg().
- *
- * Revision 1.22  1996/06/24 17:37:37  fritz
- * Bugfix: isdn_timer_ctrl() did restart timer, even if it
- *         was already running.
- *         lowlevel driver locking did use wrong parameters.
- *
- * Revision 1.21  1996/06/15 14:58:20  fritz
- * Added version signatures for data structures used
- * by userlevel programs.
- *
- * Revision 1.20  1996/06/12 16:01:49  fritz
- * Bugfix: Remote B-channel hangup sometimes did not result
- *         in a NO CARRIER on tty.
- *
- * Revision 1.19  1996/06/11 14:52:04  hipp
- * minor bugfix in isdn_writebuf_skb_stub()
- *
- * Revision 1.18  1996/06/06 14:51:51  fritz
- * Changed to support DTMF decoding on audio playback also.
- *
- * Revision 1.17  1996/06/05 02:24:10  fritz
- * Added DTMF decoder for audio mode.
- *
- * Revision 1.16  1996/06/03 20:09:05  fritz
- * Bugfix: called wrong function pointer for locking in
- *         isdn_get_free_channel().
- *
- * Revision 1.15  1996/05/31 01:10:54  fritz
- * Bugfixes:
- *   Lowlevel modules did not get locked correctly.
- *   Did show wrong revision when initializing.
- *   Minor fixes in ioctl code.
- *   sk_buff did not get freed, if error in writebuf_stub.
- *
- * Revision 1.14  1996/05/18 01:36:55  fritz
- * Added spelling corrections and some minor changes
- * to stay in sync with kernel.
- *
- * Revision 1.13  1996/05/17 15:43:30  fritz
- * Bugfix: decrement of rcvcount in readbchan() corrected.
- *
- * Revision 1.12  1996/05/17 03:55:43  fritz
- * Changed DLE handling for audio receive.
- * Some cleanup.
- * Added display of isdn_audio_revision.
- *
- * Revision 1.11  1996/05/11 21:51:32  fritz
- * Changed queue management to use sk_buffs.
- *
- * Revision 1.10  1996/05/10 08:49:16  fritz
- * Checkin before major changes of tty-code.
- *
- * Revision 1.9  1996/05/07 09:19:41  fritz
- * Adapted to changes in isdn_tty.c
- *
- * Revision 1.8  1996/05/06 11:34:51  hipp
- * fixed a few bugs
- *
- * Revision 1.7  1996/05/02 03:55:17  fritz
- * Bugfixes:
- *  - B-channel connect message for modem devices
- *    sometimes did not result in a CONNECT-message.
- *  - register_isdn did not check for driverId-conflicts.
- *
- * Revision 1.6  1996/04/30 20:57:21  fritz
- * Commit test
- *
- * Revision 1.5  1996/04/20 16:19:07  fritz
- * Changed slow timer handlers to increase accuracy.
- * Added statistic information for usage by xisdnload.
- * Fixed behaviour of isdnctrl-device on non-blocked io.
- * Fixed all io to go through generic writebuf-function without
- * bypassing. Same for incoming data.
- * Fixed bug: Last channel had been unusable.
- * Fixed kfree of tty xmit_buf on ppp initialization failure.
- *
- * Revision 1.4  1996/02/11 02:33:26  fritz
- * Fixed bug in main timer-dispatcher.
- * Bugfix: Lot of tty-callbacks got called regardless of the events already
- * been handled by network-devices.
- * Changed ioctl-names.
- *
- * Revision 1.3  1996/01/22 05:16:11  fritz
- * Changed ioctl-names.
- * Fixed bugs in isdn_open and isdn_close regarding PPP_MINOR.
- *
- * Revision 1.2  1996/01/21 16:52:40  fritz
- * Support for sk_buffs added, changed header-stuffing.
- *
- * Revision 1.1  1996/01/09 04:12:52  fritz
- * Initial revision
- *
  */
 
 #include <linux/config.h>
@@ -452,7 +46,7 @@
 
 isdn_dev *dev = (isdn_dev *) 0;
 
-static char *isdn_revision = "$Revision: 1.100 $";
+static char *isdn_revision = "$Revision: 1.111 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_common.h	Wed May  3 17:16:40 2000
+++ linux/drivers/isdn/isdn_common.h	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.h,v 1.18 2000/01/23 18:45:37 keil Exp $
+/* $Id: isdn_common.h,v 1.20 2000/06/16 13:00:27 keil Exp $
 
  * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel).
  *
@@ -19,90 +19,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_common.h,v $
- * Revision 1.18  2000/01/23 18:45:37  keil
- * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
- *
- * Revision 1.17  1999/10/27 21:21:17  detabc
- * Added support for building logically-bind-group's per interface.
- * usefull for outgoing call's with more then one isdn-card.
- *
- * Switchable support to dont reset the hangup-timeout for
- * receive frames. Most part's of the timru-rules for receiving frames
- * are now obsolete. If the input- or forwarding-firewall deny
- * the frame, the line will be not hold open.
- *
- * Revision 1.16  1999/07/01 08:29:54  keil
- * compatibility to 2.3 kernel
- *
- * Revision 1.15  1999/04/18 14:06:50  fritz
- * Removed TIMRU stuff.
- *
- * Revision 1.14  1999/04/12 12:33:18  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.13  1999/03/02 12:04:47  armin
- * -added ISDN_STAT_ADDCH to increase supported channels after
- *  register_isdn().
- * -ttyI now goes on-hook on ATZ when B-Ch is connected.
- * -added timer-function for register S7 (Wait for Carrier).
- * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
- * -on L2_MODEM a string will be appended to the CONNECT-Message,
- *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
- * -variable "dialing" used for ATA also, for interrupting call
- *  establishment and register S7.
- *
- * Revision 1.12  1998/06/26 15:12:27  fritz
- * Added handling of STAT_ICALL with incomplete CPN.
- * Added AT&L for ttyI emulator.
- * Added more locking stuff in tty_write.
- *
- * Revision 1.11  1998/04/14 16:28:47  he
- * Fixed user space access with interrupts off and remaining
- * copy_{to,from}_user() -> -EFAULT return codes
- *
- * Revision 1.10  1998/03/07 18:21:03  cal
- * Dynamic Timeout-Rule-Handling vs. 971110 included
- *
- * Revision 1.9  1998/02/20 17:19:01  fritz
- * Added common stub for sending commands to lowlevel.
- *
- * Revision 1.8  1997/10/09 21:28:49  fritz
- * New HL<->LL interface:
- *   New BSENT callback with nr. of bytes included.
- *   Sending without ACK.
- *   New L1 error status (not yet in use).
- *   Cleaned up obsolete structures.
- * Implemented Cisco-SLARP.
- * Changed local net-interface data to be dynamically allocated.
- * Removed old 2.0 compatibility stuff.
- *
- * Revision 1.7  1997/10/01 09:20:30  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.6  1997/02/28 02:32:44  fritz
- * Cleanup: Moved some tty related stuff from isdn_common.c
- *          to isdn_tty.c
- * Bugfix:  Bisync protocol did not behave like documented.
- *
- * Revision 1.5  1997/02/10 10:05:45  fritz
- * More changes for Kernel 2.1.X
- * Symbol information moved to isdn_syms.c
- *
- * Revision 1.4  1997/02/03 22:56:50  fritz
- * Removed isdn_writebuf_stub prototype.
- *
- * Revision 1.3  1996/05/19 00:13:05  fritz
- * Removed debug flag.
- *
- * Revision 1.2  1996/04/20 16:20:40  fritz
- * Misc. typos.
- *
- * Revision 1.1  1996/01/10 21:37:19  fritz
- * Initial revision
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_concap.c linux/drivers/isdn/isdn_concap.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_concap.c	Tue Oct 26 17:53:40 1999
+++ linux/drivers/isdn/isdn_concap.c	Mon Dec  3 20:27:06 2001
@@ -1,32 +1,26 @@
-/* $Id: isdn_concap.c,v 1.6 1999/08/22 20:26:01 calle Exp $
+/* $Id: isdn_concap.c,v 1.8 2000/05/11 22:29:20 kai Exp $
  
- * Stuff to support the concap_proto by isdn4linux. isdn4linux - specific
+ * Linux ISDN subsystem, protocol encapsulation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/* Stuff to support the concap_proto by isdn4linux. isdn4linux - specific
  * stuff goes here. Stuff that depends only on the concap protocol goes to
  * another -- protocol specific -- source file.
- *
- * $Log: isdn_concap.c,v $
- * Revision 1.6  1999/08/22 20:26:01  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.5  1998/10/30 18:44:48  he
- * pass return value from isdn_net_dial_req for dialmode change
- *
- * Revision 1.4  1998/10/30 17:55:24  he
- * dialmode for x25iface and multulink ppp
- *
- * Revision 1.3  1998/05/26 22:39:22  he
- * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
- * concap typo
- * cleared dev.tbusy in isdn_net BCONN status callback
- *
- * Revision 1.2  1998/01/31 22:49:21  keil
- * correct comments
- *
- * Revision 1.1  1998/01/31 22:27:57  keil
- * New files from Henner Eisen for X.25 support
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_concap.h linux/drivers/isdn/isdn_concap.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_concap.h	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/isdn_concap.h	Mon Dec  3 20:27:06 2001
@@ -1,5 +1,23 @@
-/* $Id: isdn_concap.h,v 1.2 1998/01/31 22:49:21 keil Exp $
+/* $Id: isdn_concap.h,v 1.3 2000/05/11 22:29:20 kai Exp $
+ *
+ * Linux ISDN subsystem, protocol encapsulation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
  */
+
 extern struct concap_device_ops isdn_concap_reliable_dl_dops;
 extern struct concap_device_ops isdn_concap_demand_dial_dops;
 extern struct concap_proto * isdn_concap_new( int );
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_net.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/isdn/isdn_net.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.114 2000/03/16 16:37:41 kai Exp $
+/* $Id: isdn_net.c,v 1.137 2000/09/12 19:43:47 kai Exp $
 
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
@@ -19,443 +19,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_net.c,v $
- * Revision 1.114  2000/03/16 16:37:41  kai
- * Allow phone numbers starting with "*" as outgoing numbers for
- * networking interface. Some PBX's need this to allow dialing internal
- * numbers (mine, for example ;-)
- *
- * Revision 1.113  2000/03/16 15:46:37  kai
- * a little bugfix and cosmetic changes
- *
- * Revision 1.112  2000/03/04 16:20:42  detabc
- * copy frames before rewriting frame's saddr
- *
- * Revision 1.111  2000/02/28 22:28:24  he
- * moved tx_timeout warning messages in old (2.2.x) branch where it really only
- * indicates problems.
- *
- * Revision 1.110  2000/02/26 01:00:53  keil
- * changes from 2.3.47
- *
- * Revision 1.109  2000/02/25 11:29:17  paul
- * changed chargetime to ulong from int (after about 20 days the "chargetime of
- * ipppX is now 1234" message displays a negative number on alpha).
- *
- * Revision 1.108  2000/02/15 12:54:01  kai
- * set TX timeout back to 2 secs for 2.2.x, just to be safe
- *
- * Revision 1.107  2000/02/13 09:52:05  kai
- * increased TX_TIMEOUT to 20sec
- *
- * Revision 1.106  2000/02/12 19:26:55  kai
- * adopted to latest 2.3 softnet changes.
- *
- * tested with PPP and MPPP, it works here.
- * can somebody check raw-ip?
- *
- * also changed std2kern, stddiff for bash-1 compatibility,
- * hope this doesn't break anything.
- *
- * Revision 1.105  2000/02/12 11:43:26  he
- * SOFTNET related changes, first try. Compatible with linux 2.2.x, but
- * not tested for kernels with softnet (>= 2.3.43) yet.
- *
- * Revision 1.104  2000/02/06 21:49:59  detabc
- * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections.
- * Include checksum-recompute of ip- and udp-header's.
- *
- * Revision 1.103  2000/01/23 18:45:37  keil
- * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
- *
- * Revision 1.102  2000/01/09 20:43:14  detabc
- * exand logical bind-group's for both call's (in and out).
- * add first part of kernel-config-help for abc-extension.
- *
- * Revision 1.101  1999/12/05 16:06:08  detabc
- * add resethandling for rawip-compression.
- * at now all B2-Protocols are usable with rawip-compression
- *
- * Revision 1.100  1999/12/04 15:05:25  detabc
- * bugfix abc-rawip-bsdcompress with channel-bundeling
- *
- * Revision 1.99  1999/11/30 11:29:06  detabc
- * add a on the fly frame-counter and limit
- *
- * Revision 1.98  1999/11/28 14:49:07  detabc
- * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the
- * uncompressed size.
- *
- * Revision 1.97  1999/11/26 15:54:59  detabc
- * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol.
- *
- * Revision 1.96  1999/11/20 22:14:13  detabc
- * added channel dial-skip in case of external use
- * (isdn phone or another isdn device) on the same NTBA.
- * usefull with two or more card's connected the different NTBA's.
- * global switchable in kernel-config and also per netinterface.
- *
- * add auto disable of netinterface's in case of:
- * 	to many connection's in short time.
- * 	config mistakes (wrong encapsulation, B2-protokoll or so on) on local
- * 	or remote side.
- * 	wrong password's or something else to a ISP (syncppp).
- *
- * possible encapsulations for this future are:
- * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
- * and ISDN_NET_ENCAP_CISCOHDLCK.
- *
- * Revision 1.95  1999/10/27 21:21:17  detabc
- * Added support for building logically-bind-group's per interface.
- * usefull for outgoing call's with more then one isdn-card.
- *
- * Switchable support to dont reset the hangup-timeout for
- * receive frames. Most part's of the timru-rules for receiving frames
- * are now obsolete. If the input- or forwarding-firewall deny
- * the frame, the line will be not hold open.
- *
- * Revision 1.94  1999/10/02 11:07:02  he
- * Changed tbusy logic in indn_net.c
- *
- * Revision 1.93  1999/09/23 22:22:41  detabc
- * added tcp-keepalive-detect with local response (ipv4 only)
- * added host-only-interface support
- * (source ipaddr == interface ipaddr) (ipv4 only)
- * ok with kernel 2.3.18 and 2.2.12
- *
- * Revision 1.92  1999/09/13 23:25:17  he
- * serialized xmitting frames from isdn_ppp and BSENT statcallb
- *
- * Revision 1.91  1999/09/12 16:19:39  detabc
- * added abc features
- * low cost routing for net-interfaces (only the HL side).
- * need more implementation in the isdnlog-utility
- * udp info support (first part).
- * different EAZ on outgoing call's.
- * more checks on D-Channel callbacks (double use of channels).
- * tested and running with kernel 2.3.17
- *
- * Revision 1.90  1999/09/04 22:21:39  detabc
- *
- * Revision 1.89  1999/08/22 20:26:03  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.88  1999/07/07 10:13:31  detabc
- * remove unused messages
- *
- * Revision 1.87  1999/07/06 07:53:53  calle
- * calls to dev_alloc_skb waste 16 bytes of memory, if we calculate the
- * right header space for the lowlevel driver. using alloc_skb instead.
- *
- * Revision 1.86  1999/06/09 10:12:05  paul
- * thinko in previous patch
- *
- * Revision 1.85  1999/06/07 19:42:39  paul
- * isdn_net_getpeer() fixed to return correct `outgoing' flag
- *
- * Revision 1.84  1999/04/18 14:06:55  fritz
- * Removed TIMRU stuff.
- *
- * Revision 1.83  1999/04/12 12:33:23  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.82  1999/01/17 00:55:58  he
- * added mark_bh in BCONN statcallb and cleaned up some dead code
- *
- * Revision 1.81  1999/01/15 16:36:52  he
- * replaced icmp_send() by dst_link_failure()
- *
- * Revision 1.80  1998/12/01 13:06:22  paul
- * Also huptimeout with dialmode == manual
- *
- * Revision 1.79  1998/10/30 17:55:27  he
- * dialmode for x25iface and multulink ppp
- *
- * Revision 1.78  1998/10/26 18:20:46  he
- * re-inserted p=p->next in isdn_net_find_icall() (fixes kernel lock up
- * on incoming call not matching the first interface)
- *
- * Revision 1.77  1998/10/23 10:18:44  paul
- * Implementation of "dialmode" (successor of "status")
- * You also need current isdnctrl for this!
- *
- * Revision 1.76  1998/09/07 22:00:05  he
- * flush method for 2.1.118 and above
- * updated IIOCTLNETGPN
- *
- * Revision 1.75  1998/08/31 21:09:50  he
- * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
- *     peer phone number)
- *
- * Revision 1.74  1998/07/30 11:28:32  paul
- * printk message only appeared when status is off and interface is rawIP,
- * which is confusing for people who don't know about "isdnctrl status <if> on".
- *
- * Revision 1.73  1998/06/26 22:01:37  keil
- * tx_queue_len = 5 was too small
- *
- * Revision 1.72  1998/06/26 15:12:31  fritz
- * Added handling of STAT_ICALL with incomplete CPN.
- * Added AT&L for ttyI emulator.
- * Added more locking stuff in tty_write.
- *
- * Revision 1.71  1998/06/18 22:43:08  fritz
- * Bugfix: Setting ndev->do_ioctl had beed accidetly removed at cleanup.
- *
- * Revision 1.70  1998/06/17 19:50:49  he
- * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
- * brute force fix to avoid Ugh's in isdn_tty_write()
- * cleaned up some dead code
- *
- * Revision 1.69  1998/06/09 12:27:37  cal
- * Changed default of local netdev flags: ISDN_NET_STOPPED is default now,
- * so autodial is suppressed for that device until it is switched on using
- * 'isdnctrl status dev-name on'.
- *
- *
- *
- * Revision 1.66  1998/05/26 22:39:24  he
- * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
- * concap typo
- * cleared dev.tbusy in isdn_net BCONN status callback
- *
- * Revision 1.61  1998/04/16 19:19:42  keil
- * Fix from vger (tx max qlength)
- *
- * Revision 1.60  1998/04/14 16:28:49  he
- * Fixed user space access with interrupts off and remaining
- * copy_{to,from}_user() -> -EFAULT return codes
- *
- * Revision 1.59  1998/03/07 22:37:33  fritz
- * Bugfix: restore_flags missing.
- *
- * Revision 1.58  1998/03/07 18:21:05  cal
- * Dynamic Timeout-Rule-Handling vs. 971110 included
- *
- * Revision 1.57  1998/02/25 18:31:13  fritz
- * Added debugging output in adjust_header.
- *
- * Revision 1.56  1998/02/25 17:49:42  he
- * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
- *
- * Revision 1.55  1998/02/23 19:38:22  fritz
- * Corrected check for modified feature-flags.
- *
- * Revision 1.54  1998/02/20 17:15:07  fritz
- * Changes for recent kernels.
- * Ugly workaround for adjusting Ethernet frames with recent kernels.
- * replaced direct calls to lowlevel-driver command by common hook.
- *
- * Revision 1.53  1998/01/31 22:05:54  keil
- * Lots of changes for X.25 support:
- * Added generic support for connection-controlling encapsulation protocols
- * Added support of BHUP status message
- * Added support for additional p_encap X25IFACE
- * Added support for kernels >= 2.1.72
- *
- * Revision 1.52  1998/01/31 19:29:51  calle
- * Merged changes from and for 2.1.82, not tested only compiled ...
- *
- * Revision 1.51  1997/10/09 21:28:50  fritz
- * New HL<->LL interface:
- *   New BSENT callback with nr. of bytes included.
- *   Sending without ACK.
- *   New L1 error status (not yet in use).
- *   Cleaned up obsolete structures.
- * Implemented Cisco-SLARP.
- * Changed local net-interface data to be dynamically allocated.
- * Removed old 2.0 compatibility stuff.
- *
- * Revision 1.50  1997/10/01 09:20:32  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.49  1997/08/21 14:38:13  fritz
- * Bugfix: Did not compile without SyncPPP.
- *
- * Revision 1.48  1997/06/22 11:57:15  fritz
- * Added ability to adjust slave triggerlevel.
- *
- * Revision 1.47  1997/06/21 10:52:05  fritz
- * Removed wrong SET_SKB_FREE in isdn_net_send_skb()
- *
- * Revision 1.46  1997/06/17 13:05:24  hipp
- * Applied Eric's underflow-patches (slightly modified)
- *
- * Revision 1.45  1997/06/10 16:24:22  hipp
- * hard_header changes for syncPPP (now behaves like RAWIP)
- *
- * Revision 1.44  1997/05/27 15:17:26  fritz
- * Added changes for recent 2.1.x kernels:
- *   changed return type of isdn_close
- *   queue_task_* -> queue_task
- *   clear/set_bit -> test_and_... where apropriate.
- *   changed type of hard_header_cache parameter.
- *
- * Revision 1.43  1997/03/30 16:51:13  calle
- * changed calls to copy_from_user/copy_to_user and removed verify_area
- * were possible.
- *
- * Revision 1.42  1997/03/11 08:43:51  fritz
- * Perform a hangup if number is deleted while dialing.
- *
- * Revision 1.41  1997/03/08 08:16:31  fritz
- * Bugfix: Deleting a phone number during dial gave unpredictable results.
- *
- * Revision 1.40  1997/03/05 21:16:08  fritz
- * Fix: did not compile with 2.1.27
- *
- * Revision 1.39  1997/03/04 21:36:52  fritz
- * Added sending ICMP messages when no connetion is possible.
- *
- * Revision 1.38  1997/02/23 23:41:14  fritz
- * Bugfix: Slave interfaces have to be hung up before master.
- *
- * Revision 1.37  1997/02/11 18:32:51  fritz
- * Bugfix in isdn_ppp_free_mpqueue().
- *
- * Revision 1.36  1997/02/10 21:31:11  fritz
- * Changed setup-interface (incoming and outgoing).
- *
- * Revision 1.35  1997/02/10 20:12:45  fritz
- * Changed interface for reporting incoming calls.
- *
- * Revision 1.34  1997/02/03 23:15:07  fritz
- * Reformatted according CodingStyle.
- * replaced arp_find prototype by proper include.
- * made dev_purge_queues static.
- * Bugfix in bogocps calculation.
- * removed isdn_net_receive_callback - was never used ;-)
- * Misc. fixes for Kernel 2.1.X comaptibility.
- *
- * Revision 1.33  1997/01/17 01:19:25  fritz
- * Applied chargeint patch.
- *
- * Revision 1.32  1997/01/14 01:29:31  fritz
- * Bugfix: isdn_net_hangup() did not reset ISDN_NET_CONNECTED.
- *
- * Revision 1.31  1997/01/11 23:30:42  fritz
- * Speed up dial statemachine.
- *
- * Revision 1.30  1996/11/25 17:20:50  hipp
- * fixed pppbind bug in isdn_net_find_icall()
- *
- * Revision 1.29  1996/11/13 02:31:38  fritz
- * Minor cleanup.
- *
- * Revision 1.28  1996/10/27 20:49:06  keil
- * bugfix to compile without MPP
- *
- * Revision 1.27  1996/10/25 18:46:01  fritz
- * Another bugfix in isdn_net_autohup()
- *
- * Revision 1.26  1996/10/23 23:05:36  fritz
- * Bugfix: Divide by zero in isdn_net_autohup()
- *
- * Revision 1.25  1996/10/22 23:13:58  fritz
- * Changes for compatibility to 2.0.X and 2.1.X kernels.
- *
- * Revision 1.24  1996/10/11 13:57:40  fritz
- * Bugfix: Error in BogoCPS calculation.
- *
- * Revision 1.23  1996/09/23 01:58:08  fritz
- * Fix: With syncPPP encapsulation, discard LCP packets
- *      when calculating hangup timeout.
- *
- * Revision 1.22  1996/09/23 00:03:37  fritz
- * Fix: did not compile without CONFIG_ISDN_PPP
- *
- * Revision 1.21  1996/09/07 12:44:50  hipp
- * (hopefully) fixed callback problem with syncPPP
- * syncPPP network devices now show PPP link encap
- *
- * Revision 1.20  1996/08/29 20:06:03  fritz
- * Bugfix: Transmission timeout had been much to low.
- *
- * Revision 1.19  1996/08/12 16:24:32  hipp
- * removed some (now) obsolete functions for syncPPP in rebuild_header etc.
- *
- * Revision 1.18  1996/07/03 13:48:51  hipp
- * bugfix: Call dev_purge_queues() only for master device
- *
- * Revision 1.17  1996/06/25 18:37:37  fritz
- * Fixed return count for empty return string in isdn_net_getphones().
- *
- * Revision 1.16  1996/06/24 17:48:08  fritz
- * Bugfixes:
- *   - Did not free channel on unbinding.
- *   - ioctl returned wrong callback settings.
- *
- * Revision 1.15  1996/06/16 17:42:54  tsbogend
- * fixed problem with IP addresses on Linux/Alpha (long is 8 byte there)
- *
- * Revision 1.14  1996/06/11 14:54:08  hipp
- * minor bugfix in isdn_net_send_skb
- * changes in BSENT callback handler for syncPPP
- * added lp->sav_skb stuff
- *
- * Revision 1.13  1996/06/06 14:25:44  fritz
- * Changed loglevel of "incoming ... without OAD" message, since
- * with audio support this is quite normal.
- *
- * Revision 1.12  1996/06/05 02:36:45  fritz
- * Minor bugfixes by M. Hipp.
- *
- * Revision 1.11  1996/05/18 01:36:59  fritz
- * Added spelling corrections and some minor changes
- * to stay in sync with kernel.
- *
- * Revision 1.10  1996/05/17 03:49:01  fritz
- * Some cleanup.
- *
- * Revision 1.9  1996/05/06 11:34:57  hipp
- * fixed a few bugs
- *
- * Revision 1.8  1996/04/30 21:04:40  fritz
- * Test commit
- *
- * Revision 1.7  1996/04/30 11:10:42  fritz
- * Added Michael's ippp-bind patch.
- *
- * Revision 1.6  1996/04/30 09:34:35  fritz
- * Removed compatibility-macros.
- *
- * Revision 1.5  1996/04/20 16:28:38  fritz
- * Made more parameters of the dial statemachine user-configurable and
- * added hangup after dial for more reliability using callback.
- * Changed all io going through generic routines in isdn_common.c
- * Added missing call to dev_free_skb on failed dialing.
- * Added uihdlc encapsulation.
- * Fixed isdn_net_setcfg not to destroy interface-flags anymore.
- * Misc. typos.
- *
- * Revision 1.4  1996/02/19 15:23:38  fritz
- * Bugfix: Sync-PPP packets got compressed twice, when resent due to
- *         send-queue-full reject.
- *
- * Revision 1.3  1996/02/11 02:22:28  fritz
- * Changed status- receive-callbacks to use pointer-arrays for finding
- * a corresponding interface instead of looping over all interfaces.
- * Activate Auto-hangup-timer only when interface is online.
- * Some bugfixes in the dialing-statemachine.
- * Lot of bugfixes in sk_buff'ized encapsulation handling.
- * For speedup connection-setup after dialing, remember sk_buf that triggered
- * dialing.
- * Fixed isdn_net_log_packet according to different encapsulations.
- * Correct ARP-handling for ETHERNET-encapsulation.
- *
- * Revision 1.2  1996/01/22 05:05:12  fritz
- * Changed returncode-logic for isdn_net_start_xmit() and its
- * helper-functions.
- * Changed handling of buildheader for RAWIP and ETHERNET-encapsulation.
- *
- * Revision 1.1  1996/01/09 04:12:34  fritz
- * Initial revision
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_net.h linux/drivers/isdn/isdn_net.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_net.h	Tue Oct 26 17:53:40 1999
+++ linux/drivers/isdn/isdn_net.h	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.h,v 1.10 1999/08/22 20:26:06 calle Exp $
+/* $Id: isdn_net.h,v 1.19 2000/06/21 09:54:29 keil Exp $
 
  * header for Linux ISDN subsystem, network related functions (linklevel).
  *
@@ -19,48 +19,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_net.h,v $
- * Revision 1.10  1999/08/22 20:26:06  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.9  1999/04/12 12:33:27  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.8  1998/10/30 17:55:33  he
- * dialmode for x25iface and multulink ppp
- *
- * Revision 1.7  1998/08/31 21:09:55  he
- * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
- *     peer phone number)
- *
- * Revision 1.6  1997/10/09 21:28:54  fritz
- * New HL<->LL interface:
- *   New BSENT callback with nr. of bytes included.
- *   Sending without ACK.
- *   New L1 error status (not yet in use).
- *   Cleaned up obsolete structures.
- * Implemented Cisco-SLARP.
- * Changed local net-interface data to be dynamically allocated.
- * Removed old 2.0 compatibility stuff.
- *
- * Revision 1.5  1997/02/10 20:12:47  fritz
- * Changed interface for reporting incoming calls.
- *
- * Revision 1.4  1997/02/03 23:16:48  fritz
- * Removed isdn_net_receive_callback prototype.
- *
- * Revision 1.3  1997/01/17 01:19:30  fritz
- * Applied chargeint patch.
- *
- * Revision 1.2  1996/04/20 16:29:43  fritz
- * Misc. typos
- *
- * Revision 1.1  1996/02/11 02:35:13  fritz
- * Initial revision
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_ppp.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/isdn/isdn_ppp.c	Mon Dec  3 20:27:06 2001
@@ -18,255 +18,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Log: isdn_ppp.c,v $
- * Revision 1.63  2000/03/16 15:46:37  kai
- * a little bugfix and cosmetic changes
- *
- * Revision 1.62  2000/02/12 19:26:55  kai
- * adopted to latest 2.3 softnet changes.
- *
- * tested with PPP and MPPP, it works here.
- * can somebody check raw-ip?
- *
- * also changed std2kern, stddiff for bash-1 compatibility,
- * hope this doesn't break anything.
- *
- * Revision 1.61  1999/11/20 22:14:14  detabc
- * added channel dial-skip in case of external use
- * (isdn phone or another isdn device) on the same NTBA.
- * usefull with two or more card's connected the different NTBA's.
- * global switchable in kernel-config and also per netinterface.
- *
- * add auto disable of netinterface's in case of:
- * 	to many connection's in short time.
- * 	config mistakes (wrong encapsulation, B2-protokoll or so on) on local
- * 	or remote side.
- * 	wrong password's or something else to a ISP (syncppp).
- *
- * possible encapsulations for this future are:
- * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
- * and ISDN_NET_ENCAP_CISCOHDLCK.
- *
- * Revision 1.60  1999/11/04 20:29:55  he
- * applied Andre Beck's reset_free fix
- *
- * Revision 1.59  1999/10/31 15:59:50  he
- * more skb headroom checks
- *
- * Revision 1.58  1999/10/30 13:13:01  keil
- * Henners isdn_ppp_skb_push:under fix
- *
- * Revision 1.57  1999/10/05 22:47:17  he
- * Removed dead ISDN_SYNCPPP_READDRESS code (obsoleted by sysctl_ip_dynaddr
- * and network address translation)
- *
- * Revision 1.56  1999/09/29 16:01:06  he
- * replaced dev_alloc_skb() for downstream skbs by equivalent alloc_skb()
- *
- * Revision 1.55  1999/09/23 22:07:51  detabc
- *
- * make ipc_head common usable (for use compressor with raw-ip)
- * add function before netif_rx(). needed for ipv4-tcp-keepalive-detect.
- * ~
- *
- * Revision 1.54  1999/09/13 23:25:17  he
- * serialized xmitting frames from isdn_ppp and BSENT statcallb
- *
- * Revision 1.53  1999/08/31 11:18:14  paul
- * various spelling corrections (new checksums may be needed, Karsten!)
- *
- * Revision 1.52  1999/08/22 20:26:07  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.51  1999/08/18 16:19:17  hipp
- * applied MPPP-resize-headroom patch
- *
- * Revision 1.50  1999/08/16 07:11:41  hipp
- * Additional VJ decomp-buffer-size increased from 40 to 128
- *
- * Revision 1.49  1999/07/06 07:47:11  calle
- * bugfix: dev_alloc_skb only reserve 16 bytes. We need to look at the
- *  	hdrlen the driver want. So I changed dev_alloc_skb calls
- *         to alloc_skb and skb_reserve.
- *
- * Revision 1.48  1999/07/01 08:29:56  keil
- * compatibility to 2.3 kernel
- *
- * Revision 1.47  1999/04/18 14:06:59  fritz
- * Removed TIMRU stuff.
- *
- * Revision 1.46  1999/04/12 12:33:35  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.45  1998/12/30 17:48:24  paul
- * fixed syncPPP callback out
- *
- * Revision 1.44  1998/10/30 17:55:34  he
- * dialmode for x25iface and multulink ppp
- *
- * Revision 1.43  1998/10/29 17:23:54  hipp
- * Minor MPPP fixes, verboser logging.
- *
- * Revision 1.42  1998/07/20 11:30:07  hipp
- * Readded compression check
- *
- * Revision 1.41  1998/07/08 16:50:57  hipp
- * Compression changes
- *
- * Revision 1.40  1998/04/06 19:07:27  hipp
- * added check, whether compression is enabled.
- *
- * Revision 1.39  1998/03/25 22:46:53  hipp
- * Some additional CCP changes.
- *
- * Revision 1.38  1998/03/24 16:33:06  hipp
- * More CCP changes. BSD compression now "works" on a local loopback link.
- * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h
- *
- * Revision 1.37  1998/03/22 18:50:49  hipp
- * Added BSD Compression for syncPPP .. UNTESTED at the moment
- *
- * Revision 1.36  1998/03/09 17:46:30  he
- * merged in 2.1.89 changes
- *
- * Revision 1.35  1998/03/07 18:21:11  cal
- * Dynamic Timeout-Rule-Handling vs. 971110 included
- *
- * Revision 1.34  1998/02/25 17:49:48  he
- * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
- *
- * Revision 1.33  1998/02/20 17:11:54  fritz
- * Changes for recent kernels.
- *
- * Revision 1.32  1998/01/31 19:29:55  calle
- * Merged changes from and for 2.1.82, not tested only compiled ...
- *
- * Revision 1.31  1997/10/09 21:29:01  fritz
- * New HL<->LL interface:
- *   New BSENT callback with nr. of bytes included.
- *   Sending without ACK.
- *   New L1 error status (not yet in use).
- *   Cleaned up obsolete structures.
- * Implemented Cisco-SLARP.
- * Changed local net-interface data to be dynamically allocated.
- * Removed old 2.0 compatibility stuff.
- *
- * Revision 1.30  1997/10/01 09:20:38  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.29  1997/08/21 23:11:44  fritz
- * Added changes for kernels >= 2.1.45
- *
- * Revision 1.28  1997/06/17 13:05:57  hipp
- * Applied Eric's underflow-patches (slightly modified)
- * more compression changes (but disabled at the moment)
- * changed one copy_to_user() to run with enabled IRQs
- * a few MP changes
- * changed 'proto' handling in the isdn_ppp receive code
- *
- * Revision 1.27  1997/03/30 16:51:17  calle
- * changed calls to copy_from_user/copy_to_user and removed verify_area
- * were possible.
- *
- * Revision 1.26  1997/02/23 16:53:44  hipp
- * minor cleanup
- * some initial changes for future PPP compresion
- * added AC,PC compression for outgoing frames
- *
- * Revision 1.25  1997/02/12 20:37:35  hipp
- * New ioctl() PPPIOCGCALLINFO, minor cleanup
- *
- * Revision 1.24  1997/02/11 18:32:56  fritz
- * Bugfix in isdn_ppp_free_mpqueue().
- *
- * Revision 1.23  1997/02/10 11:12:19  fritz
- * More changes for Kernel 2.1.X compatibility.
- *
- * Revision 1.22  1997/02/06 15:03:51  hipp
- * changed GFP_KERNEL kmalloc to GFP_ATOMIC in isdn_ppp_fill_mpqueue()
- *
- * Revision 1.21  1997/02/03 23:29:38  fritz
- * Reformatted according CodingStyle
- * Bugfix: removed isdn_ppp_skb_destructor, used by upper layers.
- * Misc changes for Kernel 2.1.X compatibility.
- *
- * Revision 1.20  1996/10/30 12:21:58  fritz
- * Cosmetic fix: Compiler warning when compiling without MPP.
- *
- * Revision 1.19  1996/10/25 19:03:21  hipp
- * changed/added some defines to (re)allow compilation without MP/VJ
- *
- * Revision 1.18  1996/10/22 23:14:00  fritz
- * Changes for compatibility to 2.0.X and 2.1.X kernels.
- *
- * Revision 1.17  1996/10/22 09:39:49  hipp
- * a few MP changes and bugfixes
- *
- * Revision 1.16  1996/09/23 01:58:10  fritz
- * Fix: With syncPPP encapsulation, discard LCP packets
- *      when calculating hangup timeout.
- *
- * Revision 1.15  1996/09/07 12:50:12  hipp
- * bugfixes (unknown device after failed dial attempt, minor bugs)
- *
- * Revision 1.14  1996/08/12 16:26:47  hipp
- * code cleanup
- * changed connection management from minors to slots
- *
- * Revision 1.13  1996/07/01 19:47:24  hipp
- * Fixed memory leak in VJ handling and more VJ changes
- *
- * Revision 1.12  1996/06/24 17:42:03  fritz
- * Minor bugfixes.
- *
- * Revision 1.11  1996/06/16 17:46:05  tsbogend
- * changed unsigned long to u32 to make Alpha people happy
- *
- * Revision 1.10  1996/06/11 14:50:29  hipp
- * Lot of changes and bugfixes.
- * New scheme to resend packets to busy LL devices.
- *
- * Revision 1.9  1996/05/18 01:37:01  fritz
- * Added spelling corrections and some minor changes
- * to stay in sync with kernel.
- *
- * Revision 1.8  1996/05/06 11:34:55  hipp
- * fixed a few bugs
- *
- * Revision 1.7  1996/04/30 11:07:42  fritz
- * Added Michael's ippp-bind patch.
- *
- * Revision 1.6  1996/04/30 09:33:09  fritz
- * Removed compatibility-macros.
- *
- * Revision 1.5  1996/04/20 16:32:32  fritz
- * Changed ippp_table to an array of pointers, allocating each part
- * separately.
- *
- * Revision 1.4  1996/02/19 15:25:50  fritz
- * Bugfix: Sync-PPP packets got compressed twice, when resent due to
- * send-queue-full reject.
- *
- * Revision 1.3  1996/02/11 02:27:12  fritz
- * Lot of Bugfixes my Michael.
- * Moved calls to skb_push() into isdn_net_header()
- * Fixed a possible race-condition in isdn_ppp_timer_timeout().
- *
- * Revision 1.2  1996/01/22 05:08:06  fritz
- * Merged in Michael's patches for MP.
- * Minor changes in isdn_ppp_xmit.
- *
- * Revision 1.1  1996/01/09 04:11:29  fritz
- * Initial revision
- *
  */
-
-/* TODO: right tbusy handling when using MP */
 
 #define CONFIG_ISDN_CCP 1
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_ppp.h linux/drivers/isdn/isdn_ppp.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_ppp.h	Mon Sep  4 10:39:18 2000
+++ linux/drivers/isdn/isdn_ppp.h	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.h,v 1.14 1999/08/22 20:26:10 calle Exp $
+/* $Id: isdn_ppp.h,v 1.17 2000/08/10 22:52:46 kai Exp $
 
  * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
@@ -18,65 +18,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Log: isdn_ppp.h,v $
- * Revision 1.14  1999/08/22 20:26:10  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.13  1998/03/22 18:50:50  hipp
- * Added BSD Compression for syncPPP .. UNTESTED at the moment
- *
- * Revision 1.12  1998/01/31 22:07:48  keil
- * changes for newer kernels
- *
- * Revision 1.11  1997/10/01 09:20:44  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.10  1997/06/17 13:06:00  hipp
- * Applied Eric's underflow-patches (slightly modified)
- * more compression changes (but disabled at the moment)
- * changed one copy_to_user() to run with enabled IRQs
- * a few MP changes
- * changed 'proto' handling in the isdn_ppp receive code
- *
- * Revision 1.9  1997/02/11 18:32:59  fritz
- * Bugfix in isdn_ppp_free_mpqueue().
- *
- * Revision 1.8  1997/02/10 10:11:33  fritz
- * More changes for Kernel 2.1.X compatibility.
- *
- * Revision 1.7  1997/02/03 23:18:57  fritz
- * Removed isdn_ppp_free_sqqueue prototype
- *         and ippp_table (both static in isdn_ppp.c).
- *
- * Revision 1.6  1996/09/23 01:58:11  fritz
- * Fix: With syncPPP encapsulation, discard LCP packets
- *      when calculating hangup timeout.
- *
- * Revision 1.5  1996/09/07 12:51:34  hipp
- * *** empty log message ***
- *
- * Revision 1.4  1996/05/06 11:34:56  hipp
- * fixed a few bugs
- *
- * Revision 1.3  1996/04/30 09:33:10  fritz
- * Removed compatibility-macros.
- *
- * Revision 1.2  1996/04/20 16:35:11  fritz
- * Changed isdn_ppp_receive to use sk_buff as parameter.
- * Added definition of isdn_ppp_dial_slave and ippp_table.
- *
- * Revision 1.1  1996/01/10 21:39:10  fritz
- * Initial revision
- *
  */
 
 #include <linux/ppp_defs.h>     /* for PPP_PROTOCOL */
-#include <linux/isdn_ppp.h>
+#include <linux/isdn_ppp.h>	/* for isdn_ppp info */
 extern int isdn_ppp_read(int, struct file *, char *, int);
 extern int isdn_ppp_write(int, struct file *, const char *, int);
 extern int isdn_ppp_open(int, struct file *);
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_tty.c	Wed May  3 17:16:40 2000
+++ linux/drivers/isdn/isdn_tty.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.84 2000/02/16 15:10:14 paul Exp $
+/* $Id: isdn_tty.c,v 1.93 2000/08/05 09:58:26 armin Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -18,334 +18,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_tty.c,v $
- * Revision 1.84  2000/02/16 15:10:14  paul
- * If a ttyI has no open FDs, don't connect incoming calls to it.
- * (Hangup on close of last FD is still to be done.)
- *
- * Revision 1.83  2000/02/16 14:59:33  paul
- * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers;
- * used defines for result codes;
- * fixed RING ... RUNG problem (no empty lines in between).
- *
- * Revision 1.82  2000/01/23 18:45:37  keil
- * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
- *
- * Revision 1.81  2000/01/20 19:55:33  keil
- * Add FAX Class 1 support
- *
- * Revision 1.80  1999/11/07 13:34:30  armin
- * Fixed AT command line editor
- *
- * Revision 1.79  1999/10/29 18:35:08  armin
- * Check number len in isdn_get_msnstr() to avoid buffer overflow.
- *
- * Revision 1.78  1999/10/28 23:03:51  armin
- * Bugfix: now freeing channel on modem_hup() even when
- * usage on ttyI has changed and error-report for
- * AT-commands on wrong channel-state.
- *
- * Revision 1.77  1999/10/26 21:13:14  armin
- * using define for checking phone number len in isdn_tty_getdial()
- *
- * Revision 1.76  1999/10/11 22:16:26  keil
- * Suspend/Resume is possible without explicit ID too
- *
- * Revision 1.75  1999/10/08 18:59:32  armin
- * Bugfix of too small MSN buffer and checking phone number
- * in isdn_tty_getdial()
- *
- * Revision 1.74  1999/09/04 06:20:04  keil
- * Changes from kernel set_current_state()
- *
- * Revision 1.73  1999/08/28 21:56:27  keil
- * misplaced #endif caused ttyI crash in 2.3.X
- *
- * Revision 1.72  1999/07/31 12:59:45  armin
- * Added tty fax capabilities.
- *
- * Revision 1.71  1999/07/27 10:34:34  armin
- * Fixed last change. Did not compile with AUDIO support off.
- *
- * Revision 1.70  1999/07/25 16:17:58  keil
- * Fix Suspend/Resume
- *
- * Revision 1.69  1999/07/25 12:56:15  armin
- * isdn_tty_at_cout() now queues the message if online and
- * data is in queue or flip buffer is full.
- * needed for fax connections.
- *
- * Revision 1.68  1999/07/11 17:51:51  armin
- * Bugfix, "-" was missing for AT&L settings.
- *
- * Revision 1.67  1999/07/11 17:14:12  armin
- * Added new layer 2 and 3 protocols for Fax and DSP functions.
- * Moved "Add CPN to RING message" to new register S23,
- * "Display message" is now correct on register S13 bit 7.
- * New audio command AT+VDD implemented (deactivate DTMF decoder and
- * activate possible existing hardware/DSP decoder).
- * Moved some tty defines to .h file.
- * Made whitespace possible in AT command line.
- * Some AT-emulator output bugfixes.
- * First Fax G3 implementations.
- *
- * Revision 1.66  1999/07/07 10:13:46  detabc
- * remove unused messages
- *
- * Revision 1.65  1999/07/04 21:01:59  werner
- * Added support for keypad and display (ported from 2.0)
- *
- * Revision 1.64  1999/07/01 08:30:00  keil
- * compatibility to 2.3 kernel
- *
- * Revision 1.63  1999/04/12 12:33:39  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.62  1999/03/02 12:04:48  armin
- * -added ISDN_STAT_ADDCH to increase supported channels after
- *  register_isdn().
- * -ttyI now goes on-hook on ATZ when B-Ch is connected.
- * -added timer-function for register S7 (Wait for Carrier).
- * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
- * -on L2_MODEM a string will be appended to the CONNECT-Message,
- *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
- * -variable "dialing" used for ATA also, for interrupting call
- *  establishment and register S7.
- *
- * Revision 1.61  1999/01/27 22:53:11  he
- * minor updates (spellings, jiffies wrap around in isdn_tty)
- *
- * Revision 1.60  1998/11/15 23:57:32  keil
- * changes for 2.1.127
- *
- * Revision 1.59  1998/08/20 13:50:15  keil
- * More support for hybrid modem (not working yet)
- *
- * Revision 1.58  1998/07/26 18:48:45  armin
- * Added silence detection in voice receive mode.
- *
- * Revision 1.57  1998/06/26 15:12:36  fritz
- * Added handling of STAT_ICALL with incomplete CPN.
- * Added AT&L for ttyI emulator.
- * Added more locking stuff in tty_write.
- *
- * Revision 1.56  1998/06/18 23:31:51  fritz
- * Replaced cli()/restore_flags() in isdn_tty_write() by locking.
- * Removed direct-senddown feature in isdn_tty_write because it will
- * never succeed with locking and is useless anyway.
- *
- * Revision 1.55  1998/06/17 19:50:55  he
- * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
- * brute force fix to avoid Ugh's in isdn_tty_write()
- * cleaned up some dead code
- *
- *
- *
- * Revision 1.52  1998/03/19 13:18:21  keil
- * Start of a CAPI like interface for supplementary Service
- * first service: SUSPEND
- *
- *
- * Revision 1.49  1998/03/08 00:01:59  fritz
- * Bugfix: Lowlevel module usage and channel usage were not
- *         reset on NO DCHANNEL.
- *
- * Revision 1.48  1998/03/07 12:28:15  tsbogend
- * fixed kernel unaligned traps on Linux/Alpha
- *
- * Revision 1.47  1998/02/22 19:44:14  fritz
- * Bugfixes and improvements regarding V.110, V.110 now running.
- *
- * Revision 1.46  1998/02/20 17:23:08  fritz
- * Changes for recent kernels.
- * Merged in contributions by Thomas Pfeiffer (V.110 T.70+ Extended FAX stuff)
- * Added symbolic constants for Modem-Registers.
- *
- * Revision 1.45  1998/01/31 22:07:49  keil
- * changes for newer kernels
- *
- * Revision 1.44  1998/01/31 19:30:02  calle
- * Merged changes from and for 2.1.82, not tested only compiled ...
- *
- * Revision 1.43  1997/10/09 21:29:04  fritz
- * New HL<->LL interface:
- *   New BSENT callback with nr. of bytes included.
- *   Sending without ACK.
- *   New L1 error status (not yet in use).
- *   Cleaned up obsolete structures.
- * Implemented Cisco-SLARP.
- * Changed local net-interface data to be dynamically allocated.
- * Removed old 2.0 compatibility stuff.
- *
- * Revision 1.42  1997/10/01 09:20:49  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.41  1997/05/27 15:17:31  fritz
- * Added changes for recent 2.1.x kernels:
- *   changed return type of isdn_close
- *   queue_task_* -> queue_task
- *   clear/set_bit -> test_and_... where apropriate.
- *   changed type of hard_header_cache parameter.
- *
- * Revision 1.40  1997/03/24 22:55:27  fritz
- * Added debug code for status callbacks.
- *
- * Revision 1.39  1997/03/21 18:25:56  fritz
- * Corrected CTS handling.
- *
- * Revision 1.38  1997/03/07 12:13:35  fritz
- * Bugfix: Send audio in adpcm format was broken.
- * Bugfix: CTS handling was wrong.
- *
- * Revision 1.37  1997/03/07 01:37:34  fritz
- * Bugfix: Did not compile with CONFIG_ISDN_AUDIO disabled.
- * Bugfix: isdn_tty_tint() did not handle lowlevel errors correctly.
- * Bugfix: conversion was wrong when sending ulaw audio.
- * Added proper ifdef's for CONFIG_ISDN_AUDIO
- *
- * Revision 1.36  1997/03/04 21:41:55  fritz
- * Fix: Excessive stack usage of isdn_tty_senddown()
- *      and isdn_tty_end_vrx() could lead to problems.
- *
- * Revision 1.35  1997/03/02 19:05:52  fritz
- * Bugfix: Avoid recursion.
- *
- * Revision 1.34  1997/03/02 14:29:22  fritz
- * More ttyI related cleanup.
- *
- * Revision 1.33  1997/02/28 02:32:45  fritz
- * Cleanup: Moved some tty related stuff from isdn_common.c
- *          to isdn_tty.c
- * Bugfix:  Bisync protocol did not behave like documented.
- *
- * Revision 1.32  1997/02/23 15:43:03  fritz
- * Small change in handling of incoming calls
- * documented in newest version of ttyI.4
- *
- * Revision 1.31  1997/02/21 13:05:57  fritz
- * Bugfix: Remote hangup did not set location-info on ttyI's
- *
- * Revision 1.30  1997/02/18 09:41:05  fritz
- * Added support for bitwise access to modem registers (ATSx.y=n, ATSx.y?).
- * Beautified output of AT&V.
- *
- * Revision 1.29  1997/02/16 12:11:51  fritz
- * Added S13,Bit4 option.
- *
- * Revision 1.28  1997/02/10 22:07:08  fritz
- * Added 2 modem registers for numbering plan and screening info.
- *
- * Revision 1.27  1997/02/10 21:31:14  fritz
- * Changed setup-interface (incoming and outgoing).
- *
- * Revision 1.26  1997/02/10 20:12:48  fritz
- * Changed interface for reporting incoming calls.
- *
- * Revision 1.25  1997/02/03 23:04:30  fritz
- * Reformatted according CodingStyle.
- * skb->free stuff replaced by macro.
- * Finished full-duplex audio.
- *
- * Revision 1.24  1997/01/14 01:32:42  fritz
- * Changed audio receive not to rely on skb->users and skb->lock.
- * Added ATI2 and related variables.
- * Started adding full-duplex audio capability.
- *
- * Revision 1.23  1996/10/22 23:14:02  fritz
- * Changes for compatibility to 2.0.X and 2.1.X kernels.
- *
- * Revision 1.22  1996/10/19 18:56:43  fritz
- * ATZ did not change the xmitbuf size.
- *
- * Revision 1.21  1996/06/24 17:40:28  fritz
- * Bugfix: Did not compile without CONFIG_ISDN_AUDIO
- *
- * Revision 1.20  1996/06/15 14:59:39  fritz
- * Fixed isdn_tty_tint() to handle partially sent
- * sk_buffs.
- *
- * Revision 1.19  1996/06/12 15:53:56  fritz
- * Bugfix: AT+VTX and AT+VRX could be executed without
- *         having a connection.
- *         Missing check for NULL tty in isdn_tty_flush_buffer().
- *
- * Revision 1.18  1996/06/07 11:17:33  tsbogend
- * added missing #ifdef CONFIG_ISDN_AUDIO to make compiling without
- * audio support possible
- *
- * Revision 1.17  1996/06/06 14:55:47  fritz
- * Changed to support DTMF decoding on audio playback also.
- * Bugfix: Added check for invalid info->isdn_driver in
- *         isdn_tty_senddown().
- * Clear ncarrier flag on last close() of a tty.
- *
- * Revision 1.16  1996/06/05 02:24:12  fritz
- * Added DTMF decoder for audio mode.
- *
- * Revision 1.15  1996/06/03 20:35:01  fritz
- * Fixed typos.
- *
- * Revision 1.14  1996/06/03 20:12:19  fritz
- * Fixed typos.
- * Added call to write_wakeup via isdn_tty_flush_buffer()
- * in isdn_tty_modem_hup().
- *
- * Revision 1.13  1996/05/31 01:33:29  fritz
- * Changed buffering due to bad performance with mgetty.
- * Now sk_buff is delayed allocated in isdn_tty_senddown
- * using xmit_buff like in standard serial driver.
- * Fixed module locking.
- * Added DLE-DC4 handling in voice mode.
- *
- * Revision 1.12  1996/05/19 01:34:40  fritz
- * Bugfix: ATS returned error.
- *         Register 20 made readonly.
- *
- * Revision 1.11  1996/05/18 01:37:03  fritz
- * Added spelling corrections and some minor changes
- * to stay in sync with kernel.
- *
- * Revision 1.10  1996/05/17 03:51:49  fritz
- * Changed DLE handling for audio receive.
- *
- * Revision 1.9  1996/05/11 21:52:07  fritz
- * Changed queue management to use sk_buffs.
- *
- * Revision 1.8  1996/05/10 08:49:43  fritz
- * Checkin before major changes of tty-code.
- *
- * Revision 1.7  1996/05/07 09:15:09  fritz
- * Reorganized and general cleanup.
- * Bugfixes:
- *  - Audio-transmit working now.
- *  - "NO CARRIER" now reported, when hanging up with DTR low.
- *  - Corrected CTS handling.
- *
- * Revision 1.6  1996/05/02 03:59:25  fritz
- * Bugfixes:
- *  - On dialout, layer-2 setup had been incomplete
- *    when using new auto-layer2 feature.
- *  - On hangup, "NO CARRIER" message sometimes missing.
- *
- * Revision 1.5  1996/04/30 21:05:25  fritz
- * Test commit
- *
- * Revision 1.4  1996/04/20 16:39:54  fritz
- * Changed all io to go through generic routines in isdn_common.c
- * Fixed a real ugly bug in modem-emulator: 'ATA' had been accepted
- * even when a call has been cancelled from the remote machine.
- *
- * Revision 1.3  1996/02/11 02:12:32  fritz
- * Bugfixes according to similar fixes in standard serial.c of kernel.
- *
- * Revision 1.2  1996/01/22 05:12:25  fritz
- * replaced my_atoi by simple_strtoul
- *
- * Revision 1.1  1996/01/09 04:13:18  fritz
- * Initial revision
  *
  */
 #undef ISDN_TTY_STAT_DEBUG
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_tty.h linux/drivers/isdn/isdn_tty.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_tty.h	Wed May  3 17:16:40 2000
+++ linux/drivers/isdn/isdn_tty.h	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.h,v 1.19 2000/02/16 14:59:33 paul Exp $
+/* $Id: isdn_tty.h,v 1.22 2000/06/21 09:54:29 keil Exp $
 
  * header for Linux ISDN subsystem, tty related functions (linklevel).
  *
@@ -18,89 +18,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_tty.h,v $
- * Revision 1.19  2000/02/16 14:59:33  paul
- * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers;
- * used defines for result codes;
- * fixed RING ... RUNG problem (no empty lines in between).
- *
- * Revision 1.18  2000/01/20 19:55:33  keil
- * Add FAX Class 1 support
- *
- * Revision 1.17  1999/09/21 19:00:35  armin
- * Extended FCON message with added CPN
- * can now be activated with Bit 1 of Reg 23.
- *
- * Revision 1.16  1999/08/22 20:26:10  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.15  1999/07/31 12:59:48  armin
- * Added tty fax capabilities.
- *
- * Revision 1.14  1999/07/11 17:14:15  armin
- * Added new layer 2 and 3 protocols for Fax and DSP functions.
- * Moved "Add CPN to RING message" to new register S23,
- * "Display message" is now correct on register S13 bit 7.
- * New audio command AT+VDD implemented (deactivate DTMF decoder and
- * activate possible existing hardware/DSP decoder).
- * Moved some tty defines to .h file.
- * Made whitespace possible in AT command line.
- * Some AT-emulator output bugfixes.
- * First Fax G3 implementations.
- *
- * Revision 1.13  1999/04/12 12:33:46  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.12  1999/03/02 12:04:51  armin
- * -added ISDN_STAT_ADDCH to increase supported channels after
- *  register_isdn().
- * -ttyI now goes on-hook on ATZ when B-Ch is connected.
- * -added timer-function for register S7 (Wait for Carrier).
- * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
- * -on L2_MODEM a string will be appended to the CONNECT-Message,
- *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
- * -variable "dialing" used for ATA also, for interrupting call
- *  establishment and register S7.
- *
- * Revision 1.11  1998/03/19 13:18:27  keil
- * Start of a CAPI like interface for supplementary Service
- * first service: SUSPEND
- *
- * Revision 1.10  1997/03/02 14:29:26  fritz
- * More ttyI related cleanup.
- *
- * Revision 1.9  1997/02/28 02:32:49  fritz
- * Cleanup: Moved some tty related stuff from isdn_common.c
- *          to isdn_tty.c
- * Bugfix:  Bisync protocol did not behave like documented.
- *
- * Revision 1.8  1997/02/10 20:12:50  fritz
- * Changed interface for reporting incoming calls.
- *
- * Revision 1.7  1997/02/03 23:06:10  fritz
- * Reformatted according CodingStyle
- *
- * Revision 1.6  1997/01/14 01:35:19  fritz
- * Changed prototype of isdn_tty_modem_hup.
- *
- * Revision 1.5  1996/05/17 03:52:31  fritz
- * Changed DLE handling for audio receive.
- *
- * Revision 1.4  1996/05/11 21:52:34  fritz
- * Changed queue management to use sk_buffs.
- *
- * Revision 1.3  1996/05/07 09:16:34  fritz
- * Changed isdn_try_read parameter.
- *
- * Revision 1.2  1996/04/30 21:05:27  fritz
- * Test commit
- *
- * Revision 1.1  1996/01/10 21:39:22  fritz
- * Initial revision
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_ttyfax.c linux/drivers/isdn/isdn_ttyfax.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_ttyfax.c	Wed May  3 17:16:40 2000
+++ linux/drivers/isdn/isdn_ttyfax.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,5 @@
-/* $Id: isdn_ttyfax.c,v 1.6 2000/01/26 00:41:13 keil Exp $
+/* $Id: isdn_ttyfax.c,v 1.7 2000/05/11 22:29:21 kai Exp $
+
  * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
  *
  * Copyright 1999    by Armin Schindler (mac@melware.de)
@@ -19,30 +20,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Log: isdn_ttyfax.c,v $
- * Revision 1.6  2000/01/26 00:41:13  keil
- * add "00" as dummy msn in isdn_get_free_channel call
- *
- * Revision 1.5  2000/01/20 19:55:33  keil
- * Add FAX Class 1 support
- *
- * Revision 1.4  1999/09/21 19:00:35  armin
- * Extended FCON message with added CPN
- * can now be activated with Bit 1 of Reg 23.
- *
- * Revision 1.3  1999/08/22 20:26:12  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.2  1999/08/05 10:36:10  armin
- * Bugfix: kernel oops on getting revision.
- *
- * Revision 1.1  1999/07/31 12:59:50  armin
- * Added tty fax capabilities.
- *
- *
  */
 
 #undef ISDN_TTY_FAX_STAT_DEBUG
@@ -56,7 +33,7 @@
 #include "isdn_ttyfax.h"
 
 
-static char *isdn_tty_fax_revision = "$Revision: 1.6 $";
+static char *isdn_tty_fax_revision = "$Revision: 1.7 $";
 
 #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_ttyfax.h linux/drivers/isdn/isdn_ttyfax.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_ttyfax.h	Wed Aug 25 17:29:48 1999
+++ linux/drivers/isdn/isdn_ttyfax.h	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,5 @@
-/* $Id: isdn_ttyfax.h,v 1.1 1999/07/31 12:59:51 armin Exp $
+/* $Id: isdn_ttyfax.h,v 1.2 2000/05/11 22:29:21 kai Exp $
+
  * header for Linux ISDN subsystem, tty_fax related functions (linklevel).
  *
  * Copyright 1999   by Armin Schindler (mac@melware.de)
@@ -18,11 +19,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_ttyfax.h,v $
- * Revision 1.1  1999/07/31 12:59:51  armin
- * Added tty fax capabilities.
- *
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_v110.c linux/drivers/isdn/isdn_v110.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_v110.c	Wed May  3 17:16:40 2000
+++ linux/drivers/isdn/isdn_v110.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_v110.c,v 1.4 2000/03/16 16:34:12 kai Exp $
+/* $Id: isdn_v110.c,v 1.5 2000/05/11 22:29:21 kai Exp $
 
  * Linux ISDN subsystem, V.110 related functions (linklevel).
  *
@@ -18,22 +18,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Log: isdn_v110.c,v $
- * Revision 1.4  2000/03/16 16:34:12  kai
- * some translation work
- *
- * there shouldn't be any German comments lurking around anymore ;-)
- *
- * Revision 1.3  1999/10/30 09:49:28  keil
- * Reinit of v110 structs
- *
- * Revision 1.2  1998/02/22 19:44:25  fritz
- * Bugfixes and improvements regarding V.110, V.110 now running.
- *
- * Revision 1.1  1998/02/20 17:32:09  fritz
- * First checkin (not yet completely functionable).
- *
  */
+
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
@@ -44,7 +30,7 @@
 
 #undef ISDN_V110_DEBUG
 
-char *isdn_v110_revision = "$Revision: 1.4 $";
+char *isdn_v110_revision = "$Revision: 1.5 $";
 
 #define V110_38400 255
 #define V110_19200  15
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_v110.h linux/drivers/isdn/isdn_v110.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_v110.h	Wed May  3 17:16:40 2000
+++ linux/drivers/isdn/isdn_v110.h	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_v110.h,v 1.3 2000/03/16 16:34:12 kai Exp $
+/* $Id: isdn_v110.h,v 1.4 2000/05/11 22:29:21 kai Exp $
 
  * Linux ISDN subsystem, V.110 related functions (linklevel).
  *
@@ -17,18 +17,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: isdn_v110.h,v $
- * Revision 1.3  2000/03/16 16:34:12  kai
- * some translation work
- *
- * there shouldn't be any German comments lurking around anymore ;-)
- *
- * Revision 1.2  1999/10/30 09:49:28  keil
- * Reinit of v110 structs
- *
- * Revision 1.1  1998/02/20 17:32:11  fritz
- * First checkin (not yet completely functionable).
  *
  */
 #ifndef _isdn_v110_h_
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_x25iface.c linux/drivers/isdn/isdn_x25iface.c
--- linux-2.2.18-pre9/drivers/isdn/isdn_x25iface.c	Tue Oct 26 17:53:40 1999
+++ linux/drivers/isdn/isdn_x25iface.c	Mon Dec  3 20:27:06 2001
@@ -1,4 +1,23 @@
-/* $Id: isdn_x25iface.c,v 1.7 1999/08/22 20:26:13 calle Exp $
+/* $Id: isdn_x25iface.c,v 1.9 2000/05/16 20:52:10 keil Exp $
+
+ *
+ * Linux ISDN subsystem, X.25 related functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
  * stuff needed to support the Linux X.25 PLP code on top of devices that
  * can provide a lab_b service using the concap_proto mechanism.
  * This module supports a network interface wich provides lapb_sematics
@@ -8,33 +27,6 @@
  *
  * Only protocol specific stuff goes here. Device specific stuff
  * goes to another -- device related -- concap_proto support source file.
- *
- * $Log: isdn_x25iface.c,v $
- * Revision 1.7  1999/08/22 20:26:13  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.6  1999/01/27 22:53:19  he
- * minor updates (spellings, jiffies wrap around in isdn_tty)
- *
- * Revision 1.5  1998/10/30 17:55:39  he
- * dialmode for x25iface and multulink ppp
- *
- * Revision 1.4  1998/06/17 19:51:00  he
- * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
- * brute force fix to avoid Ugh's in isdn_tty_write()
- * cleaned up some dead code
- *
- * Revision 1.3  1998/02/20 17:25:20  fritz
- * Changes for recent kernels.
- *
- * Revision 1.2  1998/01/31 22:49:22  keil
- * correct comments
- *
- * Revision 1.1  1998/01/31 22:27:58  keil
- * New files from Henner Eisen for X.25 support
  *
  */
 
diff -urN linux-2.2.18-pre9/drivers/isdn/isdn_x25iface.h linux/drivers/isdn/isdn_x25iface.h
--- linux-2.2.18-pre9/drivers/isdn/isdn_x25iface.h	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/isdn_x25iface.h	Mon Dec  3 20:27:06 2001
@@ -1,5 +1,23 @@
-/* $Id: isdn_x25iface.h,v 1.2 1998/01/31 22:49:23 keil Exp $
+/* $Id: isdn_x25iface.h,v 1.3 2000/05/11 22:29:21 kai Exp $
+
+ * header for Linux ISDN subsystem, x.25 related functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
  */
+
 #ifndef _LINUX_ISDN_X25IFACE_H
 #define _LINUX_ISDN_X25IFACE_H
 
diff -urN linux-2.2.18-pre9/drivers/net/Space.c linux/drivers/net/Space.c
--- linux-2.2.18-pre9/drivers/net/Space.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/net/Space.c	Mon Dec  3 20:27:06 2001
@@ -31,6 +31,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/netlink.h>
+#include <net/divert.h>
 
 #define	NEXT_DEV	NULL
 
@@ -172,13 +173,35 @@
 	struct devprobe *p = plist;
 	unsigned long base_addr = dev->base_addr;
 
+#ifdef CONFIG_NET_DIVERT
+	int	ret;
+#endif
+
 	while (p->probe != NULL) {
 		if (base_addr && p->probe(dev) == 0)	/* probe given addr */
+#ifdef CONFIG_NET_DIVERT
+		{
+			ret=alloc_divert_blk(dev);
+			if (ret)
+				return ret;
+			return 0;
+		}
+#else
 			return 0;
+#endif
 		else if (p->status == 0) {		/* has autoprobe failed yet? */
 			p->status = p->probe(dev);	/* no, try autoprobe */
 			if (p->status == 0)
+#ifdef CONFIG_NET_DIVERT
+			{
+				ret=alloc_divert_blk(dev);
+				if (ret)
+					return ret;
+				return 0;
+			}
+#else
 				return 0;
+#endif
 		}
 		p++;
 	}
diff -urN linux-2.2.18-pre9/drivers/net/rcif.h linux/drivers/net/rcif.h
--- linux-2.2.18-pre9/drivers/net/rcif.h	Thu Jan 14 22:58:47 1999
+++ linux/drivers/net/rcif.h	Mon Dec  3 20:27:06 2001
@@ -43,10 +43,10 @@
 /* define a single TCB & buffer */
 typedef struct                  /* a single buffer */
 {
-     U32 context;               /* context */
-     U32 scount;                /* segment count */
-     U32 size;                  /* segment size */
-     U32 addr;                  /* segment physical address */
+     u32 context;               /* context */
+     u32 scount;                /* segment count */
+     u32 size;                  /* segment size */
+     u32 addr;                  /* segment physical address */
 }
 __attribute__((packed))
 singleB, *psingleB ;
@@ -65,7 +65,7 @@
      **  |  <physical address>   |  physical address of buffer  /
      **  +-----------------------+                            _/
      */
-     U32 bcount;                /* buffer count */
+     u32 bcount;                /* buffer count */
      singleB b;                 /* buffer */
 
 }
@@ -82,7 +82,7 @@
       5) Command identifier entry
 
    For Example ("GETSPEED"):
-      1) struct  RCgetspeed_tag { U32 LinkSpeedCode; } RCgetspeed;
+      1) struct  RCgetspeed_tag { u32 LinkSpeedCode; } RCgetspeed;
       2) struct  RCgetspeed_tag *getspeed;
       3) #define RCUS_GETSPEED  data.RCgetspeed;
       4) #define RCUD_GETSPEED  _RC_user_data.getspeed
@@ -121,66 +121,66 @@
      
         /* GETSPEED structure */
         struct  RCgetspeed_tag {
-            U32 LinkSpeedCode;
+            u32 LinkSpeedCode;
         } RCgetspeed;                   /* <---- RCgetspeed */
   
         /* SETSPEED structure */
         struct RCsetspeed_tag {
-            U16 LinkSpeedCode;
+            u16 LinkSpeedCode;
         } RCsetspeed;                   /* <---- RCsetspeed */
 
         /* GETPROM structure */
         struct  RCgetprom_tag {
-            U32 PromMode;
+            u32 PromMode;
         } RCgetprom;                   /* <---- RCgetprom */
   
         /* SETPROM structure */
         struct RCsetprom_tag {
-            U16 PromMode;
+            u16 PromMode;
         } RCsetprom;                   /* <---- RCsetprom */
 
         /* GETBROADCAST structure */
         struct  RCgetbroadcast_tag {
-            U32 BroadcastMode;
+            u32 BroadcastMode;
         } RCgetbroadcast;                   /* <---- RCgetbroadcast */
   
         /* SETBROADCAST structure */
         struct RCsetbroadcast_tag {
-            U16 BroadcastMode;
+            u16 BroadcastMode;
         } RCsetbroadcast;                   /* <---- RCsetbroadcast */
 
         /* GETFIRMWAREVER structure */
         #define FirmStringLen 80
         struct RCgetfwver_tag {
-            U8 FirmString[FirmStringLen];
+            u8 FirmString[FirmStringLen];
         } RCgetfwver;                   /* <---- RCgetfwver */
   
         /* GETIPANDMASK structure */
         struct RCgetipnmask_tag {
-            U32 IpAddr;
-            U32 NetMask;
+            u32 IpAddr;
+            u32 NetMask;
         } RCgetipandmask;               /* <---- RCgetipandmask */
 
         /* SETIPANDMASK structure */
         struct RCsetipnmask_tag {
-            U32 IpAddr;
-            U32 NetMask;
+            u32 IpAddr;
+            u32 NetMask;
         } RCsetipandmask;               /* <---- RCsetipandmask */
 
         /* GETMAC structure */
         #define MAC_SIZE 10
         struct RCgetmac_tag {
-            U8 mac[MAC_SIZE];
+            u8 mac[MAC_SIZE];
         } RCgetmac;                     /* <---- RCgetmac */
 
         /* SETMAC structure */
         struct RCsetmac_tag {
-            U8 mac[MAC_SIZE];
+            u8 mac[MAC_SIZE];
         } RCsetmac;                     /* <---- RCsetmac */
 
         /* GETLINKSTATUS structure */
         struct RCgetlnkstatus_tag {
-            U32 ReturnStatus;
+            u32 ReturnStatus;
         } RCgetlnkstatus;               /* <---- RCgetlnkstatus */
 
         /* GETLINKSTATISTICS structure */
diff -urN linux-2.2.18-pre9/drivers/net/rclanmtl.c linux/drivers/net/rclanmtl.c
--- linux-2.2.18-pre9/drivers/net/rclanmtl.c	Mon Apr 12 16:18:27 1999
+++ linux/drivers/net/rclanmtl.c	Mon Dec  3 20:27:06 2001
@@ -231,13 +231,13 @@
 /* I2O message header */
 typedef struct _I2O_MESSAGE_FRAME 
 {
-    U8                          VersionOffset;
-    U8                          MsgFlags;
-    U16                         MessageSize;
+    u8                          VersionOffset;
+    u8                          MsgFlags;
+    u16                         MessageSize;
     BF                          TargetAddress:I2O_TID_SZ;
     BF                          InitiatorAddress:I2O_TID_SZ;
     BF                          Function:I2O_FUNCTION_SZ;
-    U32                         InitiatorContext;
+    u32                         InitiatorContext;
     /* SGL[] */ 
 }
 I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME;
@@ -289,15 +289,15 @@
 typedef struct
 {
     PATU             p_atu;                /* ptr to  ATU register block */
-    PU8              pPci45LinBaseAddr;
-    PU8              pLinOutMsgBlock;
-    U32              outMsgBlockPhyAddr; 
+    u8 *              pPci45LinBaseAddr;
+    u8 *              pLinOutMsgBlock;
+    u32              outMsgBlockPhyAddr; 
     PFNTXCALLBACK    pTransCallbackFunc;
     PFNRXCALLBACK    pRecvCallbackFunc;
     PFNCALLBACK      pRebootCallbackFunc;
     PFNCALLBACK      pCallbackFunc;
-    U16              IOPState;
-    U16              InboundMFrameSize;
+    u16              IOPState;
+    u16              InboundMFrameSize;
 }
 PAB, *PPAB;
 
@@ -357,8 +357,8 @@
 
 
 /* local function prototypes */
-static void ProcessOutboundI2OMsg(PPAB pPab, U32 phyMsgAddr);
-static int FillI2OMsgSGLFromTCB(PU32 pMsg, PRCTCB pXmitCntrlBlock);
+static void ProcessOutboundI2OMsg(PPAB pPab, u32 phyMsgAddr);
+static int FillI2OMsgSGLFromTCB(u32 * pMsg, PRCTCB pXmitCntrlBlock);
 static int GetI2OStatus(PPAB pPab);
 static int SendI2OOutboundQInitMsg(PPAB pPab);
 static int SendEnableSysMsg(PPAB pPab);
@@ -386,8 +386,8 @@
 ** =========================================================================
 */
 RC_RETURN
-RCInitI2OMsgLayer(U16 AdapterID, U32 pciBaseAddr, 
-                  PU8 p_msgbuf,  PU8 p_phymsgbuf,
+RCInitI2OMsgLayer(u16 AdapterID, u32 pciBaseAddr, 
+                  u8 * p_msgbuf,  u8 * p_phymsgbuf,
                   PFNTXCALLBACK  TransmitCallbackFunction,
                   PFNRXCALLBACK  ReceiveCallbackFunction,
                   PFNCALLBACK    RebootCallbackFunction)
@@ -406,7 +406,7 @@
     if (PCIAdapterBlock[AdapterID] != NULL)
     {
         printk("PCIAdapterBlock[%d]!=NULL\n", AdapterID);
-//        RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
+//        RCResetLANCard(AdapterID, 0, (u32 *)NULL, (PFNCALLBACK)NULL);
         PCIAdapterBlock[AdapterID] = NULL;
     }
 
@@ -417,11 +417,11 @@
     pPab = (PPAB)p_msgbuf;
     
     pPab->p_atu = (PATU)pciBaseAddr;
-    pPab->pPci45LinBaseAddr =  (PU8)pciBaseAddr;
+    pPab->pPci45LinBaseAddr =  (u8 *)pciBaseAddr;
     
     /* Set outbound message frame addr - skip over Adapter Block */
-    pPab->outMsgBlockPhyAddr = (U32)(p_phymsgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
-    pPab->pLinOutMsgBlock    = (PU8)(p_msgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
+    pPab->outMsgBlockPhyAddr = (u32)(p_phymsgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
+    pPab->pLinOutMsgBlock    = (u8 *)(p_msgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
 
     /* store callback function addresses */
     pPab->pTransCallbackFunc = TransmitCallbackFunction;
@@ -440,7 +440,7 @@
     if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL)
     {
         printk("pPab->IOPState == op: resetting adapter\n");
-        RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
+        RCResetLANCard(AdapterID, 0, (u32 *)NULL, (PFNCALLBACK)NULL);
     }
         
     result = SendI2OOutboundQInitMsg(pPab);
@@ -469,7 +469,7 @@
 */
 #define i960_OUT_POST_Q_INT_BIT        0x0008 /* bit set masks interrupts */
 
-RC_RETURN RCDisableI2OInterrupts(U16 AdapterID)
+RC_RETURN RCDisableI2OInterrupts(u16 AdapterID)
 {
     PPAB pPab;
 
@@ -484,7 +484,7 @@
     return RC_RTN_NO_ERROR;
 }
 
-RC_RETURN RCEnableI2OInterrupts(U16 AdapterID)
+RC_RETURN RCEnableI2OInterrupts(u16 AdapterID)
 {
     PPAB pPab;
 
@@ -506,10 +506,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCI2OSendPacket(U16 AdapterID, U32 InitiatorContext, PRCTCB pTransCtrlBlock)
+RCI2OSendPacket(u16 AdapterID, u32 InitiatorContext, PRCTCB pTransCtrlBlock)
 {
-    U32 msgOffset;
-    PU32 pMsg;
+    u32 msgOffset;
+    u32 * pMsg;
     int size;
     PPAB pPab;
 
@@ -536,7 +536,7 @@
     }
         
     /* calc virual address of msg - virual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
     size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
 
@@ -572,10 +572,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransCtrlBlock)
+RCPostRecvBuffers(u16 AdapterID, PRCTCB pTransCtrlBlock)
 {
-    U32 msgOffset;
-    PU32 pMsg;
+    u32 msgOffset;
+    u32 * pMsg;
     int size;
     PPAB pPab;
 
@@ -603,7 +603,7 @@
    
     }
     /* calc virual address of msg - virual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
     size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
 
@@ -623,7 +623,7 @@
         pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
         pMsg[1] = I2O_LAN_RECEIVE_POST << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
         pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
-        pMsg[3] = *(PU32)pTransCtrlBlock; /* number of packet buffers */
+        pMsg[3] = *(u32 *)pTransCtrlBlock; /* number of packet buffers */
         /* post to Post Q */   
         pPab->p_atu->InQueue = msgOffset;
         return RC_RTN_NO_ERROR;
@@ -639,12 +639,12 @@
 ** =========================================================================
 */
 void 
-RCProcI2OMsgQ(U16 AdapterID)
+RCProcI2OMsgQ(u16 AdapterID)
 {
-    U32 phyAddrMsg;
-    PU8 p8Msg;
-    PU32 p32;
-    U16 count;
+    u32 phyAddrMsg;
+    u8 * p8Msg;
+    u32 * p32;
+    u16 count;
     PPAB pPab;
     unsigned char debug_msg[20];
     
@@ -658,7 +658,7 @@
     while (phyAddrMsg != 0xFFFFFFFF)
     {
         p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
-        p32 = (PU32)p8Msg;
+        p32 = (u32 *)p8Msg;
         
         //printk(" msg: 0x%x  0x%x \n", p8Msg[7], p32[5]);
 
@@ -667,7 +667,7 @@
         */
         if (I2O_LAN_PACKET_SEND == p8Msg[7])  /* function code byte */
         {
-            count = *(PU16)(p8Msg+2);
+            count = *(u16 *)(p8Msg+2);
             count -= p8Msg[0] >> 4;
             /* status, count, context[], adapter */
             (*pPab->pTransCallbackFunc)(p8Msg[19], count, p32+5, AdapterID);
@@ -773,14 +773,14 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetLinkStatistics(U16 AdapterID, 
+RCGetLinkStatistics(u16 AdapterID, 
                     P_RCLINKSTATS StatsReturnAddr,
                     PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset;
-    volatile U32 timeout;
-    volatile PU32 pMsg;
-    volatile PU32 p32, pReturnAddr;
+    u32 msgOffset;
+    volatile u32 timeout;
+    volatile u32 * pMsg;
+    volatile u32 * p32, *pReturnAddr;
     P_NICSTAT pStats;
     int i;
     PPAB pPab;
@@ -803,7 +803,7 @@
     }
 
     /* calc virual address of msg - virual already mapped to physical */
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
 /*dprintf("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
 /*dprintf("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
@@ -815,7 +815,7 @@
     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_NIC_STATS;
     pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
 
-    p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
 
     pStats = (P_NICSTAT)p32;
     pStats->dump_status = 0xFFFFFFFF;
@@ -844,7 +844,7 @@
         }
     }
     
-    pReturnAddr = (PU32)StatsReturnAddr;
+    pReturnAddr = (u32 *)StatsReturnAddr;
     
     /* copy Nic stats to user's structure */
     for (i = 0; i < (int) sizeof(RCLINKSTATS) / 4; i++)
@@ -860,12 +860,12 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetLinkStatus(U16 AdapterID, PU32 ReturnAddr, PFNWAITCALLBACK WaitCallback)
+RCGetLinkStatus(u16 AdapterID, u32 * ReturnAddr, PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset;
-    volatile U32 timeout;
-    volatile PU32 pMsg;
-    volatile PU32 p32;
+    u32 msgOffset;
+    volatile u32 timeout;
+    volatile u32 * pMsg;
+    volatile u32 * p32;
     PPAB pPab;
 
 /*kprintf("Get82558LinkStatus() ReturnPhysAddr:0x%08.8ulx\n", ReturnAddr);*/
@@ -886,7 +886,7 @@
     }
 
     /* calc virual address of msg - virual already mapped to physical */
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 /*dprintf("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
 /*dprintf("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
 
@@ -897,7 +897,7 @@
     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS;
     pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
 
-    p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
     *p32 = 0xFFFFFFFF;
     
     /* post to Inbound Post Q */
@@ -906,7 +906,7 @@
     timeout = 100000;
     while (1)
     {
-        U32 i;
+        u32 i;
 
         if (WaitCallback)
             (*WaitCallback)();
@@ -941,12 +941,12 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback)
+RCGetMAC(u16 AdapterID, u8 * mac, PFNWAITCALLBACK WaitCallback)
 {
     unsigned i, timeout;
-    U32      off;
-    PU32     p;
-    U32      temp[2];
+    u32      off;
+    u32 *     p;
+    u32      temp[2];
     PPAB     pPab;
     PATU     p_atu;
     
@@ -965,7 +965,7 @@
     if (0xFFFFFFFF == off)
         return RC_RTN_FREE_Q_EMPTY;
 
-    p = (PU32)(pPab->pPci45LinBaseAddr + off);
+    p = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
 #ifdef RCDEBUG
     printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", 
@@ -1025,10 +1025,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetMAC(U16 AdapterID, PU8 mac)
+RCSetMAC(u16 AdapterID, u8 * mac)
 {
-    U32  off;
-    PU32 pMsg;
+    u32  off;
+    u32 * pMsg;
     PPAB pPab;
 
 
@@ -1042,7 +1042,7 @@
     if (0xFFFFFFFF == off)
         return RC_RTN_FREE_Q_EMPTY;
     
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
     /* setup private message */
     pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1074,10 +1074,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode)
+RCSetLinkSpeed(u16 AdapterID, u16 LinkSpeedCode)
 {
-    U32  off;
-    PU32 pMsg;
+    u32  off;
+    u32 * pMsg;
     PPAB pPab;
 
     
@@ -1091,7 +1091,7 @@
     if (0xFFFFFFFF == off)
         return RC_RTN_FREE_Q_EMPTY;
     
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
     /* setup private message */
     pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1116,10 +1116,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetPromiscuousMode(U16 AdapterID, U16 Mode)
+RCSetPromiscuousMode(u16 AdapterID, u16 Mode)
 {
-    U32  off;
-    PU32 pMsg;
+    u32  off;
+    u32 * pMsg;
     PPAB pPab;
     
     pPab =PCIAdapterBlock[AdapterID];
@@ -1132,7 +1132,7 @@
     if (0xFFFFFFFF == off)
         return RC_RTN_FREE_Q_EMPTY;
     
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
     /* setup private message */
     pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1159,11 +1159,11 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+RCGetPromiscuousMode(u16 AdapterID, u32 * pMode, PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
+    u32 msgOffset, timeout;
+    u32 * pMsg;
+    volatile u32 * p32;
     PPAB pPab;
 
     pPab =PCIAdapterBlock[AdapterID];
@@ -1179,10 +1179,10 @@
     }
 
     /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
     /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
     p32[0] = 0xff;
 
     /* setup private message */
@@ -1222,7 +1222,7 @@
     }
 
     /* get mode */
-    *pMode = (U8)((volatile PU8)p32)[0] & 0x0f;
+    *pMode = (u8)((volatile u8 *)p32)[0] & 0x0f;
 
     return RC_RTN_NO_ERROR;
 }
@@ -1237,10 +1237,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetBroadcastMode(U16 AdapterID, U16 Mode)
+RCSetBroadcastMode(u16 AdapterID, u16 Mode)
 {
-    U32  off;
-    PU32 pMsg;
+    u32  off;
+    u32 * pMsg;
     PPAB pPab;
     
     pPab =PCIAdapterBlock[AdapterID];
@@ -1253,7 +1253,7 @@
     if (0xFFFFFFFF == off)
         return RC_RTN_FREE_Q_EMPTY;
     
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
     /* setup private message */
     pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1280,11 +1280,11 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+RCGetBroadcastMode(u16 AdapterID, u32 * pMode, PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
+    u32 msgOffset, timeout;
+    u32 * pMsg;
+    volatile u32 * p32;
     PPAB pPab;
 
     pPab =PCIAdapterBlock[AdapterID];
@@ -1300,10 +1300,10 @@
     }
 
     /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
     /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
     p32[0] = 0xff;
 
     /* setup private message */
@@ -1343,7 +1343,7 @@
     }
 
     /* get mode */
-    *pMode = (U8)((volatile PU8)p32)[0] & 0x0f;
+    *pMode = (u8)((volatile u8 *)p32)[0] & 0x0f;
 
     return RC_RTN_NO_ERROR;
 }
@@ -1363,12 +1363,12 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback)
+RCGetLinkSpeed(u16 AdapterID, u32 * pLinkSpeedCode, PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
-    U8 IOPLinkSpeed;
+    u32 msgOffset, timeout;
+    u32 * pMsg;
+    volatile u32 * p32;
+    u8 IOPLinkSpeed;
     PPAB pPab;
 
     pPab =PCIAdapterBlock[AdapterID];
@@ -1384,10 +1384,10 @@
     }
 
     /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
     /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
     p32[0] = 0xff;
 
     /* setup private message */
@@ -1427,7 +1427,7 @@
     }
 
     /* get Link speed */
-    IOPLinkSpeed = (U8)((volatile PU8)p32)[0] & 0x0f;
+    IOPLinkSpeed = (u8)((volatile u8 *)p32)[0] & 0x0f;
 
     *pLinkSpeedCode= IOPLinkSpeed;
 
@@ -1436,7 +1436,7 @@
 
 /*
 ** =========================================================================
-** RCReportDriverCapability(U16 AdapterID, U32 capability)
+** RCReportDriverCapability(u16 AdapterID, u32 capability)
 **
 ** Currently defined bits:
 ** WARM_REBOOT_CAPABLE   0x01
@@ -1444,10 +1444,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCReportDriverCapability(U16 AdapterID, U32 capability)
+RCReportDriverCapability(u16 AdapterID, u32 capability)
 {
-    U32  off;
-    PU32 pMsg;
+    u32  off;
+    u32 * pMsg;
     PPAB pPab;
 
     pPab =PCIAdapterBlock[AdapterID];
@@ -1460,7 +1460,7 @@
     if (0xFFFFFFFF == off)
         return RC_RTN_FREE_Q_EMPTY;
     
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
     /* setup private message */
     pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1484,11 +1484,11 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback)
+RCGetFirmwareVer(u16 AdapterID, u8 * pFirmString, PFNWAITCALLBACK WaitCallback)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
+    u32 msgOffset, timeout;
+    u32 * pMsg;
+    volatile u32 * p32;
     PPAB pPab;
 
     pPab =PCIAdapterBlock[AdapterID];
@@ -1503,10 +1503,10 @@
     }
 
     /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
     /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
     p32[0] = 0xff;
 
     /* setup private message */
@@ -1547,7 +1547,7 @@
         }
     }
 
-    strcpy(pFirmString, (PU8)p32);
+    strcpy(pFirmString, (u8 *)p32);
     return RC_RTN_NO_ERROR;
 }
 
@@ -1565,10 +1565,10 @@
 ** =========================================================================
 */
 RC_RETURN 
-RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+RCResetLANCard(u16 AdapterID, u16 ResourceFlags, u32 * ReturnAddr, PFNCALLBACK CallbackFunction)
 {
     unsigned long off;
-    unsigned long *pMsg;
+    u32 *pMsg;
     PPAB pPab;
     int i;
     long timeout = 0;
@@ -1586,7 +1586,7 @@
     
     pPab->pCallbackFunc = CallbackFunction;
 
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
     /* setup message */
     pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1611,8 +1611,8 @@
                 break;
             }
         }
-        if (ReturnAddr != (PU32)NULL)
-            *ReturnAddr = (U32)pPab->pCallbackFunc;
+        if (ReturnAddr != (u32 *)NULL)
+            *ReturnAddr = (u32)pPab->pCallbackFunc;
     }
 
     return RC_RTN_NO_ERROR ;
@@ -1626,12 +1626,12 @@
 ** =========================================================================
 */
 RC_RETURN 
-RCResetIOP(U16 AdapterID)
+RCResetIOP(u16 AdapterID)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
+    u32 msgOffset, timeout;
+    u32 *pMsg;
     PPAB pPab;
-    volatile PU32 p32;
+    volatile u32 * p32;
     
     pPab = PCIAdapterBlock[AdapterID];
     msgOffset = pPab->p_atu->InQueue;
@@ -1642,7 +1642,7 @@
     }
 
     /* calc virtual address of msg - virtual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
     pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
     pMsg[1] = I2O_EXEC_IOP_RESET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
@@ -1656,7 +1656,7 @@
     pMsg[8] = 1;  /*  return 1 byte */
 
     /* virual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
     p32[0] = 0;
     p32[1] = 0;
 
@@ -1699,10 +1699,10 @@
 ** =========================================================================
 */
 RC_RETURN 
-RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+RCShutdownLANCard(u16 AdapterID, u16 ResourceFlags, u32 * ReturnAddr, PFNCALLBACK CallbackFunction)
 {
-    volatile PU32 pMsg;
-    U32 off;
+    volatile u32 * pMsg;
+    u32 off;
     PPAB pPab;
     int i;
     long timeout = 0;
@@ -1719,7 +1719,7 @@
 
     pPab->pCallbackFunc = CallbackFunction;
     
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
     /* setup message */
     pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1745,8 +1745,8 @@
                 break;
             }
         }
-        if (ReturnAddr != (PU32)NULL)
-            *ReturnAddr = (U32)pPab->pCallbackFunc;
+        if (ReturnAddr != (u32 *)NULL)
+            *ReturnAddr = (u32)pPab->pCallbackFunc;
     }
     return RC_RTN_NO_ERROR ;
 }
@@ -1765,10 +1765,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask)
+RCSetRavlinIPandMask(u16 AdapterID, u32 ipAddr, u32 netMask)
 {
-    volatile PU32 pMsg;
-    U32 off;
+    volatile u32 * pMsg;
+    u32 off;
     PPAB pPab;
 
     pPab = PCIAdapterBlock[AdapterID];
@@ -1781,7 +1781,7 @@
     if (0xFFFFFFFF == off)
         return RC_RTN_FREE_Q_EMPTY;
     
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
     /* setup private message */
     pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1807,12 +1807,12 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask, 
+RCGetRavlinIPandMask(u16 AdapterID, u32 * pIpAddr, u32 * pNetMask, 
                      PFNWAITCALLBACK WaitCallback)
 {
     unsigned i, timeout;
-    U32      off;
-    PU32     pMsg, p32;
+    u32      off;
+    u32 *     pMsg, *p32;
     PPAB     pPab;
     PATU     p_atu;
     
@@ -1831,10 +1831,10 @@
     if (0xFFFFFFFF == off)
         return RC_RTN_FREE_Q_EMPTY;
 
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
     *p32 = 0xFFFFFFFF;
 
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + off);
 
 #ifdef DEBUG
     kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
@@ -1907,9 +1907,9 @@
 static int 
 SendI2OOutboundQInitMsg(PPAB pPab)
 {
-    U32 msgOffset, timeout, phyOutQFrames, i;
-    volatile PU32 pMsg;
-    volatile PU32 p32;
+    u32 msgOffset, timeout, phyOutQFrames, i;
+    volatile u32 * pMsg;
+    volatile u32 * p32;
     
     
     
@@ -1926,7 +1926,7 @@
     
     
     /* calc virual address of msg - virual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
 #ifdef DEBUG
     kprintf("SendI2OOutboundQInitMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
@@ -1943,7 +1943,7 @@
     pMsg[7] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
 
     /* virual pointer to return buffer - clear first two dwords */
-    p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
     p32[0] = 0;
     
     /* post to Inbound Post Q */   
@@ -2009,9 +2009,9 @@
 static int 
 GetI2OStatus(PPAB pPab)
 {
-    U32 msgOffset, timeout;
-    PU32 pMsg;
-    volatile PU32 p32;
+    u32 msgOffset, timeout;
+    u32 * pMsg;
+    volatile u32 * p32;
     
     
     msgOffset = pPab->p_atu->InQueue; 
@@ -2027,7 +2027,7 @@
     }
 
     /* calc virual address of msg - virual already mapped to physical */    
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
     pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
     pMsg[1] = I2O_EXEC_STATUS_GET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
@@ -2041,7 +2041,7 @@
     pMsg[8] = 88;  /*  return 88 bytes */
 
     /* virual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile u32 *)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
     p32[0] = 0;
     p32[1] = 0;
 
@@ -2087,8 +2087,8 @@
     kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
 #endif /* DEBUG */
     /* get IOP state */
-    pPab->IOPState = ((volatile PU8)p32)[10];
-    pPab->InboundMFrameSize  = ((volatile PU16)p32)[6];
+    pPab->IOPState = ((volatile u8 *)p32)[10];
+    pPab->InboundMFrameSize  = ((volatile u16 *)p32)[6];
     
 #ifdef DEBUG
     kprintf("IOP state 0x%02.2x InFrameSize = 0x%04.4x\n", 
@@ -2108,8 +2108,8 @@
 static int 
 SendEnableSysMsg(PPAB pPab)
 {
-    U32 msgOffset; // timeout;
-    volatile PU32 pMsg;
+    u32 msgOffset; // timeout;
+    volatile u32 * pMsg;
 
     msgOffset = pPab->p_atu->InQueue;
 
@@ -2122,7 +2122,7 @@
     }
 
     /* calc virual address of msg - virual already mapped to physical */
-    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+    pMsg = (u32 *)(pPab->pPci45LinBaseAddr + msgOffset);
 
 #ifdef DEBUG
     kprintf("SendEnableSysMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
@@ -2145,17 +2145,17 @@
 ** =========================================================================
 ** FillI2OMsgFromTCB()
 **
-** inputs   pMsgU32 - virual pointer (mapped to physical) of message frame
+** inputs   pMsgu32 - virual pointer (mapped to physical) of message frame
 **          pXmitCntrlBlock - pointer to caller buffer control block.
 **
 ** fills in LAN SGL after Transaction Control Word or Bucket Count.
 ** =========================================================================
 */
 static int 
-FillI2OMsgSGLFromTCB(PU32 pMsgFrame, PRCTCB pTransCtrlBlock)
+FillI2OMsgSGLFromTCB(u32 * pMsgFrame, PRCTCB pTransCtrlBlock)
 {
     unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags;
-    PU32 pTCB, pMsg;
+    u32 * pTCB, *pMsg;
 
     /* SGL element flags */   
 #define EOB        0x40000000
@@ -2163,7 +2163,7 @@
 #define SIMPLE_SGL 0x10000000
 #define BC_PRESENT 0x01000000
 
-    pTCB = (PU32)pTransCtrlBlock;
+    pTCB = (u32 *)pTransCtrlBlock;
     pMsg = pMsgFrame;
     nmbrDwords = 0;
 
@@ -2248,15 +2248,15 @@
 ** =========================================================================
 */
 static void 
-ProcessOutboundI2OMsg(PPAB pPab, U32 phyAddrMsg)
+ProcessOutboundI2OMsg(PPAB pPab, u32 phyAddrMsg)
 {
-    PU8 p8Msg;
-    PU32 p32;
-    //  U16 count;
+    u8 * p8Msg;
+    u32 * p32;
+    //  u16 count;
     
     
     p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
-    p32 = (PU32)p8Msg;
+    p32 = (u32 *)p8Msg;
     
 #ifdef DEBUG
     kprintf("VXD: ProcessOutboundI2OMsg - pPab 0x%08.8ulx, phyAdr 0x%08.8ulx, linAdr 0x%08.8ulx\n", pPab, phyAddrMsg, p8Msg);
diff -urN linux-2.2.18-pre9/drivers/net/rclanmtl.h linux/drivers/net/rclanmtl.h
--- linux-2.2.18-pre9/drivers/net/rclanmtl.h	Mon Apr 12 16:18:27 1999
+++ linux/drivers/net/rclanmtl.h	Mon Dec  3 20:27:06 2001
@@ -39,11 +39,7 @@
 
 /* Linux specific includes */
 #define kprintf printk
-#ifdef RC_LINUX_MODULE     /* linux modules need non-library version of string functions */
 #include <linux/string.h>
-#else
-#include <string.h>
-#endif
 
 /* PCI/45 Configuration space values */
 #define RC_PCI45_VENDOR_ID  0x4916
@@ -68,12 +64,6 @@
 #define WARM_REBOOT_CAPABLE      0x01
 
  /* scalar data types */
-typedef unsigned char   U8;
-typedef unsigned char*  PU8;
-typedef unsigned short  U16;
-typedef unsigned short* PU16;
-typedef unsigned long   U32;
-typedef unsigned long*  PU32;
 typedef unsigned long   BF;
 typedef int             RC_RETURN;
 
@@ -97,10 +87,10 @@
  ** The User's TransmitCallbackFunction should recover (put back in free queue)
  ** the packet buffers associated with the buffer context values.
  */
-typedef void (*PFNTXCALLBACK)(U32  Status,
-                              U16  PcktCount,
-                              PU32 BufferContext,
-                              U16  AdaterID);
+typedef void (*PFNTXCALLBACK)(u32  Status,
+                              u16  PcktCount,
+                              u32 * BufferContext,
+                              u16  AdaterID);
 
  /* 
  ** type PFNRXCALLBACK 
@@ -111,11 +101,11 @@
  ** The received callback function should process the Packet Descriptor Block
  ** pointed to by PacketDescBlock. See Packet Decription Block below.
  */
-typedef void (*PFNRXCALLBACK)(U32  Status,
-                              U8   PktCount,
-                              U32  BucketsRemain,
-                              PU32 PacketDescBlock,
-                              U16  AdapterID);
+typedef void (*PFNRXCALLBACK)(u32  Status,
+                              u8   PktCount,
+                              u32  BucketsRemain,
+                              u32 * PacketDescBlock,
+                              u16  AdapterID);
 
  /* 
  ** type PFNCALLBACK 
@@ -125,10 +115,10 @@
  ** the reset or shutdown is complete.
  ** Param1 and Param2 are invalid for LANReset and LANShutdown.
  */
-typedef void (*PFNCALLBACK)(U32  Status,
-                              U32  Param1,
-                              U32  Param2,
-                              U16  AdapterID);
+typedef void (*PFNCALLBACK)(u32  Status,
+                              u32  Param1,
+                              u32  Param2,
+                              u16  AdapterID);
 
 /*
 ** Status - Transmit and Receive callback status word 
@@ -275,12 +265,12 @@
  /* Buffer Segment Descriptor */
 typedef struct
 {
-    U32 size;
-    U32 phyAddress;
+    u32 size;
+    u32 phyAddress;
 }
  BSD, *PBSD;
  
-typedef PU32 PRCTCB;
+typedef u32 * PRCTCB;
 /*
 ** -------------------------------------------------------------------------
 ** Exported functions comprising the API to the LAN I2O message transport layer
@@ -310,8 +300,8 @@
  **          ReceiveCallbackFunction  - address of user's RX callback function
  **
  */
-RC_RETURN RCInitI2OMsgLayer(U16 AdapterID, U32 pciBaseAddr, 
-                            PU8 p_msgbuf,  PU8 p_phymsgbuf,
+RC_RETURN RCInitI2OMsgLayer(u16 AdapterID, u32 pciBaseAddr, 
+                            u8 * p_msgbuf,  u8 * p_phymsgbuf,
                             PFNTXCALLBACK TransmitCallbackFunction,
                             PFNRXCALLBACK ReceiveCallbackFunction,
                             PFNCALLBACK   RebootCallbackFunction);
@@ -326,7 +316,7 @@
  ** 0x04030201 and 0x00FFFFFF on a little endian machine.
  **
  */
-RC_RETURN RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask);
+RC_RETURN RCSetRavlinIPandMask(u16 AdapterID, u32 ipAddr, u32 netMask);
 
 
 /*
@@ -338,7 +328,7 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask, 
+RCGetRavlinIPandMask(u16 AdapterID, u32 * pIpAddr, u32 * pNetMask, 
                         PFNWAITCALLBACK WaitCallback);
 
  /* 
@@ -350,7 +340,7 @@
  ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction,
  ** if a TX or RX transaction has completed.
  */
-void RCProcI2OMsgQ(U16 AdapterID);
+void RCProcI2OMsgQ(u16 AdapterID);
 
 
  /*
@@ -361,8 +351,8 @@
  ** will prevent hardware interrupt to host even though the outbound I2O msg
  ** queue is not emtpy.
  */
-RC_RETURN RCEnableI2OInterrupts(U16 adapterID);
-RC_RETURN RCDisableI2OInterrupts(U16 AdapterID);
+RC_RETURN RCEnableI2OInterrupts(u16 adapterID);
+RC_RETURN RCDisableI2OInterrupts(u16 AdapterID);
 
 
  /* 
@@ -377,7 +367,7 @@
  ** to the RedCreek adapter are considered owned by the adapter until the
  ** context is return to user through the ReceiveCallbackFunction.
  */
-RC_RETURN RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransactionCtrlBlock);
+RC_RETURN RCPostRecvBuffers(u16 AdapterID, PRCTCB pTransactionCtrlBlock);
 #define MAX_NMBR_POST_BUFFERS_PER_MSG 32
 
  /*
@@ -390,30 +380,30 @@
  ** Transmit buffer are considered owned by the adapter until context's
  ** returned to user through the TransmitCallbackFunction.
  */
-RC_RETURN RCI2OSendPacket(U16 AdapterID, 
-                          U32 context, 
+RC_RETURN RCI2OSendPacket(u16 AdapterID, 
+                          u32 context, 
                           PRCTCB pTransactionCtrlBlock);
 
 
  /* Ethernet Link Statistics structure */
 typedef struct tag_RC_link_stats
 {
-    U32 TX_good;      /* good transmit frames */
-    U32 TX_maxcol;    /* frames not TX due to MAX collisions */
-    U32 TX_latecol;   /* frames not TX due to late collisions */
-    U32 TX_urun;      /* frames not TX due to DMA underrun */
-    U32 TX_crs;       /* frames TX with lost carrier sense */
-    U32 TX_def;       /* frames deferred due to activity on link */
-    U32 TX_singlecol; /* frames TX with one and only on collision */
-    U32 TX_multcol;   /* frames TX with more than one collision */
-    U32 TX_totcol;    /* total collisions detected during TX */
-    U32 Rcv_good;     /* good frames received */
-    U32 Rcv_CRCerr;   /* frames RX and discarded with CRC errors */
-    U32 Rcv_alignerr; /* frames RX with alignment and CRC errors */
-    U32 Rcv_reserr;   /* good frames discarded due to no RX buffer */
-    U32 Rcv_orun;     /* RX frames lost due to FIFO overrun */
-    U32 Rcv_cdt;      /* RX frames with collision during RX */
-    U32 Rcv_runt;     /* RX frames shorter than 64 bytes */
+    u32 TX_good;      /* good transmit frames */
+    u32 TX_maxcol;    /* frames not TX due to MAX collisions */
+    u32 TX_latecol;   /* frames not TX due to late collisions */
+    u32 TX_urun;      /* frames not TX due to DMA underrun */
+    u32 TX_crs;       /* frames TX with lost carrier sense */
+    u32 TX_def;       /* frames deferred due to activity on link */
+    u32 TX_singlecol; /* frames TX with one and only on collision */
+    u32 TX_multcol;   /* frames TX with more than one collision */
+    u32 TX_totcol;    /* total collisions detected during TX */
+    u32 Rcv_good;     /* good frames received */
+    u32 Rcv_CRCerr;   /* frames RX and discarded with CRC errors */
+    u32 Rcv_alignerr; /* frames RX with alignment and CRC errors */
+    u32 Rcv_reserr;   /* good frames discarded due to no RX buffer */
+    u32 Rcv_orun;     /* RX frames lost due to FIFO overrun */
+    u32 Rcv_cdt;      /* RX frames with collision during RX */
+    u32 Rcv_runt;     /* RX frames shorter than 64 bytes */
 }
  RCLINKSTATS, *P_RCLINKSTATS;
 
@@ -424,7 +414,7 @@
  ** If given, not NULL, the function WaitCallback is called during the wait
  ** loop while waiting for the adapter to respond.
  */
-RC_RETURN RCGetLinkStatistics(U16 AdapterID,
+RC_RETURN RCGetLinkStatistics(u16 AdapterID,
                               P_RCLINKSTATS StatsReturnAddr,
                               PFNWAITCALLBACK WaitCallback);
 
@@ -435,8 +425,8 @@
  ** If given, not NULL, the function WaitCallback is called during the wait
  ** loop while waiting for the adapter to respond.
  */
-RC_RETURN RCGetLinkStatus(U16 AdapterID, 
-                          PU32 pReturnStatus,
+RC_RETURN RCGetLinkStatus(u16 AdapterID, 
+                          u32 * pReturnStatus,
                           PFNWAITCALLBACK WaitCallback);
                                
  /* Link Status defines - value returned in pReturnStatus */
@@ -452,7 +442,7 @@
  ** adapter runs in promiscous mode because of the dual address requirement.
  ** The MAC address is returned to the unsigned char array pointer to by mac.
  */
-RC_RETURN RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback);
+RC_RETURN RCGetMAC(u16 AdapterID, u8 * mac, PFNWAITCALLBACK WaitCallback);
 
  /*
  ** RCSetMAC()
@@ -460,14 +450,14 @@
  ** Set a new user port MAC address.  This address will be returned on
  ** subsequent RCGetMAC() calls.
  */
-RC_RETURN RCSetMAC(U16 AdapterID, PU8 mac);
+RC_RETURN RCSetMAC(u16 AdapterID, u8 * mac);
 
  /*
  ** RCSetLinkSpeed()
  **
  ** set adapter's link speed based on given input code.
  */
-RC_RETURN RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode);
+RC_RETURN RCSetLinkSpeed(u16 AdapterID, u16 LinkSpeedCode);
  /* Set link speed codes */
 #define LNK_SPD_AUTO_NEG_NWAY   0
 #define LNK_SPD_100MB_FULL      1
@@ -491,10 +481,10 @@
 #define LNK_SPD_10MB_HALF       4
 
 RC_RETURN
-RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback);
+RCGetLinkSpeed(u16 AdapterID, u32 * pLinkSpeedCode, PFNWAITCALLBACK WaitCallback);
 /*
 ** =========================================================================
-** RCSetPromiscuousMode(U16 AdapterID, U16 Mode)
+** RCSetPromiscuousMode(u16 AdapterID, u16 Mode)
 **
 ** Defined values for Mode:
 **  0 - turn off promiscuous mode
@@ -505,10 +495,10 @@
 #define PROMISCUOUS_MODE_OFF 0
 #define PROMISCUOUS_MODE_ON  1
 RC_RETURN
-RCSetPromiscuousMode(U16 AdapterID, U16 Mode);
+RCSetPromiscuousMode(u16 AdapterID, u16 Mode);
 /*
 ** =========================================================================
-** RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+** RCGetPromiscuousMode(u16 AdapterID, u32 * pMode, PFNWAITCALLBACK WaitCallback)
 **
 ** get promiscuous mode setting
 **
@@ -519,11 +509,11 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+RCGetPromiscuousMode(u16 AdapterID, u32 * pMode, PFNWAITCALLBACK WaitCallback);
 
 /*
 ** =========================================================================
-** RCSetBroadcastMode(U16 AdapterID, U16 Mode)
+** RCSetBroadcastMode(u16 AdapterID, u16 Mode)
 **
 ** Defined values for Mode:
 **  0 - turn off promiscuous mode
@@ -534,10 +524,10 @@
 #define BROADCAST_MODE_OFF 0
 #define BROADCAST_MODE_ON  1
 RC_RETURN
-RCSetBroadcastMode(U16 AdapterID, U16 Mode);
+RCSetBroadcastMode(u16 AdapterID, u16 Mode);
 /*
 ** =========================================================================
-** RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+** RCGetBroadcastMode(u16 AdapterID, u32 * pMode, PFNWAITCALLBACK WaitCallback)
 **
 ** get broadcast mode setting
 **
@@ -548,10 +538,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+RCGetBroadcastMode(u16 AdapterID, u32 * pMode, PFNWAITCALLBACK WaitCallback);
 /*
 ** =========================================================================
-** RCReportDriverCapability(U16 AdapterID, U32 capability)
+** RCReportDriverCapability(u16 AdapterID, u32 capability)
 **
 ** Currently defined bits:
 ** WARM_REBOOT_CAPABLE   0x01
@@ -559,7 +549,7 @@
 ** =========================================================================
 */
 RC_RETURN
-RCReportDriverCapability(U16 AdapterID, U32 capability);
+RCReportDriverCapability(u16 AdapterID, u32 capability);
 
 /*
 ** RCGetFirmwareVer()
@@ -569,7 +559,7 @@
 ** WARNING: user's space pointed to by pFirmString should be at least 60 bytes.
 */
 RC_RETURN
-RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback);
+RCGetFirmwareVer(u16 AdapterID, u8 * pFirmString, PFNWAITCALLBACK WaitCallback);
 
 /*
 ** ----------------------------------------------
@@ -600,7 +590,7 @@
  ** operation if the receive buffers were returned during LANReset.
  ** Note: The IOP status is not affected by a LAN reset.
  */
-RC_RETURN RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+RC_RETURN RCResetLANCard(u16 AdapterID, u16 ResourceFlags, u32 * ReturnAddr, PFNCALLBACK CallbackFunction);
 
 
  /*
@@ -622,7 +612,7 @@
  ** Note: The IOP status is not affected by a LAN shutdown.
  */                                      
 RC_RETURN 
-RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+RCShutdownLANCard(u16 AdapterID, u16 ResourceFlags, u32 * ReturnAddr, PFNCALLBACK CallbackFunction);
 
  /*
  ** RCResetIOP();
@@ -632,6 +622,6 @@
  **     Clears outbound message Q. 
  */
 RC_RETURN 
-RCResetIOP(U16 AdapterID);
+RCResetIOP(u16 AdapterID);
 
 #endif /* RCLANMTL_H */
diff -urN linux-2.2.18-pre9/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- linux-2.2.18-pre9/drivers/net/rcpci45.c	Wed May  3 17:16:41 2000
+++ linux/drivers/net/rcpci45.c	Mon Dec  3 20:27:06 2001
@@ -114,7 +114,7 @@
 #define DEFAULT_RECV_INIT_CONTEXT  0xA17  
 
 
-static U32 DriverControlWord =  0;
+static u32 DriverControlWord =  0;
 
 static void rc_timer(unsigned long);
 
@@ -131,10 +131,10 @@
     struct device *dev;            
      
     char devname[8];                /* "ethN" string */
-    U8     id;                        /* the AdapterID */
-    U32    pci_addr;               /* the pci address of the adapter */
-    U32    bus;
-    U32    function;
+    u8     id;                        /* the AdapterID */
+    u32    pci_addr;               /* the pci address of the adapter */
+    u32    bus;
+    u32    function;
     struct timer_list timer;        /*  timer */
     struct enet_statistics  stats; /* the statistics structure */
     struct device *next;            /* points to the next RC adapter */
@@ -142,7 +142,7 @@
     unsigned char shutdown;
     unsigned char reboot;
     unsigned char nexus;
-    PU8    PLanApiPA;             /* Pointer to Lan Api Private Area */
+    u8 *    PLanApiPA;             /* Pointer to Lan Api Private Area */
 
 }
 DPA, *PDPA;
@@ -169,10 +169,10 @@
 static struct enet_statistics *RCget_stats(struct device *);
 static int RCioctl(struct device *, struct ifreq *, int);
 static int RCconfig(struct device *, struct ifmap *);
-static void RCxmit_callback(U32, U16, PU32, U16);
-static void RCrecv_callback(U32, U8, U32, PU32, U16);
-static void RCreset_callback(U32, U32, U32, U16);
-static void RCreboot_callback(U32, U32, U32, U16);
+static void RCxmit_callback(u32, u16, u32 *, u16);
+static void RCrecv_callback(u32, u8, u32, u32 *, u16);
+static void RCreset_callback(u32, u32, u32, u16);
+static void RCreboot_callback(u32, u32, u32, u16);
 static int RC_allocate_and_post_buffers(struct device *, int);
 
 
@@ -405,14 +405,14 @@
     if ( request_irq(dev->irq, (void *)RCinterrupt,
                      SA_INTERRUPT|SA_SHIRQ, "RedCreek VPN Adapter", dev) )
     {
-        printk( "RC PCI 45: %s: unable to get IRQ %d\n", (PU8)dev->name, (uint)dev->irq );
+        printk( "RC PCI 45: %s: unable to get IRQ %d\n", (u8 *)dev->name, (uint)dev->irq );
         iounmap(vaddr);
         kfree(dev);
         return 1;
     }
 
     init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr, 
-                  pDpa->PLanApiPA, (PU8)virt_to_bus((void *)pDpa->PLanApiPA),
+                  pDpa->PLanApiPA, (u8 *)virt_to_bus((void *)pDpa->PLanApiPA),
                   (PFNTXCALLBACK)RCxmit_callback,
                   (PFNRXCALLBACK)RCrecv_callback,
                   (PFNCALLBACK)RCreboot_callback);
@@ -560,7 +560,7 @@
      * we'll get the context when the adapter interrupts us to tell us that
      * the transmision is done. At that time, we can free skb.
      */
-    ptcb->b.context = (U32)skb;    
+    ptcb->b.context = (u32)skb;    
     ptcb->b.scount = 1;
     ptcb->b.size = skb->len;
     ptcb->b.addr = virt_to_bus((void *)skb->data);
@@ -569,7 +569,7 @@
     printk("rc: RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n", 
            (uint)skb, (uint)pDpa, (uint)pDpa->id, (uint)ptcb);
 #endif
-    if ( (status = RCI2OSendPacket(pDpa->id, (U32)NULL, (PRCTCB)ptcb))
+    if ( (status = RCI2OSendPacket(pDpa->id, (u32)NULL, (PRCTCB)ptcb))
          != RC_RTN_NO_ERROR)
     {
 #ifdef RCDEBUG
@@ -600,10 +600,10 @@
  * All we need to do is free the buffers.
  */
 static void 
-RCxmit_callback(U32 Status, 
-                U16 PcktCount, 
-                PU32 BufferContext, 
-                U16 AdapterID)
+RCxmit_callback(u32 Status, 
+                u16 PcktCount, 
+                u32 * BufferContext, 
+                u16 AdapterID)
 {
     struct sk_buff *skb;
     PDPA pDpa;
@@ -649,7 +649,7 @@
 }
 
 static void
-RCreset_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
+RCreset_callback(u32 Status, u32 p1, u32 p2, u16 AdapterID)
 {
     PDPA pDpa;
     struct device *dev;
@@ -693,7 +693,7 @@
 }
 
 static void
-RCreboot_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
+RCreboot_callback(u32 Status, u32 p1, u32 p2, u16 AdapterID)
 {
     PDPA pDpa;
     
@@ -742,14 +742,14 @@
  * filled (one ethernet packet per buffer).
  */
 static void
-RCrecv_callback(U32  Status, 
-                U8   PktCount, 
-                U32  BucketsRemain, 
-                PU32 PacketDescBlock, 
-                U16  AdapterID)
+RCrecv_callback(u32  Status, 
+                u8   PktCount, 
+                u32  BucketsRemain, 
+                u32 * PacketDescBlock, 
+                u16  AdapterID)
 {
 
-    U32 len, count;
+    u32 len, count;
     PDPA pDpa;
     struct sk_buff *skb;
     struct device *dev;
@@ -845,7 +845,7 @@
                      * post one buffer at a time but ... may be that should be 
                      * optimized at some point.
                      */
-                    ptcb->b.context = (U32)skb;    
+                    ptcb->b.context = (u32)skb;    
                     ptcb->b.scount = 1;
                     ptcb->b.size = MAX_ETHER_SIZE;
                     ptcb->b.addr = virt_to_bus((void *)skb->data);
@@ -946,7 +946,7 @@
     {
         init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr, 
                                     pDpa->PLanApiPA, 
-                                    (PU8)virt_to_bus((void *)pDpa->PLanApiPA),
+                                    (u8 *)virt_to_bus((void *)pDpa->PLanApiPA),
                                     (PFNTXCALLBACK)RCxmit_callback,
                                     (PFNRXCALLBACK)RCrecv_callback,
                                     (PFNCALLBACK)RCreboot_callback);
@@ -1180,7 +1180,7 @@
         case RCUC_GETFWVER:
             printk("RC GETFWVER\n");
             RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;
-            RCGetFirmwareVer(pDpa->id, (PU8) &RCUD_GETFWVER->FirmString, NULL);
+            RCGetFirmwareVer(pDpa->id, (u8 *) &RCUD_GETFWVER->FirmString, NULL);
             break;
         case RCUC_GETINFO:
             printk("RC GETINFO\n");
@@ -1193,8 +1193,8 @@
         case RCUC_GETIPANDMASK:
             printk("RC GETIPANDMASK\n");
             RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;
-            RCGetRavlinIPandMask(pDpa->id, (PU32) &RCUD_GETIPANDMASK->IpAddr,
-                                 (PU32) &RCUD_GETIPANDMASK->NetMask, NULL);
+            RCGetRavlinIPandMask(pDpa->id, (u32 *) &RCUD_GETIPANDMASK->IpAddr,
+                                 (u32 *) &RCUD_GETIPANDMASK->NetMask, NULL);
             break;
         case RCUC_GETLINKSTATISTICS:
             printk("RC GETLINKSTATISTICS\n");
@@ -1204,22 +1204,22 @@
         case RCUC_GETLINKSTATUS:
             printk("RC GETLINKSTATUS\n");
             RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;
-            RCGetLinkStatus(pDpa->id, (PU32) &RCUD_GETLINKSTATUS->ReturnStatus, NULL);
+            RCGetLinkStatus(pDpa->id, (u32 *) &RCUD_GETLINKSTATUS->ReturnStatus, NULL);
             break;
         case RCUC_GETMAC:
             printk("RC GETMAC\n");
             RCUD_GETMAC = &RCuser.RCUS_GETMAC;
-            RCGetMAC(pDpa->id, (PU8) &RCUD_GETMAC->mac, NULL);
+            RCGetMAC(pDpa->id, (u8 *) &RCUD_GETMAC->mac, NULL);
             break;
         case RCUC_GETPROM:
             printk("RC GETPROM\n");
             RCUD_GETPROM = &RCuser.RCUS_GETPROM;
-            RCGetPromiscuousMode(pDpa->id, (PU32) &RCUD_GETPROM->PromMode, NULL);
+            RCGetPromiscuousMode(pDpa->id, (u32 *) &RCUD_GETPROM->PromMode, NULL);
             break;
         case RCUC_GETBROADCAST:
             printk("RC GETBROADCAST\n");
             RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST;
-            RCGetBroadcastMode(pDpa->id, (PU32) &RCUD_GETBROADCAST->BroadcastMode, NULL);
+            RCGetBroadcastMode(pDpa->id, (u32 *) &RCUD_GETBROADCAST->BroadcastMode, NULL);
             break;
         case RCUC_GETSPEED:
             printk("RC GETSPEED\n");
@@ -1229,47 +1229,47 @@
                 return -ENODATA;
             }
             RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;
-            RCGetLinkSpeed(pDpa->id, (PU32) &RCUD_GETSPEED->LinkSpeedCode, NULL);
+            RCGetLinkSpeed(pDpa->id, (u32 *) &RCUD_GETSPEED->LinkSpeedCode, NULL);
             printk("RC speed = 0x%ld\n", RCUD_GETSPEED->LinkSpeedCode);
             break;
         case RCUC_SETIPANDMASK:
             printk("RC SETIPANDMASK\n");
             RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK;
-            printk ("RC New IP Addr = %d.%d.%d.%d, ", (U8) ((RCUD_SETIPANDMASK->IpAddr) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->IpAddr >>  8) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->IpAddr >> 16) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->IpAddr >> 24) & 0xff));
-            printk ("RC New Mask = %d.%d.%d.%d\n", (U8) ((RCUD_SETIPANDMASK->NetMask) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->NetMask >>  8) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->NetMask >> 16) & 0xff),
-                    (U8) ((RCUD_SETIPANDMASK->NetMask >> 24) & 0xff));
-            RCSetRavlinIPandMask(pDpa->id, (U32) RCUD_SETIPANDMASK->IpAddr,
-                                 (U32) RCUD_SETIPANDMASK->NetMask);
+            printk ("RC New IP Addr = %d.%d.%d.%d, ", (u8) ((RCUD_SETIPANDMASK->IpAddr) & 0xff),
+                    (u8) ((RCUD_SETIPANDMASK->IpAddr >>  8) & 0xff),
+                    (u8) ((RCUD_SETIPANDMASK->IpAddr >> 16) & 0xff),
+                    (u8) ((RCUD_SETIPANDMASK->IpAddr >> 24) & 0xff));
+            printk ("RC New Mask = %d.%d.%d.%d\n", (u8) ((RCUD_SETIPANDMASK->NetMask) & 0xff),
+                    (u8) ((RCUD_SETIPANDMASK->NetMask >>  8) & 0xff),
+                    (u8) ((RCUD_SETIPANDMASK->NetMask >> 16) & 0xff),
+                    (u8) ((RCUD_SETIPANDMASK->NetMask >> 24) & 0xff));
+            RCSetRavlinIPandMask(pDpa->id, (u32) RCUD_SETIPANDMASK->IpAddr,
+                                 (u32) RCUD_SETIPANDMASK->NetMask);
             break;
         case RCUC_SETMAC:
             printk("RC SETMAC\n");
             RCUD_SETMAC = &RCuser.RCUS_SETMAC;
             printk ("RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n",
-                    (U8) (RCUD_SETMAC->mac[0]), (U8) (RCUD_SETMAC->mac[1]), (U8) (RCUD_SETMAC->mac[2]),
-                    (U8) (RCUD_SETMAC->mac[3]), (U8) (RCUD_SETMAC->mac[4]), (U8) (RCUD_SETMAC->mac[5]));
-            RCSetMAC(pDpa->id, (PU8) &RCUD_SETMAC->mac);
+                    (u8) (RCUD_SETMAC->mac[0]), (u8) (RCUD_SETMAC->mac[1]), (u8) (RCUD_SETMAC->mac[2]),
+                    (u8) (RCUD_SETMAC->mac[3]), (u8) (RCUD_SETMAC->mac[4]), (u8) (RCUD_SETMAC->mac[5]));
+            RCSetMAC(pDpa->id, (u8 *) &RCUD_SETMAC->mac);
             break;
         case RCUC_SETSPEED:
             printk("RC SETSPEED\n");
             RCUD_SETSPEED = &RCuser.RCUS_SETSPEED;
-            RCSetLinkSpeed(pDpa->id, (U16) RCUD_SETSPEED->LinkSpeedCode);
+            RCSetLinkSpeed(pDpa->id, (u16) RCUD_SETSPEED->LinkSpeedCode);
             printk("RC New speed = 0x%d\n", RCUD_SETSPEED->LinkSpeedCode);
             break;
         case RCUC_SETPROM:
             printk("RC SETPROM\n");
             RCUD_SETPROM = &RCuser.RCUS_SETPROM;
-            RCSetPromiscuousMode(pDpa->id,(U16)RCUD_SETPROM->PromMode);
+            RCSetPromiscuousMode(pDpa->id,(u16)RCUD_SETPROM->PromMode);
             printk("RC New prom mode = 0x%d\n", RCUD_SETPROM->PromMode);
             break;
         case RCUC_SETBROADCAST:
             printk("RC SETBROADCAST\n");
             RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST;
-            RCSetBroadcastMode(pDpa->id,(U16)RCUD_SETBROADCAST->BroadcastMode);
+            RCSetBroadcastMode(pDpa->id,(u16)RCUD_SETBROADCAST->BroadcastMode);
             printk("RC New broadcast mode = 0x%d\n", RCUD_SETBROADCAST->BroadcastMode);
             break;
         default:
@@ -1349,7 +1349,7 @@
 
     int i;
     PDPA pDpa = (PDPA)dev->priv;
-    PU32 p;
+    u32 * p;
     psingleB pB;
     struct sk_buff *skb;
     RC_RETURN status;
@@ -1365,7 +1365,7 @@
         numBuffers = 32;
     }
     
-    p = (PU32) kmalloc(sizeof(U32) + numBuffers*sizeof(singleB), GFP_ATOMIC);
+    p = (u32 *) kmalloc(sizeof(u32) + numBuffers*sizeof(singleB), GFP_ATOMIC);
 
 #ifdef RCDEBUG
     printk("rc: TCB = 0x%x\n", (uint)p);
@@ -1378,7 +1378,7 @@
     }
 
     p[0] = 0;                              /* Buffer Count */
-    pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
+    pB = (psingleB)((u32)p + sizeof(u32)); /* point to the first buffer */
 
 #ifdef RCDEBUG
     printk("rc: p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint)p[0], (uint)p, (uint)pB);
@@ -1408,7 +1408,7 @@
         printk("post 0x%x\n", (uint)skb);
 #endif
         skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
-        pB->context = (U32)skb;
+        pB->context = (u32)skb;
         pB->scount = 1;        /* segment count */
         pB->size = MAX_ETHER_SIZE;
         pB->addr = virt_to_bus((void *)skb->data);
@@ -1419,7 +1419,7 @@
     if ( (status = RCPostRecvBuffers(pDpa->id, (PRCTCB)p )) != RC_RTN_NO_ERROR)
     {
         printk("rc: Post buffer failed with error code 0x%x!\n", status);
-        pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
+        pB = (psingleB)((u32)p + sizeof(u32)); /* point to the first buffer */
         while(p[0])
         {
             skb = (struct sk_buff *)pB->context;
diff -urN linux-2.2.18-pre9/drivers/sound/Config.in linux/drivers/sound/Config.in
--- linux-2.2.18-pre9/drivers/sound/Config.in	Mon Dec  3 20:26:36 2001
+++ linux/drivers/sound/Config.in	Mon Dec  3 20:27:07 2001
@@ -100,6 +100,8 @@
    int 'MSND buffer size (kB)' CONFIG_MSND_FIFOSIZE 128
 fi
 
+dep_tristate 'VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_SOUND
+
 
 dep_tristate 'OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
 
@@ -202,8 +204,6 @@
       fi
   fi
   
-  dep_tristate 'VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_SOUND_OSS
-
   dep_tristate 'Support for OPTi MAD16 and/or Mozart based cards' CONFIG_SOUND_MAD16 $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_MAD16" = "y" -o "$CONFIG_SOUND_MAD16" = "m" ]; then
     bool 'Support MIDI in older MAD16 based cards (requires SB)' CONFIG_MAD16_OLDCARD
diff -urN linux-2.2.18-pre9/drivers/sound/Makefile linux/drivers/sound/Makefile
--- linux-2.2.18-pre9/drivers/sound/Makefile	Mon Sep  4 10:39:21 2000
+++ linux/drivers/sound/Makefile	Mon Dec  3 20:27:07 2001
@@ -60,7 +60,6 @@
 obj-$(CONFIG_SOUND_CS4232)	+= uart401.o
 obj-$(CONFIG_SOUND_GUS)		+= gus.o ad1848.o
 obj-$(CONFIG_SOUND_MAD16)	+= mad16.o ad1848.o sb.o uart401.o
-obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx.o sb.o uart401.o 
 obj-$(CONFIG_SOUND_YMPCI)	+= ymfsb.o sb.o uart401.o ac97.o
 obj-$(CONFIG_SOUND_MAUI)	+= maui.o mpu401.o
 obj-$(CONFIG_SOUND_MPU401)	+= mpu401.o
@@ -97,6 +96,7 @@
 obj-$(CONFIG_SOUND_MAESTRO)	+= maestro.o
 obj-$(CONFIG_SOUND_SONICVIBES)	+= sonicvibes.o
 obj-$(CONFIG_SOUND_TRIDENT)     += trident.o ac97_codec.o
+obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o ac97_codec.o
 
 ifeq ($(CONFIG_SOUND_EMU10K1),y)
   obj-y				+= emu10k1/emu10k1.o
diff -urN linux-2.2.18-pre9/drivers/sound/trident.c linux/drivers/sound/trident.c
--- linux-2.2.18-pre9/drivers/sound/trident.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/sound/trident.c	Mon Dec  3 20:27:07 2001
@@ -30,6 +30,8 @@
  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  History
+ *  v0.14.5b Sept 17 2000 Eric Brombaugh
+ *      Fix hang when trying ALi MIDI init on Trident
  *  v0.14.5 June 3 2000 Ollie Lho
  *  	Misc bug fix from the Net
  *	Backported from 2.4.0-test1 to 2.2.16 (Eric Brombaugh)
@@ -2863,30 +2865,37 @@
 		return -ENODEV;
 	}
 	
-	if ((card->dev_midi = register_sound_midi(&trident_midi_fops, -1))<0)
-		printk(KERN_WARNING "trident: Unable to register midi.\n");
-	else
-	{
-		struct midi_stuff *midi = &card->midi;
-		init_waitqueue(&midi->iwait);
-		init_waitqueue(&midi->owait);
-		midi->ird = midi->iwr = midi->icnt = 0;
-		midi->ord = midi->owr = midi->ocnt = 0;
-		outb(0xbc, card->iobase+ALI_MPUR2);
+	if(card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+		/* ALi 5451 has special MIDI regs and FM emulation */
+		if ((card->dev_midi = register_sound_midi(&trident_midi_fops, -1))<0)
+			printk(KERN_WARNING "trident: Unable to register midi.\n");
+		else
+		{
+			struct midi_stuff *midi = &card->midi;
+			init_waitqueue(&midi->iwait);
+			init_waitqueue(&midi->owait);
+			midi->ird = midi->iwr = midi->icnt = 0;
+			midi->ord = midi->owr = midi->ocnt = 0;
+			outb(0xbc, card->iobase+ALI_MPUR2);
 		
-		/* reset command */
-		while (inb(card->iobase + ALI_MPUR1) & 0x40);
-		outb(0xff, card->iobase + ALI_MPUR1);
-		while (inb(card->iobase + ALI_MPUR1) & 0x80);
-		while ((inb(card->iobase + ALI_MPUR0) != 0xfe) && (inb(card->iobase+ALI_MPUR1) != 0x10)) 
+			/* reset command */
+			while (inb(card->iobase + ALI_MPUR1) & 0x40);
+			outb(0xff, card->iobase + ALI_MPUR1);
 			while (inb(card->iobase + ALI_MPUR1) & 0x80);
+			while ((inb(card->iobase + ALI_MPUR0) != 0xfe) && (inb(card->iobase+ALI_MPUR1) != 0x10)) 
+				while (inb(card->iobase + ALI_MPUR1) & 0x80);
 			
-		midi->ird = midi->iwr = midi->icnt = 0;
-	}
-		
-	if ((card->dev_dmfm = register_sound_special(&trident_dmfm_fops, 15))<0)
-		printk(KERN_WARNING "trident: Unable to register FM.\n");
+			midi->ird = midi->iwr = midi->icnt = 0;
+		}
 	
+		if ((card->dev_dmfm = register_sound_special(&trident_dmfm_fops, 15))<0)
+			printk(KERN_WARNING "trident: Unable to register FM.\n");
+	} else {
+		/* don't try to enable MIDI and FM on other chips */
+		card->dev_midi = -1;
+		card->dev_dmfm = -1;
+	}
+
 	outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
 
 	if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
diff -urN linux-2.2.18-pre9/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- linux-2.2.18-pre9/drivers/sound/via82cxxx_audio.c	Wed Jun  7 14:26:43 2000
+++ linux/drivers/sound/via82cxxx_audio.c	Mon Dec  3 20:27:07 2001
@@ -5,48 +5,48 @@
  * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
  * See the "COPYING" file distributed with this software for more info.
  *
- * Documentation for this driver available as
- * linux/Documentation/sound/via82cxxx.txt.
+ * For a list of known bugs (errata) and documentation,
+ * see via-audio.pdf in linux/Documentation/DocBook.
+ * If this documentation does not exist, run "make pdfdocs".
+ * If "make pdfdocs" fails, obtain the documentation from
+ * the driver's Website at
+ * http://gtf.org/garzik/drivers/via82cxxx/
  *
- * Since the mixer is called from the OSS glue the kernel lock is always held
- * on our AC97 mixing
  */
  
 
-#define VIA_VERSION	"1.1.2.1"
+#define VIA_VERSION	"1.1.8-2.2"
+
 
-#include <linux/module.h>
 #include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/fs.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
-
+#include <linux/spinlock.h>
+#include <linux/sound.h>
+#include <linux/poll.h>
+#include <linux/soundcard.h>
+#include <linux/ac97_codec.h>
+#include <linux/smp_lock.h>
 #include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
 
 #include "sound_config.h"
-#include "soundmodule.h"
-#include "sb.h"
-#include "ac97.h"
-
-#ifndef SOUND_LOCK
-#define SOUND_LOCK do {} while (0)
-#define SOUND_LOCK_END do {} while (0)
-#endif
 
-#define VIA_DEBUG 0	/* define to 1 to enable debugging output and checks */
-#if VIA_DEBUG
+#undef VIA_DEBUG	/* define to enable debugging output and checks */
+#ifdef VIA_DEBUG
 /* note: prints function name for you */
 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 #else
 #define DPRINTK(fmt, args...)
 #endif
 
-#define VIA_NDEBUG 0	/* define to 1 to disable lightweight runtime checks */
-#if VIA_NDEBUG
+#define VIA_NDEBUG	/* define to disable lightweight runtime checks */
+#ifdef VIA_NDEBUG
 #define assert(expr)
 #else
 #define assert(expr) \
@@ -58,27 +58,99 @@
 
 #define arraysize(x)            (sizeof(x)/sizeof(*(x)))
 
-#define MAX_CARDS	2
+#define MAX_CARDS	1
 
 #define	LINE_SIZE	10
 
 #define VIA_CARD_NAME	"VIA 82Cxxx Audio driver " VIA_VERSION
-#define VIA_MODULE_NAME "via_audio"
+#define VIA_MODULE_NAME "via82cxxx"
 #define PFX		VIA_MODULE_NAME ": "
 
 #define VIA_COUNTER_LIMIT	100000
 
+/* size of DMA buffers */
+#define VIA_DMA_BUFFERS		16
+#define VIA_DMA_BUF_SIZE	PAGE_SIZE
+
 /* 82C686 function 5 (audio codec) PCI configuration registers */
+#define VIA_ACLINK_CTRL		0x41
 #define VIA_FUNC_ENABLE		0x42
 #define VIA_PNP_CONTROL		0x43
-#define VIA_AC97_CTRL		0x80
+#define VIA_FM_NMI_CTRL		0x48
+
+/*
+ * controller base 0 (scatter-gather) registers
+ *
+ * NOTE: Via datasheet lists first channel as "read"
+ * channel and second channel as "write" channel.
+ * I changed the naming of the constants to be more
+ * clear than I felt the datasheet to be.
+ */
+
+#define VIA_BASE0_PCM_OUT_CHAN	0x00 /* output PCM to user */
+#define VIA_BASE0_PCM_OUT_CHAN_STATUS 0x00
+#define VIA_BASE0_PCM_OUT_CHAN_CTRL	0x01
+#define VIA_BASE0_PCM_OUT_CHAN_TYPE	0x02
+#define VIA_BASE0_PCM_OUT_BLOCK_COUNT	0x0C
+
+#define VIA_BASE0_PCM_IN_CHAN		0x10 /* input PCM from user */
+#define VIA_BASE0_PCM_IN_CHAN_STATUS	0x10
+#define VIA_BASE0_PCM_IN_CHAN_CTRL	0x11
+#define VIA_BASE0_PCM_IN_CHAN_TYPE	0x12
+
+/* offsets from base */
+#define VIA_PCM_STATUS			0x00
+#define VIA_PCM_CONTROL			0x01
+#define VIA_PCM_TYPE			0x02
+#define VIA_PCM_TABLE_ADDR		0x04
+
+/* XXX unused DMA channel for FM PCM data */
+#define VIA_BASE0_FM_OUT_CHAN		0x20
+#define VIA_BASE0_FM_OUT_CHAN_STATUS	0x20
+#define VIA_BASE0_FM_OUT_CHAN_CTRL	0x21
+#define VIA_BASE0_FM_OUT_CHAN_TYPE	0x22
+
+#define VIA_BASE0_AC97_CTRL		0x80
+#define VIA_BASE0_SGD_STATUS_SHADOW	0x84
+#define VIA_BASE0_GPI_INT_ENABLE	0x8C
+
+/* VIA_BASE0_AUDIO_xxx_CHAN_TYPE bits */
+#define VIA_IRQ_ON_FLAG			(1<<0)	/* int on each flagged scatter block */
+#define VIA_IRQ_ON_EOL			(1<<1)	/* int at end of scatter list */
+#define VIA_INT_SEL_PCI_LAST_LINE_READ	(0)	/* int at PCI read of last line */
+#define VIA_INT_SEL_LAST_SAMPLE_SENT	(1<<2)	/* int at last sample sent */
+#define VIA_INT_SEL_ONE_LINE_LEFT	(1<<3)	/* int at less than one line to send */
+#define VIA_PCM_FMT_STEREO		(1<<4)	/* PCM stereo format (bit clear == mono) */
+#define VIA_PCM_FMT_16BIT		(1<<5)	/* PCM 16-bit format (bit clear == 8-bit) */
+#define VIA_PCM_FIFO			(1<<6)	/* enable FIFO?  documented as "reserved" */
+#define VIA_RESTART_SGD_ON_EOL		(1<<7)	/* restart scatter-gather at EOL */
+#define VIA_PCM_FMT_MASK		(VIA_PCM_FMT_STEREO|VIA_PCM_FMT_16BIT)
+#define VIA_CHAN_TYPE_MASK		(VIA_RESTART_SGD_ON_EOL | \
+					 VIA_PCM_FIFO | \
+					 VIA_IRQ_ON_FLAG | \
+					 VIA_IRQ_ON_EOL)
+#define VIA_CHAN_TYPE_INT_SELECT	(VIA_INT_SEL_LAST_SAMPLE_SENT)
 
 /* PCI configuration register bits and masks */
 #define VIA_CR40_AC97_READY	0x01
 #define VIA_CR40_AC97_LOW_POWER	0x02
 #define VIA_CR40_SECONDARY_READY 0x04
 
-#define VIA_CR41_ACLINK_ENABLE	0x80
+#define VIA_CR41_AC97_ENABLE	0x80 /* enable AC97 codec */
+#define VIA_CR41_AC97_RESET	0x40 /* clear bit to reset AC97 */
+#define VIA_CR41_AC97_WAKEUP	0x20 /* wake up from power-down mode */
+#define VIA_CR41_AC97_SDO	0x10 /* force Serial Data Out (SDO) high */
+#define VIA_CR41_VRA		0x08 /* enable variable sample rate */
+#define VIA_CR41_PCM_ENABLE	0x04 /* AC Link SGD Read Channel PCM Data Output */
+#define VIA_CR41_FM_PCM_ENABLE	0x02 /* AC Link FM Channel PCM Data Out */
+#define VIA_CR41_SB_PCM_ENABLE	0x01 /* AC Link SB PCM Data Output */
+#define VIA_CR41_BOOT_MASK	(VIA_CR41_AC97_ENABLE | \
+				 VIA_CR41_AC97_WAKEUP | \
+				 VIA_CR41_AC97_SDO)
+#define VIA_CR41_RUN_MASK	(VIA_CR41_AC97_ENABLE | \
+				 VIA_CR41_AC97_RESET | \
+				 VIA_CR41_VRA | \
+				 VIA_CR41_PCM_ENABLE)
 
 #define VIA_CR42_SB_ENABLE	0x01
 #define VIA_CR42_MIDI_ENABLE	0x02
@@ -88,642 +160,2268 @@
 #define VIA_CR44_SECOND_CODEC_SUPPORT	(1 << 6)
 #define VIA_CR44_AC_LINK_ACCESS		(1 << 7)
 
+#define VIA_CR48_FM_TRAP_TO_NMI		(1 << 2)
+
+/* controller base 0 register bitmasks */
+#define VIA_INT_DISABLE_MASK		(~(0x01|0x02))
+#define VIA_SGD_STOPPED			(1 << 2)
+#define VIA_SGD_ACTIVE			(1 << 7)
+#define VIA_SGD_TERMINATE		(1 << 6)
+#define VIA_SGD_FLAG			(1 << 0)
+#define VIA_SGD_EOL			(1 << 1)
+#define VIA_SGD_START			(1 << 7)
+
 #define VIA_CR80_FIRST_CODEC		0
 #define VIA_CR80_SECOND_CODEC		(1 << 30)
 #define VIA_CR80_FIRST_CODEC_VALID	(1 << 25)
+#define VIA_CR80_VALID			(1 << 25)
 #define VIA_CR80_SECOND_CODEC_VALID	(1 << 27)
 #define VIA_CR80_BUSY			(1 << 24)
-#define VIA_CR80_READ_MODE		(1 << 23)
+#define VIA_CR83_BUSY			(1)
+#define VIA_CR83_FIRST_CODEC_VALID	(1 << 1)
+#define VIA_CR80_READ			(1 << 23)
 #define VIA_CR80_WRITE_MODE		0
-#define VIA_CR80_REG_IDX(idx)		(((idx) & 0x7E) << 16)
+#define VIA_CR80_REG_IDX(idx)		((((idx) & 0xFF) >> 1) << 16)
 
-struct via_info {
-	struct address_info sb_data;
-	struct address_info opl3_data;
-	struct pci_dev *pdev;
-	struct ac97_hwint ac97;
-	int mixer_oss_dev;
-	int have_ac97;
+/* h r puff n stuff */
+#define VIA_FMT_STEREO	0x01
+#define VIA_FMT_16BIT	0x02
+#define VIA_FMT_MASK	0x03
+#define VIA_DAC_SHIFT	0   
+#define VIA_ADC_SHIFT	4
+
+/* undocumented(?) values for setting rate, from Via's source */
+#define VIA_SET_RATE_IN		0x00320000 /* set input rate */
+#define VIA_SET_RATE_OUT	0x002c0000 /* set output rate */
+
+
+/* scatter-gather DMA table entry, exactly as passed to hardware */
+struct via_sgd_table {
+	u32 addr;
+	u32 count;	/* includes additional bits also */
 };
-static struct via_info		cards [MAX_CARDS];
-static unsigned			num_cards = 0;
+#define VIA_EOL (1 << 31)
+#define VIA_FLAG (1 << 30)
 
 
-static const struct {
-	int revision;
-	const char *rev_name;
-} via_chip_revs[] __initdata = {
-	{ 0x10, "A" },
-	{ 0x11, "B" },
-	{ 0x12, "C" },
-	{ 0x13, "D" },
-	{ 0x14, "E" },
-	{ 0x20, "H" },
+enum via_channel_states {
+	sgd_stopped = 0,
+	sgd_in_progress = 1,
 };
 
-static inline void via_ac97_write32 (struct pci_dev *pdev, int port, u32 data)
-{
 
-	int iobase = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
-	
-	outw ((u16)data,iobase+port);	
-	outw ((u16)(data>>16),iobase+port+2);	
-}
+struct via_sgd_data {
+	dma_addr_t handle;
+	volatile void *cpuaddr;
+};
 
-static inline u32 via_ac97_read32 (struct pci_dev *pdev, int port)
-{
-	int iobase = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 
-	return
-		((u32)inw (iobase+port)) |
-		(((u32)inw (iobase+port+2)) << 16);
-}
+struct via_channel {
+	unsigned rate;		/* sample rate */
 
-/****************************************************************
- *
- * Intel Audio Codec '97 interface
- *
- *
- */
- 
-static inline void via_ac97_wait_idle (struct pci_dev *pdev)
-{
-	u32 tmp;
-	int counter = VIA_COUNTER_LIMIT;
+	u8 pcm_fmt;		/* VIA_PCM_FMT_xxx */
 	
-	DPRINTK ("ENTER\n");
-
-	assert (pdev != NULL);
+	atomic_t state;
+	atomic_t buf_in_use;
+	atomic_t next_buf;
 	
-	do {
-		tmp = via_ac97_read32 (pdev,VIA_AC97_CTRL);
-	} while ((tmp & VIA_CR80_BUSY) && (counter-- > 0));
-
-	DPRINTK ("EXIT%s\n", counter > 0 ? "" : ", counter limit reached");
-}
+	volatile struct via_sgd_table *sgtable;
+	dma_addr_t sgt_handle;
+	
+	struct via_sgd_data sgbuf [VIA_DMA_BUFFERS];
+	
+	wait_queue_head_t wait;
+	
+	long iobase;
+};
 
 
-static int via_ac97_read_reg (struct ac97_hwint *dev, u8 reg)
-{
-	u32 data;
-	struct via_info *card;
+/* data stored for each chip */
+struct via_info {
 	struct pci_dev *pdev;
+	long baseaddr;
 	
-	DPRINTK ("ENTER\n");
+	struct ac97_codec ac97;
+	spinlock_t lock;
+	int card_num;		/* unique card number, from 0 */
 
-	assert (dev != NULL);
-	assert (dev->driver_private != NULL);
+	int dev_dsp;		/* /dev/dsp index from register_sound_dsp() */
+	
+	unsigned rev_h : 1;
 
-	card = (struct via_info *) dev->driver_private;
-	pdev = card->pdev;
-	assert (pdev != NULL);
+	wait_queue_head_t open_wait;
+	int open_mode;
+	
+	struct via_channel ch_in;
+	struct via_channel ch_out;
+};
 
-	via_ac97_wait_idle (pdev);
-	data =	VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
-		VIA_CR80_READ_MODE | VIA_CR80_REG_IDX(reg);
-	via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
-	via_ac97_wait_idle (pdev);
-	data = via_ac97_read32 (pdev,VIA_AC97_CTRL);
 
-#if 0
-	if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
-		DPRINTK ("EXIT, first codec not valid, returning -1\n");
-		return -1;
-	}
-#endif
+/* number of cards, used for assigning unique numbers to cards */
+static unsigned via_num_cards;
 
-	DPRINTK ("EXIT, returning %d\n", data & 0xFFFF);
-	return data & 0xFFFF;
-}
+static void *via_driver_data;
+static struct pci_dev *via_pdev;
 
+/****************************************************************
+ *
+ * compatibility
+ *
+ *
+ */
 
-static int via_ac97_write_reg (struct ac97_hwint *dev, u8 reg, u16 value)
+static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+					 dma_addr_t *dma_handle)
 {
-	u32 data;
-	struct via_info *card;
-	struct pci_dev *pdev;
-	
-	DPRINTK ("ENTER\n");
-
-	assert (dev != NULL);
-	assert (dev->driver_private != NULL);
+	void *virt_ptr;
 
-	card = (struct via_info *) dev->driver_private;
-	pdev = card->pdev;
-	assert (pdev != NULL);
+	virt_ptr = kmalloc(size, GFP_KERNEL);
+	*dma_handle = virt_to_bus(virt_ptr);
+	return virt_ptr;
+}
+#define pci_free_consistent(cookie, size, ptr, dma_ptr)	kfree(ptr)
+#define pci_map_single(cookie, address, size, dir)	virt_to_bus(address)
+#define pci_unmap_single(cookie, address, size, dir)
 
-	via_ac97_wait_idle (pdev);
-	data =	VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
-		VIA_CR80_WRITE_MODE | VIA_CR80_REG_IDX(reg) | value;
-	via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
+#define pci_resource_start(dev,bar) \
+(((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_SPACE) ? \
+ ((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_IO_MASK) : \
+ ((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_MEM_MASK))
 
-#if 0
-	if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
-		DPRINTK ("EXIT, first codec invalid, returning -1\n");
-		return -1;
-	}
-#endif
+static inline int pci_enable_device (struct pci_dev *pdev) { return 0; }
 
-	DPRINTK ("EXIT, returning 0\n");
+static inline int pci_set_power_state(struct pci_dev *dev, int new_state)
+{
 	return 0;
 }
+ 
+/****************************************************************
+ *
+ * prototypes
+ *
+ *
+ */
 
+static int via_init_one (struct pci_dev *dev);
+static void via_remove_one (struct pci_dev *pdev);
 
-static int via_ac97_reset (struct ac97_hwint *dev)
-{
-	struct via_info *card;
-	struct pci_dev *pdev;
-	
-	DPRINTK ("ENTER\n");
+static ssize_t via_dsp_read(struct file *file, char *buffer, size_t count, loff_t *ppos);
+static ssize_t via_dsp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos);
+static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wait);
+static int via_dsp_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+static int via_dsp_open (struct inode *inode, struct file *file);
+static int via_dsp_release(struct inode *inode, struct file *file);
+
+static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg);
+static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value);
+static u8 via_ac97_wait_idle (struct via_info *card);
+
+static void via_chan_free (struct via_info *card, struct via_channel *chan);
+static void via_chan_clear (struct via_channel *chan);
+static void via_chan_pcm_fmt (struct via_info *card,
+			      struct via_channel *chan, int reset);
 
-	assert (dev != NULL);
-	assert (dev->driver_private != NULL);
 
-	card = (struct via_info *) dev->driver_private;
-	pdev = card->pdev;
-	assert (pdev != NULL);
-	
-	pci_write_config_word (pdev, PCI_COMMAND, PCI_COMMAND_IO);
+/****************************************************************
+ *
+ * Low-level base 0 register read/write helpers
+ *
+ *
+ */
 
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
+/**
+ *	via_chan_stop - Terminate DMA on specified PCM channel
+ *	@iobase: PCI base address for SGD channel registers
+ *
+ *	Terminate scatter-gather DMA operation for given
+ *	channel (derived from @iobase), if DMA is active.
+ *
+ *	Note that @iobase is not the PCI base address,
+ *	but the PCI base address plus an offset to
+ *	one of three PCM channels supported by the chip.
+ *
+ */
+ 
+static inline void via_chan_stop (int iobase)
+{
+	if (inb (iobase + VIA_PCM_STATUS) & VIA_SGD_ACTIVE)
+		outb (VIA_SGD_TERMINATE, iobase + VIA_PCM_CONTROL);
 }
 
 
-static struct via_info *via_ac97_find_card_for_mixer (int dev)
+/**
+ *	via_chan_status_clear - Clear status flags on specified DMA channel
+ *	@iobase: PCI base address for SGD channel registers
+ *
+ *	Clear any pending status flags for the given
+ *	DMA channel (derived from @iobase), if any
+ *	flags are asserted.
+ *
+ *	Note that @iobase is not the PCI base address,
+ *	but the PCI base address plus an offset to
+ *	one of three PCM channels supported by the chip.
+ *
+ */
+ 
+static inline void via_chan_status_clear (int iobase)
 {
-	int x;
-
-	DPRINTK ("ENTER\n");
-
-	for (x = 0; x < num_cards; x++)
-		if (cards[x].mixer_oss_dev == dev) {
-			DPRINTK ("EXIT, returning %p\n", cards + x);
-			return cards + x;
-		}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return NULL;
+	u8 tmp = inb (iobase + VIA_PCM_STATUS);
+	
+	if (tmp != 0)
+		outb (tmp, iobase + VIA_PCM_STATUS);
 }
 
 
-static int
-via_ac97_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+/**
+ *	sg_begin - Begin recording or playback on a PCM channel
+ *	@chan: Channel for which DMA operation shall begin
+ *
+ *	Start scatter-gather DMA for the given channel.
+ *
+ */
+ 
+static inline void sg_begin (struct via_channel *chan)
 {
-	int rc;
-	struct via_info *card = via_ac97_find_card_for_mixer (dev);
-
-	DPRINTK ("ENTER\n");
-
-	if (card != NULL) {
-		rc = ac97_mixer_ioctl (&card->ac97, cmd, arg);
-		DPRINTK ("EXIT, returning %d\n", rc);
-		return rc;
-	}
-	
-	DPRINTK ("EXIT, returning -ENODEV\n");
-	return -ENODEV;
-
+	outb (VIA_SGD_START, chan->iobase + VIA_PCM_CONTROL);
 }
 
-static struct mixer_operations via_ac97_mixer_operations =
-{
-	"VIA82Cxxx",
-	"via82cxxxAC97Mixer",
-	via_ac97_default_mixer_ioctl
-};
 
-static int __init via_attach_ac97 (struct via_info *card)
+/**
+ *	via_chan_bufs_in_use - Number of buffers waiting to be consumed
+ *	@chan: Channel for which DMA buffers will be counted
+ *
+ *	Count the number of buffers waiting to be consumed.  For a
+ *	playback operation, this is the number of buffers which have
+ *	yet to be sent to the DAC.  For a recording operation, this
+ *	is the number of buffers waiting to be consumed by software
+ *	calling read() system call.
+ *
+ */
+ 
+static inline int via_chan_bufs_in_use (struct via_channel *chan)
 {
-	int mixer;
-	struct ac97_hwint *mdev;
+	return atomic_read(&chan->next_buf) -
+	       atomic_read(&chan->buf_in_use);
+}
 
-	DPRINTK ("ENTER\n");
 
-	assert (card != NULL);
+/**
+ *	via_chan_full - Check for no-free-buffers condition
+ *	@chan: Channel for which DMA full condition will be checked
+ *
+ *	Count the number of buffers waiting to be consumed, and return
+ *	true (non-zero) if no buffers are available to be filled on the
+ *	given DMA channel.
+ *
+ */
+ 
+static inline int via_chan_full (struct via_channel *chan)
+{
+	return (via_chan_bufs_in_use (chan) == VIA_DMA_BUFFERS);
+}
 
-	mdev = &card->ac97;
 
-	memset (mdev, 0, sizeof (*mdev));
-	mdev->reset_device = via_ac97_reset;
-	mdev->read_reg = via_ac97_read_reg;
-	mdev->write_reg = via_ac97_write_reg;
-	mdev->driver_private = (void *) card;
+/**
+ *	via_chan_empty - Check for no-buffers-in-use condition
+ *	@chan: Channel for which DMA empty condition will be checked
+ *
+ *	Count the number of buffers waiting to be consumed, and return
+ *	true (non-zero) if no buffers are currently in use.
+ *
+ */
+ 
+static inline int via_chan_empty (struct via_channel *chan)
+{
+	return (atomic_read(&chan->next_buf) ==
+	        atomic_read(&chan->buf_in_use));
+}
 
-	if (ac97_init (mdev)) {
-		printk (KERN_ERR PFX "Unable to init AC97\n");
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
-	}
-	mixer = sound_alloc_mixerdev ();
-	if (mixer < 0 || num_mixers >= MAX_MIXER_DEV) {
-		printk (KERN_ERR PFX "Unable to alloc mixerdev\n");
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
-	}
-	mixer_devs[mixer] = &via_ac97_mixer_operations;
-	card->mixer_oss_dev = mixer;
 
-	/* Some reasonable default values.  */
-	ac97_set_mixer (mdev, SOUND_MIXER_VOLUME, (85 << 8) | 85);
-	ac97_set_mixer (mdev, SOUND_MIXER_SPEAKER, 100);
-	ac97_set_mixer (mdev, SOUND_MIXER_PCM, (65 << 8) | 65);
-	ac97_set_mixer (mdev, SOUND_MIXER_CD, (65 << 8) | 65);
+/****************************************************************
+ *
+ * Miscellaneous debris
+ *
+ *
+ */
 
-	printk (KERN_INFO PFX "Initialized AC97 mixer\n");
-	
-	card->have_ac97 = mixer;
-	
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
 
+/**
+ *	via_stop_everything - Stop all audio operations
+ *	@card: Private info for specified board
+ *
+ *	Stops all DMA operations and interrupts, and clear
+ *	any pending status bits resulting from those operations.
+ */
 
-static void via_unload_ac97 (struct via_info *card)
+static void via_stop_everything (struct via_info *card)
 {
 	DPRINTK ("ENTER\n");
 
 	assert (card != NULL);
 
-	if (card->have_ac97 >= 0)
-		sound_unload_mixerdev (card->have_ac97);
+	/*
+	 * terminate any existing operations on audio read/write channels
+	 */
+	via_chan_stop (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
+	via_chan_stop (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
+	via_chan_stop (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
 
+	/*
+	 * clear any existing stops / flags (sanity check mainly)
+	 */
+	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
+	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
+	via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
+	
+	/*
+	 * clear any enabled interrupt bits, reset to 8-bit mono PCM mode
+	 */
+	outb (0, card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
+	outb (0, card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
+	outb (0, card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
 	DPRINTK ("EXIT\n");
 }
 
-#if 0
-#ifdef CONFIG_PROC_FS
 
-/****************************************************************
+/**
+ *	via_set_rate - Set PCM rate for given channel
+ *	@card: Private info for specified board
+ *	@rate: Desired PCM sample rate, in Khz
+ *	@inhale_deeply: Boolean.  If non-zero (true), the recording sample rate
+ *			is set.  If zero (false), the playback sample rate
+ *			is set.
  *
- * /proc/driver/via82cxxx/info
+ *	Sets the PCM sample rate for a channel.
  *
+ *	Values for @rate are clamped to a range of 4000 Khz through 48000 Khz,
+ *	due to hardware constraints.
  *
+ *	FIXME:  @inhale_deeply argument is ignored, and %AC97_PCM_FRONT_DAC_RATE
+ *	is the only rate which is really set.  This needs to be fixed when
+ *	recording support is added.
  */
-static int via_info_read_proc (char *page, char **start, off_t off,
-			       int count, int *eof, void *data)
-{
-#define YN(val,bit) (((val) & (bit)) ? "yes" : "no")
-
-	int len = 0, i;
-	u8 r40, r41, r42, r44;
-	
-	DPRINTK ("ENTER\n");
 
-	len += sprintf (page+len, VIA_CARD_NAME "\n\n");
-	
-	for (i = 0; i < num_cards; i++) {
-		pci_read_config_byte (cards[i].pdev, 0x40, &r40);
-		pci_read_config_byte (cards[i].pdev, 0x42, &r41);
-		pci_read_config_byte (cards[i].pdev, 0x42, &r42);
-		pci_read_config_byte (cards[i].pdev, 0x44, &r44);
-	
-		len += sprintf (page+len,
-			"40  AC97 Codec Ready: %s\n"
-			"    AC97 Codec Low-power: %s\n"
-			"    Secondary Codec Ready: %s\n"
-
-			"41  AC-Link Interface Enable: %s\n"
+static int via_set_rate (struct via_info *card, unsigned rate, int inhale_deeply)
+{
 
-			"42  Game port enabled: %s\n"
-			"    SoundBlaster enabled: %s\n"
-			"    FM enabled: %s\n"
-			"    MIDI enabled: %s\n"
-			
-			"44  AC-Link Interface Access: %s\n"
-			"    Secondary Codec Support: %s\n"
-			
-			"\n",
-			
-			YN (r40, VIA_CR40_AC97_READY),
-			YN (r40, VIA_CR40_AC97_LOW_POWER),
-			YN (r40, VIA_CR40_SECONDARY_READY),
-
-			YN (r41, VIA_CR41_ACLINK_ENABLE),
-
-			YN (r42, VIA_CR42_GAME_ENABLE),
-			YN (r42, VIA_CR42_SB_ENABLE),
-			YN (r42, VIA_CR42_FM_ENABLE),
-			YN (r42, VIA_CR42_MIDI_ENABLE),
+	DPRINTK ("ENTER, rate = %d, inhale = %s\n",
+		 rate, inhale_deeply ? "yes" : "no");
 
-			YN (r44, VIA_CR44_AC_LINK_ACCESS),
-			YN (r44, VIA_CR44_SECOND_CODEC_SUPPORT)
-			
-			);
-	}
+	if (rate > 48000)		rate = 48000;
+	if (rate < 4000) 		rate = 4000;
 	
-	DPRINTK("EXIT, returning %d\n", len);
-	return len;
+	via_ac97_write_reg (&card->ac97, AC97_POWER_CONTROL,
+		(via_ac97_read_reg (&card->ac97, AC97_POWER_CONTROL) & ~0x0200) |
+		0x0200);
+	via_ac97_write_reg (&card->ac97, AC97_PCM_FRONT_DAC_RATE, rate);
+	via_ac97_write_reg (&card->ac97, AC97_POWER_CONTROL,
+		via_ac97_read_reg (&card->ac97, AC97_POWER_CONTROL) & ~0x0200);
 
-#undef YN
+	DPRINTK ("EXIT, returning 0\n");
+	return rate;
 }
 
 
-/****************************************************************
- *
- * /proc/driver/via82cxxx
+/**
+ *	via_set_adc_rate - Set PCM rate for recording channel
+ *	@card: Private info for specified board
+ *	@rate: Desired PCM sample rate, in Khz
  *
+ *	Sets the PCM sample rate for a recording channel.
  *
+ *	FIXME:  @inhale_deeply argument to via_set_rate is ignored, and %AC97_PCM_FRONT_DAC_RATE
+ *	is the only rate which is really set.  Thus, this function will
+ *	not work until via_set_rate is fixed.
  */
 
-static int __init via_init_proc (void)
+static inline int via_set_adc_rate (struct via_info *card, int rate)
 {
-	DPRINTK ("ENTER\n");
-
-
-	proc_mkdir ("driver/via_audio", 0);
-	create_proc_read_entry ("driver/via_audio/info", 0, 0, via_info_read_proc, NULL);
-	
-	DPRINTK("EXIT\n");
-	return 0;
+	return via_set_rate (card, rate, 1);
 }
 
 
+/**
+ *	via_set_dac_rate - Set PCM rate for playback channel
+ *	@card: Private info for specified board
+ *	@rate: Desired PCM sample rate, in Khz
+ *
+ *	Sets the PCM sample rate for a playback channel.
+ */
 
-static void __exit via_cleanup_proc (void)
+static inline int via_set_dac_rate (struct via_info *card, int rate)
 {
-	DPRINTK ("ENTER\n");
-	remove_proc_entry ("driver/via_audio/info", NULL);
-	remove_proc_entry ("driver/via_audio", NULL);
-	DPRINTK("EXIT\n");
+	return via_set_rate (card, rate, 0);
 }
 
 
-#else
-#endif /* CONFIG_PROC_FS */
-
-#endif /* if 0 */
-
-static inline int via_init_proc (void) { return 0; }
-static inline void via_cleanup_proc (void) {}
-
-
-
 /****************************************************************
  *
- * Legacy SoundBlaster Pro, FM support via OSS
+ * Channel-specific operations
  *
  *
  */
+ 
+/**
+ *	via_chan_init - Initialize PCM channel
+ *	@card: Private audio chip info
+ *	@chan: Channel to be initialized
+ *	@chan_ofs: Offset from PCI address, which determines the
+ *		   set of SGD registers to use.
+ *
+ *	Performs all the preparations necessary to begin
+ *	using a PCM channel.
+ *
+ *	Currently the preparations include allocating the
+ *	scatter-gather DMA table and buffers, setting the
+ *	PCM channel to a known state, and passing the
+ *	address of the DMA table to the hardware.
+ *
+ *	Note that special care is taken when passing the
+ *	DMA table address to hardware, because it was found
+ *	during driver development that the hardware did not
+ *	always "take" the address.
+ */
 
-static void via_attach_sb(struct address_info *hw_config)
+static int via_chan_init (struct via_info *card, 
+			  struct via_channel *chan, long chan_ofs)
 {
+	int i;
+	unsigned long flags;
+	
 	DPRINTK ("ENTER\n");
 
-	if(!sb_dsp_init(hw_config))
-		hw_config->slots[0] = -1;
+	memset (chan, 0, sizeof (*chan));
 
-	DPRINTK("EXIT\n");
-}
+	/* alloc DMA-able memory for scatter-gather table */
+	chan->sgtable = pci_alloc_consistent (card->pdev,
+		(sizeof (struct via_sgd_table) * VIA_DMA_BUFFERS),
+		&chan->sgt_handle);
+	if (!chan->sgtable) {
+		printk (KERN_ERR PFX "DMA table alloc fail, aborting\n");
+		DPRINTK ("EXIT\n");
+		return -ENOMEM;
+	}
+	
+	memset ((void*)chan->sgtable, 0, 
+		(sizeof (struct via_sgd_table) * VIA_DMA_BUFFERS));
 
+	/* alloc DMA-able memory for scatter-gather buffers */
+	for (i = 0; i < VIA_DMA_BUFFERS; i++) {
+		chan->sgbuf[i].cpuaddr =
+			pci_alloc_consistent (card->pdev, VIA_DMA_BUF_SIZE,
+					      &chan->sgbuf[i].handle);
+
+		if (!chan->sgbuf[i].cpuaddr)
+			goto err_out_nomem;
+
+		if (i < (VIA_DMA_BUFFERS - 1))
+			chan->sgtable[i].count = cpu_to_le32 (VIA_DMA_BUF_SIZE | VIA_FLAG);
+		else
+			chan->sgtable[i].count = cpu_to_le32 (VIA_DMA_BUF_SIZE | VIA_EOL);
+		chan->sgtable[i].addr = cpu_to_le32 (chan->sgbuf[i].handle);
 
-static int via_probe_sb(struct address_info *hw_config)
-{
-	DPRINTK ("ENTER\n");
+#ifndef VIA_NDEBUG
+		memset (chan->sgbuf[i].cpuaddr, 0xBC, VIA_DMA_BUF_SIZE);
+#endif
 
-	if (check_region(hw_config->io_base, 16))
-	{
-		printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
-		       hw_config->io_base);
-		return 0;
+#if 1
+		DPRINTK ("dmabuf #%d (h=%lx, 32(h)=%lx, v2p=%lx, a=%p)\n",
+			 i, (long)chan->sgbuf[i].handle,
+			 (long)chan->sgtable[i].addr,
+			 virt_to_phys(chan->sgbuf[i].cpuaddr),
+			 chan->sgbuf[i].cpuaddr);
+#endif
 	}
-	DPRINTK("EXIT after sb_dsp_detect\n");
-	return sb_dsp_detect(hw_config, 0, 0);
-}
 
+	init_waitqueue_head (&chan->wait);
 
-static void via_unload_sb(struct address_info *hw_config)
-{
-	DPRINTK ("ENTER\n");
-
-	if(hw_config->slots[0] != -1)
-		sb_dsp_unload(hw_config, 1);
+	chan->pcm_fmt = VIA_PCM_FMT_MASK;
+	chan->iobase = card->baseaddr + chan_ofs;
+	
+	spin_lock_irqsave (&card->lock, flags);
 
-	DPRINTK("EXIT\n");
-}
+	/* stop any existing channel output */
+	via_chan_clear (chan);
+	via_chan_status_clear (chan->iobase);
+	via_chan_pcm_fmt (card, chan, 1);
+
+	spin_unlock_irqrestore (&card->lock, flags);
+
+	/* set location of DMA-able scatter-gather info table */
+	DPRINTK("outl (0x%X, 0x%04lX)\n",
+		cpu_to_le32 (chan->sgt_handle),
+		card->baseaddr + chan_ofs + VIA_PCM_TABLE_ADDR);
+
+	via_ac97_wait_idle (card);
+	outl (cpu_to_le32 (chan->sgt_handle),
+	      card->baseaddr + chan_ofs + VIA_PCM_TABLE_ADDR);
+	udelay (20);
+	via_ac97_wait_idle (card);
+	
+	DPRINTK("inl (0x%lX) = %x\n",
+		chan->iobase + VIA_PCM_TABLE_ADDR,
+		inl(chan->iobase + VIA_PCM_TABLE_ADDR));
 
+	DPRINTK ("EXIT\n");
+	return 0;
 
-static const struct {
-	int sb_irq,
-	    sb_dma,
-	    midi_base,
-	    sb_io_base;
-} via_pnp_data[] __initdata = {
-	{ 5, 0, 0x300, 0x220 },
-	{ 7, 1, 0x310, 0x240 },
-	{ 9, 2, 0x320, 0x260 },
-	{ 10,3, 0x330, 0x280 },
-};
+err_out_nomem:
+	printk (KERN_ERR PFX "DMA buffer alloc fail, aborting\n");
+	via_chan_free (card, chan);
+	DPRINTK ("EXIT\n");
+	return -ENOMEM;
+}
 
 
-/****************************************************************
- *
- * Chip setup and kernel registration
+/**
+ *	via_chan_free - Release a PCM channel
+ *	@card: Private audio chip info
+ *	@chan: Channel to be released
  *
+ *	Performs all the functions necessary to clean up
+ *	an initialized channel.
  *
+ *	Currently these functions include disabled any
+ *	active DMA operations, setting the PCM channel
+ *	back to a known state, and releasing any allocated
+ *	sound buffers.
  */
-
-static int __init via82cxxx_install (struct pci_dev *pcidev)
+ 
+static void via_chan_free (struct via_info *card, struct via_channel *chan)
 {
-	int sb_io_base;
-	int sb_irq;
-	int sb_dma;
-	int midi_base, rc;
-	u8 tmp8;
-	struct via_info *card = &cards[num_cards];
+	int i;
+	unsigned long flags;
 	
 	DPRINTK ("ENTER\n");
-
-	card->pdev = pcidev;
-	card->have_ac97 = -1;
 	
-	/* turn off legacy features, if not already */
-	pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
-	tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
-		  VIA_CR42_FM_ENABLE);
-	pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
+	synchronize_irq();
 
-	/* 
-	 * try to init AC97 mixer device
-	 */
-	rc = via_attach_ac97 (card);
-	if (rc) {
-		printk (KERN_WARNING PFX
-			"AC97 init failed, SB legacy mode only\n");
-	}
-	
-	/* turn on legacy features */
-	pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
-	tmp8 |= VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
-		VIA_CR42_FM_ENABLE;
-	pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
-
-	/* read legacy PNP info byte */
-	pci_read_config_byte (pcidev, VIA_PNP_CONTROL, &tmp8);
-	pci_write_config_byte (pcidev, VIA_PNP_CONTROL, tmp8);
-	
-	sb_irq = via_pnp_data[((tmp8 >> 6) & 0x03)].sb_irq;
-	sb_dma = via_pnp_data[((tmp8 >> 4) & 0x03)].sb_dma;
-	midi_base = via_pnp_data[((tmp8 >> 2) & 0x03)].midi_base;
-	sb_io_base = via_pnp_data[(tmp8 & 0x03)].sb_io_base;
-
-	udelay(100);
-	
-	printk(KERN_INFO PFX "legacy "
-	       "MIDI: 0x%X, SB: 0x%X / %d IRQ / %d DMA\n",
-		midi_base, sb_io_base, sb_irq, sb_dma);
-		
-	card->sb_data.name = VIA_CARD_NAME;
-	card->sb_data.card_subtype = MDL_SBPRO;
-	card->sb_data.io_base = sb_io_base;
-	card->sb_data.irq = sb_irq;
-	card->sb_data.dma = sb_dma;
-	
-	/* register legacy SoundBlaster Pro */
-	if (!via_probe_sb (&card->sb_data)) {
-		printk (KERN_ERR PFX
-			"SB probe @ 0x%X failed, aborting\n",
-			sb_io_base);
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
-	}
-	via_attach_sb (&card->sb_data);
-
-	card->opl3_data.name = card->sb_data.name;
-	card->opl3_data.io_base = midi_base;
-	card->opl3_data.irq = -1;
-	
-	/* register legacy MIDI */
-	if (!probe_uart401 (&card->opl3_data)) {
-		printk (KERN_WARNING PFX
-			"MIDI probe @ 0x%X failed, continuing\n",
-			midi_base);
-		card->opl3_data.io_base = 0;
-	} else {
-		attach_uart401 (&card->opl3_data);
+	spin_lock_irqsave (&card->lock, flags);
+
+	/* stop any existing channel output */
+	via_chan_stop (chan->iobase);
+	via_chan_status_clear (chan->iobase);
+	via_chan_pcm_fmt (card, chan, 1);
+
+	spin_unlock_irqrestore (&card->lock, flags);
+
+	/* zero location of DMA-able scatter-gather info table */
+	via_ac97_wait_idle(card);
+	outl (0, chan->iobase + VIA_PCM_TABLE_ADDR);
+
+	for (i = 0; i < VIA_DMA_BUFFERS; i++)
+		if (chan->sgbuf[i].cpuaddr) {
+			pci_free_consistent (card->pdev, VIA_DMA_BUF_SIZE,
+					     (void*)chan->sgbuf[i].cpuaddr,
+					     chan->sgbuf[i].handle);
+			chan->sgbuf[i].cpuaddr = NULL;
+			chan->sgbuf[i].handle = 0;
+		}
+
+	if (chan->sgtable) {
+		pci_free_consistent (card->pdev, 
+			(sizeof (struct via_sgd_table) * VIA_DMA_BUFFERS),
+			(void*)chan->sgtable, chan->sgt_handle);
+		chan->sgtable = NULL;
 	}
 
-	num_cards++;	
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
+	DPRINTK ("EXIT\n");
 }
 
 
-/*
- * 	This loop walks the PCI configuration database and finds where
- *	the sound cards are.
- *
- *	Note - only a single PCI scan occurs, eliminating possibility
- *	of multiple audio chips
+/**
+ *	via_chan_pcm_fmt - Update PCM channel settings
+ *	@card: Private audio chip info
+ *	@chan: Channel to be updated
+ *	@reset: Boolean.  If non-zero, channel will be reset
+ *		to 8-bit mono mode.
  *
+ *	Stores the settings of the current PCM format,
+ *	8-bit or 16-bit, and mono/stereo, into the
+ *	hardware settings for the specified channel.
+ *	If @reset is non-zero, the channel is reset
+ *	to 8-bit mono mode.  Otherwise, the channel
+ *	is set to the values stored in the channel
+ *	information struct @chan.
  */
  
-static int __init probe_via82cxxx (void)
+static void via_chan_pcm_fmt (struct via_info *card,
+			      struct via_channel *chan, int reset)
 {
-	struct pci_dev *pcidev = NULL;
+	DPRINTK ("ENTER, pcm_fmt=0x%02X, reset=%s\n",
+		 chan->pcm_fmt, reset ? "yes" : "no");
 
-	DPRINTK ("ENTER\n");
+	assert (card != NULL);
+	assert (chan != NULL);
 
-	pcidev = pci_find_device (PCI_VENDOR_ID_VIA,
-				  PCI_DEVICE_ID_VIA_82C686_5, NULL);
+	if (reset)
+		/* reset to 8-bit mono mode */
+		chan->pcm_fmt = 0;
+	
+	/* enable interrupts on FLAG and EOL */
+	chan->pcm_fmt |= VIA_CHAN_TYPE_MASK;
+	
+	/* set interrupt select bits where applicable (PCM & FM out channels) */
+	if (chan == &card->ch_out)
+		chan->pcm_fmt |= VIA_CHAN_TYPE_INT_SELECT;
+
+	outb (chan->pcm_fmt, chan->iobase + 2);
+
+	DPRINTK ("EXIT, pcm_fmt = 0x%02X, reg = 0x%02X\n",
+		 chan->pcm_fmt,
+		 inb (chan->iobase + 2));
+}
+
+
+/**
+ *	via_chan_clear - Stop DMA channel operation, and reset pointers
+ *	@chan: Channel to be cleared
+ *
+ *	Call via_chan_stop to halt DMA operations, and then resets
+ *	all software pointers which track DMA operation.
+ */
+
+static void via_chan_clear (struct via_channel *chan)
+{
+	via_chan_stop (chan->iobase);
+	atomic_set (&chan->state, sgd_stopped);
+	atomic_set (&chan->buf_in_use, 0);
+	atomic_set (&chan->next_buf, 0);
+}
+
+
+/**
+ *	via_chan_set_speed - Set PCM sample rate for given channel
+ *	@card: Private info for specified board
+ *	@chan: Channel whose sample rate will be adjusted
+ *	@val: New sample rate, in Khz
+ *
+ *	Helper function for the %SNDCTL_DSP_SPEED ioctl.  OSS semantics
+ *	demand that all audio operations halt (if they are not already
+ *	halted) when the %SNDCTL_DSP_SPEED is given.
+ *
+ *	This function halts all audio operations for the given channel
+ *	@chan, and then calls via_set_rate to set the audio hardware
+ *	to the new rate.
+ */
+
+static int via_chan_set_speed (struct via_info *card,
+			       struct via_channel *chan, int val)
+{
+	DPRINTK ("ENTER, requested rate = %d\n", val);
+
+	via_chan_clear (chan);
+
+	val = via_set_rate (card, val, chan == &card->ch_in);	
+	
+	DPRINTK ("EXIT, returning %d\n", val);
+	return val;
+}
+
+
+/**
+ *	via_chan_set_fmt - Set PCM sample size for given channel
+ *	@card: Private info for specified board
+ *	@chan: Channel whose sample size will be adjusted
+ *	@val: New sample size, use the %AFMT_xxx constants
+ *
+ *	Helper function for the %SNDCTL_DSP_SETFMT ioctl.  OSS semantics
+ *	demand that all audio operations halt (if they are not already
+ *	halted) when the %SNDCTL_DSP_SETFMT is given.
+ *
+ *	This function halts all audio operations for the given channel
+ *	@chan, and then calls via_chan_pcm_fmt to set the audio hardware
+ *	to the new sample size, either 8-bit or 16-bit.
+ */
+
+static int via_chan_set_fmt (struct via_info *card,
+			     struct via_channel *chan, int val)
+{
+	DPRINTK ("ENTER, val=%s\n",
+		 val == AFMT_U8 ? "AFMT_U8" :
+	 	 val == AFMT_S16_LE ? "AFMT_S16_LE" :
+		 "unknown");
+
+	via_chan_clear (chan);
+	
+	switch (val) {
+	case AFMT_U8:
+		chan->pcm_fmt &= ~VIA_PCM_FMT_16BIT;
+		via_chan_pcm_fmt (card, chan, 0);
+		break;
+	case AFMT_S16_LE:
+		chan->pcm_fmt |= VIA_PCM_FMT_16BIT;
+		via_chan_pcm_fmt (card, chan, 0);
+		break;
+	default:
+		printk (KERN_WARNING PFX "unknown AFMT\n");
+		val = -EINVAL;
+		break;
+	}
+	
+	DPRINTK ("EXIT, returning %d\n", val);
+	return val;
+}
+
+
+/**
+ *	via_chan_set_stereo - Enable or disable stereo for a DMA channel
+ *	@card: Private info for specified board
+ *	@chan: Channel whose stereo setting will be adjusted
+ *	@val: New sample size, use the %AFMT_xxx constants
+ *
+ *	Helper function for the %SNDCTL_DSP_CHANNELS and %SNDCTL_DSP_STEREO ioctls.  OSS semantics
+ *	demand that all audio operations halt (if they are not already
+ *	halted) when %SNDCTL_DSP_CHANNELS or SNDCTL_DSP_STEREO is given.
+ *
+ *	This function halts all audio operations for the given channel
+ *	@chan, and then calls via_chan_pcm_fmt to set the audio hardware
+ *	to enable or disable stereo.
+ */
+
+static int via_chan_set_stereo (struct via_info *card,
+			        struct via_channel *chan, int val)
+{
+	DPRINTK ("ENTER, channels = %d\n", val);
+
+	via_chan_clear (chan);
+	
+	switch (val) {
+
+	/* mono */
+	case 1:
+		chan->pcm_fmt &= ~VIA_PCM_FMT_STEREO;
+		via_chan_pcm_fmt (card, chan, 0);
+		break;
+
+	/* stereo */
+	case 2:
+		chan->pcm_fmt |= VIA_PCM_FMT_STEREO;
+		via_chan_pcm_fmt (card, chan, 0);
+		break;
+
+	/* unknown */
+	default:
+		printk (KERN_WARNING PFX "unknown number of channels\n");
+		val = -EINVAL;
+		break;
+	}
+	
+	DPRINTK ("EXIT, returning %d\n", val);
+	return val;
+}
+
+
+#if 0
+/**
+ *	via_chan_dump_bufs - Display DMA table contents
+ *	@chan: Channel whose DMA table will be displayed
+ *
+ *	Debugging function which displays the contents of the
+ *	scatter-gather DMA table for the given channel @chan.
+ */
+
+static void via_chan_dump_bufs (struct via_channel *chan)
+{
+	int i;
+	
+	for (i = 0; i < VIA_DMA_BUFFERS; i++) {
+		DPRINTK ("#%02d: addr=%x, count=%u, flag=%d, eol=%d\n",
+			 i, chan->sgtable[i].addr,
+			 chan->sgtable[i].count & 0x00FFFFFF,
+			 chan->sgtable[i].count & VIA_FLAG ? 1 : 0,
+			 chan->sgtable[i].count & VIA_EOL ? 1 : 0);
+	}
+	DPRINTK ("buf_in_use = %d, nextbuf = %d\n",
+		 atomic_read (&chan->buf_in_use),
+		 atomic_read (&chan->next_buf));
+}
+#endif
+
+
+/****************************************************************
+ *
+ * Interface to ac97-codec module
+ *
+ *
+ */
+ 
+/**
+ *	via_ac97_wait_idle - Wait until AC97 codec is not busy
+ *	@card: Private info for specified board
+ *
+ *	Sleep until the AC97 codec is no longer busy.
+ *	Returns the final value read from the SGD
+ *	register being polled.
+ */
+
+static u8 via_ac97_wait_idle (struct via_info *card)
+{
+	u8 tmp8;
+	int counter = VIA_COUNTER_LIMIT;
+	
+	DPRINTK ("ENTER/EXIT\n");
+
+	assert (card != NULL);
+	assert (card->pdev != NULL);
+	
+	do {
+		if (current->need_resched)
+			schedule ();
+		else
+			udelay (10);
+
+		spin_lock_irq (&card->lock);
+		tmp8 = inb (card->baseaddr + 0x83);
+		spin_unlock_irq (&card->lock);
+	} while ((tmp8 & VIA_CR83_BUSY) && (counter-- > 0));
+
+	return tmp8;
+}
+
+
+/**
+ *	via_ac97_read_reg - Read AC97 standard register
+ *	@codec: Pointer to generic AC97 codec info
+ *	@reg: Index of AC97 register to be read
+ *
+ *	Read the value of a single AC97 codec register,
+ *	as defined by the Intel AC97 specification.
+ *
+ *	Defines the standard AC97 read-register operation
+ *	required by the kernel's ac97_codec interface.
+ *
+ *	Returns the 16-bit value stored in the specified
+ *	register.
+ */
+
+static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg)
+{
+	u32 data;
+	struct via_info *card;
+	int counter;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (codec != NULL);
+	assert (codec->private_data != NULL);
+
+	card = codec->private_data;
+
+	data = (reg << 16) | VIA_CR80_READ;
+
+	outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL);
+	udelay (20);
+
+	for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) {
+		if (inl (card->baseaddr + 0x80) & VIA_CR80_VALID)
+			goto out;
+		udelay(10);
+		if (current->need_resched)
+			schedule ();
+	}
+
+	printk (KERN_WARNING PFX "timeout while reading AC97 codec\n");
+	goto err_out;
+
+out:
+	data = inl (card->baseaddr + 0x80);
+	outb (0x02, card->baseaddr + 0x83);
+
+	if (((data & 0x007F0000) >> 16) == reg) {
+		DPRINTK ("EXIT, success, data=0x%x, retval=0x%x\n",
+			 data, data & 0x0000FFFF);
+		return data & 0x0000FFFF;
+	}
+
+	DPRINTK ("WARNING: not our index: reg=0x%x, newreg=0x%x\n",
+		 reg, ((data & 0x007F0000) >> 16));
+
+err_out:
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+/**
+ *	via_ac97_write_reg - Write AC97 standard register
+ *	@codec: Pointer to generic AC97 codec info
+ *	@reg: Index of AC97 register to be written
+ *	@value: Value to be written to AC97 register
+ *
+ *	Write the value of a single AC97 codec register,
+ *	as defined by the Intel AC97 specification.
+ *
+ *	Defines the standard AC97 write-register operation
+ *	required by the kernel's ac97_codec interface.
+ */
+
+static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value)
+{
+	u32 data;
+	struct via_info *card;
+	int counter;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (codec != NULL);
+	assert (codec->private_data != NULL);
+
+	card = codec->private_data;
+
+	data = (reg << 16) + value;
+	outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL);
+	udelay (20);
+
+	for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) {
+		if ((inb (card->baseaddr + 0x83) & VIA_CR83_BUSY) == 0)
+			goto out;
+		udelay(10);
+		if (current->need_resched)
+			schedule ();
+	}
+	
+	printk (KERN_WARNING PFX "timeout after AC97 codec write\n");
+
+out:
+	DPRINTK ("EXIT\n");
+}
+
+
+static int via_mixer_open (struct inode *inode, struct file *file)
+{
+	int minor = MINOR(inode->i_rdev);
+	struct via_info *card;
+	
+	DPRINTK ("ENTER\n");
+	
+	MOD_INC_USE_COUNT;
+
+	assert (via_driver_data != NULL);
+			
+	card = via_driver_data;
+	if (card->ac97.dev_mixer == minor)
+		goto match;
+
+	DPRINTK ("EXIT, returning -ENODEV\n");
+	MOD_DEC_USE_COUNT;
+	return -ENODEV;
+
+match:
+	file->private_data = &card->ac97;
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+static int via_mixer_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
+			    unsigned long arg)
+{
+	struct ac97_codec *codec = file->private_data;
+	int rc;
+
+	assert (codec != NULL);
+	
+	rc = codec->mixer_ioctl(codec, cmd, arg);
+	
+	return rc;
+}
+
+
+static loff_t via_llseek(struct file *file, loff_t offset, int origin)
+{
+	DPRINTK ("ENTER\n");
+
+	DPRINTK("EXIT, returning -ESPIPE\n");
+	return -ESPIPE;
+}
+
+
+
+static int via_mixer_release(struct inode *inode, struct file *file)
+{
+        MOD_DEC_USE_COUNT;
+        return 0;
+}
+
+static struct file_operations via_mixer_fops = {
+	open:		via_mixer_open,
+	release:	via_mixer_release,
+	llseek:		via_llseek,
+	ioctl:		via_mixer_ioctl,
+};
+
+
+#if 0 /* values reasoned from debugging dumps of via's driver */
+static struct {
+	u8 reg;
+	u16 data;
+} mixer_init_vals[] __devinitdata = {
+	{ 0x2, 0x404 },
+	{ 0x4, 0x404 },
+	{ 0x6, 0x404 },
+	{ 0x18, 0x404 },
+	{ 0x10, 0x404 },
+	{ 0x1a, 0x404 },
+	{ 0x1c, 0x404 },
+	{ 0x1a, 0x404 },
+	{ 0x1c, 0xc0c },
+	{ 0x12, 0x808 },
+	{ 0x10, 0x808 },
+	{ 0xe, 0x2 },
+	{ 0x2, 0x808 },
+	{ 0x18, 0x808 },
+};
+#endif
+
+
+static int __init via_ac97_reset (struct via_info *card)
+{
+	struct pci_dev *pdev = card->pdev;
+	u8 tmp8;
+	u16 tmp16;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (pdev != NULL);
+	
+#ifndef NDEBUG
+	{
+		u8 r40,r41,r42,r43,r44,r48;
+		pci_read_config_byte (card->pdev, 0x40, &r40);
+		pci_read_config_byte (card->pdev, 0x41, &r41);
+		pci_read_config_byte (card->pdev, 0x42, &r42);
+		pci_read_config_byte (card->pdev, 0x43, &r43);
+		pci_read_config_byte (card->pdev, 0x44, &r44);
+		pci_read_config_byte (card->pdev, 0x48, &r48);
+		DPRINTK("PCI config: %02X %02X %02X %02X %02X %02X\n",
+			r40,r41,r42,r43,r44,r48);
+
+		spin_lock_irq (&card->lock);
+		DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
+			 inb (card->baseaddr + 0x00),
+			 inb (card->baseaddr + 0x01),
+			 inb (card->baseaddr + 0x02),
+			 inl (card->baseaddr + 0x04),
+			 inl (card->baseaddr + 0x0C),
+			 inl (card->baseaddr + 0x80),
+			 inl (card->baseaddr + 0x84));
+		spin_unlock_irq (&card->lock);
+		
+	}
+#endif
+
+        /*
+         * reset AC97 controller: enable, disable, enable
+         * pause after each command for good luck
+         */
+        pci_write_config_byte (pdev, VIA_ACLINK_CTRL, VIA_CR41_AC97_ENABLE |
+                               VIA_CR41_AC97_RESET | VIA_CR41_AC97_WAKEUP);
+        udelay (100);
+ 
+        pci_write_config_byte (pdev, VIA_ACLINK_CTRL, 0);
+        udelay (100);
+ 
+        pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
+			       VIA_CR41_AC97_ENABLE | VIA_CR41_PCM_ENABLE |
+                               VIA_CR41_VRA | VIA_CR41_AC97_RESET);
+        udelay (100);
+
+#if 0 /* this breaks on K7M */
+	/* disable legacy stuff */
+	pci_write_config_byte (pdev, 0x42, 0x00);
+	udelay(10);
+#endif
+
+	/* route FM trap to IRQ, disable FM trap */
+	pci_write_config_byte (pdev, 0x48, 0x05);
+	udelay(10);
+	
+	/* disable all codec GPI interrupts */
+	outl (0, pci_resource_start (pdev, 0) + 0x8C);
+
+	/* enable variable rate */
+	tmp16 = via_ac97_read_reg (&card->ac97, 0x2A);
+	via_ac97_write_reg (&card->ac97, 0x2A, tmp16 | 0x01);
+	
+	/* boost headphone vol if disabled */
+	tmp16 = via_ac97_read_reg (&card->ac97, AC97_HEADPHONE_VOL);
+	if (tmp16 == 0)
+		via_ac97_write_reg (&card->ac97, AC97_HEADPHONE_VOL, 0x1F1F);
+	
+	pci_read_config_byte (pdev, VIA_ACLINK_CTRL, &tmp8);
+	if ((tmp8 & (VIA_CR41_AC97_ENABLE | VIA_CR41_AC97_RESET)) == 0) {
+		printk (KERN_ERR PFX "cannot enable AC97 controller, aborting\n");
+		DPRINTK ("EXIT, tmp8=%X, returning -ENODEV\n", tmp8);
+		return -ENODEV;
+	}
+	
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+static int __init via_ac97_init (struct via_info *card)
+{
+	int rc;
+	u16 tmp16;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (card != NULL);
+
+	memset (&card->ac97, 0, sizeof (card->ac97));	
+	card->ac97.private_data = card;
+	card->ac97.codec_read = via_ac97_read_reg;
+	card->ac97.codec_write = via_ac97_write_reg;
+	
+	card->ac97.dev_mixer = register_sound_mixer (&via_mixer_fops, -1);
+	if (card->ac97.dev_mixer < 0) {
+		printk (KERN_ERR PFX "unable to register AC97 mixer, aborting\n");
+		DPRINTK("EXIT, returning -EIO\n");
+		return -EIO;
+	}
+
+	rc = via_ac97_reset (card);
+	if (rc) {
+		printk (KERN_ERR PFX "unable to reset AC97 codec, aborting\n");
+		goto err_out;
+	}
+
+	if (ac97_probe_codec (&card->ac97) == 0) {
+		printk (KERN_ERR PFX "unable to probe AC97 codec, aborting\n");
+		rc = -EIO;
+		goto err_out;
+	}
+
+	tmp16 = via_ac97_read_reg (&card->ac97, 0x2A);
+	via_ac97_write_reg (&card->ac97, 0x2A, tmp16 | 0x01);
+	
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+
+err_out:
+	unregister_sound_mixer (card->ac97.dev_mixer);
+	DPRINTK("EXIT, returning %d\n", rc);
+	return rc;
+}
+
+
+static void via_ac97_cleanup (struct via_info *card)
+{
+	DPRINTK("ENTER\n");
+	
+	assert (card != NULL);
+	assert (card->ac97.dev_mixer >= 0);
+	
+	unregister_sound_mixer (card->ac97.dev_mixer);
+
+	DPRINTK("EXIT\n");
+}
+
+
+
+/****************************************************************
+ *
+ * Interrupt-related code
+ *
+ */
+ 
+static inline void via_interrupt_write (struct via_channel *chan)
+{
+	assert (atomic_read(&chan->buf_in_use) <
+		atomic_read(&chan->next_buf));
+
+	/* XXX sanity check: read h/w counter to 
+	 * ensure no lost frames */
+
+	atomic_inc (&chan->buf_in_use);
+
+	/* if SG ptr catches up with userland ptr, stop playback */
+	if (atomic_read(&chan->buf_in_use) == atomic_read(&chan->next_buf)) {
+		atomic_set (&chan->state, sgd_stopped);
+		via_chan_stop (chan->iobase);
+	}
+
+	/* wake up anybody listening */
+	if (waitqueue_active (&chan->wait))
+		wake_up (&chan->wait);
+}
+
+
+
+static void via_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct via_info *card = dev_id;
+	struct via_channel *chan;
+	u8 status;
+
+	status = inb (card->baseaddr + 0x00);
+	if (status) {
+		assert (card->open_mode & FMODE_WRITE);
+		
+		chan = &card->ch_out;
+		
+		if (status & VIA_SGD_FLAG) {
+			assert ((status & VIA_SGD_EOL) == 0);
+			outb (VIA_SGD_FLAG, chan->iobase + 0x00);
+			DPRINTK("FLAG intr, status=0x%02X\n", status);
+			via_interrupt_write (chan);
+		}
+		
+		if (status & VIA_SGD_EOL) {
+			assert ((status & VIA_SGD_FLAG) == 0);
+			outb (VIA_SGD_EOL, chan->iobase + 0x00);
+			DPRINTK("EOL intr, status=0x%02X\n", status);
+			via_interrupt_write (chan);
+		}
+		
+		if (status & VIA_SGD_STOPPED) {
+			outb (VIA_SGD_STOPPED, chan->iobase + 0x00);
+			DPRINTK("STOPPED intr, status=0x%02X\n", status);
+		}
+
+#if 0
+		via_chan_dump_bufs (&card->ch_out);
+#endif
+	}
+}
+
+
+static void via_interrupt_disable (struct via_info *card)
+{
+	u8 tmp8;
+	unsigned long flags;
+
+	DPRINTK ("ENTER\n");
+
+	assert (card != NULL);
+	
+	spin_lock_irqsave (&card->lock, flags);
+
+	pci_read_config_byte (card->pdev, VIA_FM_NMI_CTRL, &tmp8);
+	if ((tmp8 & VIA_CR48_FM_TRAP_TO_NMI) == 0) {
+		tmp8 |= VIA_CR48_FM_TRAP_TO_NMI;
+		pci_write_config_byte (card->pdev, VIA_FM_NMI_CTRL, tmp8);
+	}
+
+	outb (inb (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE) &
+	      VIA_INT_DISABLE_MASK,
+	      card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
+	outb (inb (card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE) &
+	      VIA_INT_DISABLE_MASK,
+	      card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
+	outb (inb (card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE) &
+	      VIA_INT_DISABLE_MASK,
+	      card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
+
+	spin_unlock_irqrestore (&card->lock, flags);
+
+	DPRINTK ("EXIT\n");
+}
+
+
+static int via_interrupt_init (struct via_info *card)
+{
+	DPRINTK ("ENTER\n");
+
+	assert (card != NULL);
+	assert (card->pdev != NULL);
+	
+	/* check for sane IRQ number. can this ever happen? */
+	if (card->pdev->irq < 2) {
+		printk (KERN_ERR PFX "insane IRQ %d, aborting\n",
+			card->pdev->irq);
+		DPRINTK ("EXIT, returning -EIO\n");
+		return -EIO;
+	}
+	
+	if (request_irq (card->pdev->irq, via_interrupt, SA_SHIRQ, VIA_MODULE_NAME, card)) {
+		printk (KERN_ERR PFX "unable to obtain IRQ %d, aborting\n",
+			card->pdev->irq);
+		DPRINTK ("EXIT, returning -EBUSY\n");
+		return -EBUSY;
+	}
+
+	/* we don't want interrupts until we're opened */
+	via_interrupt_disable (card);
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+static void via_interrupt_cleanup (struct via_info *card)
+{
+	DPRINTK ("ENTER\n");
+
+	assert (card != NULL);
+	assert (card->pdev != NULL);
+
+	via_interrupt_disable (card);
+
+	free_irq (card->pdev->irq, card);
+
+	DPRINTK ("EXIT\n");
+}
+
+
+/****************************************************************
+ *
+ * OSS DSP device
+ *
+ */
+ 
+static struct file_operations via_dsp_fops = {
+	open:		via_dsp_open,
+	release:	via_dsp_release,
+	read:		via_dsp_read,
+	write:		via_dsp_write,
+	poll:		via_dsp_poll,
+	llseek: 	via_llseek,
+	ioctl:		via_dsp_ioctl,
+};
+
+
+static int __init via_dsp_init (struct via_info *card)
+{
+	u8 tmp8;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (card != NULL);
+
+	/* turn off legacy features, if not already */
+	pci_read_config_byte (card->pdev, VIA_FUNC_ENABLE, &tmp8);
+	tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
+		  VIA_CR42_FM_ENABLE);
+	pci_write_config_byte (card->pdev, VIA_FUNC_ENABLE, tmp8);
 
-	if (!pcidev || via82cxxx_install (pcidev) != 0) {
-		printk (KERN_ERR PFX "audio init failed\n");
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
-	}
+	via_stop_everything (card);
 
+	card->dev_dsp = register_sound_dsp (&via_dsp_fops, -1);
+	if (card->dev_dsp < 0) {
+		DPRINTK ("EXIT, returning -ENODEV\n");
+		return -ENODEV;
+	}
 	DPRINTK ("EXIT, returning 0\n");
 	return 0;
 }
 
 
-/*
- *	This function is called when the user or kernel loads the 
- *	module into memory.
- */
+static void via_dsp_cleanup (struct via_info *card)
+{
+	DPRINTK ("ENTER\n");
 
+	assert (card != NULL);
+	assert (card->dev_dsp >= 0);
+
+	via_stop_everything (card);
+
+	unregister_sound_dsp (card->dev_dsp);
+
+	DPRINTK ("EXIT\n");
+}
 
-static int init_via82cxxx_module(void)
+
+static ssize_t via_dsp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
-	u8 tmp;
-	int i;
-	const char *rev = "unknown!";
+	struct via_info *card;
+
+	DPRINTK ("ENTER\n");
 	
-	memset (cards, 0, sizeof (cards));
+	assert (file != NULL);
+	assert (buffer != NULL);
+	card = file->private_data;
+	assert (card != NULL);
+
+	DPRINTK("EXIT, returning -EINVAL\n");
+	return -EINVAL;
+}
+
+
+
+#define sgcount(n) (sgtable[(n)].count & 0x00FFFFFF)
+#define NEXTBUF (atomic_read(&chan->next_buf) % VIA_DMA_BUFFERS)
+#define BUF_IN_USE (atomic_read(&chan->buf_in_use) % VIA_DMA_BUFFERS)
+#define STATE_STOPPED (atomic_read (state) == sgd_stopped)
+#define STATE_STARTED (atomic_read (state) == sgd_in_progress)
+static ssize_t via_dsp_do_write (struct via_info *card,
+				 const char *userbuf, size_t count,
+				 int non_blocking)
+{
+	const char *orig_userbuf = userbuf;
+	struct via_channel *chan = &card->ch_out;
+	volatile struct via_sgd_table *sgtable = chan->sgtable;
+	atomic_t *state = &chan->state;
+	size_t size;
+	int nextbuf, prevbuf, n, realcount;
+	ssize_t rc;
+	
+	while (count > 0) {
+		if (current->need_resched)
+			schedule ();
+
+		spin_lock_irq (&card->lock);
+		DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
+			 inb (card->baseaddr + 0x00),
+			 inb (card->baseaddr + 0x01),
+			 inb (card->baseaddr + 0x02),
+			 inl (card->baseaddr + 0x04),
+			 inl (card->baseaddr + 0x0C),
+			 inl (card->baseaddr + 0x80),
+			 inl (card->baseaddr + 0x84));
+		spin_unlock_irq (&card->lock);
+		
+		size = (count < VIA_DMA_BUF_SIZE) ? count : VIA_DMA_BUF_SIZE;
+
+		/* case 1: SGD not active, list is ours for the mangling */
+
+		if (STATE_STOPPED) {
+			DPRINTK ("case 1\n");
+
+			if (copy_from_user ((void*)chan->sgbuf[0].cpuaddr,
+					     userbuf, size))
+				return -EFAULT;
+
+			assert (sgtable[0].addr == cpu_to_le32 (chan->sgbuf[0].handle));
+			sgtable[0].count = size | VIA_FLAG;
+
+			atomic_set (state, sgd_in_progress);
+			atomic_set (&chan->buf_in_use, 0);
+			atomic_set (&chan->next_buf, 1);
+			
+			count -= size;
+			userbuf += size;
+
+			spin_lock_irq (&card->lock);
+			sg_begin (chan);
+			spin_unlock_irq (&card->lock);
+
+			continue;
+		}
+
+		nextbuf = NEXTBUF;
+		if (nextbuf)
+			prevbuf = nextbuf - 1;
+		else
+			prevbuf = VIA_DMA_BUFFERS - 1;
+
+		/* case 2: if final buffer is (a) a fragment, and (b) not
+		 * currently being consumed by the SGD engine, then append
+		 * as much data as possible to the fragment. */
+
+		realcount = sgcount(prevbuf);
+		if (STATE_STARTED && (prevbuf != BUF_IN_USE) &&
+		    (realcount < VIA_DMA_BUF_SIZE)) {
+			DPRINTK ("case 2\n");
+			DPRINTK ("st=%d, fb=%d -- nb=%d, pb=%d, n=%d, rc=%d\n",
+				 atomic_read (state),
+				 BUF_IN_USE,
+				 nextbuf,
+				 prevbuf,
+				 prevbuf /* n */,
+				 realcount);
+
+			n = prevbuf;
+
+			if ((VIA_DMA_BUF_SIZE - realcount) < size)
+				size = VIA_DMA_BUF_SIZE - realcount;
+
+			if (copy_from_user ((void*)(chan->sgbuf[n].cpuaddr +
+					     realcount),
+					     userbuf, size))
+				return -EFAULT;
+
+			/* slack way to try and prevent races */
+			if (prevbuf == BUF_IN_USE || !STATE_STARTED)
+				continue;
+
+			assert (sgtable[n].addr == cpu_to_le32 (chan->sgbuf[n].handle));
+			if (n == (VIA_DMA_BUFFERS - 1))
+				sgtable[n].count = (realcount + size) | VIA_EOL;
+			else
+				sgtable[n].count = (realcount + size) | VIA_FLAG;
+
+			count -= size;
+			userbuf += size;
+			continue;
+		}
+
+		/* case 3: if there are buffers left, use one
+		 * XXX needs more review for possible races */
+
+		else if (STATE_STARTED && !via_chan_full (chan)) {
+			DPRINTK ("case 3\n");
+			DPRINTK ("st=%d, fb=%d -- nb=%d, pb=%d, n=%d\n",
+				 atomic_read (state),
+				 BUF_IN_USE,
+				 nextbuf,
+				 prevbuf,
+				 nextbuf /* n */);
+
+			n = nextbuf;
+
+			if (copy_from_user ((void*)chan->sgbuf[n].cpuaddr,
+					     userbuf, size))
+				return -EFAULT;
+
+			if (n == (VIA_DMA_BUFFERS - 1))
+				sgtable[n].count = size | VIA_EOL;
+			else
+				sgtable[n].count = size | VIA_FLAG;
+
+			/* if SGD stopped during data copy or SG table update,
+			 * then loop back to the beginning without updating
+			 * any pointers.
+			 * ie. slack way to prevent race */
+			if (!STATE_STARTED)
+				continue;
+
+			atomic_inc (&chan->next_buf);
+
+			count -= size;
+			userbuf += size;
+			continue;
+		}
+
+		/* case 4, final SGT active case: no free buffers, wait for one */
+
+		else {
+			DPRINTK ("case 4\n");
+			DPRINTK ("st=%d, fb=%d -- nb=%d, pb=%d\n",
+				 atomic_read (state),
+				 BUF_IN_USE,
+				 nextbuf,
+				 prevbuf);
+
+			/* if playback stopped, no need to sleep */
+			if (!STATE_STARTED)
+				continue;
+			
+			/* if buffer free, no need to sleep */
+			if (!via_chan_full (chan))
+				continue;
+			
+			if (non_blocking) {
+				rc = userbuf - orig_userbuf;
+				if (rc == 0)
+					rc = -EAGAIN;
+				return rc;
+			}
+
+			DPRINTK ("sleeping\n");
+			interruptible_sleep_on (&chan->wait);
+			if (signal_pending (current))
+				return -ERESTARTSYS;
+		}
+	}
+
+#if 0
+	{
+		u8 r40,r41,r42,r43,r44,r48;
+		pci_read_config_byte (card->pdev, 0x40, &r40);
+		pci_read_config_byte (card->pdev, 0x41, &r41);
+		pci_read_config_byte (card->pdev, 0x42, &r42);
+		pci_read_config_byte (card->pdev, 0x43, &r43);
+		pci_read_config_byte (card->pdev, 0x44, &r44);
+		pci_read_config_byte (card->pdev, 0x48, &r48);
+		DPRINTK("PCI config: %02X %02X %02X %02X %02X %02X\n",
+			r40,r41,r42,r43,r44,r48);
+	}
+#endif
+
+	DPRINTK ("EXIT, returning %d\n",
+		 userbuf - orig_userbuf);
+	return userbuf - orig_userbuf;
+}
+#undef sgcount
+#undef NEXTBUF
+#undef BUF_IN_USE
+#undef STATE_STOPPED
+#undef STATE_STARTED
+
+
+static ssize_t via_dsp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	struct via_info *card;
+	ssize_t rc;
+
+	DPRINTK ("ENTER, file=%p, buffer=%p, count=%u, ppos=%lu\n",
+		 file, buffer, count, ppos ? ((unsigned long)*ppos) : 0);
 	
+	assert (file != NULL);
+	assert (buffer != NULL);
+	card = file->private_data;
+	assert (card != NULL);
+
+	if (ppos != &file->f_pos) {
+		DPRINTK ("EXIT, returning -ESPIPE\n");
+		return -ESPIPE;
+	}
+
+	rc = via_dsp_do_write (card, buffer, count, (file->f_flags & O_NONBLOCK));
+
+	DPRINTK("EXIT, returning %ld\n",(long) rc);
+	return rc;
+}
+
+
+static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct via_info *card;
+	unsigned int mask = 0;
+
 	DPRINTK ("ENTER\n");
 
-	if (!pci_present ()) {
-		printk (KERN_DEBUG PFX "PCI not present, exiting\n");
-		DPRINTK ("EXIT, returning -ENODEV\n");
-		return -ENODEV;
+	assert (file != NULL);
+	assert (wait != NULL);
+	card = file->private_data;
+	assert (card != NULL);
+
+	if ((file->f_mode & FMODE_WRITE) &&
+	    (atomic_read (&card->ch_out.state) != sgd_stopped)) {
+		poll_wait(file, &card->ch_out.wait, wait);
+		
+		/* XXX is this correct */
+		if (atomic_read (&card->ch_out.buf_in_use) <
+		    atomic_read (&card->ch_out.next_buf))
+			mask |= POLLOUT | POLLWRNORM;
 	}
 
-	if (probe_via82cxxx() != 0) {
-		printk(KERN_ERR PFX "probe failed, aborting\n");
-		/* XXX unload cards registered so far, if any */
-		DPRINTK ("EXIT, returning -ENODEV\n");
-		return -ENODEV;
+	DPRINTK("EXIT, returning %u\n", mask);
+	return mask;
+}
+
+
+static int via_dsp_drain_dac (struct via_info *card, int non_block)
+{
+	DPRINTK ("ENTER, non_block = %d\n", non_block);
+
+	while (!via_chan_empty (&card->ch_out)) {
+		if (non_block) {
+			DPRINTK ("EXIT, returning -EBUSY\n");
+			return -EBUSY;
+		}
+		if (signal_pending (current)) {
+			DPRINTK ("EXIT, returning -ERESTARTSYS\n");
+			return -ERESTARTSYS;
+		}
+
+#ifndef NDEBUG
+	{
+		u8 r40,r41,r42,r43,r44,r48;
+		pci_read_config_byte (card->pdev, 0x40, &r40);
+		pci_read_config_byte (card->pdev, 0x41, &r41);
+		pci_read_config_byte (card->pdev, 0x42, &r42);
+		pci_read_config_byte (card->pdev, 0x43, &r43);
+		pci_read_config_byte (card->pdev, 0x44, &r44);
+		pci_read_config_byte (card->pdev, 0x48, &r48);
+		DPRINTK("PCI config: %02X %02X %02X %02X %02X %02X\n",
+			r40,r41,r42,r43,r44,r48);
+
+		spin_lock_irq (&card->lock);
+		DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
+			 inb (card->baseaddr + 0x00),
+			 inb (card->baseaddr + 0x01),
+			 inb (card->baseaddr + 0x02),
+			 inl (card->baseaddr + 0x04),
+			 inl (card->baseaddr + 0x0C),
+			 inl (card->baseaddr + 0x80),
+			 inl (card->baseaddr + 0x84));
+		spin_unlock_irq (&card->lock);
+		
 	}
+#endif
 
-	pci_read_config_byte (cards[0].pdev, PCI_REVISION_ID, &tmp);
-	for (i = 0; i < arraysize(via_chip_revs); i++)
-		if (via_chip_revs[i].revision == tmp) {
-			rev = via_chip_revs[i].rev_name;
-			break;
-		}
-	printk (KERN_INFO PFX VIA_CARD_NAME " loaded\n");
-	printk (KERN_INFO PFX "Chip rev %s.  Features: SBPro compat%s%s\n",
-		rev,
-		cards[0].opl3_data.io_base == 0 ? "" : ", MPU-401 MIDI",
-		cards[0].have_ac97 == -1 ? "" : ", AC97 mixer");
-	
-	if (via_init_proc () != 0) {
-		printk (KERN_WARNING PFX
-			"Unable to init experimental /proc, ignoring\n");
+		DPRINTK ("sleeping\n");		
+		interruptible_sleep_on (&card->ch_out.wait);
 	}
+	
+	DPRINTK ("EXIT\n");
+	return 0;
+}
 
-	/*
-	 *	Binds us to the sound subsystem	
+
+static int via_dsp_ioctl_space (struct via_info *card,
+				struct via_channel *chan,
+				void *arg)
+{
+	audio_buf_info info;
+	int n;
+
+	info.fragstotal = VIA_DMA_BUFFERS;
+	info.fragsize = VIA_DMA_BUF_SIZE;
+
+	/* number of full fragments we can read without blocking */
+	n = atomic_read (&chan->next_buf) - atomic_read (&chan->buf_in_use);
+	info.fragments = VIA_DMA_BUFFERS - n;
+
+	/* number of bytes that can be read or written immediately
+	 * without blocking.  FIXME: we are lazy and ignore partially-full
+	 * buffers.
 	 */
-	SOUND_LOCK;
+	info.bytes = info.fragments * VIA_DMA_BUF_SIZE;
+
+	DPRINTK ("EXIT, returning fragstotal=%d, fragsize=%d, fragments=%d, bytes=%d\n",
+		info.fragstotal,
+		info.fragsize,
+		info.fragments,
+		info.bytes);
+
+	return copy_to_user (arg, &info, sizeof (info));
+}
+
+
+
+static int via_dsp_ioctl (struct inode *inode, struct file *file,
+			  unsigned int cmd, unsigned long arg)
+{
+	int rc = -EINVAL, rd=0, wr=0, val=0;
+	struct via_info *card;
+
+	DPRINTK ("ENTER, cmd = 0x%08X\n", cmd);
+
+	assert (file != NULL);
+	card = file->private_data;
+	assert (card != NULL);
+
+	if (file->f_mode & FMODE_WRITE)
+		wr = 1;
+	if (file->f_mode & FMODE_READ)
+		rd = 1;
+	
+	switch (cmd) {
+
+	/* OSS API version.  XXX unverified */		
+	case OSS_GETVERSION:
+		DPRINTK("EXIT, returning SOUND_VERSION\n");
+		return put_user (SOUND_VERSION, (int *)arg);
+
+	/* list of supported PCM data formats */
+	case SNDCTL_DSP_GETFMTS:
+		DPRINTK("EXIT, returning AFMT U8|S16_LE\n");
+                return put_user (AFMT_U8 | AFMT_S16_LE, (int *)arg);
+
+	/* query or set current channel's PCM data format */
+	case SNDCTL_DSP_SETFMT:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val != AFMT_QUERY) {
+			rc = 0;
+
+			spin_lock_irq (&card->lock);
+			if (rc == 0 && rd)
+				rc = via_chan_set_fmt (card, &card->ch_in, val);
+			if (rc == 0 && wr)
+				rc = via_chan_set_fmt (card, &card->ch_out, val);
+			spin_unlock_irq (&card->lock);
+
+			if (rc <= 0)
+				return rc ? rc : -EINVAL;
+			val = rc;
+		} else {
+			spin_lock_irq (&card->lock);
+			if ((rd && (card->ch_in.pcm_fmt & VIA_PCM_FMT_16BIT)) ||
+			    (wr && (card->ch_out.pcm_fmt & VIA_PCM_FMT_16BIT)))
+				val = AFMT_S16_LE;
+			else
+				val = AFMT_U8;
+			spin_unlock_irq (&card->lock);
+		}
+		DPRINTK("SETFMT EXIT, returning %d\n", val);
+                return put_user (val, (int *)arg);
+
+	/* query or set number of channels (1=mono, 2=stereo) */
+        case SNDCTL_DSP_CHANNELS:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val != 0) {
+			rc = 0;
+			spin_lock_irq (&card->lock);
+			if (rc == 0 && rd)
+				rc = via_chan_set_stereo (card, &card->ch_in, val);
+			if (rc == 0 && wr)
+				rc = via_chan_set_stereo (card, &card->ch_out, val);
+			spin_unlock_irq (&card->lock);
+			if (rc <= 0)
+				return rc ? rc : -EINVAL;
+			val = rc;
+		} else {
+			spin_lock_irq (&card->lock);
+			if ((rd && (card->ch_in.pcm_fmt & VIA_PCM_FMT_STEREO)) ||
+			    (wr && (card->ch_out.pcm_fmt & VIA_PCM_FMT_STEREO)))
+				val = 2;
+			else
+				val = 1;
+			spin_unlock_irq (&card->lock);
+		}
+		DPRINTK("CHANNELS EXIT, returning %d\n", val);
+                return put_user (val, (int *)arg);
+	
+	/* enable (val is not zero) or disable (val == 0) stereo */
+        case SNDCTL_DSP_STEREO:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		rc = 0;
+		spin_lock_irq (&card->lock);
+		if (rc == 0 && rd)
+			rc = via_chan_set_stereo (card, &card->ch_in, val ? 2 : 1);
+		if (rc == 0 && wr)
+			rc = via_chan_set_stereo (card, &card->ch_out, val ? 2 : 1);
+		spin_unlock_irq (&card->lock);
+		if (rc <= 0)
+			return rc ? rc : -EINVAL;
+		DPRINTK("STEREO EXIT, returning %d\n", val);
+                return 0;
+	
+	/* query or set sampling rate */
+        case SNDCTL_DSP_SPEED:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val < 0)
+			return -EINVAL;
+		if (val > 0) {
+			rc = 0;
+			spin_lock_irq (&card->lock);
+			if (rc == 0 && rd)
+				rc = via_chan_set_speed (card, &card->ch_in, val);
+			if (rc == 0 && wr)
+				rc = via_chan_set_speed (card, &card->ch_out, val);
+			spin_unlock_irq (&card->lock);
+			if (rc <= 0)
+				return rc ? rc : -EINVAL;
+			val = rc;
+		} else {
+			spin_lock_irq (&card->lock);
+			if (rd)
+				val = card->ch_in.rate;
+			else if (wr)
+				val = card->ch_out.rate;
+			else
+				val = 0;
+			spin_unlock_irq (&card->lock);
+		}
+		DPRINTK("SPEED EXIT, returning %d\n", val);
+                return put_user (val, (int *)arg);
+	
+	/* wait until all buffers have been played, and then stop device */
+	case SNDCTL_DSP_SYNC:
+		if (wr) {
+			DPRINTK("SYNC EXIT (after calling via_dsp_drain_dac)\n");
+			return via_dsp_drain_dac (card, file->f_flags & O_NONBLOCK);
+		}
+		break;
+
+	/* stop recording/playback immediately */
+        case SNDCTL_DSP_RESET:
+		spin_lock_irq (&card->lock);
+		if (rd) {
+			via_chan_clear (&card->ch_in);
+			via_chan_pcm_fmt (card, &card->ch_in, 1);
+		}
+		if (wr) {
+			via_chan_clear (&card->ch_out);
+			via_chan_pcm_fmt (card, &card->ch_out, 1);
+		}
+		spin_unlock_irq (&card->lock);
+		DPRINTK("RESET EXIT, returning 0\n");
+		return 0;
+
+	/* obtain bitmask of device capabilities, such as mmap, full duplex, etc. */
+	case SNDCTL_DSP_GETCAPS:
+		DPRINTK("GETCAPS EXIT\n");
+		return put_user(DSP_CAP_REVISION, (int *)arg);
+		
+	/* obtain bitmask of device capabilities, such as mmap, full duplex, etc. */
+	case SNDCTL_DSP_GETBLKSIZE:
+		DPRINTK("GETBLKSIZE EXIT\n");
+		return put_user(VIA_DMA_BUF_SIZE, (int *)arg);
+		
+	/* obtain information about input buffering */
+	case SNDCTL_DSP_GETISPACE:
+		DPRINTK("GETISPACE EXIT\n");
+		return via_dsp_ioctl_space (card, &card->ch_in, (void*) arg);
+	
+	/* obtain information about output buffering */
+	case SNDCTL_DSP_GETOSPACE:
+		DPRINTK("GETOSPACE EXIT\n");
+		return via_dsp_ioctl_space (card, &card->ch_out, (void*) arg);
+
+	/* return number of bytes remaining to be played by DMA engine */
+	case SNDCTL_DSP_GETODELAY:
+		{
+		int n;
+		
+		n = atomic_read (&card->ch_out.next_buf) -
+		    atomic_read (&card->ch_out.buf_in_use);
+		assert (n >= 0);
+
+		if (n == 0)
+			val = 0;
+		else {
+			val = (n - 1) * VIA_DMA_BUF_SIZE;
+			val += inl (card->ch_out.iobase + VIA_BASE0_PCM_OUT_BLOCK_COUNT);
+		}
+		
+		DPRINTK("GETODELAY EXIT, val = %d bytes\n", val);
+                return put_user (val, (int *)arg);
+		}
+
+	/* set fragment size.  implemented as a successful no-op for now */
+	case SNDCTL_DSP_SETFRAGMENT:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+
+		DPRINTK ("SNDCTL_DSP_SETFRAGMENT (fragshift==0x%04X (%d), maxfrags==0x%04X (%d))\n",
+			 val & 0xFFFF,
+			 val & 0xFFFF,
+			 (val >> 16) & 0xFFFF,
+			 (val >> 16) & 0xFFFF);
+
+		/* just to shut up some programs */
+		return 0;
+
+	/* inform device of an upcoming pause in input (or output).  not implemented */
+	case SNDCTL_DSP_POST:
+		DPRINTK("POST EXIT (null ioctl, returning -EINVAL)\n");
+                return -EINVAL;
+
+	/* not implemented */
+	default:
+		DPRINTK ("unhandled ioctl\n");
+		break;
+	}
+		
+	DPRINTK("EXIT, returning %d\n", rc);
+	return rc;
+}
+
+
+static int via_dsp_open (struct inode *inode, struct file *file)
+{
+	int open_mode, rc = -EINVAL, minor = MINOR(inode->i_rdev);
+	int got_read_chan = 0, is_busy;
+	struct via_info *card;
+	unsigned long flags;
+
+	DPRINTK ("ENTER, minor=%d, file->f_mode=0x%x\n", minor, file->f_mode);
+	
+	if (file->f_mode & FMODE_READ) /* no input ATM */
+		goto err_out;
+
+	card = NULL;
+	assert (via_driver_data != NULL);
+			
+	card = via_driver_data;	
+	DPRINTK ("dev_dsp = %d, minor = %d, assn = %d\n",
+		 card->dev_dsp, minor,
+		 (card->dev_dsp ^ minor) & ~0xf);
+
+	if (((card->dev_dsp ^ minor) & ~0xf) == 0)
+		goto match;
+	
+	DPRINTK ("no matching %s found\n", card ? "minor" : "driver");
+	rc = -ENODEV;
+	goto err_out;
+
+match:
+	file->private_data = card;
+
+	/* wait for device to become free */
+	spin_lock_irqsave (&card->lock, flags);
+	open_mode = card->open_mode;
+	if (open_mode & file->f_mode)
+		is_busy = 1;
+	else {
+		is_busy = 0;
+		card->open_mode |= file->f_mode;
+		open_mode = card->open_mode;
+	}
+	spin_unlock_irqrestore (&card->lock, flags);
+	if (is_busy) {
+		rc = -EBUSY;
+		goto err_out;
+	}
+
+	DPRINTK("open_mode now 0x%x\n", open_mode);
+
+	/* handle input from analog source */
+	if (file->f_mode & FMODE_READ) {
+		rc = via_chan_init (card, &card->ch_in, 0x10);
+		if (rc)
+			goto err_out_clear_mode;
+			
+		got_read_chan = 1;
+		
+		/* why is this forced to 16-bit stereo in all drivers? */
+		card->ch_in.pcm_fmt =
+			VIA_PCM_FMT_16BIT | VIA_PCM_FMT_STEREO;
+
+		spin_lock_irqsave (&card->lock, flags);
+		via_chan_pcm_fmt (card, &card->ch_out, 0);
+		spin_unlock_irqrestore (&card->lock, flags);
+
+		via_set_adc_rate (card, 8000);
+	}
+
+	/* handle output to analog source */
+	if (file->f_mode & FMODE_WRITE) {
+		rc = via_chan_init (card, &card->ch_out, 0x00);
+		if (rc)
+			goto err_out_clear_mode;
+		
+		if ((minor & 0xf) == SND_DEV_DSP16)
+			card->ch_out.pcm_fmt |= VIA_PCM_FMT_16BIT;
+
+		spin_lock_irqsave (&card->lock, flags);
+		via_chan_pcm_fmt (card, &card->ch_out, 0);
+		spin_unlock_irqrestore (&card->lock, flags);
+
+		via_set_dac_rate (card, 8000);
+	}
+
+	MOD_INC_USE_COUNT;
 	DPRINTK ("EXIT, returning 0\n");
 	return 0;
+
+err_out_clear_mode:
+	if (got_read_chan)
+		via_chan_free (card, &card->ch_in);
+	spin_lock_irqsave (&card->lock, flags);
+	card->open_mode &= ~file->f_mode;
+	spin_unlock_irqrestore (&card->lock, flags);
+err_out:
+	DPRINTK("ERROR EXIT, returning %d\n", rc);
+	return rc;
 }
 
-int init_module(void) {
-	return init_via82cxxx_module();
+
+static int via_dsp_release(struct inode *inode, struct file *file)
+{
+	struct via_info *card;
+	unsigned long flags;
+
+	DPRINTK ("ENTER\n");
+	
+	assert (file != NULL);
+	card = file->private_data;
+	assert (card != NULL);
+	
+	lock_kernel();
+	if (file->f_mode & FMODE_READ)
+		via_chan_free (card, &card->ch_in);
+
+	if (file->f_mode & FMODE_WRITE) {
+		via_dsp_drain_dac (card, file->f_flags & O_NONBLOCK);
+		via_chan_free (card, &card->ch_out);
+	}
+			
+	spin_lock_irqsave (&card->lock, flags);
+	card->open_mode &= ~(file->f_mode);
+	spin_unlock_irqrestore (&card->lock, flags);
+
+ 	wake_up (&card->open_wait);
+	unlock_kernel();
+
+	MOD_DEC_USE_COUNT;
+	DPRINTK("EXIT, returning 0\n");
+	return 0;
 }
 
-/*
- *	This is called when it is removed. It will only be removed 
- *	when its use count is 0. For sound the SOUND_LOCK/SOUND_UNLOCK
- *	macros hide the entire work for this.
+
+/****************************************************************
+ *
+ * Chip setup and kernel registration
+ *
+ *
  */
- 
-static void cleanup_via82cxxx_module(void)
+
+static int __init via_init_one (struct pci_dev *pdev)
 {
-	DPRINTK("ENTER\n");
+	int rc;
+	struct via_info *card;
+	u8 tmp;
+	static int printed_version = 0;
+	
+	DPRINTK ("ENTER\n");
 	
-	if (cards[0].opl3_data.io_base)
-		unload_uart401 (&cards[0].opl3_data);
+	if (printed_version++ == 0)
+		printk (KERN_INFO "Via 686a audio driver " VIA_VERSION "\n");
+
+	if (!check_region (pci_resource_start (pdev, 0),
+	    		     pci_resource_len (pdev, 0))) {
+		printk (KERN_ERR PFX "unable to obtain I/O resources, aborting\n");
+		rc = -EBUSY;
+		goto err_out;
+	}
+	request_region (pci_resource_start (pdev, 0),
+	    		pci_resource_len (pdev, 0), VIA_MODULE_NAME);
 
-	via_unload_sb (&cards[0].sb_data);
+	if (pci_enable_device (pdev)) {
+		rc = -EIO;
+		goto err_out_none;
+	}
 	
-	via_unload_ac97 (&cards[0]);
+	card = kmalloc (sizeof (*card), GFP_KERNEL);
+	if (!card) {
+		printk (KERN_ERR PFX "out of memory, aborting\n");
+		rc = -ENOMEM;
+		goto err_out_none;
+	}
+
+	via_driver_data = card;
+
+	memset (card, 0, sizeof (*card));
+	card->pdev = pdev;
+	card->baseaddr = pci_resource_start (pdev, 0);
+	card->card_num = via_num_cards++;
+	spin_lock_init (&card->lock);
+	init_waitqueue_head(&card->open_wait);
+	
+	/* if BAR 2 is present, chip is Rev H or later,
+	 * which means it has a few extra features */
+	if (pci_resource_start (pdev, 2) > 0)
+		card->rev_h = 1;
+
+	if (pdev->irq < 1) {
+		printk (KERN_ERR PFX "invalid PCI IRQ %d, aborting\n", pdev->irq);
+		rc = -ENODEV;
+		goto err_out_kfree;
+	}
+
+	/* 
+	 * init AC97 mixer and codec
+	 */
+	rc = via_ac97_init (card);
+	if (rc) {
+		printk (KERN_ERR PFX "AC97 init failed, aborting\n");
+		goto err_out_kfree;
+	}
 
-	via_cleanup_proc ();
+	/*
+	 * init DSP device
+	 */
+	rc = via_dsp_init (card);
+	if (rc) {
+		printk (KERN_ERR PFX "DSP device init failed, aborting\n");
+		goto err_out_have_mixer;
+	}
 	
 	/*
-	 *	Final clean up with the sound layer
+	 * init and turn on interrupts, as the last thing we do
 	 */
-	SOUND_LOCK_END;
+	rc = via_interrupt_init (card);
+	if (rc) {
+		printk (KERN_ERR PFX "interrupt init failed, aborting\n");
+		goto err_out_have_dsp;
+	}
+	
+	pci_read_config_byte (pdev, 0x3C, &tmp);
+	if ((tmp & 0x0F) != pdev->irq) {
+		printk (KERN_WARNING PFX "IRQ fixup, 0x3C==0x%02X\n", tmp);
+		tmp &= 0xF0;
+		tmp |= pdev->irq;
+		pci_write_config_byte (pdev, 0x3C, tmp);
+		DPRINTK("new 0x3c==0x%02x\n", tmp);
+	} else {
+		DPRINTK("IRQ reg 0x3c==0x%02x, irq==%d\n",
+			tmp, tmp & 0x0F);
+	}
 
-	DPRINTK("EXIT\n");
+	printk (KERN_INFO PFX "board #%d at 0x%04lX, IRQ %d\n",
+		card->card_num + 1, card->baseaddr, pdev->irq);
+	
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+
+err_out_have_dsp:
+	via_dsp_cleanup (card);
+
+err_out_have_mixer:
+	via_ac97_cleanup (card);
+
+err_out_kfree:
+#ifndef VIA_NDEBUG
+	memset (card, 0xAB, sizeof (*card)); /* poison memory */
+#endif
+	kfree (card);
+
+err_out_none:
+	release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));
+err_out:
+	via_driver_data = NULL;
+	DPRINTK ("EXIT - returning %d\n", rc);
+	return rc;
+}
+
+
+static void via_remove_one (struct pci_dev *pdev)
+{
+	struct via_info *card;
+	
+	DPRINTK ("ENTER\n");
+	
+	assert (pdev != NULL);
+	card = via_driver_data;
+	assert (card != NULL);
+	
+	via_interrupt_cleanup (card);
+	via_dsp_cleanup (card);
+	via_ac97_cleanup (card);
+
+	release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));
+
+#ifndef VIA_NDEBUG
+	memset (card, 0xAB, sizeof (*card)); /* poison memory */
+#endif
+	kfree (card);
+
+	via_driver_data = NULL;
+	
+	pci_set_power_state (pdev, 3); /* ...zzzzzz */
+
+	DPRINTK ("EXIT\n");
+	return;
+}
+
+
+/****************************************************************
+ *
+ * Driver initialization and cleanup
+ *
+ *
+ */
+
+static int __init init_via82cxxx_audio(void)
+{
+	DPRINTK ("ENTER\n");
+	
+	via_pdev = pci_find_device (PCI_VENDOR_ID_VIA,
+				    PCI_DEVICE_ID_VIA_82C686_5, NULL);
+	if (!via_pdev) return -ENODEV;
+
+	if (via_init_one (via_pdev)) {
+		DPRINTK ("EXIT, returning -ENODEV\n");
+		return -ENODEV;
+	}
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
 }
 
-void cleanup_module(void) {
-	cleanup_via82cxxx_module();
+ 
+static void cleanup_via82cxxx_audio(void)
+{
+	DPRINTK("ENTER\n");
+	
+	via_remove_one (via_pdev);
+	
+	via_pdev = via_driver_data = NULL;
+
+	DPRINTK("EXIT\n");
 }
 
+
+module_init(init_via82cxxx_audio);
+module_exit(cleanup_via82cxxx_audio);
diff -urN linux-2.2.18-pre9/drivers/usb/acm.c linux/drivers/usb/acm.c
--- linux-2.2.18-pre9/drivers/usb/acm.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/acm.c	Mon Dec  3 20:27:07 2001
@@ -690,3 +690,6 @@
 
 module_init(acm_init);
 module_exit(acm_exit);
+
+MODULE_AUTHOR("Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik");
+MODULE_DESCRIPTION("USB Abstract Control Model driver for USB modems and ISDN adapters");
diff -urN linux-2.2.18-pre9/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c
--- linux-2.2.18-pre9/drivers/usb/dabusb.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/dabusb.c	Mon Dec  3 20:27:07 2001
@@ -21,7 +21,7 @@
  *
  *
  *
- *  $Id: dabusb.c,v 1.45 2000/01/31 10:23:44 fliegl Exp $
+ *  $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $
  *
  */
 
@@ -38,6 +38,7 @@
 #include <asm/atomic.h>
 #include <linux/delay.h>
 #include <linux/usb.h>
+#include <linux/smp_lock.h>
 
 #include "dabusb.h"
 #include "dabfirmware.h"
@@ -271,16 +272,22 @@
 	else
 		pipe = usb_sndbulkpipe (s->usbdev, 2);
 
-	ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 1000);
+	ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100);
 	if(ret<0) {
 		err("dabusb: usb_bulk_msg failed(%d)",ret);
+
+		if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
+			err("set_interface failed");
+			return -EINVAL;
+		}
+
 	}
 	
 	if( ret == -EPIPE ) {
 		warn("CLEAR_FEATURE request to remove STALL condition.");
 		if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
 			err("request failed");
-		}
+	}
 
 	pb->size = actual_length;
 	return ret;
@@ -613,6 +620,7 @@
 
 	dbg("dabusb_release");
 
+	lock_kernel();
 	down (&s->mutex);
 	dabusb_stop (s);
 	dabusb_free_buffers (s);
@@ -626,6 +634,7 @@
 		wake_up (&s->remove_ok);
 
 	s->opened = 0;
+	unlock_kernel();
 	return 0;
 }
 
@@ -664,8 +673,9 @@
 			break;
 		}
 
-		dabusb_bulk (s, pbulk);
-		ret = copy_to_user ((void *) arg, pbulk, sizeof (bulk_transfer_t));
+		ret=dabusb_bulk (s, pbulk);
+		if(ret==0)
+			ret = copy_to_user ((void *) arg, pbulk, sizeof (bulk_transfer_t));
 		kfree (pbulk);
 		break;
 
@@ -791,14 +801,10 @@
 
 /* --------------------------------------------------------------------- */
 
-int __init dabusb_init (void)
+static int __init dabusb_init (void)
 {
 	unsigned u;
 
-	/* register misc device */
-	if (usb_register(&dabusb_driver))
-		return -1;
-
 	/* initialize struct */
 	for (u = 0; u < NRDABUSB; u++) {
 		pdabusb_t s = &dabusb[u];
@@ -813,11 +819,15 @@
 		INIT_LIST_HEAD (&s->rec_buff_list);
 	}
 
+	/* register misc device */
+	if (usb_register(&dabusb_driver))
+		return -1;
+
 	dbg("dabusb_init: driver registered");
 	return 0;
 }
 
-void __exit dabusb_cleanup (void)
+static void __exit dabusb_cleanup (void)
 {
 	dbg("dabusb_cleanup");
 
@@ -826,21 +836,12 @@
 
 /* --------------------------------------------------------------------- */
 
-#ifdef MODULE
 MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");
 MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999");
 MODULE_PARM (buffers, "i");
+MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
 
-int __init init_module (void)
-{
-	return dabusb_init ();
-}
-
-void __exit cleanup_module (void)
-{
-	dabusb_cleanup ();
-}
-
-#endif
+module_init (dabusb_init);
+module_exit (dabusb_cleanup);
 
 /* --------------------------------------------------------------------- */
diff -urN linux-2.2.18-pre9/drivers/usb/devices.c linux/drivers/usb/devices.c
--- linux-2.2.18-pre9/drivers/usb/devices.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/devices.c	Mon Dec  3 20:27:07 2001
@@ -45,6 +45,9 @@
  *   up an eventual usbd
  * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
  *   Turned into its own filesystem
+ * 2000-07-05: Ashley Montanaro <ashley@compsoc.man.ac.uk>
+ *   Converted file reading routine to dump to buffer once
+ *   per device, not per bus
  *
  * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $
  */
@@ -133,9 +136,11 @@
 	{USB_CLASS_COMM,		"comm."},
 	{USB_CLASS_HID,			"HID"},
 	{USB_CLASS_HUB,			"hub"},
+	{USB_CLASS_PHYSICAL,		"PID"},
 	{USB_CLASS_PRINTER,		"print"},
 	{USB_CLASS_MASS_STORAGE,	"stor."},
 	{USB_CLASS_DATA,		"data"},
+	{USB_CLASS_APP_SPEC,		"app."},
 	{USB_CLASS_VENDOR_SPEC,		"vend."},
 	{-1,				"unk."}		/* leave as last */
 };
@@ -367,23 +372,40 @@
 
 /*****************************************************************/
 
-static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev,
-			     struct usb_bus *bus, int level, int index, int count)
+/* This is a recursive function. Parameters:
+ * buffer - the user-space buffer to write data into
+ * nbytes - the maximum number of bytes to write
+ * skip_bytes - the number of bytes to skip before writing anything
+ * file_offset - the offset into the devices file on completion
+ */
+static ssize_t usb_device_dump(char **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset,
+				struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count)
 {
 	int chix;
-	int cnt = 0;
+	int ret, cnt = 0;
 	int parent_devnum = 0;
-
+	char *pages_start, *data_end;
+	unsigned int length;
+	ssize_t total_written = 0;
+	
+	/* don't bother with anything else if we're not writing any data */
+	if (*nbytes <= 0)
+		return 0;
+	
 	if (level > MAX_TOPO_LEVEL)
-		return start;
+		return total_written;
+	/* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
+        if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
+                return -ENOMEM;
+		
 	if (usbdev->parent && usbdev->parent->devnum != -1)
 		parent_devnum = usbdev->parent->devnum;
 	/*
 	 * So the root hub's parent is 0 and any device that is
 	 * plugged into the root hub has a parent of 0.
 	 */
-	start += sprintf(start, format_topo, bus->busnum, level, parent_devnum, index, count,
-			 usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
+	data_end = pages_start + sprintf(pages_start, format_topo, bus->busnum, level, parent_devnum, index, count,
+					usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
 	/*
 	 * level = topology-tier level;
 	 * parent_devnum = parent device number;
@@ -392,30 +414,58 @@
 	 */
 	/* If this is the root hub, display the bandwidth information */
 	if (level == 0)
-		start += sprintf(start, format_bandwidth, bus->bandwidth_allocated, 
+		data_end += sprintf(data_end, format_bandwidth, bus->bandwidth_allocated,
 				FRAME_TIME_MAX_USECS_ALLOC,
 				(100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
 			         bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
-	start = usb_dump_desc(start, end, usbdev);
-	if (start > end)
-		return start + sprintf(start, "(truncated)\n");
+	
+	data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev);
+	
+	if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
+		data_end += sprintf(data_end, "(truncated)\n");
+	
+	length = data_end - pages_start;
+	/* if we can start copying some data to the user */
+	if (length > *skip_bytes) {
+		length -= *skip_bytes;
+		if (length > *nbytes)
+			length = *nbytes;
+		if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) {
+			free_pages((unsigned long)pages_start, 1);
+			
+			if (total_written == 0)
+				return -EFAULT;
+			return total_written;
+		}
+		*nbytes -= length;
+		*file_offset += length;
+		total_written += length;
+		*buffer += length;
+		*skip_bytes = 0;
+	} else
+		*skip_bytes -= length;
+	
+	free_pages((unsigned long)pages_start, 1);
+	
 	/* Now look at all of this device's children. */
 	for (chix = 0; chix < usbdev->maxchild; chix++) {
-		if (start > end)
-			return start;
-		if (usbdev->children[chix])
-			start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt);
+		if (usbdev->children[chix]) {
+			ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, usbdev->children[chix],
+					bus, level + 1, chix, ++cnt);
+			if (ret == -EFAULT)
+				return total_written;
+			total_written += ret;
+		}
 	}
-	return start;
+	return total_written;
 }
 
 static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
 {
 	struct list_head *buslist;
 	struct usb_bus *bus;
-	char *page, *end;
-	ssize_t ret = 0;
-	unsigned int pos, len;
+	ssize_t ret, total_written = 0;
+	loff_t skip_bytes = *ppos;
 
 	if (*ppos < 0)
 		return -EINVAL;
@@ -423,34 +473,18 @@
 		return 0;
 	if (!access_ok(VERIFY_WRITE, buf, nbytes))
 		return -EFAULT;
-        if (!(page = (char*) __get_free_pages(GFP_KERNEL,1)))
-                return -ENOMEM;
-	pos = *ppos;
+
 	/* enumerate busses */
 	for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
 		/* print devices for this bus */
 		bus = list_entry(buslist, struct usb_bus, bus_list);
-		end = usb_device_dump(page, page + (2*PAGE_SIZE - 256), bus->root_hub, bus, 0, 0, 0);
-		len = end - page;
-		if (len > pos) {
-			len -= pos;
-			if (len > nbytes)
-				len = nbytes;
-			if (copy_to_user(buf, page + pos, len)) {
-				if (!ret)
-					ret = -EFAULT;
-				break;
-			}
-			nbytes -= len;
-			buf += len;
-			ret += len;
-			pos = 0;
-			*ppos += len;
-		} else
-			pos -= len;
+		/* recurse through all children of the root hub */
+		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
+		if (ret < 0)
+			return ret;
+		total_written += ret;
 	}
-	free_pages((unsigned long)page, 1);
-	return ret;
+	return total_written;
 }
 
 /* Kernel lock for "lastev" protection */
diff -urN linux-2.2.18-pre9/drivers/usb/dsbr100.c linux/drivers/usb/dsbr100.c
--- linux-2.2.18-pre9/drivers/usb/dsbr100.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/dsbr100.c	Mon Dec  3 20:27:07 2001
@@ -33,6 +33,10 @@
 
  History:
 
+ Version 0.24:
+ 	Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
+	right.  Some minor cleanup, improved standalone compilation
+
  Version 0.23:
  	Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
 
@@ -135,11 +139,11 @@
 
 static int dsbr100_setfreq(usb_dsbr100 *radio, int freq)
 {
-	freq = (freq*80)/16+856;
+	freq = (freq/16*80)/1000+856;
 	if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-		0x01, 0xC0, (freq&0xff00)>>8, freq&0xff, 
-		radio->transfer_buffer, 8, 300)<0
-	 || usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+		0x01, 0xC0, (freq>>8)&0x00ff, freq&0xff, 
+		radio->transfer_buffer, 8, 300)<0 ||
+	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
 		0x00, 0xC0, 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
 	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
 		0x00, 0xC0, 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
@@ -172,7 +176,7 @@
 	usb_dsbr100_radio.priv = radio;
 	radio->dev = dev;
 	radio->ifnum = ifnum;
-	radio->curfreq = 1454;
+	radio->curfreq = 1454000;
 	return (void*)radio;
 }
 
@@ -218,8 +222,8 @@
 				return -EFAULT;
 			if(v.tuner)	/* Only 1 tuner */ 
 				return -EINVAL;
-			v.rangelow = 87*16;
-			v.rangehigh = 108*16;
+			v.rangelow = 87*16000;
+			v.rangehigh = 108*16000;
 			v.flags = VIDEO_TUNER_LOW;
 			v.mode = VIDEO_MODE_AUTO;
 			v.signal = radio->stereo*0x7000;
@@ -321,7 +325,7 @@
 	MOD_DEC_USE_COUNT;
 }
 
-int __init dsbr100_init(void)
+static int __init dsbr100_init(void)
 {
 	usb_dsbr100_radio.priv = NULL;
 	usb_register(&usb_dsbr100_driver);
@@ -332,12 +336,7 @@
 	return 0;
 }
 
-int __init init_module(void)
-{
-	return dsbr100_init();
-}
-
-void cleanup_module(void)
+static void __exit dsbr100_exit(void)
 {
 	usb_dsbr100 *radio=usb_dsbr100_radio.priv;
 
@@ -346,6 +345,12 @@
 	video_unregister_device(&usb_dsbr100_radio);
 	usb_deregister(&usb_dsbr100_driver);
 }
+
+module_init (dsbr100_init);
+module_exit (dsbr100_exit);
+
+MODULE_AUTHOR("Markus Demleitner <msdemlei@tucana.harvard.edu>");
+MODULE_DESCRIPTION("D-Link DSB-R100 USB radio driver");
 
 /*
 vi: ts=8
diff -urN linux-2.2.18-pre9/drivers/usb/evdev.c linux/drivers/usb/evdev.c
--- linux-2.2.18-pre9/drivers/usb/evdev.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/evdev.c	Mon Dec  3 20:27:07 2001
@@ -1,5 +1,5 @@
 /*
- * $Id: evdev.c,v 1.8 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: evdev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
@@ -37,10 +37,11 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/smp_lock.h>
 #include <linux/kcomp.h>
 
 struct evdev {
-	int used;
+	int exist;
 	int open;
 	int minor;
 	struct input_handle handle;
@@ -92,24 +93,28 @@
 static int evdev_release(struct inode * inode, struct file * file)
 {
 	struct evdev_list *list = file->private_data;
-	struct evdev_list **listptr = &list->evdev->list;
+	struct evdev_list **listptr;
 
+	lock_kernel();
+	listptr = &list->evdev->list;
 	evdev_fasync(-1, file, 0);
 
 	while (*listptr && (*listptr != list))
 		listptr = &((*listptr)->next);
 	*listptr = (*listptr)->next;
 
-	if (!--list->evdev->open)
-		input_close_device(&list->evdev->handle);	
-	
-	if (!--list->evdev->used) {
-		input_unregister_minor(list->evdev->devfs);
-		evdev_table[list->evdev->minor] = NULL;
-		kfree(list->evdev);
+	if (!--list->evdev->open) {
+		if (list->evdev->exist) {
+			input_close_device(&list->evdev->handle);	
+		} else {
+			input_unregister_minor(list->evdev->devfs);
+			evdev_table[list->evdev->minor] = NULL;
+			kfree(list->evdev);
+		}
 	}
 
 	kfree(list);
+	unlock_kernel();
 
 	return 0;
 }
@@ -122,9 +127,8 @@
 	if (i > EVDEV_MINORS || !evdev_table[i])
 		return -ENODEV;
 
-	if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) {
+	if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
 		return -ENOMEM;
-	}
 	memset(list, 0, sizeof(struct evdev_list));
 
 	list->evdev = evdev_table[i];
@@ -133,10 +137,9 @@
 
 	file->private_data = list;
 
-	list->evdev->used++;
-
 	if (!list->evdev->open++)
-		input_open_device(&list->evdev->handle);	
+		if (list->evdev->exist)
+			input_open_device(&list->evdev->handle);	
 
 	return 0;
 }
@@ -303,7 +306,7 @@
 	evdev->handle.handler = handler;
 	evdev->handle.private = evdev;
 
-	evdev->used = 1;
+	evdev->exist = 1;
 
 	evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
 
@@ -316,10 +319,11 @@
 {
 	struct evdev *evdev = handle->private;
 
-	if (evdev->open)
-		input_close_device(handle);
+	evdev->exist = 0;
 
-	if (!--evdev->used) {
+	if (evdev->open) {
+		input_close_device(handle);
+	} else {
 		input_unregister_minor(evdev->devfs);
 		evdev_table[evdev->minor] = NULL;
 		kfree(evdev);
@@ -347,3 +351,6 @@
 
 module_init(evdev_init);
 module_exit(evdev_exit);
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Event character device driver");
diff -urN linux-2.2.18-pre9/drivers/usb/hid.c linux/drivers/usb/hid.c
--- linux-2.2.18-pre9/drivers/usb/hid.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/hid.c	Mon Dec  3 20:27:07 2001
@@ -1,5 +1,5 @@
 /*
- * $Id: hid.c,v 1.6 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: hid.c,v 1.16 2000/09/18 21:38:55 vojtech Exp $
  *
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000 Vojtech Pavlik
@@ -65,8 +65,8 @@
 	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
 	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
 	120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
-	115,114,unk,unk,unk,unk,unk,124,unk,unk,unk,unk,unk,unk,unk,unk,
-	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	115,114,unk,unk,unk,124,unk,181,182,183,184,185,186,187,188,189,
+	190,191,192,193,194,195,196,197,198,unk,unk,unk,unk,unk,unk,unk,
 	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
 	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
 	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
@@ -149,7 +149,7 @@
 
 	usage = parser->local.usage[0];
 
-	if (type == HID_COLLECTION_APPLICATION)
+	if (type == HID_COLLECTION_APPLICATION && !parser->device->application)
 		parser->device->application = usage;
 
 	if (parser->collection_stack_ptr < HID_COLLECTION_STACK_SIZE) { /* PUSH on stack */
@@ -197,7 +197,7 @@
 
 static int hid_add_usage(struct hid_parser *parser, unsigned usage)
 {
-	if (parser->local.usage_index >= MAX_USAGES) {
+	if (parser->local.usage_index >= HID_MAX_USAGES) {
 		dbg("usage index exceeded");
 		return -1;
 	}
@@ -346,7 +346,7 @@
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
-			if ((parser->global.report_count = item_udata(item)) > MAX_USAGES) {
+			if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
 				dbg("invalid report_count %d", parser->global.report_count);
 				return -1;
 			}
@@ -924,6 +924,8 @@
 		usage->code = find_next_zero_bit(bit, max + 1, usage->code);
 	}
 
+	if (usage->code > max) return;
+
 	if (usage->type == EV_ABS) {
 		int a = field->logical_minimum;
 		int b = field->logical_maximum;
@@ -936,7 +938,7 @@
 
 	if (usage->hat) {
 		int i;
-		for (i = usage->code; i < usage->code + 2; i++) {
+		for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
 			input->absmax[i] = 1;
 			input->absmin[i] = -1;
 			input->absfuzz[i] = 0;
@@ -1224,10 +1226,31 @@
 	return -1;
 }
 
+static int hid_submit_out(struct hid_device *hid)
+{
+	hid->urbout.transfer_buffer_length = hid->out[hid->outtail].dr.length;
+	hid->urbout.transfer_buffer = hid->out[hid->outtail].buffer;
+	hid->urbout.setup_packet = (void *) &(hid->out[hid->outtail].dr);
+
+	if (usb_submit_urb(&hid->urbout)) {
+		err("usb_submit_urb(out) failed");
+		return -1;
+	}
+
+	return 0;
+}
+
 static void hid_ctrl(struct urb *urb)
 {
+	struct hid_device *hid = urb->context;
+
         if (urb->status)
-                warn("ctrl urb status %d received", urb->status);
+		warn("ctrl urb status %d received", urb->status);
+	
+	hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+
+	if (hid->outhead != hid->outtail)
+		hid_submit_out(hid);
 }       
 
 static int hid_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -1242,22 +1265,18 @@
 	}
 
 	hid_set_field(field, offset, value);
+	hid_output_report(field->report, hid->out[hid->outhead].buffer);
 
-	if (hid->urbout.status == -EINPROGRESS) {
-		warn("had to kill output urb");
-		usb_unlink_urb(&hid->urbout);
-	}
+	hid->out[hid->outhead].dr.value = 0x200 | field->report->id;
+	hid->out[hid->outhead].dr.length = ((field->report->size - 1) >> 3) + 1;
 
-	hid_output_report(field->report, hid->bufout);
+	hid->outhead = (hid->outhead + 1) & (HID_CONTROL_FIFO_SIZE - 1);
 
-	hid->dr.value = 0x200 | field->report->id;
-	hid->dr.length = ((field->report->size - 1) >> 3) + 1;
-	hid->urbout.transfer_buffer_length = hid->dr.length;
+	if (hid->outhead == hid->outtail)
+		hid->outtail = (hid->outtail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
 
-	if (usb_submit_urb(&hid->urbout)) {
-		err("usb_submit_urb(out) failed");
-		return -1;
-	}
+	if (hid->urbout.status != -EINPROGRESS)
+		hid_submit_out(hid);
 
 	return 0;
 }
@@ -1364,7 +1383,7 @@
 		if (hdesc->desc[n].bDescriptorType == USB_DT_REPORT)
 			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
 
-	if (!rsize || rsize > 1024) {
+	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
 		dbg("weird size of report descriptor (%u)", rsize);
 		return NULL;
 	}
@@ -1420,11 +1439,11 @@
 	hid->dev = dev;
 	hid->ifnum = interface->bInterfaceNumber;
 
-	hid->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-	hid->dr.request = USB_REQ_SET_REPORT;
-	hid->dr.value = 0x200;
-	hid->dr.index = hid->ifnum;
-	hid->dr.length = 1;
+	for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) {
+		hid->out[n].dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+		hid->out[n].dr.request = USB_REQ_SET_REPORT;
+		hid->out[n].dr.index = hid->ifnum;
+	}
 
 	hid->input.name = hid->name;
 	hid->input.idbus = BUS_USB;
@@ -1441,7 +1460,7 @@
 			hid->input.idvendor, hid->input.idproduct);
 
 	FILL_CONTROL_URB(&hid->urbout, dev, usb_sndctrlpipe(dev, 0),
-		(void*) &hid->dr, hid->bufout, 1, hid_ctrl, hid);
+		(void*) &hid->out[0].dr, hid->out[0].buffer, 1, hid_ctrl, hid);
 
 	if (interface->bInterfaceSubClass == 1)
         	usb_set_protocol(dev, hid->ifnum, 1);
@@ -1524,3 +1543,6 @@
 
 module_init(hid_init);
 module_exit(hid_exit);
+
+MODULE_AUTHOR("Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("USB HID support drivers");
diff -urN linux-2.2.18-pre9/drivers/usb/hid.h linux/drivers/usb/hid.h
--- linux-2.2.18-pre9/drivers/usb/hid.h	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/hid.h	Mon Dec  3 20:27:07 2001
@@ -2,7 +2,7 @@
 #define __HID_H
 
 /*
- * $Id: hid.h,v 1.4 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: hid.h,v 1.7 2000/05/31 22:57:48 vojtech Exp $
  *
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000 Vojtech Pavlik
@@ -208,10 +208,11 @@
  * This is the local enviroment. It is resistent up the the next main-item.
  */
 
-#define MAX_USAGES 1024
+#define HID_MAX_DESCRIPTOR_SIZE		4096
+#define HID_MAX_USAGES			1024
 
 struct hid_local {
-	unsigned usage[MAX_USAGES]; /* usage array */
+	unsigned usage[HID_MAX_USAGES]; /* usage array */
 	unsigned usage_index;
 	unsigned usage_minimum;
 	unsigned delimiter_depth;
@@ -275,6 +276,14 @@
 
 #define HID_REPORT_TYPES 3
 
+#define HID_BUFFER_SIZE		32
+#define HID_CONTROL_FIFO_SIZE	8
+
+struct hid_control_fifo {
+	devrequest dr;
+	char buffer[HID_BUFFER_SIZE];
+};
+
 struct hid_device {							/* device report descriptor */
 	 __u8 *rdesc;
 	unsigned rsize;
@@ -286,11 +295,13 @@
 	struct usb_device *dev;						/* USB device */
 	int ifnum;							/* USB interface number */
 
-	char buffer[32];						/* Receive buffer */
-	char bufout[32];						/* Transmit buffer */
-	devrequest dr;							/* Startup packet */
 	struct urb urb;							/* USB URB structure */
+	char buffer[HID_BUFFER_SIZE];					/* Rx buffer */
+
 	struct urb urbout;						/* Output URB */
+	struct hid_control_fifo out[HID_CONTROL_FIFO_SIZE];		/* Transmit buffer */
+	unsigned char outhead, outtail;					/* Tx buffer head & tail */
+
 	struct input_dev input;						/* input device structure */
 	int open;							/* is the device open by input? */
 	int quirks;							/* Various nasty tricks the device can pull on us */
diff -urN linux-2.2.18-pre9/drivers/usb/hub.c linux/drivers/usb/hub.c
--- linux-2.2.18-pre9/drivers/usb/hub.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/hub.c	Mon Dec  3 20:27:07 2001
@@ -368,7 +368,7 @@
 static void usb_hub_port_connect_change(struct usb_device *hub, int port)
 {
 	struct usb_device *usb;
- 	struct usb_port_status portsts;
+	struct usb_port_status portsts;
 	unsigned short portstatus, portchange;
 	int ret, tries;
 
@@ -451,7 +451,7 @@
 
 	/* Run it through the hoops (find a driver, etc) */
 	ret = usb_new_device(usb);
-	if (ret && usb->devnum != -1) {
+	if (ret) {
 		/* Try resetting the device. Windows does this and it */
 		/*  gets some devices working correctly */
 		usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
@@ -588,8 +588,8 @@
 	 * so get rid of all our resources
 	 */
 	exit_files(current);  /* daemonize doesn't do exit_files */
-        current->files = init_task.files;
-        atomic_inc(&current->files->count);
+	current->files = init_task.files;
+	atomic_inc(&current->files->count);
 	daemonize();
 
 	/* Setup a nice name */
@@ -758,6 +758,7 @@
 		ret = usb_get_configuration(dev);
 		if (ret < 0) {
 			err("unable to get configuration (error=%d)", ret);
+			usb_destroy_configuration(dev);
 			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
 			dev->devnum = -1;
 			return 1;
diff -urN linux-2.2.18-pre9/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c
--- linux-2.2.18-pre9/drivers/usb/ibmcam.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/ibmcam.c	Mon Dec  3 20:27:07 2001
@@ -35,6 +35,7 @@
 #include <linux/vmalloc.h>
 #include <linux/wrapper.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/usb.h>
 
@@ -127,21 +128,36 @@
 static int init_model2_yb = -1;
 
 MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
 MODULE_PARM(flags, "i");
+MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=seperate frames, 6=clean frames");
 MODULE_PARM(framerate, "i");
+MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
 MODULE_PARM(lighting, "i");
+MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
 MODULE_PARM(sharpness, "i");
+MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
 MODULE_PARM(videosize, "i");
+MODULE_PARM_DESC(videosize, "Image size: 0=128x96, 1=176x144, 2=352x288, 3=320x240, 4=352x240 (default=1)");
 MODULE_PARM(init_brightness, "i");
+MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
 MODULE_PARM(init_contrast, "i");
+MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
 MODULE_PARM(init_color, "i");
+MODULE_PARM_DESC(init_color, "Dolor preconfiguration: 0-255 (default=128)");
 MODULE_PARM(init_hue, "i");
+MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
 MODULE_PARM(hue_correction, "i");
+MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
 
 MODULE_PARM(init_model2_rg, "i");
+MODULE_PARM_DESC(init_model2_rg, "Model2 preconfiguration: 0-255 (default=112)");
 MODULE_PARM(init_model2_rg2, "i");
+MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");
 MODULE_PARM(init_model2_sat, "i");
+MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");
 MODULE_PARM(init_model2_yb, "i");
+MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
 
 MODULE_AUTHOR ("module author");
 MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
@@ -190,8 +206,10 @@
 		if (!pmd_none(*pmd)) {
 			ptep = pte_offset(pmd, adr);
 			pte = *ptep;
-			if (pte_present(pte))
-				ret = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1));
+			if (pte_present(pte)) {
+				ret = (unsigned long) page_address(pte_page(pte));
+				ret |= (adr & (PAGE_SIZE - 1));
+			}
 		}
 	}
 	MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
@@ -2933,11 +2951,11 @@
  * 1/22/00  Moved camera init code to ibmcam_open()
  * 1/27/00  Changed to use static structures, added locking.
  * 5/24/00  Corrected to prevent race condition (MOD_xxx_USE_COUNT).
+ * 7/3/00   Fixed endianness bug.
  */
 static void *usb_ibmcam_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_ibmcam *ibmcam = NULL;
-	const unsigned char *p_rev;
 	const struct usb_interface_descriptor *interface;
 	const struct usb_endpoint_descriptor *endpoint;
 	int devnum, model=0;
@@ -2955,20 +2973,24 @@
 		return NULL;
 
 	/* Check the version/revision */
-	p_rev = (const unsigned char *) &dev->descriptor.bcdDevice;
-	if (p_rev[1] == 0x00 && p_rev[0] == 0x02) {
+	switch (dev->descriptor.bcdDevice) {
+	case 0x0002:
 		if (ifnum != 2)
 			return NULL;
-		printk(KERN_INFO "IBM USB camera found (model 1).\n");
+		printk(KERN_INFO "IBM USB camera found (model 1, rev. 0x%04x).\n",
+			dev->descriptor.bcdDevice);
 		model = IBMCAM_MODEL_1;
-	} else if (p_rev[1] == 0x03 && p_rev[0] == 0x0A) {
+		break;
+	case 0x030A:
 		if (ifnum != 0)
 			return NULL;
-		printk(KERN_INFO "IBM USB camera found (model 2).\n");
+		printk(KERN_INFO "IBM USB camera found (model 2, rev. 0x%04x).\n",
+			dev->descriptor.bcdDevice);
 		model = IBMCAM_MODEL_2;
-	} else {
-		printk(KERN_ERR "IBM camera revision=%02x.%02x not supported\n",
-		       p_rev[1], p_rev[0]);
+		break;
+	default:
+		printk(KERN_ERR "IBM camera with revision 0x%04x is not supported.\n",
+			dev->descriptor.bcdDevice);
 		return NULL;
 	}
 
@@ -3051,6 +3073,7 @@
 	if (debug > 0)
 		printk(KERN_DEBUG "usb_ibmcam_release: Video unregistered.\n");
 	ibmcam->ibmcam_used = 0;
+	ibmcam->initialized = 0;
 }
 
 /*
@@ -3116,7 +3139,7 @@
  * History:
  * 1/27/00  Reworked to use statically allocated usb_ibmcam structures.
  */
-int usb_ibmcam_init(void)
+static int __init usb_ibmcam_init(void)
 {
 	unsigned u;
 
@@ -3128,19 +3151,12 @@
 	return usb_register(&ibmcam_driver);
 }
 
-void usb_ibmcam_cleanup(void)
+static void __exit usb_ibmcam_cleanup(void)
 {
 	usb_deregister(&ibmcam_driver);
 }
 
-#ifdef MODULE
-int init_module(void)
-{
-	return usb_ibmcam_init();
-}
+module_init(usb_ibmcam_init);
+module_exit(usb_ibmcam_cleanup);
+
 
-void cleanup_module(void)
-{
-	usb_ibmcam_cleanup();
-}
-#endif
diff -urN linux-2.2.18-pre9/drivers/usb/input.c linux/drivers/usb/input.c
--- linux-2.2.18-pre9/drivers/usb/input.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/input.c	Mon Dec  3 20:27:07 2001
@@ -35,6 +35,7 @@
 #include <linux/kcomp.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Input layer module");
 
 EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
diff -urN linux-2.2.18-pre9/drivers/usb/joydev.c linux/drivers/usb/joydev.c
--- linux-2.2.18-pre9/drivers/usb/joydev.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/joydev.c	Mon Dec  3 20:27:07 2001
@@ -1,7 +1,7 @@
 /*
- * $Id: joydev.c,v 1.7 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: joydev.c,v 1.13 2000/08/14 21:05:26 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *  Copyright (c) 1999-2000 Vojtech Pavlik 
  *  Copyright (c) 1999 Colin Van Dyke 
  *
  *  Joystick device driver for the input driver suite.
@@ -44,13 +44,14 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 
 #define JOYDEV_MINOR_BASE	0
 #define JOYDEV_MINORS		32
 #define JOYDEV_BUFFER_SIZE	64
 
 struct joydev {
-	int used;
+	int exist;
 	int open;
 	int minor;
 	struct input_handle handle;
@@ -66,6 +67,7 @@
 	__u16 keypam[KEY_MAX - BTN_MISC];
 	__u8 absmap[ABS_MAX];
 	__u8 abspam[ABS_MAX];
+	__s16 abs[ABS_MAX];
 };
 
 struct joydev_list {
@@ -81,6 +83,7 @@
 static struct joydev *joydev_table[JOYDEV_MINORS];
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Joystick device driver");
 MODULE_SUPPORTED_DEVICE("input/js");
 
 static int joydev_correct(int value, struct js_corr *corr)
@@ -121,7 +124,9 @@
 		case EV_ABS:
 			event.type = JS_EVENT_AXIS;
 			event.number = joydev->absmap[code];
-			event.value = joydev_correct(value, &joydev->corr[event.number]);
+			event.value = joydev_correct(value, joydev->corr + event.number);
+			if (event.value == joydev->abs[event.number]) return;
+			joydev->abs[event.number] = event.value;
 			break;
 
 		default:
@@ -157,24 +162,28 @@
 static int joydev_release(struct inode * inode, struct file * file)
 {
 	struct joydev_list *list = file->private_data;
-	struct joydev_list **listptr = &list->joydev->list;
+	struct joydev_list **listptr;
 
+	lock_kernel();
+	listptr = &list->joydev->list;
 	joydev_fasync(-1, file, 0);
 
 	while (*listptr && (*listptr != list))
 		listptr = &((*listptr)->next);
 	*listptr = (*listptr)->next;
 
-	if (!--list->joydev->open)
-		input_close_device(&list->joydev->handle);
-	
-	if (!--list->joydev->used) {
-		input_unregister_minor(list->joydev->devfs);
-		joydev_table[list->joydev->minor] = NULL;
-		kfree(list->joydev);
+	if (!--list->joydev->open) {
+		if (list->joydev->exist) {
+			input_close_device(&list->joydev->handle);
+		} else {
+			input_unregister_minor(list->joydev->devfs);
+			joydev_table[list->joydev->minor] = NULL;
+			kfree(list->joydev);
+		}
 	}
 
 	kfree(list);
+	unlock_kernel();
 
 	return 0;
 }
@@ -187,9 +196,8 @@
 	if (i > JOYDEV_MINORS || !joydev_table[i])
 		return -ENODEV;
 
-	if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) {
+	if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
 		return -ENOMEM;
-	}
 	memset(list, 0, sizeof(struct joydev_list));
 
 	list->joydev = joydev_table[i];
@@ -198,10 +206,9 @@
 
 	file->private_data = list;
 
-	list->joydev->used++;
-
 	if (!list->joydev->open++)
-		input_open_device(&list->joydev->handle);
+		if (list->joydev->exist)
+			input_open_device(&list->joydev->handle);
 
 	return 0;
 }
@@ -228,8 +235,8 @@
 
 		data.buttons =  ((joydev->nkey > 0 && test_bit(joydev->keypam[0], input->key)) ? 1 : 0) |
 				((joydev->nkey > 1 && test_bit(joydev->keypam[1], input->key)) ? 2 : 0);
-		data.x = ((joydev_correct(input->abs[ABS_X], &joydev->corr[0]) / 256) + 128) >> joydev->glue.JS_CORR.x;
-		data.y = ((joydev_correct(input->abs[ABS_Y], &joydev->corr[1]) / 256) + 128) >> joydev->glue.JS_CORR.y;
+		data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
+		data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
 
 		if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
 			return -EFAULT;
@@ -274,13 +281,12 @@
 
 		if (list->startup < joydev->nkey) {
 			event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
-			event.value = !!test_bit(joydev->keypam[list->startup], input->key);
 			event.number = list->startup;
+			event.value = !!test_bit(joydev->keypam[event.number], input->key);
 		} else {
 			event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
-			event.value = joydev_correct(input->abs[joydev->abspam[list->startup - joydev->nkey]],
-							&joydev->corr[list->startup - joydev->nkey]);
 			event.number = list->startup - joydev->nkey;
+			event.value = joydev->abs[event.number];
 		}
 
 		if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
@@ -383,7 +389,7 @@
 	int i, j, minor;
 
 	if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) &&
-	      test_bit(ABS_X, dev->absbit) && test_bit(ABS_Y, dev->absbit) &&
+	     (test_bit(ABS_X, dev->absbit) || test_bit(ABS_Y, dev->absbit)) &&
 	     (test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit)
 		|| test_bit(BTN_1, dev->keybit)))) return NULL; 
 
@@ -406,7 +412,7 @@
 	joydev->handle.handler = handler;
 	joydev->handle.private = joydev;
 
-	joydev->used = 1;
+	joydev->exist = 1;
 
 	for (i = 0; i < ABS_MAX; i++)
 		if (test_bit(i, dev->absbit)) {
@@ -441,6 +447,8 @@
 		joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
 		joydev->corr[i].coef[2] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
 		joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
+
+		joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
 	}
 
 	joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
@@ -454,10 +462,11 @@
 {
 	struct joydev *joydev = handle->private;
 
-	if (joydev->open)
-		input_close_device(handle);	
+	joydev->exist = 0;
 
-	if (!--joydev->used) {
+	if (joydev->open) {
+		input_close_device(handle);	
+	} else {
 		input_unregister_minor(joydev->devfs);
 		joydev_table[joydev->minor] = NULL;
 		kfree(joydev);
diff -urN linux-2.2.18-pre9/drivers/usb/keybdev.c linux/drivers/usb/keybdev.c
--- linux-2.2.18-pre9/drivers/usb/keybdev.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/keybdev.c	Mon Dec  3 20:27:07 2001
@@ -41,22 +41,23 @@
 
 static int x86_sysrq_alt = 0;
 
-static unsigned short x86_keycodes[256] =
-	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+static unsigned short x86_keycodes[256] = {
+	  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
 	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
 	 80, 81, 82, 83, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90,
 	284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
-	367,294,293,286,350, 92,334,512,116,377,109,111,373,347,348,349,
+	367,294,293,286,350, 92,334,512,116,377,109,111,259,347,348,349,
 	360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
 	103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361,
 	291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114,
-	118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269,
+	118,117,125,374,379,125,260,261,262,263,264,265,266,267,268,269,
 	271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307,
 	308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330,
-	332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 };
+	332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372
+};
 
 static int emulate_raw(unsigned int keycode, int down)
 {
@@ -196,3 +197,6 @@
 
 module_init(keybdev_init);
 module_exit(keybdev_exit);
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Input driver to keyboard driver binding");
diff -urN linux-2.2.18-pre9/drivers/usb/mousedev.c linux/drivers/usb/mousedev.c
--- linux-2.2.18-pre9/drivers/usb/mousedev.c	Mon Dec  3 20:26:36 2001
+++ linux/drivers/usb/mousedev.c	Mon Dec  3 20:27:07 2001
@@ -1,5 +1,5 @@
 /*
- * $Id: mousedev.c,v 1.8 2000/05/28 17:31:36 vojtech Exp $
+ * $Id: mousedev.c,v 1.15 2000/08/14 21:05:26 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
@@ -38,6 +38,7 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/config.h>
+#include <linux/smp_lock.h>
 #include <linux/kcomp.h>
 
 #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
@@ -48,7 +49,7 @@
 #endif
 
 struct mousedev {
-	int used;
+	int exist;
 	int open;
 	int minor;
 	wait_queue_head_t wait;
@@ -62,7 +63,7 @@
 	struct mousedev *mousedev;
 	struct mousedev_list *next;
 	int dx, dy, dz, oldx, oldy;
-	char ps2[6];
+	signed char ps2[6];
 	unsigned long buttons;
 	unsigned char ready, buffer, bufsiz;
 	unsigned char mode, genseq, impseq;
@@ -91,6 +92,8 @@
 		while (list) {
 			switch (type) {
 				case EV_ABS:
+					if (test_bit(BTN_TRIGGER, handle->dev->keybit))
+						break;
 					switch (code) {
 						case ABS_X:	
 							size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
@@ -104,6 +107,7 @@
 							break;
 					}
 					break;
+
 				case EV_REL:
 					switch (code) {
 						case REL_X:	list->dx += value; break;
@@ -160,8 +164,10 @@
 static int mousedev_release(struct inode * inode, struct file * file)
 {
 	struct mousedev_list *list = file->private_data;
-	struct mousedev_list **listptr = &list->mousedev->list;
+	struct mousedev_list **listptr;
 
+	lock_kernel();
+	listptr = &list->mousedev->list;
 	mousedev_fasync(-1, file, 0);
 
 	while (*listptr && (*listptr != list))
@@ -173,23 +179,32 @@
 			struct input_handle *handle = mousedev_handler.handle;
 			while (handle) {
 				struct mousedev *mousedev = handle->private;
-				if (!mousedev->open)
-					input_close_device(handle);
+				if (!mousedev->open) {
+					if (mousedev->exist) {
+						input_close_device(&mousedev->handle);
+					} else {
+						input_unregister_minor(mousedev->devfs);
+						mousedev_table[mousedev->minor] = NULL;
+						kfree(mousedev);
+					}
+				}
 				handle = handle->hnext;
 			}
 		} else {
-			if (!mousedev_mix.open)	
-				input_close_device(&list->mousedev->handle);
+			if (!mousedev_mix.open) {
+				if (list->mousedev->exist) {
+					input_close_device(&list->mousedev->handle);
+				} else {
+					input_unregister_minor(list->mousedev->devfs);
+					mousedev_table[list->mousedev->minor] = NULL;
+					kfree(list->mousedev);
+				}
+			}
 		}
 	}
 	
-	if (!--list->mousedev->used) {
-		input_unregister_minor(list->mousedev->devfs);
-		mousedev_table[list->mousedev->minor] = NULL;
-		kfree(list->mousedev);
-	}
-
 	kfree(list);
+	unlock_kernel();
 
 	return 0;
 }
@@ -211,20 +226,20 @@
 	mousedev_table[i]->list = list;
 	file->private_data = list;
 
-	list->mousedev->used++;
-
 	if (!list->mousedev->open++) {
 		if (list->mousedev->minor == MOUSEDEV_MIX) {
 			struct input_handle *handle = mousedev_handler.handle;
 			while (handle) {
 				struct mousedev *mousedev = handle->private;
 				if (!mousedev->open)
-					input_open_device(handle);
+					if (mousedev->exist)	
+						input_open_device(handle);
 				handle = handle->hnext;
 			}
 		} else {
-			if (!mousedev_mix.open)	
-				input_open_device(&list->mousedev->handle);
+			if (!mousedev_mix.open)
+				if (list->mousedev->exist)	
+					input_open_device(&list->mousedev->handle);
 		}
 	}
 
@@ -241,7 +256,7 @@
 	list->bufsiz = off + 3;
 
 	if (list->mode > 1)
-		list->ps2[off] |= ((list->buttons & 0x30) << 2);
+		list->ps2[off] |= ((list->buttons & 0x18) << 3);
 	
 	if (list->mode) {
 		list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz));
@@ -402,7 +417,7 @@
 	memset(mousedev, 0, sizeof(struct mousedev));
 	init_waitqueue_head(&mousedev->wait);
 
-	mousedev->used = 1;
+	mousedev->exist = 1;
 	mousedev->minor = minor;
 	mousedev_table[minor] = mousedev;
 
@@ -424,10 +439,13 @@
 {
 	struct mousedev *mousedev = handle->private;
 
-	if (mousedev->open || mousedev_mix.open)
-		input_close_device(handle);
+	mousedev->exist = 0;
 
-	if (!--mousedev->used) {
+	if (mousedev->open) {
+		input_close_device(handle);
+	} else {
+		if (mousedev_mix.open)
+			input_close_device(handle);
 		input_unregister_minor(mousedev->devfs);
 		mousedev_table[mousedev->minor] = NULL;
 		kfree(mousedev);
@@ -449,7 +467,7 @@
 	memset(&mousedev_mix, 0, sizeof(struct mousedev));
 	init_waitqueue_head(&mousedev_mix.wait);
 	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
-	mousedev_mix.used = 1;
+	mousedev_mix.exist = 1;
 	mousedev_mix.minor = MOUSEDEV_MIX;
 	mousedev_mix.devfs = input_register_minor("mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE);
 
@@ -466,3 +484,6 @@
 
 module_init(mousedev_init);
 module_exit(mousedev_exit);
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver");
diff -urN linux-2.2.18-pre9/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c
--- linux-2.2.18-pre9/drivers/usb/serial/digi_acceleport.c	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/serial/digi_acceleport.c	Mon Dec  3 20:27:07 2001
@@ -2014,7 +2014,7 @@
 }
 
 
-int digi_init (void)
+static int __init digi_init (void)
 {
 	usb_serial_register (&digi_acceleport_2_device);
 	usb_serial_register (&digi_acceleport_4_device);
@@ -2022,7 +2022,7 @@
 }
 
 
-void digi_exit (void)
+static void __exit digi_exit (void)
 {
 	usb_serial_deregister (&digi_acceleport_2_device);
 	usb_serial_deregister (&digi_acceleport_4_device);
diff -urN linux-2.2.18-pre9/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c
--- linux-2.2.18-pre9/drivers/usb/serial/ftdi_sio.c	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/serial/ftdi_sio.c	Mon Dec  3 20:27:07 2001
@@ -12,6 +12,9 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (09/11/2000) gkh
+ *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
+ *
  * (07/19/2000) gkh
  *	Added module_init and module_exit functions to handle the fact that this
  *	driver is a loadable module now.
@@ -331,26 +334,9 @@
 		first_byte = port->write_urb->transfer_buffer;
 		*first_byte = 1 | ((count-data_offset) << 2) ; 
 
-#ifdef CONFIG_USB_SERIAL_DEBUG
 		dbg("Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]);
-
-		if (count) {
-			int i;
-			printk (KERN_DEBUG __FILE__ ": data written - length = %d, data = ", count);
-			for (i = 0; i < count; ++i) {
-				printk ( "0x%02x ", first_byte[i]);
-				if (first_byte[i] > ' ' && first_byte[i] < '~') {
-					printk( "%c ", first_byte[i]);
-				} else {
-					printk( "  ");
-				}
-			}
-
-		     
-			printk ( "\n");
-		}
-
-#endif
+		usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
+		
 		/* send the data out the bulk port */
 		port->write_urb->transfer_buffer_length = count;
 
@@ -429,23 +415,11 @@
 		return;
 	}
 
-#ifdef CONFIG_USB_SERIAL_DEBUG
 	if (urb->actual_length > 2) {
-		printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length);
-		for (i = 0; i < urb->actual_length; ++i) {
-			printk ( "0x%.2x ", data[i]);
-			if (data[i] > ' ' && data[i] < '~') {
-				printk( "%c ", data[i]);
-			} else {
-				printk( "  ");
-			}
-		}
-		printk ( "\n");
+		usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 	} else {
                 dbg("Just status");
         }
-#endif
-	
 
 	if (urb->actual_length > data_offset) {
 		for (i = data_offset ; i < urb->actual_length ; ++i) {
@@ -725,14 +699,14 @@
 } /* ftdi_sio_ioctl */
 
 
-int ftdi_sio_init (void)
+static int __init ftdi_sio_init (void)
 {
 	usb_serial_register (&ftdi_sio_device);
 	return 0;
 }
 
 
-void ftdi_sio_exit (void)
+static void __exit ftdi_sio_exit (void)
 {
 	usb_serial_deregister (&ftdi_sio_device);
 }
diff -urN linux-2.2.18-pre9/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c
--- linux-2.2.18-pre9/drivers/usb/serial/keyspan.c	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/serial/keyspan.c	Mon Dec  3 20:27:07 2001
@@ -687,7 +687,7 @@
 }
 
 
-int keyspan_init (void)
+static int __init keyspan_init (void)
 {
 	usb_serial_register (&keyspan_usa18x_pre_device);
 	usb_serial_register (&keyspan_usa19_pre_device);
@@ -703,7 +703,7 @@
 }
 
 
-void keyspan_exit (void)
+static void __exit keyspan_exit (void)
 {
 	usb_serial_deregister (&keyspan_usa18x_pre_device);
 	usb_serial_deregister (&keyspan_usa19_pre_device);
diff -urN linux-2.2.18-pre9/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c
--- linux-2.2.18-pre9/drivers/usb/serial/keyspan_pda.c	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/serial/keyspan_pda.c	Mon Dec  3 20:27:07 2001
@@ -12,6 +12,11 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (08/28/2000) gkh
+ *	Added locks for SMP safeness.
+ *	Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
+ *	than once.
+ * 
  * (07/20/2000) borchers
  *	- keyspan_pda_write no longer sleeps if it is called on interrupt time;
  *	  PPP and the line discipline with stty echo on can call write on
@@ -416,6 +421,7 @@
 	int request_unthrottle = 0;
 	int rc = 0;
 	struct keyspan_pda_private *priv;
+	unsigned long flags;
 
 	priv = (struct keyspan_pda_private *)(port->private);
 	/* guess how much room is left in the device's ring buffer, and if we
@@ -445,6 +451,7 @@
 	   finished).  Also, the tx process is not throttled. So we are
 	   ready to write. */
 
+	spin_lock_irqsave (&port->port_lock, flags);
 	count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
 
 	/* Check if we might overrun the Tx buffer.   If so, ask the
@@ -464,10 +471,12 @@
 				     2*HZ);
 		if (rc < 0) {
 			dbg(" roomquery failed");
+			spin_unlock_irqrestore (&port->port_lock, flags);
 			return rc; /* failed */
 		}
 		if (rc == 0) {
 			dbg(" roomquery returned 0 bytes");
+			spin_unlock_irqrestore (&port->port_lock, flags);
 			return -EIO; /* device didn't return any data */
 		}
 		dbg(" roomquery says %d", room);
@@ -484,8 +493,10 @@
 		/* now transfer data */
 		if (from_user) {
 			if( copy_from_user(port->write_urb->transfer_buffer,
-			buf, count) )
+			buf, count) ) {
+				spin_unlock_irqrestore (&port->port_lock, flags);
 				return( -EFAULT );
+			}
 		}
 		else {
 			memcpy (port->write_urb->transfer_buffer, buf, count);
@@ -495,8 +506,11 @@
 		
 		priv->tx_room -= count;
 
-		if (usb_submit_urb(port->write_urb))
+		if (usb_submit_urb(port->write_urb)) {
 			dbg(" usb_submit_urb(write bulk) failed");
+			spin_unlock_irqrestore (&port->port_lock, flags);
+			return (0);
+		}
 	}
 	else {
 		/* There wasn't any room left, so we are throttled until
@@ -509,6 +523,7 @@
 		queue_task( &priv->unthrottle_task, &tq_scheduler );
 	}
 
+	spin_unlock_irqrestore (&port->port_lock, flags);
 	return (count);
 }
 
@@ -568,61 +583,92 @@
 	unsigned char room;
 	int rc;
 	struct keyspan_pda_private *priv;
-	priv = (struct keyspan_pda_private *)(port->private);
+	unsigned long flags;
 
-	if (port->active) {
-		return -EINVAL;
-	}
-	port->active = 1;
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	MOD_INC_USE_COUNT;
+	++port->open_count;
+
+	if (!port->active) {
+		port->active = 1;
  
-	/* find out how much room is in the Tx ring */
-	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-			     6, /* write_room */
-			     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
-			     | USB_DIR_IN,
-			     0, /* value */
-			     0, /* index */
-			     &room,
-			     1,
-			     2*HZ);
-	if (rc < 0) {
-		dbg(" roomquery failed");
-		return rc; /* failed */
-	}
-	if (rc == 0) {
-		dbg(" roomquery returned 0 bytes");
-		return -EIO; /* device didn't return any data */
-	}
-	priv->tx_room = room;
-	priv->tx_throttled = room ? 0 : 1;
-
-	/* the normal serial device seems to always turn on DTR and RTS here,
-	   so do the same */
-	if (port->tty->termios->c_cflag & CBAUD)
-		keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
-	else
-		keyspan_pda_set_modem_info(serial, 0);
+		/* find out how much room is in the Tx ring */
+		spin_unlock_irqrestore (&port->port_lock, flags);
+		rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+				     6, /* write_room */
+				     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
+				     | USB_DIR_IN,
+				     0, /* value */
+				     0, /* index */
+				     &room,
+				     1,
+				     2*HZ);
+		spin_lock_irqsave (&port->port_lock, flags);
+		if (rc < 0) {
+			dbg(__FUNCTION__" - roomquery failed");
+			goto error;
+		}
+		if (rc == 0) {
+			dbg(__FUNCTION__" - roomquery returned 0 bytes");
+			rc = -EIO;
+			goto error;
+		}
+		priv = (struct keyspan_pda_private *)(port->private);
+		priv->tx_room = room;
+		priv->tx_throttled = room ? 0 : 1;
+
+		/* the normal serial device seems to always turn on DTR and RTS here,
+		   so do the same */
+		spin_unlock_irqrestore (&port->port_lock, flags);
+		if (port->tty->termios->c_cflag & CBAUD)
+			keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
+		else
+			keyspan_pda_set_modem_info(serial, 0);
+
+		/*Start reading from the device*/
+		if (usb_submit_urb(port->interrupt_in_urb))
+			dbg(__FUNCTION__" - usb_submit_urb(read int) failed");
+	} else {
+		spin_unlock_irqrestore (&port->port_lock, flags);
+	}
 
-	/*Start reading from the device*/
-	if (usb_submit_urb(port->interrupt_in_urb))
-		dbg(" usb_submit_urb(read int) failed");
 
 	return (0);
+error:
+	--port->open_count;
+	port->active = 0;
+	MOD_DEC_USE_COUNT;
+	spin_unlock_irqrestore (&port->port_lock, flags);
+	return rc;
 }
 
 
 static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
+	unsigned long flags;
 
-	/* the normal serial device seems to always shut off DTR and RTS now */
-	if (port->tty->termios->c_cflag & HUPCL)
-		keyspan_pda_set_modem_info(serial, 0);
-
-	/* shutdown our bulk reads and writes */
-	usb_unlink_urb (port->write_urb);
-	usb_unlink_urb (port->interrupt_in_urb);
-	port->active = 0;
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	--port->open_count;
+	MOD_DEC_USE_COUNT;
+
+	if (port->open_count <= 0) {
+		/* the normal serial device seems to always shut off DTR and RTS now */
+		spin_unlock_irqrestore (&port->port_lock, flags);
+		if (port->tty->termios->c_cflag & HUPCL)
+			keyspan_pda_set_modem_info(serial, 0);
+		spin_lock_irqsave (&port->port_lock, flags);
+
+		/* shutdown our bulk reads and writes */
+		usb_unlink_urb (port->write_urb);
+		usb_unlink_urb (port->interrupt_in_urb);
+		port->active = 0;
+		port->open_count = 0;
+	}
+
+	spin_unlock_irqrestore (&port->port_lock, flags);
 }
 
 
@@ -683,6 +729,11 @@
 
 static void keyspan_pda_shutdown (struct usb_serial *serial)
 {
+	dbg (__FUNCTION__);
+	
+	while (serial->port[0].open_count > 0) {
+		keyspan_pda_close (&serial->port[0], NULL);
+	}
 	kfree(serial->port[0].private);
 }
 
@@ -728,7 +779,7 @@
 };
 
 
-int keyspan_pda_init (void)
+static int __init keyspan_pda_init (void)
 {
 	usb_serial_register (&keyspan_pda_fake_device);
 	usb_serial_register (&keyspan_pda_device);
@@ -736,7 +787,7 @@
 }
 
 
-void keyspan_pda_exit (void)
+static void __exit keyspan_pda_exit (void)
 {
 	usb_serial_deregister (&keyspan_pda_fake_device);
 	usb_serial_deregister (&keyspan_pda_device);
diff -urN linux-2.2.18-pre9/drivers/usb/serial/omninet.c linux/drivers/usb/serial/omninet.c
--- linux-2.2.18-pre9/drivers/usb/serial/omninet.c	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/serial/omninet.c	Mon Dec  3 20:27:07 2001
@@ -10,6 +10,12 @@
  *
  * Please report both successes and troubles to the author at omninet@kroah.com
  *
+ * (08/28/2000) gkh
+ *	Added locks for SMP safeness.
+ *	Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
+ *	than once.
+ *	Fixed potential race in omninet_write_bulk_callback
+ *
  * (07/19/2000) gkh
  *	Added module_init and module_exit functions to handle the fact that this
  *	driver is a loadable module now.
@@ -54,6 +60,7 @@
 static void omninet_write_bulk_callback	(struct urb *urb);
 static int  omninet_write		(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
 static int  omninet_write_room		(struct usb_serial_port *port);
+static void omninet_shutdown		(struct usb_serial *serial);
 
 /* All of the device info needed for the omni.net */
 static __u16	zyxel_vendor_id			= ZYXEL_VENDOR_ID;
@@ -76,6 +83,7 @@
 	write_room:		omninet_write_room,
 	read_bulk_callback:	omninet_read_bulk_callback,
 	write_bulk_callback:	omninet_write_bulk_callback,
+	shutdown:		omninet_shutdown,
 };
 
 
@@ -117,52 +125,87 @@
 
 static int omninet_open (struct usb_serial_port *port, struct file *filp)
 {
-	struct usb_serial 	*serial = port->serial;
-	struct usb_serial_port 	*wport	= &serial->port[1];
-	struct omninet_data 	*od;
-
-	dbg("omninet_open port %d", port->number);
-
-	if (port->active) {
-		dbg ("device already open");
-		return -EINVAL;
-	}
-	port->active = 1;
+	struct usb_serial	*serial;
+	struct usb_serial_port	*wport;
+	struct omninet_data	*od;
+	unsigned long		flags;
+
+	if (port_paranoia_check (port, __FUNCTION__))
+		return -ENODEV;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	serial = get_usb_serial (port, __FUNCTION__);
+	if (!serial)
+		return -ENODEV;
+
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	MOD_INC_USE_COUNT;
+	++port->open_count;
+
+	if (!port->active) {
+		port->active = 1;
+
+		od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
+		if( !od ) {
+			err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct omninet_data));
+			--port->open_count;
+			port->active = 0;
+			spin_unlock_irqrestore (&port->port_lock, flags);
+			MOD_DEC_USE_COUNT;
+			return -ENOMEM;
+		}
 
-	od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
+		port->private = od;
+		wport = &serial->port[1];
+		wport->tty = port->tty;
 
-	if( !od )
-	{
-		err("omninet_open: kmalloc(%d) failed.", sizeof(struct omninet_data));
-		return -ENOMEM;
+		/* Start reading from the device */
+		if (usb_submit_urb(port->read_urb))
+			dbg(__FUNCTION__" - read bulk (%p) failed", port->read_urb);
 	}
 
-	port->private = od;
-
-	/* Start reading from the device */
-	if (usb_submit_urb(port->read_urb))
-		dbg("usb_submit_urb(read bulk, %p) failed", port->read_urb);
-
-	wport->tty = port->tty;
+	spin_unlock_irqrestore (&port->port_lock, flags);
 
 	return (0);
 }
 
 static void omninet_close (struct usb_serial_port *port, struct file * filp)
 {
-	struct usb_serial 	*serial = port->serial;
-	struct usb_serial_port 	*wport 	= &serial->port[1];
-	struct omninet_data 	*od 	= (struct omninet_data *) port->private;
+	struct usb_serial 	*serial;
+	struct usb_serial_port 	*wport;
+	struct omninet_data 	*od;
+	unsigned long		flags;
 
-	port->active = 0;
+	if (port_paranoia_check (port, __FUNCTION__))
+		return;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	serial = get_usb_serial (port, __FUNCTION__);
+	if (!serial)
+		return;
 
+	spin_lock_irqsave (&port->port_lock, flags);
 
-	dbg("zyxel_close port %d", port->number);
+	--port->open_count;
+	MOD_DEC_USE_COUNT;
 
-	usb_unlink_urb (wport->write_urb);
-	usb_unlink_urb (port->read_urb);
+	if (port->open_count <= 0) {
+		od = (struct omninet_data *)port->private;
+		wport = &serial->port[1];
 
-	if(od) kfree(od);
+		usb_unlink_urb (wport->write_urb);
+		usb_unlink_urb (port->read_urb);
+
+		port->active = 0;
+		port->open_count = 0;
+		if (od)
+			kfree(od);
+	}
+
+	spin_unlock_irqrestore (&port->port_lock, flags);
 }
 
 
@@ -173,7 +216,7 @@
 static void omninet_read_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port 	*port 	= (struct usb_serial_port *)urb->context;
-	struct usb_serial 	*serial = port->serial;
+	struct usb_serial	*serial = get_usb_serial (port, __FUNCTION__);
 
 	unsigned char 		*data 	= urb->transfer_buffer;
 	struct omninet_header 	*header = (struct omninet_header *) &data[0];
@@ -182,22 +225,18 @@
 
 //	dbg("omninet_read_bulk_callback");
 
-	if (port_paranoia_check (port, "omninet_read_bulk_callback")) {
-		return;
-	}
-
-	if (serial_paranoia_check (serial, "omninet_read_bulk_callback")) {
+	if (!serial) {
+		dbg(__FUNCTION__ " - bad serial pointer, exiting");
 		return;
 	}
 
 	if (urb->status) {
-		dbg("nonzero read bulk status received: %d", urb->status);
+		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
 		return;
 	}
 
 #ifdef DEBUG
-	if(header->oh_xxx != 0x30)
-	{
+	if(header->oh_xxx != 0x30) {
 		if (urb->actual_length) {
 			printk (KERN_DEBUG __FILE__ ": omninet_read %d: ", header->oh_len);
 			for (i = 0; i < (header->oh_len + OMNINET_HEADERLEN); i++) {
@@ -208,8 +247,7 @@
 	}
 #endif
 
-	if (urb->actual_length && header->oh_len)
-	{
+	if (urb->actual_length && header->oh_len) {
 		for (i = 0; i < header->oh_len; i++) {
 			 tty_insert_flip_char(port->tty, data[OMNINET_DATAOFFSET + i], 0);
 	  	}
@@ -218,7 +256,7 @@
 
 	/* Continue trying to always read  */
 	if (usb_submit_urb(urb))
-		dbg("failed resubmitting read urb");
+		dbg(__FUNCTION__" - failed resubmitting read urb");
 
 	return;
 }
@@ -230,6 +268,8 @@
 
 	struct omninet_data 	*od 	= (struct omninet_data   *) port->private;
 	struct omninet_header	*header = (struct omninet_header *) wport->write_urb->transfer_buffer;
+
+	unsigned long		flags;
 /*
 #ifdef DEBUG
 	int i;
@@ -239,7 +279,7 @@
 //	dbg("omninet_write port %d", port->number);
 
 	if (count == 0) {
-		dbg("write request of 0 bytes");
+		dbg(__FUNCTION__" - write request of 0 bytes");
 		return (0);
 	}
 /*
@@ -255,10 +295,12 @@
 #endif
 */
 	if (wport->write_urb->status == -EINPROGRESS) {
-		dbg ("already writing");
+		dbg (__FUNCTION__" - already writing");
 		return (0);
 	}
 
+	spin_lock_irqsave (&port->port_lock, flags);
+	
 	count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
 
 	if (from_user) {
@@ -277,11 +319,15 @@
 	/* send the data out the bulk port, always 64 bytes */
 	wport->write_urb->transfer_buffer_length = 64;
 
-	if (usb_submit_urb(wport->write_urb))
-		dbg("usb_submit_urb(write bulk) failed");
+	if (usb_submit_urb(wport->write_urb)) {
+		dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
+		spin_unlock_irqrestore (&port->port_lock, flags);
+		return 0;
+	}
 
 //	dbg("omninet_write returns %d", count);
 
+	spin_unlock_irqrestore (&port->port_lock, flags);
 	return (count);
 }
 
@@ -306,31 +352,26 @@
 /*	struct omninet_header	*header = (struct omninet_header  *) urb->transfer_buffer; */
 	struct usb_serial_port 	*port   = (struct usb_serial_port *) urb->context;
 	struct usb_serial 	*serial;
-	struct tty_struct 	*tty;
 
 //	dbg("omninet_write_bulk_callback, port %0x\n", port);
 
 
-	if (port_paranoia_check (port, "omninet_write_bulk_callback")) {
+	if (port_paranoia_check (port, __FUNCTION__)) {
 		return;
 	}
 
 	serial = port->serial;
-	if (serial_paranoia_check (serial, "omninet_write_bulk_callback")) {
+	if (serial_paranoia_check (serial, __FUNCTION__)) {
 		return;
 	}
 
 	if (urb->status) {
-		dbg("nonzero write bulk status received: %d", urb->status);
+		dbg(__FUNCTION__" - nonzero write bulk status received: %d", urb->status);
 		return;
 	}
 
-	tty = port->tty;
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-
-	wake_up_interruptible(&tty->write_wait);
+	queue_task(&port->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
 
 //	dbg("omninet_write_bulk_callback, tty %0x\n", tty);
 
@@ -338,14 +379,24 @@
 }
 
 
-int omninet_init (void)
+static void omninet_shutdown (struct usb_serial *serial)
+{
+	dbg (__FUNCTION__);
+
+	while (serial->port[0].open_count > 0) {
+		omninet_close (&serial->port[0], NULL);
+	}
+}
+
+
+static int __init omninet_init (void)
 {
 	usb_serial_register (&zyxel_omninet_device);
 	return 0;
 }
 
 
-void omninet_exit (void)
+static void __exit omninet_exit (void)
 {
 	usb_serial_deregister (&zyxel_omninet_device);
 }
diff -urN linux-2.2.18-pre9/drivers/usb/serial/usb-serial.h linux/drivers/usb/serial/usb-serial.h
--- linux-2.2.18-pre9/drivers/usb/serial/usb-serial.h	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/serial/usb-serial.h	Mon Dec  3 20:27:07 2001
@@ -11,6 +11,13 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (09/11/2000) gkh
+ *	Added usb_serial_debug_data function to help get rid of #DEBUG in the
+ *	drivers.
+ *
+ * (08/28/2000) gkh
+ *	Added port_lock to port structure.
+ *
  * (08/08/2000) gkh
  *	Added open_count to port structure.
  *
@@ -63,6 +70,7 @@
 
 	struct tq_struct	tqueue;		/* task queue for line discipline waking up */
 	int			open_count;	/* number of times this port has been opened */
+	spinlock_t		port_lock;
 	
 	void *			private;	/* data private to the specific port */
 };
@@ -183,6 +191,34 @@
 	}
 
 	return 0;
+}
+
+
+static inline struct usb_serial* get_usb_serial (struct usb_serial_port *port, const char *function) 
+{ 
+	/* if no port was specified, or it fails a paranoia check */
+	if (!port || 
+		port_paranoia_check (port, function) ||
+		serial_paranoia_check (port->serial, function)) {
+		/* then say that we dont have a valid usb_serial thing, which will
+		 * end up genrating -ENODEV return values */ 
+		return NULL;
+	}
+
+	return port->serial;
+}
+
+
+static inline void usb_serial_debug_data (const char *file, const char *function, int size, const unsigned char *data)
+{
+#ifdef CONFIG_USB_SERIAL_DEBUG
+	int i;
+	printk (KERN_DEBUG "%s: %s - length = %d, data = ", file, function, size);
+	for (i = 0; i < size; ++i) {
+		printk ("%.2x ", data[i]);
+	}
+	printk ("\n");
+#endif
 }
 
 #endif	/* ifdef __LINUX_USB_SERIAL_H */
diff -urN linux-2.2.18-pre9/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
--- linux-2.2.18-pre9/drivers/usb/serial/usbserial.c	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/serial/usbserial.c	Mon Dec  3 20:27:07 2001
@@ -15,6 +15,14 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (09/11/2000) gkh
+ *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
+ *
+ * (08/28/2000) gkh
+ *	Added port_lock to port structure.
+ *	Added locks for SMP safeness to generic driver
+ *	Fixed the ability to open a generic device's port more than once.
+ *
  * (07/23/2000) gkh
  *	Added bulk_out_endpointAddress to port structure.
  *
@@ -265,6 +273,7 @@
 static int  generic_chars_in_buffer	(struct usb_serial_port *port);
 static void generic_read_bulk_callback	(struct urb *urb);
 static void generic_write_bulk_callback	(struct urb *urb);
+static void generic_shutdown		(struct usb_serial *serial);
 
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
@@ -288,6 +297,7 @@
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
 	num_ports:		1,
+	shutdown:		generic_shutdown,
 };
 #endif
 
@@ -322,21 +332,6 @@
 LIST_HEAD(usb_serial_driver_list);
 
 
-static inline struct usb_serial* get_usb_serial (struct usb_serial_port *port, const char *function) 
-{ 
-	/* if no port was specified, or it fails a paranoia check */
-	if (!port || 
-		port_paranoia_check (port, function) ||
-		serial_paranoia_check (port->serial, function)) {
-		/* then say that we dont have a valid usb_serial thing, which will
-		 * end up genrating -ENODEV return values */ 
-		return NULL;
-	}
-
-	return port->serial;
-}
-
-
 static struct usb_serial *get_serial_by_minor (int minor)
 {
 	return serial_table[minor];
@@ -698,47 +693,65 @@
 static int generic_open (struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
+	unsigned long flags;
+
+	if (port_paranoia_check (port, __FUNCTION__))
+		return -ENODEV;
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	if (port->active) {
-		dbg (__FUNCTION__ " - device already open");
-		return -EINVAL;
-	}
-	port->active = 1;
- 
-	/* if we have a bulk interrupt, start reading from it */
-	if (serial->num_bulk_in) {
-		/*Start reading from the device*/
-		if (usb_submit_urb(port->read_urb))
-			dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed");
-	}
+	spin_lock_irqsave (&port->port_lock, flags);
+	
+	++port->open_count;
+	MOD_INC_USE_COUNT;
+	
+	if (!port->active) {
+		port->active = 1;
 
-	return (0);
+		/* if we have a bulk interrupt, start reading from it */
+		if (serial->num_bulk_in) {
+			/*Start reading from the device*/
+			if (usb_submit_urb(port->read_urb))
+				dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed");
+		}
+	}
+	
+	spin_unlock_irqrestore (&port->port_lock, flags);
+	
+	return 0;
 }
 
 
 static void generic_close (struct usb_serial_port *port, struct file * filp)
 {
 	struct usb_serial *serial = port->serial;
+	unsigned long flags;
 
 	dbg(__FUNCTION__ " - port %d", port->number);
-	
-	/* shutdown any bulk reads that might be going on */
-	if (serial->num_bulk_out) {
-		usb_unlink_urb (port->write_urb);
-	}
-	if (serial->num_bulk_in) {
-		usb_unlink_urb (port->read_urb);
+
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	--port->open_count;
+
+	if (port->open_count <= 0) {
+		/* shutdown any bulk reads that might be going on */
+		if (serial->num_bulk_out)
+			usb_unlink_urb (port->write_urb);
+		if (serial->num_bulk_in)
+			usb_unlink_urb (port->read_urb);
+		
+		port->active = 0;
+		port->open_count = 0;
 	}
 
-	port->active = 0;
+	spin_unlock_irqrestore (&port->port_lock, flags);
 }
 
 
 static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
+	unsigned long flags;
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
@@ -754,18 +767,10 @@
 			return (0);
 		}
 
+		spin_lock_irqsave (&port->port_lock, flags);
 		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
 
-#ifdef DEBUG
-		{
-			int i;
-			printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count);
-			for (i = 0; i < count; ++i) {
-				printk ("%.2x ", buf[i]);
-			}
-			printk ("\n");
-		}
-#endif
+		usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf);
 
 		if (from_user) {
 			copy_from_user(port->write_urb->transfer_buffer, buf, count);
@@ -777,9 +782,13 @@
 		/* send the data out the bulk port */
 		port->write_urb->transfer_buffer_length = count;
 
-		if (usb_submit_urb(port->write_urb))
+		if (usb_submit_urb(port->write_urb)) {
 			dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed");
+			spin_unlock_irqrestore (&port->port_lock, flags);
+			return 0;
+		}
 
+		spin_unlock_irqrestore (&port->port_lock, flags);
 		return (count);
 	}
 	
@@ -840,15 +849,7 @@
 		return;
 	}
 
-#ifdef DEBUG
-	if (urb->actual_length) {
-		printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", urb->actual_length);
-		for (i = 0; i < urb->actual_length; ++i) {
-			printk ("%.2x ", data[i]);
-		}
-		printk ("\n");
-	}
-#endif
+	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 
 	tty = port->tty;
 	if (urb->actual_length) {
@@ -890,6 +891,21 @@
 }
 
 
+static void generic_shutdown (struct usb_serial *serial)
+{
+	int i;
+
+	dbg (__FUNCTION__);
+
+	/* stop reads and writes on all ports */
+	for (i=0; i < serial->num_ports; ++i) {
+		while (serial->port[i].open_count > 0) {
+			generic_close (&serial->port[i], NULL);
+		}
+	}
+}
+
+
 static void port_softint(void *private)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)private;
@@ -1128,6 +1144,7 @@
 		port->magic = USB_SERIAL_PORT_MAGIC;
 		port->tqueue.routine = port_softint;
 		port->tqueue.data = port;
+		spin_lock_init (&port->port_lock);
 	}
 	
 	/* initialize the devfs nodes for this device and let the user know what ports we are bound to */
diff -urN linux-2.2.18-pre9/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c
--- linux-2.2.18-pre9/drivers/usb/serial/visor.c	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/serial/visor.c	Mon Dec  3 20:27:07 2001
@@ -10,11 +10,21 @@
  *	(at your option) any later version.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ * (09/11/2000) gkh
+ *	Got rid of always calling kmalloc for every urb we wrote out to the
+ *	device.
+ *	Added visor_read_callback so we can keep track of bytes in and out for
+ *	those people who like to know the speed of their device.
+ *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
  *
  * (09/06/2000) gkh
  *	Fixed oops in visor_exit.  Need to uncomment usb_unlink_urb call _after_
  *	the host controller drivers set urb->dev = NULL when the urb is finished.
  *
+ * (08/28/2000) gkh
+ *	Added locks for SMP safeness.
+ *
  * (08/08/2000) gkh
  *	Fixed endian problem in visor_startup.
  *	Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
@@ -72,6 +82,7 @@
 
 #include "visor.h"
 
+#define MIN(a,b)                (((a)<(b))?(a):(b))
 
 /* function prototypes for a handspring visor */
 static int  visor_open		(struct usb_serial_port *port, struct file *filp);
@@ -83,7 +94,8 @@
 static void visor_shutdown	(struct usb_serial *serial);
 static int  visor_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
 static void visor_set_termios	(struct usb_serial_port *port, struct termios *old_termios);
-static void visor_write_bulk_callback (struct urb *urb);
+static void visor_write_bulk_callback	(struct urb *urb);
+static void visor_read_bulk_callback	(struct urb *urb);
 
 /* All of the device info needed for the Handspring Visor */
 static __u16	handspring_vendor_id	= HANDSPRING_VENDOR_ID;
@@ -109,11 +121,16 @@
 	set_termios:		visor_set_termios,
 	write:			visor_write,
 	write_bulk_callback:	visor_write_bulk_callback,
+	read_bulk_callback:	visor_read_bulk_callback,
 };
 
 
-#define NUM_URBS	24
-static struct urb *write_urb_pool[NUM_URBS];
+#define NUM_URBS			24
+#define URB_TRANSFER_BUFFER_SIZE	64
+static struct urb	*write_urb_pool[NUM_URBS];
+static spinlock_t	write_urb_pool_lock;
+static int		bytes_in;
+static int		bytes_out;
 
 
 /******************************************************************************
@@ -121,39 +138,56 @@
  ******************************************************************************/
 static int visor_open (struct usb_serial_port *port, struct file *filp)
 {
-	dbg(__FUNCTION__ " - port %d", port->number);
+	unsigned long flags;
 
-	if (port->active) {
-		dbg (__FUNCTION__ " - device already open");
-		return -EINVAL;
-	}
+	if (port_paranoia_check (port, __FUNCTION__))
+		return -ENODEV;
+	
+	dbg(__FUNCTION__ " - port %d", port->number);
 
+	spin_lock_irqsave (&port->port_lock, flags);
+	
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 	
 	if (!port->active) {
 		port->active = 1;
+		bytes_in = 0;
+		bytes_out = 0;
 
 		/*Start reading from the device*/
 		if (usb_submit_urb(port->read_urb))
 			dbg(__FUNCTION__  " - usb_submit_urb(read bulk) failed");
 	}
 	
+	spin_unlock_irqrestore (&port->port_lock, flags);
+	
 	return 0;
 }
 
 
 static void visor_close (struct usb_serial_port *port, struct file * filp)
 {
-	struct usb_serial *serial = port->serial;
-	unsigned char *transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
+	struct usb_serial *serial;
+	unsigned char *transfer_buffer;
+	unsigned long flags;
+
+	if (port_paranoia_check (port, __FUNCTION__))
+		return;
 	
 	dbg(__FUNCTION__ " - port %d", port->number);
 			 
+	serial = get_usb_serial (port, __FUNCTION__);
+	if (!serial)
+		return;
+	
+	spin_lock_irqsave (&port->port_lock, flags);
+
 	--port->open_count;
 	MOD_DEC_USE_COUNT;
 
 	if (port->open_count <= 0) {
+		transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
 		if (!transfer_buffer) {
 			err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
 		} else {
@@ -167,73 +201,79 @@
 		usb_unlink_urb (port->read_urb);
 		port->active = 0;
 		port->open_count = 0;
+
 	}
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
+	/* Uncomment the following line if you want to see some statistics in your syslog */
+	/* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
 }
 
 
 static int visor_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
-	struct urb *urb = NULL;
-	unsigned char *buffer = NULL;
+	struct urb *urb;
+	const unsigned char *current_position = buf;
+	unsigned long flags;
 	int status;
 	int i;
+	int bytes_sent = 0;
+	int transfer_size;
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	if (count == 0) {
-		dbg(__FUNCTION__ " - write request of 0 bytes");
-		return 0;
-	}
-
-	/* try to find a free urb in our list of them */
-	for (i = 0; i < NUM_URBS; ++i) {
-		if (write_urb_pool[i]->status != -EINPROGRESS) {
-			urb = write_urb_pool[i];
-			break;
+	usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf);
+	
+	while (count > 0) {
+		/* try to find a free urb in our list of them */
+		urb = NULL;
+		spin_lock_irqsave (&write_urb_pool_lock, flags);
+		for (i = 0; i < NUM_URBS; ++i) {
+			if (write_urb_pool[i]->status != -EINPROGRESS) {
+				urb = write_urb_pool[i];
+				break;
+			}
 		}
+		spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+		if (urb == NULL) {
+			dbg (__FUNCTION__ " - no more free urbs");
+			goto exit;
+		}
+		if (urb->transfer_buffer == NULL) {
+			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+			if (urb->transfer_buffer == NULL) {
+				err(__FUNCTION__" no more kernel memory...");
+				goto exit;
+			}
+		}
+		
+		transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE);
+		if (from_user)
+			copy_from_user (urb->transfer_buffer, current_position, transfer_size);
+		else
+			memcpy (urb->transfer_buffer, current_position, transfer_size);
+		
+		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+
+		/* build up our urb */
+		FILL_BULK_URB (urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), 
+				urb->transfer_buffer, transfer_size, visor_write_bulk_callback, port);
+		urb->transfer_flags |= USB_QUEUE_BULK;
+
+		/* send it down the pipe */
+		status = usb_submit_urb(urb);
+		if (status)
+			dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
+
+		current_position += transfer_size;
+		bytes_sent += transfer_size;
+		count -= transfer_size;
+		bytes_out += transfer_size;
 	}
-	if (urb == NULL) {
-		dbg (__FUNCTION__ " - no free urbs");
-		return 0;
-	}
-
-	count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-
-#ifdef DEBUG
-	printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count);
-	for (i = 0; i < count; ++i) {
-		printk ("%.2x ", buf[i]);
-	}
-	printk ("\n");
-#endif
-
-	if (urb->transfer_buffer != NULL)
-		kfree(urb->transfer_buffer);
-	buffer = kmalloc (count, GFP_KERNEL);
-	if (buffer == NULL) {
-		err(__FUNCTION__" no more kernel memory...");
-		return 0;
-	}
-	
-	if (from_user) {
-		copy_from_user(buffer, buf, count);
-	}
-	else {
-		memcpy (buffer, buf, count);
-	}  
-
-	/* build up our urb */
-	FILL_BULK_URB (urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
-			buffer, count, visor_write_bulk_callback, port);
-	urb->transfer_flags |= USB_QUEUE_BULK;
-
-	/* send it down the pipe */
-	status = usb_submit_urb(urb);
-	if (status)
-		dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
 
-	return (count);
+exit:
+	return bytes_sent;
 } 
 
 
@@ -258,23 +298,70 @@
 }
 
 
+static void visor_read_bulk_callback (struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct tty_struct *tty;
+	unsigned char *data = urb->transfer_buffer;
+	int i;
+
+	if (port_paranoia_check (port, __FUNCTION__))
+		return;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	if (urb->status) {
+		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+		return;
+	}
+
+	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+
+	tty = port->tty;
+	if (urb->actual_length) {
+		for (i = 0; i < urb->actual_length ; ++i) {
+			tty_insert_flip_char(tty, data[i], 0);
+		}
+		tty_flip_buffer_push(tty);
+		bytes_in += urb->actual_length;
+	}
+
+	/* Continue trying to always read  */
+	if (usb_submit_urb(urb))
+		dbg(__FUNCTION__ " - failed resubmitting read urb");
+	return;
+}
+
+
 static void visor_throttle (struct usb_serial_port *port)
 {
+	unsigned long flags;
+
 	dbg(__FUNCTION__ " - port %d", port->number);
 
+	spin_lock_irqsave (&port->port_lock, flags);
+
 	usb_unlink_urb (port->read_urb);
 
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
 	return;
 }
 
 
 static void visor_unthrottle (struct usb_serial_port *port)
 {
+	unsigned long flags;
+
 	dbg(__FUNCTION__ " - port %d", port->number);
 
+	spin_lock_irqsave (&port->port_lock, flags);
+
 	if (usb_submit_urb (port->read_urb))
 		dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed");
 
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
 	return;
 }
 
@@ -341,7 +428,7 @@
 	kfree (transfer_buffer);
 
 	/* continue on with initialization */
-	return (0);
+	return 0;
 }
 
 
@@ -433,42 +520,57 @@
 }
 
 
-int visor_init (void)
+static int __init visor_init (void)
 {
+	struct urb *urb;
 	int i;
 
 	usb_serial_register (&handspring_device);
 	
-	/* create our write urb pool */ 
+	/* create our write urb pool and transfer buffers */ 
+	spin_lock_init (&write_urb_pool_lock);
 	for (i = 0; i < NUM_URBS; ++i) {
-		struct urb  *urb = usb_alloc_urb(0);
+		urb = usb_alloc_urb(0);
+		write_urb_pool[i] = urb;
 		if (urb == NULL) {
 			err("No more urbs???");
 			continue;
 		}
+
 		urb->transfer_buffer = NULL;
-		write_urb_pool[i] = urb;
+		urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+		if (!urb->transfer_buffer) {
+			err (__FUNCTION__ " - out of memory for urb buffers.");
+			continue;
+		}
 	}
 	
 	return 0;
 }
 
 
-void visor_exit (void)
+static void __exit visor_exit (void)
 {
 	int i;
+	unsigned long flags;
 
 	usb_serial_deregister (&handspring_device);
-	
+
+	spin_lock_irqsave (&write_urb_pool_lock, flags);
+
 	for (i = 0; i < NUM_URBS; ++i) {
-		/* FIXME - uncomment the following usb_unlink_urb call when
-		 * the host controllers get fixed to set urb->dev = NULL after
-		 * the urb is finished.  Otherwise this call oopses. */
-		/* usb_unlink_urb(write_urb_pool[i]); */
-		if (write_urb_pool[i]->transfer_buffer)
-			kfree(write_urb_pool[i]->transfer_buffer);
-		usb_free_urb (write_urb_pool[i]);
+		if (write_urb_pool[i]) {
+			/* FIXME - uncomment the following usb_unlink_urb call when
+			 * the host controllers get fixed to set urb->dev = NULL after
+			 * the urb is finished.  Otherwise this call oopses. */
+			/* usb_unlink_urb(write_urb_pool[i]); */
+			if (write_urb_pool[i]->transfer_buffer)
+				kfree(write_urb_pool[i]->transfer_buffer);
+			usb_free_urb (write_urb_pool[i]);
+		}
 	}
+
+	spin_unlock_irqrestore (&write_urb_pool_lock, flags);
 }
 
 
diff -urN linux-2.2.18-pre9/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c
--- linux-2.2.18-pre9/drivers/usb/serial/whiteheat.c	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/serial/whiteheat.c	Mon Dec  3 20:27:07 2001
@@ -11,6 +11,9 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (09/11/2000) gkh
+ *	Removed DEBUG #ifdefs with call to usb_serial_debug_data
+ *
  * (07/19/2000) gkh
  *	Added module_init and module_exit functions to handle the fact that this
  *	driver is a loadable module now.
@@ -130,11 +133,6 @@
  *****************************************************************************/
 static void command_port_write_callback (struct urb *urb)
 {
-	unsigned char *data = urb->transfer_buffer;
-#ifdef DEBUG
-	int i;
-#endif
-
 	dbg (__FUNCTION__);
 
 	if (urb->status) {
@@ -142,15 +140,7 @@
 		return;
 	}
 
-#ifdef DEBUG
-	if (urb->actual_length) {
-		printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", urb->actual_length);
-		for (i = 0; i < urb->actual_length; ++i) {
-			printk ("%.2x ", data[i]);
-		}
-		printk ("\n");
-	}
-#endif
+	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
 
 	return;
 }
@@ -160,9 +150,6 @@
 {
 	struct whiteheat_private *info = (struct whiteheat_private *)urb->context;
 	unsigned char *data = urb->transfer_buffer;
-#ifdef DEBUG
-	int i;
-#endif
 
 	dbg (__FUNCTION__);
 
@@ -171,15 +158,7 @@
 		return;
 	}
 
-#ifdef DEBUG
-	if (urb->actual_length) {
-		printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", urb->actual_length);
-		for (i = 0; i < urb->actual_length; ++i) {
-			printk ("%.2x ", data[i]);
-		}
-		printk ("\n");
-	}
-#endif
+	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 
 	/* right now, if the command is COMMAND_COMPLETE, just flip the bit saying the command finished */
 	/* in the future we're going to have to pay attention to the actual command that completed */
@@ -531,7 +510,7 @@
 }
 
 
-int whiteheat_init (void)
+static int __init whiteheat_init (void)
 {
 	usb_serial_register (&whiteheat_fake_device);
 	usb_serial_register (&whiteheat_device);
@@ -539,7 +518,7 @@
 }
 
 
-void whiteheat_exit (void)
+static void __exit whiteheat_exit (void)
 {
 	usb_serial_deregister (&whiteheat_fake_device);
 	usb_serial_deregister (&whiteheat_device);
diff -urN linux-2.2.18-pre9/drivers/usb/usb-core.c linux/drivers/usb/usb-core.c
--- linux-2.2.18-pre9/drivers/usb/usb-core.c	Mon Dec  3 20:26:37 2001
+++ linux/drivers/usb/usb-core.c	Mon Dec  3 20:27:07 2001
@@ -13,6 +13,7 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/config.h>
+#include <linux/init.h>
 #include <linux/usb.h>
 
 /*
@@ -24,35 +25,6 @@
 int usb_major_init(void);
 void usb_major_cleanup(void);
 
-/*
- * USB device drivers
- */
-
-int input_init_module(void);
-int acm_init_module(void);
-int usb_dc2xx_init_module(void);
-int evdev_init_module(void);
-int hid_init_module(void);
-int joydev_init_module(void);
-int keybdev_init_module(void);
-int mousedev_init_module(void);
-int microtek_drv_init_module(void);
-int usblp_init_module(void);
-int usb_ov511_init_module(void);
-int usb_rio_init_module(void);
-int usb_scanner_init_module(void);
-int usb_serial_init_module(void);
-int usb_stor_init_module(void);
-int usb_kbd_init_module(void);
-int usb_mouse_init_module(void);
-int wacom_init_module(void);
-int wmforce_init_module(void);
-
-int usb_audio_init(void);
-int usb_ibmcam_init(void);
-int dabusb_init(void);
-int plusb_init(void);
-int dsbr100_init(void);
 
 /*
  * HCI drivers
@@ -88,21 +60,6 @@
 	usb_hub_init();
 
 #ifndef CONFIG_USB_MODULE
-#ifdef CONFIG_USB_AUDIO
-	usb_audio_init();
-#endif
-#ifdef CONFIG_USB_IBMCAM
-	usb_ibmcam_init();
-#endif
-#ifdef CONFIG_USB_DABUSB
-	dabusb_init();
-#endif
-#ifdef CONFIG_USB_DSBR
-	dsbr100_init();
-#endif
-#ifdef CONFIG_USB_PLUSB
-	plusb_init();
-#endif
 #ifdef CONFIG_USB_UHCI
 	uhci_init();
 #endif
diff -urN linux-2.2.18-pre9/fs/adfs/adfs.h linux/fs/adfs/adfs.h
--- linux-2.2.18-pre9/fs/adfs/adfs.h	Mon Dec  3 20:26:37 2001
+++ linux/fs/adfs/adfs.h	Mon Dec  3 20:27:11 2001
@@ -97,6 +97,7 @@
 /* dir_*.c */
 extern struct inode_operations adfs_dir_inode_operations;
 extern struct file_operations adfs_dir_operations;
+extern struct dentry_operations adfs_dentry_operations;
 extern struct adfs_dir_ops adfs_f_dir_ops;
 extern struct adfs_dir_ops adfs_fplus_dir_ops;
 
diff -urN linux-2.2.18-pre9/fs/adfs/super.c linux/fs/adfs/super.c
--- linux-2.2.18-pre9/fs/adfs/super.c	Mon Dec  3 20:26:37 2001
+++ linux/fs/adfs/super.c	Mon Dec  3 20:27:11 2001
@@ -439,6 +439,8 @@
 		adfs_error(sb, "get root inode failed\n");
 		goto error_dec_use;
 	}
+	else
+		sb->s_root->d_op = &adfs_dentry_operations;
 	return sb;
 
 error_free_bh:
diff -urN linux-2.2.18-pre9/fs/ext2/inode.c linux/fs/ext2/inode.c
--- linux-2.2.18-pre9/fs/ext2/inode.c	Mon Dec  3 20:26:37 2001
+++ linux/fs/ext2/inode.c	Mon Dec  3 20:27:11 2001
@@ -215,7 +215,8 @@
 		bh = bread (inode->i_dev, i, inode->i_sb->s_blocksize);
 		if (!bh)
 			goto fail;
-		i = le32_to_cpu(((u32 *) bh->b_data)[*++p]);
+		++p;
+		i = le32_to_cpu(((u32 *) bh->b_data)[*p]);
 		brelse (bh);
 	}
 	return i;
diff -urN linux-2.2.18-pre9/fs/nfs/file.c linux/fs/nfs/file.c
--- linux-2.2.18-pre9/fs/nfs/file.c	Mon Dec  3 20:26:37 2001
+++ linux/fs/nfs/file.c	Mon Dec  3 20:27:11 2001
@@ -274,11 +274,14 @@
 		status = 0;
 
 	/*
-	 * Make sure we re-validate anything we've got cached.
+	 * Make sure we clear the cache whenever we try to get the lock.
 	 * This makes locking act as a cache coherency point.
 	 */
  out_unlock:
  out_ok:
-	NFS_CACHEINV(inode);
+	if ((cmd == F_SETLK || cmd == F_SETLKW) && fl->fl_type != F_UNLCK) {
+		nfs_wb_all(inode);	/* we may have slept */
+		nfs_zap_caches(inode);
+	}
 	return status;
 }
diff -urN linux-2.2.18-pre9/include/asm-sparc/io.h linux/include/asm-sparc/io.h
--- linux-2.2.18-pre9/include/asm-sparc/io.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc/io.h	Mon Dec  3 20:27:11 2001
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.18 1998/09/21 05:07:17 jj Exp $ */
+/* $Id: io.h,v 1.18.2.1 2000/09/17 05:11:47 davem Exp $ */
 #ifndef __SPARC_IO_H
 #define __SPARC_IO_H
 
@@ -98,6 +98,8 @@
 #define inb_p inb
 #define outb_p outb
 
+#ifdef __KERNEL__
+
 extern void sun4c_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly);
 extern void srmmu_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly);
 
@@ -161,5 +163,7 @@
 
 #define virt_to_phys(x) __pa((unsigned long)(x))
 #define phys_to_virt(x) __va((unsigned long)(x))
+
+#endif /* __KERNEL__ */
 
 #endif /* !(__SPARC_IO_H) */
diff -urN linux-2.2.18-pre9/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- linux-2.2.18-pre9/include/asm-sparc64/io.h	Wed May  3 17:16:51 2000
+++ linux/include/asm-sparc64/io.h	Mon Dec  3 20:27:11 2001
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.19.2.1 2000/01/14 03:55:36 davem Exp $ */
+/* $Id: io.h,v 1.19.2.2 2000/09/17 05:11:47 davem Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -244,6 +244,8 @@
 	return retval;
 }
 
+#ifdef __KERNEL__
+
 /*
  * On the sparc we have the whole physical IO address space mapped at all
  * times, so ioremap() and iounmap() do not need to do anything.
@@ -279,5 +281,7 @@
 			    u32 io, int rdonly);
 extern void sparc_free_io (void *va, int sz);
 extern void *sparc_dvma_malloc (int sz, char *name, __u32 *dvma_addr);
+
+#endif /* __KERNEL__ */
 
 #endif /* !(__SPARC64_IO_H) */
diff -urN linux-2.2.18-pre9/include/linux/capi.h linux/include/linux/capi.h
--- linux-2.2.18-pre9/include/linux/capi.h	Mon Nov  3 10:09:21 1997
+++ linux/include/linux/capi.h	Mon Dec  3 20:27:11 2001
@@ -1,21 +1,10 @@
 /*
- * $Id: capi.h,v 1.1 1997/03/04 21:27:33 calle Exp $
+ * $Id: capi.h,v 1.4 2000/06/12 09:20:20 kai Exp $
  * 
  * CAPI 2.0 Interface for Linux
  * 
  * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
- * $Log: capi.h,v $
- * Revision 1.1  1997/03/04 21:27:33  calle
- * First version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
- *
- * 
  */
 
 #ifndef __LINUX_CAPI_H__
@@ -107,6 +96,7 @@
  * CAPI_INSTALLED
  */
 #define CAPI_INSTALLED		_IOR('C',0x22, __u16)
+
 
 /*
  * member contr is input for
diff -urN linux-2.2.18-pre9/include/linux/i2c.h linux/include/linux/i2c.h
--- linux-2.2.18-pre9/include/linux/i2c.h	Mon Dec  3 20:26:37 2001
+++ linux/include/linux/i2c.h	Tue Jan  4 10:12:24 2000
@@ -35,13 +35,12 @@
 #define I2C_DRIVERID_VIDEOTEXT		 3
 #define I2C_DRIVERID_VIDEODECODER	 4
 #define I2C_DRIVERID_VIDEOENCODER	 5
-  
+
 #define I2C_BUSID_BT848		1	/* I2C bus on a BT848 */
 	/* 2 is used in 2.3.x */
 #define I2C_BUSID_BUZ		3	/* I2C bus on a BUZ */
 #define I2C_BUSID_ZORAN		4	/* I2C bus on a Zoran */
-#define I2C_BUSID_CYBER2000	5	/* I2C bus on a Cyber2000 */
-
+#define I2C_BUSID_SGIVWFB	5	/* Moved to be unique */
 
 /*
  * struct for a driver for a i2c chip (tuner, soundprocessor,
diff -urN linux-2.2.18-pre9/include/linux/isdn.h linux/include/linux/isdn.h
--- linux-2.2.18-pre9/include/linux/isdn.h	Wed Jun  7 14:26:44 2000
+++ linux/include/linux/isdn.h	Mon Dec  3 20:27:11 2001
@@ -1,5 +1,5 @@
-/* $Id: isdn.h,v 1.95 2000/03/04 16:20:42 detabc Exp $
- *
+/* $Id: isdn.h,v 1.107 2000/09/10 20:29:18 detabc Exp $
+
  * Main header for the Linux ISDN subsystem (linklevel).
  *
  * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
@@ -19,338 +19,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
- * $Log: isdn.h,v $
- * Revision 1.95  2000/03/04 16:20:42  detabc
- * copy frames before rewriting frame's saddr
- *
- * Revision 1.94  2000/02/26 00:29:40  keil
- * more softnet changes
- *
- * Revision 1.93  2000/02/25 11:29:17  paul
- * changed chargetime to ulong from int (after about 20 days the "chargetime of
- * ipppX is now 1234" message displays a negative number on alpha).
- *
- * Revision 1.92  2000/02/17 13:15:56  keil
- * fix backward compatibility for 2.2
- *
- * Revision 1.91  2000/02/16 14:56:27  paul
- * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers
- *
- * Revision 1.90  2000/02/06 21:50:00  detabc
- * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections.
- * Include checksum-recompute of ip- and udp-header's.
- *
- * Revision 1.89  2000/02/05 22:11:33  detabc
- * Add rewriting of socket's and frame's saddr adressfield for
- * dynip-connections.  Only for tcp/ipv4 and switchable per interface.
- * Include checksum-recompute of ip- and tcp-header's.
- *
- * Revision 1.88  2000/01/20 19:59:43  keil
- * Add FAX Class 1 support
- *
- * Revision 1.87  2000/01/09 20:43:15  detabc
- * exand logical bind-group's for both call's (in and out).
- * add first part of kernel-config-help for abc-extension.
- *
- * Revision 1.86  1999/12/05 16:06:09  detabc
- * add resethandling for rawip-compression.
- * at now all B2-Protocols are usable with rawip-compression
- *
- * Revision 1.85  1999/11/30 11:29:06  detabc
- * add a on the fly frame-counter and limit
- *
- * Revision 1.84  1999/11/28 14:49:08  detabc
- * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the
- * uncompressed size.
- *
- * Revision 1.83  1999/11/26 15:54:59  detabc
- * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol.
- *
- * Revision 1.82  1999/11/20 22:14:14  detabc
- * added channel dial-skip in case of external use
- * (isdn phone or another isdn device) on the same NTBA.
- * usefull with two or more card's connected the different NTBA's.
- * global switchable in kernel-config and also per netinterface.
- *
- * add auto disable of netinterface's in case of:
- * 	to many connection's in short time.
- * 	config mistakes (wrong encapsulation, B2-protokoll or so on) on local
- * 	or remote side.
- * 	wrong password's or something else to a ISP (syncppp).
- *
- * possible encapsulations for this future are:
- * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
- * and ISDN_NET_ENCAP_CISCOHDLCK.
- *
- * Revision 1.81  1999/10/27 21:21:18  detabc
- * Added support for building logically-bind-group's per interface.
- * usefull for outgoing call's with more then one isdn-card.
- *
- * Switchable support to dont reset the hangup-timeout for
- * receive frames. Most part's of the timru-rules for receiving frames
- * are now obsolete. If the input- or forwarding-firewall deny
- * the frame, the line will be not hold open.
- *
- * Revision 1.80  1999/10/26 21:09:29  armin
- * New bufferlen for phonenumber only with kernel 2.3.x
- *
- * Revision 1.79  1999/10/16 17:52:38  keil
- * Changing the MSN length need new data versions
- *
- * Revision 1.78  1999/10/08 18:59:33  armin
- * Bugfix of too small MSN buffer and checking phone number
- * in isdn_tty_getdial()
- *
- * Revision 1.77  1999/09/23 22:22:42  detabc
- * added tcp-keepalive-detect with local response (ipv4 only)
- * added host-only-interface support
- * (source ipaddr == interface ipaddr) (ipv4 only)
- * ok with kernel 2.3.18 and 2.2.12
- *
- * Revision 1.76  1999/09/14 10:16:21  keil
- * change ABC include
- *
- * Revision 1.75  1999/09/13 23:25:17  he
- * serialized xmitting frames from isdn_ppp and BSENT statcallb
- *
- * Revision 1.74  1999/09/12 16:19:39  detabc
- * added abc features
- * low cost routing for net-interfaces (only the HL side).
- * need more implementation in the isdnlog-utility
- * udp info support (first part).
- * different EAZ on outgoing call's.
- * more checks on D-Channel callbacks (double use of channels).
- * tested and running with kernel 2.3.17
- *
- * Revision 1.73  1999/09/06 07:29:36  fritz
- * Changed my mail-address.
- *
- * Revision 1.72  1999/09/04 22:20:19  detabc
- *
- * Revision 1.71  1999/08/23 15:54:22  keil
- * more backported changes from kernel 2.3.14
- *
- * Revision 1.70  1999/07/31 12:59:58  armin
- * Added tty fax capabilities.
- *
- * Revision 1.69  1999/07/13 20:47:53  werner
- * added channel bit ISDN_USAGE_DISABLED for limiting b-channel access.
- *
- * Revision 1.68  1999/07/11 17:07:37  armin
- * Added tty modem register S23.
- * Added new layer 2 and 3 protocols for Fax and DSP functions.
- *
- * Revision 1.67  1999/07/07 10:17:24  detabc
- * remove unused messages
- *
- * Revision 1.66  1999/07/01 08:35:37  keil
- * compatibility to 2.3
- *
- * Revision 1.65  1999/06/10 11:51:27  paul
- * fixed comment for NET_DV
- *
- * Revision 1.64  1999/04/18 14:57:14  fritz
- * Removed TIMRU stuff
- *
- * Revision 1.63  1999/04/18 14:07:18  fritz
- * Removed TIMRU stuff.
- *
- * Revision 1.62  1999/04/12 13:16:54  fritz
- * Changes from 2.0 tree.
- *
- * Revision 1.61  1999/03/02 11:43:21  armin
- * Added variable to store connect-message of Modem.
- * Added Timer-define for RegS7 (Wait for Carrier).
- *
- * Revision 1.60  1998/10/25 14:50:29  fritz
- * Backported from MIPS (Cobalt).
- *
- * Revision 1.59  1998/10/23 10:18:55  paul
- * Implementation of "dialmode" (successor of "status")
- * You also need current isdnctrl for this!
- *
- * Revision 1.58  1998/10/23 10:10:06  fritz
- * Test-Checkin
- *
- * Revision 1.57  1998/08/31 21:10:01  he
- * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
- *     peer phone number)
- *
- * Revision 1.56  1998/07/26 18:46:52  armin
- * Added silence detection in voice receive mode.
- *
- * Revision 1.55  1998/06/26 15:13:17  fritz
- * Added handling of STAT_ICALL with incomplete CPN.
- * Added AT&L for ttyI emulator.
- * Added more locking stuff in tty_write.
- *
- * Revision 1.54  1998/06/18 23:32:01  fritz
- * Replaced cli()/restore_flags() in isdn_tty_write() by locking.
- * Removed direct-senddown feature in isdn_tty_write because it will
- * never succeed with locking and is useless anyway.
- *
- * Revision 1.53  1998/06/17 19:51:51  he
- * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
- * brute force fix to avoid Ugh's in isdn_tty_write()
- * cleaned up some dead code
- *
- * Revision 1.46  1998/04/14 16:28:59  he
- * Fixed user space access with interrupts off and remaining
- * copy_{to,from}_user() -> -EFAULT return codes
- *
- * Revision 1.45  1998/03/24 16:33:12  hipp
- * More CCP changes. BSD compression now "works" on a local loopback link.
- * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h
- *
- * Revision 1.44  1998/03/22 18:50:56  hipp
- * Added BSD Compression for syncPPP .. UNTESTED at the moment
- *
- * Revision 1.43  1998/03/09 17:46:44  he
- * merged in 2.1.89 changes
- *
- *
- * Revision 1.40  1998/03/08 01:08:29  fritz
- * Increased NET_DV because of TIMRU
- *
- * Revision 1.39  1998/03/07 22:42:49  fritz
- * Starting generic module support (Nothing usable yet).
- *
- * Revision 1.38  1998/03/07 18:21:29  cal
- * Dynamic Timeout-Rule-Handling vs. 971110 included
- *
- * Revision 1.37  1998/02/22 19:45:24  fritz
- * Some changes regarding V.110
- *
- * Revision 1.36  1998/02/20 17:35:55  fritz
- * Added V.110 stuff.
- *
- * Revision 1.35  1998/01/31 22:14:14  keil
- * changes for 2.1.82
- *
- * Revision 1.34  1997/10/09 21:28:11  fritz
- * New HL<->LL interface:
- *   New BSENT callback with nr. of bytes included.
- *   Sending without ACK.
- *   New L1 error status (not yet in use).
- *   Cleaned up obsolete structures.
- * Implemented Cisco-SLARP.
- * Changed local net-interface data to be dynamically allocated.
- * Removed old 2.0 compatibility stuff.
- *
- * Revision 1.33  1997/08/21 14:44:22  fritz
- * Moved triggercps to end of struct for backwards-compatibility.
- *
- * Revision 1.32  1997/08/21 09:49:46  fritz
- * Increased NET_DV
- *
- * Revision 1.31  1997/06/22 11:57:07  fritz
- * Added ability to adjust slave triggerlevel.
- *
- * Revision 1.30  1997/06/17 13:07:23  hipp
- * compression changes , MP changes
- *
- * Revision 1.29  1997/05/27 15:18:02  fritz
- * Added changes for recent 2.1.x kernels:
- *   changed return type of isdn_close
- *   queue_task_* -> queue_task
- *   clear/set_bit -> test_and_... where apropriate.
- *   changed type of hard_header_cache parameter.
- *
- * Revision 1.28  1997/03/07 01:33:01  fritz
- * Added proper ifdef's for CONFIG_ISDN_AUDIO
- *
- * Revision 1.27  1997/03/05 21:11:49  fritz
- * Minor fixes.
- *
- * Revision 1.26  1997/02/28 02:37:53  fritz
- * Added some comments.
- *
- * Revision 1.25  1997/02/23 16:54:23  hipp
- * some initial changes for future PPP compresion
- *
- * Revision 1.24  1997/02/18 09:42:45  fritz
- * Bugfix: Increased ISDN_MODEM_ANZREG.
- * Increased TTY_DV.
- *
- * Revision 1.23  1997/02/10 22:07:13  fritz
- * Added 2 modem registers for numbering plan and screening info.
- *
- * Revision 1.22  1997/02/03 23:42:08  fritz
- * Added ISDN_TIMER_RINGING
- * Misc. changes for Kernel 2.1.X compatibility
- *
- * Revision 1.21  1997/01/17 01:19:10  fritz
- * Applied chargeint patch.
- *
- * Revision 1.20  1997/01/17 00:41:19  fritz
- * Increased TTY_DV.
- *
- * Revision 1.19  1997/01/14 01:41:07  fritz
- * Added ATI2 related variables.
- * Added variables for audio support in skbuffs.
- *
- * Revision 1.18  1996/11/06 17:37:50  keil
- * more changes for 2.1.X
- *
- * Revision 1.17  1996/09/07 12:53:57  hipp
- * moved a few isdn_ppp.c specific defines to drives/isdn/isdn_ppp.h
- *
- * Revision 1.16  1996/08/12 16:20:56  hipp
- * renamed ppp_minor to ppp_slot
- *
- * Revision 1.15  1996/06/15 14:56:57  fritz
- * Added version signatures for data structures used
- * by userlevel programs.
- *
- * Revision 1.14  1996/06/06 21:24:23  fritz
- * Started adding support for suspend/resume.
- *
- * Revision 1.13  1996/06/05 02:18:20  fritz
- * Added DTMF decoding stuff.
- *
- * Revision 1.12  1996/06/03 19:55:08  fritz
- * Fixed typos.
- *
- * Revision 1.11  1996/05/31 01:37:47  fritz
- * Minor changes, due to changes in isdn_tty.c
- *
- * Revision 1.10  1996/05/18 01:37:18  fritz
- * Added spelling corrections and some minor changes
- * to stay in sync with kernel.
- *
- * Revision 1.9  1996/05/17 03:58:20  fritz
- * Added flags for DLE handling.
- *
- * Revision 1.8  1996/05/11 21:49:55  fritz
- * Removed queue management variables.
- * Changed queue management to use sk_buffs.
- *
- * Revision 1.7  1996/05/07 09:10:06  fritz
- * Reorganized tty-related structs.
- *
- * Revision 1.6  1996/05/06 11:38:27  hipp
- * minor change in ippp struct
- *
- * Revision 1.5  1996/04/30 11:03:16  fritz
- * Added Michael's ippp-bind patch.
- *
- * Revision 1.4  1996/04/29 23:00:02  fritz
- * Added variables for voice-support.
- *
- * Revision 1.3  1996/04/20 16:54:58  fritz
- * Increased maximum number of channels.
- * Added some flags for isdn_net to handle callback more reliable.
- * Fixed delay-definitions to be more accurate.
- * Misc. typos
- *
- * Revision 1.2  1996/02/11 02:10:02  fritz
- * Changed IOCTL-names
- * Added rx_netdev, st_netdev, first_skb, org_hcb, and org_hcu to
- * Netdevice-local struct.
- *
- * Revision 1.1  1996/01/10 20:55:07  fritz
- * Initial revision
  *
  */
 
diff -urN linux-2.2.18-pre9/include/linux/isdn_divertif.h linux/include/linux/isdn_divertif.h
--- linux-2.2.18-pre9/include/linux/isdn_divertif.h	Mon Aug  9 12:04:41 1999
+++ linux/include/linux/isdn_divertif.h	Mon Dec  3 20:27:11 2001
@@ -1,6 +1,5 @@
-/* 
- * $Id: isdn_divertif.h,v 1.3 1999/07/05 20:22:00 werner Exp $
- *
+/* $Id: isdn_divertif.h,v 1.4 2000/05/11 22:29:22 kai Exp $
+
  * Header for the diversion supplementary interface for i4l.
  *
  * Copyright 1998       by Werner Cornelius (werner@isdn4linux.de)
@@ -18,15 +17,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
- * $Log: isdn_divertif.h,v $
- * Revision 1.3  1999/07/05 20:22:00  werner
- * changes to use diversion sources for all kernel versions.
- * removed static device, only proc filesystem used
- *
- * Revision 1.2  1999/07/04 21:38:38  werner
- * ported from kernel version 2.0
- *
  *
  */
 
diff -urN linux-2.2.18-pre9/include/linux/isdnif.h linux/include/linux/isdnif.h
--- linux-2.2.18-pre9/include/linux/isdnif.h	Wed May  3 17:16:51 2000
+++ linux/include/linux/isdnif.h	Mon Dec  3 20:27:11 2001
@@ -1,5 +1,5 @@
-/* $Id: isdnif.h,v 1.33 2000/01/20 19:59:43 keil Exp $
- *
+/* $Id: isdnif.h,v 1.35 2000/06/16 13:19:38 keil Exp $
+
  * Linux ISDN subsystem
  *
  * Definition of the interface between the subsystem and its low-level drivers.
@@ -20,126 +20,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
- *
- * $Log: isdnif.h,v $
- * Revision 1.33  2000/01/20 19:59:43  keil
- * Add FAX Class 1 support
- *
- * Revision 1.32  1999/10/11 22:03:00  keil
- * COMPAT_NEED_UACCESS (no include in isdn_compat.h)
- *
- * Revision 1.31  1999/09/06 07:29:36  fritz
- * Changed my mail-address.
- *
- * Revision 1.30  1999/08/23 15:54:29  keil
- * more backported changes from kernel 2.3.14
- *
- * Revision 1.29  1999/07/31 13:00:02  armin
- * Added tty fax capabilities.
- *
- * Revision 1.28  1999/07/13 20:57:48  werner
- * added callback ISDN_STAT_DISCH for limiting b-channel resources.
- *
- * Revision 1.27  1999/07/11 17:07:39  armin
- * Added tty modem register S23.
- * Added new layer 2 and 3 protocols for Fax and DSP functions.
- *
- * Revision 1.26  1999/07/01 08:35:44  keil
- * compatibility to 2.3
- *
- * Revision 1.25  1998/06/17 19:51:55  he
- * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
- * brute force fix to avoid Ugh's in isdn_tty_write()
- * cleaned up some dead code
- *
- * Revision 1.24  1998/03/19 13:18:57  keil
- * Start of a CAPI like interface for supplementary Service
- * first service: SUSPEND
- *
- * Revision 1.23  1998/02/20 17:36:52  fritz
- * Added L2-protocols for V.110, changed FEATURE-Flag-constants.
- *
- * Revision 1.22  1998/01/31 22:14:12  keil
- * changes for 2.1.82
- *
- * Revision 1.21  1997/10/09 21:28:13  fritz
- * New HL<->LL interface:
- *   New BSENT callback with nr. of bytes included.
- *   Sending without ACK.
- *   New L1 error status (not yet in use).
- *   Cleaned up obsolete structures.
- * Implemented Cisco-SLARP.
- * Changed local net-interface data to be dynamically allocated.
- * Removed old 2.0 compatibility stuff.
- *
- * Revision 1.20  1997/05/27 15:18:06  fritz
- * Added changes for recent 2.1.x kernels:
- *   changed return type of isdn_close
- *   queue_task_* -> queue_task
- *   clear/set_bit -> test_and_... where apropriate.
- *   changed type of hard_header_cache parameter.
- *
- * Revision 1.19  1997/03/25 23:13:56  keil
- * NI-1 US protocol
- *
- * Revision 1.18  1997/03/04 22:09:18  calle
- * Change macros copy_from_user and copy_to_user in inline function.
- * These are now correct replacements of the functions for 2.1.xx
- *
- * Revision 1.17  1997/02/10 21:12:53  fritz
- * More setup-interface changes.
- *
- * Revision 1.16  1997/02/10 19:42:57  fritz
- * New interface for reporting incoming calls.
- *
- * Revision 1.15  1997/02/09 00:18:42  keil
- * leased line support
- *
- * Revision 1.14  1997/02/03 23:43:00  fritz
- * Misc changes for Kernel 2.1.X compatibility.
- *
- * Revision 1.13  1996/11/13 02:39:59  fritz
- * More compatibility changes.
- *
- * Revision 1.12  1996/11/06 17:38:48  keil
- * more changes for 2.1.X
- *
- * Revision 1.11  1996/10/23 11:59:42  fritz
- * More compatibility changes.
- *
- * Revision 1.10  1996/10/22 23:14:19  fritz
- * Changes for compatibility to 2.0.X and 2.1.X kernels.
- *
- * Revision 1.9  1996/06/06 21:24:24  fritz
- * Started adding support for suspend/resume.
- *
- * Revision 1.8  1996/05/18 01:45:37  fritz
- * More spelling corrections.
- *
- * Revision 1.7  1996/05/18 01:37:19  fritz
- * Added spelling corrections and some minor changes
- * to stay in sync with kernel.
- *
- * Revision 1.6  1996/05/17 03:59:28  fritz
- * Marked rcvcallb and writebuf obsolete.
- *
- * Revision 1.5  1996/05/01 11:43:54  fritz
- * Removed STANDALONE
- *
- * Revision 1.4  1996/05/01 11:38:40  fritz
- * Added ISDN_FEATURE_L2_TRANS
- *
- * Revision 1.3  1996/04/29 22:57:54  fritz
- * Added driverId and channel parameters to
- * writecmd() and readstat().
- * Added constant for voice-support.
- *
- * Revision 1.2  1996/04/20 17:02:40  fritz
- * Changes to support skbuffs for Lowlevel-Drivers.
- * Misc. typos
- *
- * Revision 1.1  1996/01/09 05:50:51  fritz
- * Initial revision
  *
  */
 
diff -urN linux-2.2.18-pre9/include/linux/isicom.h linux/include/linux/isicom.h
--- linux-2.2.18-pre9/include/linux/isicom.h	Mon Aug  9 12:04:41 1999
+++ linux/include/linux/isicom.h	Mon Dec  3 20:27:11 2001
@@ -55,7 +55,6 @@
  *      PCI definitions
  */
 
- #define        DEVID_COUNT     9
  #define        VENDOR_ID       0x10b5
 
 /*
@@ -137,6 +136,8 @@
 	struct isi_port		* ports;
 	signed char		count;
 	unsigned char		isa;
+	spinlock_t		card_lock; /* Card wide lock 11/5/00 -sameer */
+	unsigned long		flags;
 };
 
 struct	isi_port {
@@ -164,6 +165,70 @@
 	struct termios		callout_termios;
 };
 
+/*
+ *	Locking/UnLocking primitives...
+ */
+
+extern inline unsigned char lock_card(struct isi_board *card)
+{
+	char		retries;
+	unsigned short base = card->base;
+
+	for (retries = 0; retries < 100; retries++) {
+		spin_lock_irqsave(&card->card_lock, card->flags);
+
+		if (inw(base + 0xe) & 0x1) {
+#ifdef ISICOM_DEBUG
+/*			printk(KERN_DEBUG "ISICOM:lock_card(0x%x)\n", 
+				card->base);*/
+#endif
+			return 1; 
+		}
+		else {
+			spin_unlock_irqrestore(&card->card_lock, card->flags);
+			schedule_timeout(HZ/100); /* 10ms */
+		}
+	}
+#ifdef ISICOM_DEBUG
+	printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%x)\n", card->base);
+#endif /* ISICOM_DEBUG */
+	return 0;	/* Failed to aquire the card! */
+}
+
+extern inline unsigned char lock_card_at_interrupt(struct isi_board *card)
+{
+	unsigned char		retries;
+	unsigned short 		base = card->base;
+
+	for (retries = 0; retries < 200; retries++) {
+		spin_lock_irqsave(&card->card_lock, card->flags);
+
+		if (inw(base + 0xe) & 0x1) {
+#ifdef ISICOM_DEBUG
+/*			printk(KERN_DEBUG "ISICOM:lock_card_at_interrupt(0x%x)"
+				"\n", 
+				card->base);*/
+#endif
+			return 1; 
+		}
+		else {
+			spin_unlock_irqrestore(&card->card_lock, card->flags);
+		}
+	}
+#ifdef ISICOM_DEBUG
+	printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%x)\n", card->base);
+#endif /* ISICOM_DEBUG */
+	return 0;	/* Failed to aquire the card! */
+}
+
+extern inline void unlock_card(struct isi_board *card)
+{
+	spin_unlock_irqrestore(&card->card_lock, card->flags);
+#ifdef ISICOM_DEBUG
+/*			printk(KERN_DEBUG "ISICOM:unlock_card(0x%x)\n", 
+				card->base);*/
+#endif
+}
 
 /*
  *  ISI Card specific ops ...
@@ -174,12 +239,18 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=400;
+
+/*	short wait=400;		SMPCHG
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr.\n");
 		return;
 	}
+*/
+	if (!lock_card(card)) {
+		printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr.\n");
+		return;
+	}
 #ifdef ISICOM_DEBUG_DTR_RTS	
 	printk(KERN_DEBUG "ISICOM: raise_dtr.\n");
 #endif	
@@ -187,6 +258,7 @@
 	outw(0x0504, base);
 	InterruptTheCard(base);
 	port->status |= ISI_DTR;
+	unlock_card(card);
 }
 
 extern inline void drop_dtr(struct isi_port * port)
@@ -194,12 +266,18 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=400;
+
+/*	short wait=400;		SMPCHG
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr.\n");
 		return;
 	}
+*/
+	if (!lock_card(card)) {
+		printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr.\n");
+		return;
+	}
 #ifdef ISICOM_DEBUG_DTR_RTS	
 	printk(KERN_DEBUG "ISICOM: drop_dtr.\n");
 #endif	
@@ -207,18 +285,25 @@
 	outw(0x0404, base);
 	InterruptTheCard(base);	
 	port->status &= ~ISI_DTR;
+	unlock_card(card);
 }
 extern inline void raise_rts(struct isi_port * port)
 {
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=400;
+
+/*	short wait=400;		SMPCHG
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in raise_rts.\n");
 		return;
 	}
+*/
+	if (!lock_card(card)) {
+		printk(KERN_WARNING "ISICOM: Card found busy in raise_rts.\n");
+		return;
+	}
 #ifdef ISICOM_DEBUG_DTR_RTS	
 	printk(KERN_DEBUG "ISICOM: raise_rts.\n");
 #endif	
@@ -226,18 +311,25 @@
 	outw(0x0a04, base);
 	InterruptTheCard(base);	
 	port->status |= ISI_RTS;
+	unlock_card(card);
 }
 extern inline void drop_rts(struct isi_port * port)
 {
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=400;
+
+/*	short wait=400;		SMPCHG
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in drop_rts.\n");
 		return;
 	}
+*/
+	if (!lock_card(card)) {
+		printk(KERN_WARNING "ISICOM: Card found busy in drop_rts.\n");
+		return;
+	}
 #ifdef ISICOM_DEBUG_DTR_RTS	
 	printk(KERN_DEBUG "ISICOM: drop_rts.\n");
 #endif	
@@ -245,18 +337,25 @@
 	outw(0x0804, base);
 	InterruptTheCard(base);	
 	port->status &= ~ISI_RTS;
+	unlock_card(card);
 }
 extern inline void raise_dtr_rts(struct isi_port * port)
 {
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=400;
+
+/*	short wait=400;		SMPCHG
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr_rts.\n");
 		return;
 	}
+*/
+	if (!lock_card(card)) {
+		printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr_rts.\n");
+		return;
+	}
 #ifdef ISICOM_DEBUG_DTR_RTS	
 	printk(KERN_DEBUG "ISICOM: raise_dtr_rts.\n");
 #endif	
@@ -264,18 +363,25 @@
 	outw(0x0f04, base);
 	InterruptTheCard(base);
 	port->status |= (ISI_DTR | ISI_RTS);
+	unlock_card(card);
 }
 extern inline void drop_dtr_rts(struct isi_port * port)
 {
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=400;
+
+/*	short wait=400;
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr_rts.\n");
 		return;
 	}
+*/
+	if (!lock_card(card)) {
+		printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr_rts.\n");
+		return;
+	}
 #ifdef ISICOM_DEBUG_DTR_RTS	
 	printk(KERN_DEBUG "ISICOM: drop_dtr_rts.\n");
 #endif	
@@ -283,6 +389,7 @@
 	outw(0x0c04, base);
 	InterruptTheCard(base);	
 	port->status &= ~(ISI_RTS | ISI_DTR);
+	unlock_card(card);
 }
 
 extern inline void kill_queue(struct isi_port * port, short queue)
@@ -290,18 +397,45 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=400;
+
+/*	short wait=400;		SMPCHG
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in kill_queue.\n");
 		return;
 	}
+*/
+	if (!lock_card(card)) {
+		printk(KERN_WARNING "ISICOM: Card found busy in kill_queue.\n");
+		return;
+	}
 #ifdef ISICOM_DEBUG	
 	printk(KERN_DEBUG "ISICOM: kill_queue 0x%x.\n", queue);
 #endif	
 	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
 	outw((queue << 8) | 0x06, base);
 	InterruptTheCard(base);	
+	unlock_card(card);
+}
+
+extern inline void set_signal_mask(struct isi_port * port, char mask)
+{
+	struct isi_board * card = port->card;
+	unsigned short base = card->base;
+	unsigned char channel = port->channel;
+
+	if (!lock_card(card)) {
+		printk(KERN_WARNING "ISICOM: Card found busy"
+					"in set_signal_mask.\n");
+		return;
+	}
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: set_signal_mask 0x%x.\n", mask);
+#endif	
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+	outw((mask << 8) | 0x7, base);
+	InterruptTheCard(base);
+	unlock_card(card);
 }
 
 #endif	/*	__KERNEL__	*/
diff -urN linux-2.2.18-pre9/include/linux/netdevice.h linux/include/linux/netdevice.h
--- linux-2.2.18-pre9/include/linux/netdevice.h	Tue Jan  4 10:12:25 2000
+++ linux/include/linux/netdevice.h	Mon Dec  3 20:27:11 2001
@@ -30,6 +30,7 @@
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
+#include <net/divert.h>
 
 #include <asm/atomic.h>
 
@@ -317,6 +318,11 @@
 	/* Semi-private data. Keep it at the end of device struct. */
 	struct dst_entry	*fastpath[NETDEV_FASTROUTE_HMASK+1];
 #endif
+
+#ifdef CONFIG_NET_DIVERT
+	/* this will get initialized at each interface type init routine */
+	struct divert_blk	*divert;
+#endif /* CONFIG_NET_DIVERT */
 };
 
 
diff -urN linux-2.2.18-pre9/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.2.18-pre9/include/linux/sched.h	Mon Dec  3 20:26:37 2001
+++ linux/include/linux/sched.h	Mon Dec  3 20:27:11 2001
@@ -499,7 +499,7 @@
 
 #define __set_current_state(state_value)	do { current->state = state_value; } while (0)
 #ifdef __SMP__
-#define set_current_state(state_value)		do { mb(); __set_current_state(state_value); } while (0)
+#define set_current_state(state_value)		do { __set_current_state(state_value); mb(); } while (0)
 #else
 #define set_current_state(state_value)		__set_current_state(state_value)
 #endif
diff -urN linux-2.2.18-pre9/include/linux/sockios.h linux/include/linux/sockios.h
--- linux-2.2.18-pre9/include/linux/sockios.h	Thu Aug 27 19:33:08 1998
+++ linux/include/linux/sockios.h	Mon Dec  3 20:27:11 2001
@@ -68,6 +68,9 @@
 #define SIOCGIFTXQLEN	0x8942		/* Get the tx queue length	*/
 #define SIOCSIFTXQLEN	0x8943		/* Set the tx queue length 	*/
 
+#define SIOCGIFDIVERT	0x8944		/* Frame diversion support */
+#define SIOCSIFDIVERT	0x8945		/* Set frame diversion options */
+
 
 /* ARP cache control calls. */
 		    /*  0x8950 - 0x8952  * obsolete calls, don't re-use */
diff -urN linux-2.2.18-pre9/include/linux/sysctl.h linux/include/linux/sysctl.h
--- linux-2.2.18-pre9/include/linux/sysctl.h	Wed Jun  7 14:26:44 2000
+++ linux/include/linux/sysctl.h	Mon Dec  3 20:27:11 2001
@@ -166,7 +166,8 @@
 	NET_CORE_FASTROUTE=7,
 	NET_CORE_MSG_COST=8,
 	NET_CORE_MSG_BURST=9,
-	NET_CORE_OPTMEM_MAX=10
+	NET_CORE_OPTMEM_MAX=10,
+	NET_CORE_DIVERT_VERSION=12
 };
 
 /* /proc/sys/net/ethernet */
diff -urN linux-2.2.18-pre9/include/net/divert.h linux/include/net/divert.h
--- linux-2.2.18-pre9/include/net/divert.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/divert.h	Mon Dec  3 20:27:11 2001
@@ -0,0 +1,132 @@
+/*
+ * Frame Diversion, Benoit Locher <Benoit.Locher@skf.com>
+ *
+ * Changes:
+ * 		06/09/2000	BL:	initial version
+ * 
+ */
+ 
+#ifndef _LINUX_DIVERT_H
+#define _LINUX_DIVERT_H
+
+#define	MAX_DIVERT_PORTS	8	/* Max number of ports to divert (tcp, udp) */
+
+/* Divertable protocols */
+#define	DIVERT_PROTO_NONE	0x0000
+#define	DIVERT_PROTO_IP		0x0001
+#define	DIVERT_PROTO_ICMP	0x0002
+#define	DIVERT_PROTO_TCP	0x0004
+#define	DIVERT_PROTO_UDP	0x0008
+
+#ifdef __KERNEL__
+	#define S16     s16
+	#define U16     u16
+	#define S32     s32
+	#define U32     u32
+	#define S64     s64
+	#define U64     u64
+#else
+	#define	S16		__s16
+	#define	U16		__u16
+	#define	S32		__s32
+	#define	U32		__u32
+	#define	S64		__s64
+	#define	U64		__u64
+#endif
+
+/*
+ *	This is an Ethernet Frame Diverter option block
+ */
+struct divert_blk
+{
+	int		divert;  /* are we active */
+	unsigned int protos;	/* protocols */
+	U16		tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */
+	U16		tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */
+	U16		udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */
+	U16		udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */
+};
+
+/*
+ * Diversion control block, for configuration with the userspace tool
+ * divert
+ */
+
+typedef union _divert_cf_arg
+{
+	S16		int16;
+	U16		uint16;
+	S32		int32;
+	U32		uint32;
+	S64		int64;
+	U64		uint64;
+	void	*ptr;
+} divert_cf_arg;
+
+
+struct divert_cf
+{
+	int	cmd;				/* Command */
+	divert_cf_arg 	arg1,
+					arg2,
+					arg3;
+	int	dev_index;	/* device index (eth0=0, etc...) */
+};
+
+
+/* Diversion commands */
+#define	DIVCMD_DIVERT			1 /* ENABLE/DISABLE diversion */
+#define	DIVCMD_IP				2 /* ENABLE/DISABLE whold IP diversion */
+#define	DIVCMD_TCP				3 /* ENABLE/DISABLE whold TCP diversion */
+#define	DIVCMD_TCPDST			4 /* ADD/REMOVE TCP DST port for diversion */
+#define	DIVCMD_TCPSRC			5 /* ADD/REMOVE TCP SRC port for diversion */
+#define	DIVCMD_UDP				6 /* ENABLE/DISABLE whole UDP diversion */
+#define	DIVCMD_UDPDST			7 /* ADD/REMOVE UDP DST port for diversion */
+#define	DIVCMD_UDPSRC			8 /* ADD/REMOVE UDP SRC port for diversion */
+#define	DIVCMD_ICMP				9 /* ENABLE/DISABLE whole ICMP diversion */
+#define	DIVCMD_GETSTATUS		10 /* GET the status of the diverter */
+#define	DIVCMD_RESET			11 /* Reset the diverter on the specified dev */
+#define DIVCMD_GETVERSION		12 /* Retrieve the diverter code version (char[32]) */
+
+/* General syntax of the commands:
+ * 
+ * DIVCMD_xxxxxx(arg1, arg2, arg3, dev_index)
+ * 
+ * SIOCSIFDIVERT:
+ *   DIVCMD_DIVERT(DIVARG1_ENABLE|DIVARG1_DISABLE, , ,ifindex)
+ *   DIVCMD_IP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex)
+ *   DIVCMD_TCP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex)
+ *   DIVCMD_TCPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex)
+ *   DIVCMD_TCPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex)
+ *   DIVCMD_UDP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex)
+ *   DIVCMD_UDPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex)
+ *   DIVCMD_UDPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex)
+ *   DIVCMD_ICMP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex)
+ *   DIVCMD_RESET(, , , ifindex)
+ *   
+ * SIOGIFDIVERT:
+ *   DIVCMD_GETSTATUS(divert_blk, , , ifindex)
+ *   DIVCMD_GETVERSION(string[3])
+ */
+
+
+/* Possible values for arg1 */
+#define	DIVARG1_ENABLE			0 /* ENABLE something */
+#define	DIVARG1_DISABLE			1 /* DISABLE something */
+#define DIVARG1_ADD				2 /* ADD something */
+#define DIVARG1_REMOVE			3 /* REMOVE something */
+
+
+#ifdef __KERNEL__
+
+/* diverter functions */
+#include <linux/skbuff.h>
+void dv_init(void);
+int alloc_divert_blk(struct device *);
+void free_divert_blk(struct device *);
+int divert_ioctl(unsigned int cmd, struct divert_cf *arg);
+void divert_frame(struct sk_buff *skb);
+
+#endif __KERNEL__
+
+#endif	/* _LINUX_DIVERT_H */
diff -urN linux-2.2.18-pre9/mm/swapfile.c linux/mm/swapfile.c
--- linux-2.2.18-pre9/mm/swapfile.c	Tue Jan  4 10:12:26 2000
+++ linux/mm/swapfile.c	Mon Dec  3 20:27:11 2001
@@ -494,6 +494,7 @@
 	int lock_map_size = PAGE_SIZE;
 	int nr_good_pages = 0;
 	unsigned long tmp_lock_map = 0;
+	int swapfilesize;
 	
 	lock_kernel();
 	if (!capable(CAP_SYS_ADMIN))
@@ -532,27 +533,32 @@
 	error = -EINVAL;
 
 	if (S_ISBLK(swap_dentry->d_inode->i_mode)) {
-		p->swap_device = swap_dentry->d_inode->i_rdev;
-		set_blocksize(p->swap_device, PAGE_SIZE);
+		kdev_t dev = swap_dentry->d_inode->i_rdev;
+
+		p->swap_device = dev;
+		set_blocksize(dev, PAGE_SIZE);
 		
 		filp.f_dentry = swap_dentry;
 		filp.f_mode = 3; /* read write */
 		error = blkdev_open(swap_dentry->d_inode, &filp);
 		if (error)
 			goto bad_swap_2;
-		set_blocksize(p->swap_device, PAGE_SIZE);
+		set_blocksize(dev, PAGE_SIZE);
 		error = -ENODEV;
-		if (!p->swap_device ||
-		    (blk_size[MAJOR(p->swap_device)] &&
-		     !blk_size[MAJOR(p->swap_device)][MINOR(p->swap_device)]))
+		if (!dev || (blk_size[MAJOR(dev)] &&
+			     !blk_size[MAJOR(dev)][MINOR(dev)]))
 			goto bad_swap;
 		error = -EBUSY;
 		for (i = 0 ; i < nr_swapfiles ; i++) {
 			if (i == type)
 				continue;
-			if (p->swap_device == swap_info[i].swap_device)
+			if (dev == swap_info[i].swap_device)
 				goto bad_swap;
 		}
+		swapfilesize = 0;
+		if (blk_size[MAJOR(dev)])
+			swapfilesize = blk_size[MAJOR(dev)][MINOR(dev)]
+				>> (PAGE_SHIFT - 10);
 	} else if (S_ISREG(swap_dentry->d_inode->i_mode)) {
 		error = -EBUSY;
 		for (i = 0 ; i < nr_swapfiles ; i++) {
@@ -561,6 +567,7 @@
 			if (swap_dentry->d_inode == swap_info[i].swap_file->d_inode)
 				goto bad_swap;
 		}
+		swapfilesize = swap_dentry->d_inode->i_size  >> PAGE_SHIFT;
 	} else
 		goto bad_swap;
 
@@ -656,7 +663,13 @@
 		if (error) 
 			goto bad_swap;
 	}
-	
+
+	if (swapfilesize && p->max > swapfilesize) {
+		printk(KERN_WARNING
+		       "Swap area shorter than signature indicates\n");
+		error = -EINVAL;
+		goto bad_swap;
+	}
 	if (!nr_good_pages) {
 		printk(KERN_WARNING "Empty swap-file\n");
 		error = -EINVAL;
diff -urN linux-2.2.18-pre9/net/Config.in linux/net/Config.in
--- linux-2.2.18-pre9/net/Config.in	Tue Jan  4 10:12:26 2000
+++ linux/net/Config.in	Mon Dec  3 20:27:11 2001
@@ -42,6 +42,7 @@
   if [ "$CONFIG_BRIDGE" != "n" ]; then
 	int '  Maximum number of bridged interfaces' CONFIG_BRIDGE_NUM_PORTS 8
   fi
+  bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT
   bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC
 #  if [ "$CONFIG_LLC" = "y" ]; then
 #   bool 'Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI
diff -urN linux-2.2.18-pre9/net/core/Makefile linux/net/core/Makefile
--- linux-2.2.18-pre9/net/core/Makefile	Tue Dec 29 11:21:49 1998
+++ linux/net/core/Makefile	Mon Dec  3 20:27:11 2001
@@ -29,6 +29,10 @@
 OX_OBJS += firewall.o
 endif
 
+ifeq ($(CONFIG_NET_DIVERT),y)
+O_OBJS += dv.o
+endif
+
 endif
 
 ifdef CONFIG_NET_PROFILE
diff -urN linux-2.2.18-pre9/net/core/dev.c linux/net/core/dev.c
--- linux-2.2.18-pre9/net/core/dev.c	Mon Dec  3 20:26:40 2001
+++ linux/net/core/dev.c	Mon Dec  3 20:27:11 2001
@@ -59,6 +59,7 @@
  *	Paul Rusty Russel	:	SIOCSIFNAME
  *	Andrea Arcangeli	:	dev_clear_backlog() needs the
  *					skb_queue_lock held.
+ *	Benoit Locher	:	Added the Frame Diversion code
  */
 
 #include <asm/uaccess.h>
@@ -84,6 +85,7 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <net/br.h>
+#include <net/divert.h>
 #include <net/dst.h>
 #include <net/pkt_sched.h>
 #include <net/profile.h>
@@ -839,6 +841,17 @@
 }
 #endif
 
+
+#ifdef CONFIG_NET_DIVERT
+static inline void handle_diverter(struct sk_buff *skb)
+{
+	/* if diversion is supported on device, then divert */
+	if (skb->dev->divert && skb->dev->divert->divert)
+		divert_frame(skb);
+	return;
+}
+#endif	 /* CONFIG_NET_DIVERT */
+
 /*
  *	When we are called the queue is ready to grab, the interrupts are
  *	on and hardware can interrupt and queue to the receive queue as we
@@ -948,6 +961,15 @@
 
 		type = skb->protocol;
 
+#ifdef CONFIG_NET_DIVERT
+		/*
+		 * Have the frame diverted ?
+		 *
+		 */
+		handle_diverter(skb);
+#endif	/* CONFIG_NET_DIVERT */
+		
+
 #ifdef CONFIG_BRIDGE
 		/*
 		 *	If we are bridging then pass the frame up to the
@@ -1760,10 +1782,12 @@
 
 static int dev_boot_phase = 1;
 
-
 int register_netdevice(struct device *dev)
 {
 	struct device *d, **dp;
+#ifdef CONFIG_NET_DIVERT
+	int	ret;
+#endif
 
 	if (dev_boot_phase) {
 		/* This is NOT bug, but I am not sure, that all the
@@ -1786,6 +1810,11 @@
 		}
 		dev->next = NULL;
 		*dp = dev;
+#ifdef CONFIG_NET_DIVERT
+		ret=alloc_divert_blk(dev);
+		if (ret)
+			return ret;
+#endif /* CONFIG_NET_DIVERT */
 		return 0;
 	}
 
@@ -1809,7 +1838,11 @@
 
 	/* Notify protocols, that a new device appeared. */
 	notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
-
+#ifdef CONFIG_NET_DIVERT
+	ret=alloc_divert_blk(dev);
+	if (ret)
+		return ret;
+#endif
 	return 0;
 }
 
@@ -1857,6 +1890,9 @@
 
 			if (dev->destructor)
 				dev->destructor(dev);
+#ifdef CONFIG_NET_DIVERT
+			free_divert_blk(dev);	
+#endif /* CONFIG_NET_DIVERT */
 			return 0;
 		}
 	}
@@ -1932,6 +1968,13 @@
 #ifdef CONFIG_BRIDGE	 
 	br_init();
 #endif	
+
+	/*
+	 * Frame Diverter init
+	 */
+#ifdef CONFIG_NET_DIVERT
+	dv_init();
+#endif /* CONFIG_NET_DIVERT */
 	
 	/*
 	 * This is Very Ugly(tm).
diff -urN linux-2.2.18-pre9/net/core/dv.c linux/net/core/dv.c
--- linux-2.2.18-pre9/net/core/dv.c	Wed Dec 31 16:00:00 1969
+++ linux/net/core/dv.c	Mon Dec  3 20:27:11 2001
@@ -0,0 +1,552 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Generic frame diversion
+ *
+ * Version:	@(#)eth.c	0.41	09/09/2000
+ *
+ * Authors:	
+ * 		Benoit LOCHER:	initial integration within the kernel with support for ethernet
+ * 		Dave Miller:	improvement on the code (correctness, performance and source files)
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <net/dst.h>
+#include <net/arp.h>
+#include <net/sock.h>
+#include <net/ipv6.h>
+#include <net/ip.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/checksum.h>
+#include <net/divert.h>
+#include <linux/sockios.h>
+
+const char sysctl_divert_version[32]="0.45";	/* Current version */
+
+__initfunc(void dv_init(void))
+{
+	printk(KERN_INFO "NET4: Frame Diverter %s\n", sysctl_divert_version);
+}
+
+/*
+ * Allocate a divert_blk for a device. This must be an ethernet nic.
+ *
+ */
+
+int alloc_divert_blk(struct device *dev)
+{
+    int alloc_size=(sizeof(struct divert_blk)+3)&~3;
+
+	if (!strncmp(dev->name, "eth", 3))
+	{
+		printk(KERN_DEBUG "divert: allocating divert_blk for %s\n",
+		dev->name);
+		dev->divert=(struct divert_blk *)kmalloc(alloc_size, GFP_KERNEL);
+		if (dev->divert==NULL)
+		{
+			printk(KERN_DEBUG "divert: unable to allocate divert_blk for %s\n",
+			dev->name);
+			return -EFAULT;
+		}
+		else
+			memset(dev->divert, 0, sizeof(struct divert_blk));
+	}
+	else
+	{
+		printk(KERN_DEBUG "divert: not allocating divert_blk for non-ethernet device %s\n",
+					dev->name);
+		dev->divert=NULL;
+	}
+	return 0;
+} 
+
+
+/*
+ * Free a divert_blk allocated by the above function, if it was 
+ * allocated on that device.
+ *
+ */
+
+
+void free_divert_blk(struct device *dev)
+{
+	if (dev->divert)
+	{
+		kfree(dev->divert);
+		dev->divert=NULL;
+		 printk(KERN_DEBUG "divert: freeing divert_blk for %s\n",
+						 dev->name);
+	}
+	else
+	{
+		printk(KERN_DEBUG "divert: no divert_blk to free, %s not ethernet\n",
+						dev->name);
+	}
+	return;
+}
+
+
+
+/*
+ * Adds a tcp/udp (source or dest) port to an array
+ */
+int add_port(u16 ports[], u16 port)
+{
+	int	i;
+
+	if (port==0)
+		return -EINVAL;
+
+	/* Storing directly in network format for performance, thanks Dave :) */
+	port=htons(port);
+
+	for (i=0; i<MAX_DIVERT_PORTS; i++)
+		if (ports[i]==port)
+			return -EALREADY;
+	
+	for (i=0; i<MAX_DIVERT_PORTS; i++)
+		if (ports[i]==0)
+		{
+			ports[i]=port;
+			return 0;
+		}
+	return -ENOBUFS;
+}
+
+/*
+ * Removes a port from an array tcp/udp (source or dest)
+ */
+int remove_port(u16 ports[], u16 port)
+{
+	int i;
+
+	if (port==0)
+		return -EINVAL;
+	
+	/* Storing directly in network format for performance, thanks Dave ! */
+	port=htons(port);
+
+	for (i=0; i<MAX_DIVERT_PORTS; i++)
+		if (ports[i]==port)
+		{
+			ports[i]=0;
+			return 0;
+		}
+	return -EINVAL;
+}
+
+/* Some basic sanity checks on the arguments passed to divert_ioctl() */
+int check_args(struct divert_cf *div_cf, struct device **dev)
+{
+	char	devname[32];
+		
+	if (dev==NULL)
+		return -EFAULT;
+
+	/* GETVERSION: all other args are unused */
+	if (div_cf->cmd==DIVCMD_GETVERSION)
+		return 0;
+	
+	/* Network device index should reasonably be between 0 and 1000 :) */
+	if (div_cf->dev_index<0 || div_cf->dev_index>1000) 
+		return -EINVAL;
+			
+	/* Let's try to find the ifname */
+	sprintf(devname, "eth%d", div_cf->dev_index);
+	*dev=dev_get(devname);
+	
+	/* dev should NOT be null */
+	if (*dev==NULL)
+		return -EINVAL;
+	
+	/* user issuing the ioctl must be a super one :) */
+	if (!suser())
+		return -EPERM;
+
+	/* Device must have a divert_blk member NOT null */
+	if ((*dev)->divert==NULL)
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * control function of the diverter
+ */
+int divert_ioctl(unsigned int cmd, struct divert_cf *arg)
+{
+	struct divert_cf	div_cf;
+	struct divert_blk	*div_blk;
+	struct device		*dev;
+	int					ret;
+
+
+	switch(cmd)
+	{
+		case SIOCGIFDIVERT:
+			if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf)))
+				return -EFAULT;
+			
+			ret=check_args(&div_cf, &dev);
+			if (ret)
+				return ret;
+
+			div_blk=dev->divert;
+			
+			switch(div_cf.cmd)
+			{
+				case DIVCMD_GETSTATUS:
+					/* Now, just give the user the raw divert block for him to play with :) */
+					if(copy_to_user(div_cf.arg1.ptr, dev->divert, sizeof(struct divert_blk)))
+						return -EFAULT;
+					break;
+
+				case DIVCMD_GETVERSION:
+					if (div_cf.arg1.ptr == NULL)
+						return -EINVAL;
+					if(copy_to_user(div_cf.arg1.ptr, sysctl_divert_version, 32))
+						return -EFAULT;
+					break;
+
+				default:
+					return -EINVAL;
+			}
+			break;
+
+		case SIOCSIFDIVERT:
+			if(copy_from_user(&div_cf, arg, sizeof(struct divert_cf)))
+				return -EFAULT;
+
+			ret=check_args(&div_cf, &dev);
+			if (ret)
+				return ret;
+
+			div_blk=dev->divert;
+			
+			switch(div_cf.cmd)
+			{
+				case DIVCMD_RESET:
+					div_blk->divert=0;
+					div_blk->protos=DIVERT_PROTO_NONE;
+					memset(div_blk->tcp_dst, 0, MAX_DIVERT_PORTS*sizeof(u16));
+					memset(div_blk->tcp_src, 0, MAX_DIVERT_PORTS*sizeof(u16));
+					memset(div_blk->udp_dst, 0, MAX_DIVERT_PORTS*sizeof(u16));
+					memset(div_blk->udp_src, 0, MAX_DIVERT_PORTS*sizeof(u16));
+					return 0;
+					break;
+						
+				
+				case DIVCMD_DIVERT:
+					switch(div_cf.arg1.int32)
+					{
+						case DIVARG1_ENABLE:
+							if (div_blk->divert)
+								return -EALREADY;
+							div_blk->divert=1;
+							break;
+							
+						case DIVARG1_DISABLE:
+							if (!div_blk->divert)
+								return -EALREADY;
+							div_blk->divert=0;
+							break;
+							
+						default:
+							return -EINVAL;
+					}
+					break;
+				
+					
+				case DIVCMD_IP:
+					switch(div_cf.arg1.int32)
+					{
+						case DIVARG1_ENABLE:
+							if (div_blk->protos&DIVERT_PROTO_IP)
+								return -EALREADY;
+							div_blk->protos|=DIVERT_PROTO_IP;
+							break;
+
+						case DIVARG1_DISABLE:
+							if (!(div_blk->protos&DIVERT_PROTO_IP))
+								return -EALREADY;
+							div_blk->protos&=~DIVERT_PROTO_IP;
+							break;
+
+						default:
+							return -EINVAL;
+					}
+					break;
+
+					
+				case DIVCMD_TCP:
+					switch(div_cf.arg1.int32)
+					{
+						case DIVARG1_ENABLE:
+							if (div_blk->protos&DIVERT_PROTO_TCP)
+								return -EALREADY;
+							div_blk->protos|=DIVERT_PROTO_TCP;
+							break;
+
+						case DIVARG1_DISABLE:
+							if (!(div_blk->protos&DIVERT_PROTO_TCP))
+								return -EALREADY;
+							div_blk->protos&=~DIVERT_PROTO_TCP;
+							break;
+
+						default:
+							return -EINVAL;
+					}
+					break;
+
+					
+				case DIVCMD_TCPDST:
+					switch(div_cf.arg1.int32)
+					{
+						case DIVARG1_ADD:
+							return add_port(div_blk->tcp_dst, div_cf.arg2.uint16);
+							break;
+
+						case DIVARG1_REMOVE:
+							return remove_port(div_blk->tcp_dst, div_cf.arg2.uint16);
+							break;
+
+						default:
+							return -EINVAL;
+					}
+					break;
+
+					
+				case DIVCMD_TCPSRC:
+					switch(div_cf.arg1.int32)
+					{
+						case DIVARG1_ADD:
+							return add_port(div_blk->tcp_src, div_cf.arg2.uint16);
+							break;
+
+						case DIVARG1_REMOVE:
+							return remove_port(div_blk->tcp_src, div_cf.arg2.uint16);
+							break;
+
+						default:
+							return -EINVAL;
+					}
+					break;
+
+					
+				case DIVCMD_UDP:
+					switch(div_cf.arg1.int32)
+					{
+						case DIVARG1_ENABLE:
+							if (div_blk->protos&DIVERT_PROTO_UDP)
+								return -EALREADY;
+							div_blk->protos|=DIVERT_PROTO_UDP;
+							break;
+
+						case DIVARG1_DISABLE:
+							if (!(div_blk->protos&DIVERT_PROTO_UDP))
+								return -EALREADY;
+							div_blk->protos&=~DIVERT_PROTO_UDP;
+							break;
+
+						default:
+							return -EINVAL;
+					}
+					break;
+
+					
+				case DIVCMD_UDPDST:
+					switch(div_cf.arg1.int32)
+					{
+						case DIVARG1_ADD:
+							return add_port(div_blk->udp_dst, div_cf.arg2.uint16);
+							break;
+
+						case DIVARG1_REMOVE:
+							return remove_port(div_blk->udp_dst, div_cf.arg2.uint16);
+							break;
+
+						default:
+							return -EINVAL;
+					}
+					break;
+
+					
+				case DIVCMD_UDPSRC:
+					switch(div_cf.arg1.int32)
+					{
+						case DIVARG1_ADD:
+							return add_port(div_blk->udp_src, div_cf.arg2.uint16);
+							break;
+
+						case DIVARG1_REMOVE:
+							return remove_port(div_blk->udp_src, div_cf.arg2.uint16);
+							break;
+
+						default:
+							return -EINVAL;
+					}
+					break;
+
+					
+				case DIVCMD_ICMP:
+					switch(div_cf.arg1.int32)
+					{
+						case DIVARG1_ENABLE:
+							if (div_blk->protos&DIVERT_PROTO_ICMP)
+								return -EALREADY;
+							div_blk->protos|=DIVERT_PROTO_ICMP;
+							break;
+
+						case DIVARG1_DISABLE:
+							if (!(div_blk->protos&DIVERT_PROTO_ICMP))
+								return -EALREADY;
+							div_blk->protos&=~DIVERT_PROTO_ICMP;
+							break;
+
+						default:
+							return -EINVAL;
+					}
+					break;
+
+					
+				default:
+					return -EINVAL;
+			}
+			break;
+
+			
+		default:
+			return -EINVAL;
+	}
+	return 0;
+}
+
+
+/*
+ * Check if packet should have its dest mac address set to the box itself
+ * for diversion
+ */
+
+#define	ETH_DIVERT_FRAME(skb) \
+	memcpy(skb->mac.ethernet, skb->dev->dev_addr, ETH_ALEN)
+		
+void divert_frame(struct sk_buff *skb)
+{
+	struct ethhdr			*eth=skb->mac.ethernet;
+	struct iphdr			*iph;
+	struct tcphdr			*tcph;
+	struct udphdr			*udph;
+	struct divert_blk		*divert=skb->dev->divert;
+	int						i, src, dst;
+	unsigned char			*skb_data_end=skb->data+skb->len;
+
+	/* Packet is already aimed at us, return */
+	if (!memcmp(eth, skb->dev->dev_addr, ETH_ALEN))
+		return;
+	
+	/* proto is not IP, do nothing */
+	if (eth->h_proto != htons(ETH_P_IP))
+		return;
+	
+	/* Divert all IP frames ? */
+	if (divert->protos&DIVERT_PROTO_IP)
+	{
+		ETH_DIVERT_FRAME(skb);
+		return;
+	}
+	
+	iph=(struct iphdr *)(skb->data);
+	/* Check for possible (maliciously) malformed IP frame (thanks Dave) */
+	if (((iph->ihl<<2)+(unsigned char*)(iph))>=skb_data_end)
+	{
+		printk(KERN_INFO "divert: malformed IP packet !\n");
+		return;
+	}
+	switch(iph->protocol)
+	{
+		/* Divert all ICMP frames ? */
+		case IPPROTO_ICMP:
+			if (divert->protos&DIVERT_PROTO_ICMP)
+			{
+				ETH_DIVERT_FRAME(skb);
+				return;
+			}
+			break;
+	
+		/* Divert all TCP frames ? */
+		case IPPROTO_TCP:
+			if (divert->protos&DIVERT_PROTO_TCP)
+			{
+				ETH_DIVERT_FRAME(skb);
+				return;
+			}
+			tcph=(struct tcphdr *)(((unsigned char *)iph) + (iph->ihl<<2));
+			/* Check for possible (maliciously) malformed IP frame (thanx Dave) */
+			if (((unsigned char *)(tcph+1))>=skb_data_end)
+			{
+				printk(KERN_INFO "divert: malformed TCP packet !\n");
+				return;
+			}
+			/* Divert some tcp dst/src ports only ?*/
+			for (i=0; i<MAX_DIVERT_PORTS; i++)
+			{
+				dst=divert->tcp_dst[i];
+				src=divert->tcp_src[i];
+				if ((dst && dst==tcph->dest) ||
+					(src && src==tcph->source))
+				{
+					ETH_DIVERT_FRAME(skb);
+					return;
+				}
+			}
+			break;
+			
+		/* Divert all UDP frames ? */
+		case IPPROTO_UDP:
+			if (divert->protos&DIVERT_PROTO_UDP)
+			{
+				ETH_DIVERT_FRAME(skb);
+				return;
+			}
+			udph=(struct udphdr *)(((unsigned char *)iph) + (iph->ihl<<2));
+			/* Check for possible (maliciously) malformed IP packet (thanks Dave) */
+			if (((unsigned char *)(udph+1))>=skb_data_end)
+			{
+				printk(KERN_INFO "divert: malformed UDP packet !\n");
+				return;
+			}
+			/* Divert some udp dst/src ports only ? */
+			for (i=0; i<MAX_DIVERT_PORTS; i++)
+			{
+				dst=divert->udp_dst[i];
+				src=divert->udp_src[i];
+				if ((dst && dst==udph->dest) ||
+					(src && src==udph->source))
+				{
+					ETH_DIVERT_FRAME(skb);
+					return;
+				}
+			}
+			break;
+	}
+	return;
+}
+
diff -urN linux-2.2.18-pre9/net/core/sysctl_net_core.c linux/net/core/sysctl_net_core.c
--- linux-2.2.18-pre9/net/core/sysctl_net_core.c	Sat Nov  7 11:00:32 1998
+++ linux/net/core/sysctl_net_core.c	Mon Dec  3 20:27:11 2001
@@ -23,6 +23,9 @@
 
 extern int sysctl_core_destroy_delay;
 extern int sysctl_optmem_max;
+#ifdef CONFIG_NET_DIVERT
+extern char sysctl_divert_version[];
+#endif /* CONFIG_NET_DIVERT */
 
 ctl_table core_table[] = {
 #ifdef CONFIG_NET
@@ -55,6 +58,11 @@
 	{NET_CORE_OPTMEM_MAX, "optmem_max",
 	 &sysctl_optmem_max, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
+#ifdef CONFIG_NET_DIVERT
+	{NET_CORE_DIVERT_VERSION, "divert_version",
+	 (void *)sysctl_divert_version, 32, 0444, NULL,
+	 &proc_dostring},
+#endif /* CONFIG_NET_DIVERT */
 #endif /* CONFIG_NET */
 	{ 0 }
 };
diff -urN linux-2.2.18-pre9/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- linux-2.2.18-pre9/net/ipv4/af_inet.c	Mon Dec  3 20:26:40 2001
+++ linux/net/ipv4/af_inet.c	Mon Dec  3 20:27:11 2001
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.87.2.9 2000/09/14 10:44:31 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.87.2.10 2000/09/20 01:47:40 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -109,6 +109,11 @@
 #ifdef CONFIG_BRIDGE
 #include <net/br.h>
 #endif
+ 
+#ifdef CONFIG_NET_DIVERT
+#include <net/divert.h>
+#endif /* CONFIG_NET_DIVERT */
+ 
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
@@ -913,6 +918,14 @@
 			return -ENOPKG;
 #endif						
 			
+		case SIOCGIFDIVERT:
+		case SIOCSIFDIVERT:
+#ifdef CONFIG_NET_DIVERT
+			return(divert_ioctl(cmd, (struct divert_cf *) arg));
+#else
+			return -ENOPKG;
+#endif	/* CONFIG_NET_DIVERT */
+
 		case SIOCADDDLCI:
 		case SIOCDELDLCI:
 #ifdef CONFIG_DLCI
diff -urN linux-2.2.18-pre9/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- linux-2.2.18-pre9/net/ipv4/ip_fw.c	Mon Sep  4 10:39:29 2000
+++ linux/net/ipv4/ip_fw.c	Mon Dec  3 20:27:11 2001
@@ -573,7 +573,7 @@
 			strcpy(outskb->data+sizeof(__u32)*2, rif);
 			memcpy(outskb->data+sizeof(__u32)*2+IFNAMSIZ, ip, 
 			       len-(sizeof(__u32)*2+IFNAMSIZ));
-			netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_KERNEL);
+			netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
 		}
 		else {
 			if (net_ratelimit())
diff -urN linux-2.2.18-pre9/net/ipv4/proc.c linux/net/ipv4/proc.c
--- linux-2.2.18-pre9/net/ipv4/proc.c	Mon Sep  4 10:39:29 2000
+++ linux/net/ipv4/proc.c	Mon Dec  3 20:27:12 2001
@@ -7,7 +7,7 @@
  *		PROC file system.  It is mainly used for debugging and
  *		statistics.
  *
- * Version:	$Id: proc.c,v 1.34.2.1 2000/01/14 01:22:20 davem Exp $
+ * Version:	$Id: proc.c,v 1.34.2.3 2000/06/21 02:14:45 davem Exp $
  *
  * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
diff -urN linux-2.2.18-pre9/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c
--- linux-2.2.18-pre9/net/ipv4/sysctl_net_ipv4.c	Wed Jun  7 14:26:44 2000
+++ linux/net/ipv4/sysctl_net_ipv4.c	Mon Dec  3 20:27:12 2001
@@ -1,7 +1,7 @@
 /*
  * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
  *
- * $Id: sysctl_net_ipv4.c,v 1.38.2.3 2000/04/17 05:46:06 davem Exp $
+ * $Id: sysctl_net_ipv4.c,v 1.38.2.4 2000/09/16 09:40:00 davem Exp $
  *
  * Begun April 1, 1996, Mike Shaver.
  * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
@@ -15,19 +15,6 @@
 #include <net/route.h>
 #include <net/tcp.h>
 
-/*
- *	TCP configuration parameters
- */
-
-#define TCP_PMTU_DISC	0x00000001	/* perform PMTU discovery	  */
-#define TCP_CONG_AVOID	0x00000002	/* congestion avoidance algorithm */
-#define TCP_DELAY_ACKS	0x00000003	/* delayed ack stategy		  */
-
-#if 0
-static int boolean_min = 0;
-static int boolean_max = 1;
-#endif
-
 /* From icmp.c */
 extern int sysctl_icmp_echo_ignore_all;
 extern int sysctl_icmp_echo_ignore_broadcasts;
@@ -74,7 +61,10 @@
 /* From igmp.c */
 extern int sysctl_igmp_max_memberships;
 
-int tcp_retr1_max = 255; 
+static int tcp_retr1_max = 255; 
+
+static int ip_local_port_range_min[] = { 1, 1 };
+static int ip_local_port_range_max[] = { 65535, 65535 };
 
 struct ipv4_config ipv4_config;
 
@@ -184,7 +174,8 @@
 	 sizeof(int), 0644, NULL, &proc_dointvec},
 	{NET_IPV4_LOCAL_PORT_RANGE, "ip_local_port_range",
 	 &sysctl_local_port_range, sizeof(sysctl_local_port_range), 0644, 
-	 NULL, &proc_dointvec},
+	 NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
+	 ip_local_port_range_min, ip_local_port_range_max },
 	{NET_IPV4_ICMP_ECHO_IGNORE_ALL, "icmp_echo_ignore_all",
 	 &sysctl_icmp_echo_ignore_all, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
diff -urN linux-2.2.18-pre9/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- linux-2.2.18-pre9/net/ipv4/tcp_input.c	Mon Dec  3 20:26:40 2001
+++ linux/net/ipv4/tcp_input.c	Mon Dec  3 20:27:12 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.164.2.16 2000/06/28 04:54:16 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.164.2.17 2000/09/16 16:32:57 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -367,16 +367,16 @@
 
 		switch (opcode) {
 			case TCPOPT_EOL:
-				return;
+				goto check_syn;
 			case TCPOPT_NOP:	/* Ref: RFC 793 section 3.1 */
 				length--;
 				continue;
 			default:
 				opsize=*ptr++;
 				if (opsize < 2) /* "silly options" */
-					return;
+					goto check_syn;
 				if (opsize > length)
-					break;	/* don't parse partial options */
+					goto check_syn;	/* don't parse partial options */
 	  			switch(opcode) {
 				case TCPOPT_MSS:
 					if(opsize==TCPOLEN_MSS && th->syn) {
@@ -439,7 +439,8 @@
 	  			length-=opsize;
 	  	};
 	}
-	if(th->syn && saw_mss == 0)
+check_syn:
+	if (th->syn && saw_mss == 0)
 		tp->mss_clamp = 536;
 }
 
diff -urN linux-2.2.18-pre9/net/ipv6/ip6_input.c linux/net/ipv6/ip6_input.c
--- linux-2.2.18-pre9/net/ipv6/ip6_input.c	Mon Dec  3 20:26:40 2001
+++ linux/net/ipv6/ip6_input.c	Mon Dec  3 20:27:12 2001
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *	Ian P. Morris		<I.P.Morris@soton.ac.uk>
  *
- *	$Id: ip6_input.c,v 1.11.2.1 1999/08/14 04:02:43 davem Exp $
+ *	$Id: ip6_input.c,v 1.11.2.2 2000/09/13 01:27:53 davem Exp $
  *
  *	Based in linux/net/ipv4/ip_input.c
  *
diff -urN linux-2.2.18-pre9/net/ipv6/ip6_output.c linux/net/ipv6/ip6_output.c
--- linux-2.2.18-pre9/net/ipv6/ip6_output.c	Mon Dec  3 20:26:40 2001
+++ linux/net/ipv6/ip6_output.c	Mon Dec  3 20:27:12 2001
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: ip6_output.c,v 1.17 1999/04/22 10:07:42 davem Exp $
+ *	$Id: ip6_output.c,v 1.17.2.1 2000/09/13 01:27:53 davem Exp $
  *
  *	Based on linux/net/ipv4/ip_output.c
  *
diff -urN linux-2.2.18-pre9/net/ipv6/reassembly.c linux/net/ipv6/reassembly.c
--- linux-2.2.18-pre9/net/ipv6/reassembly.c	Mon Dec  3 20:26:40 2001
+++ linux/net/ipv6/reassembly.c	Mon Dec  3 20:27:12 2001
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: reassembly.c,v 1.11 1998/08/26 12:05:16 davem Exp $
+ *	$Id: reassembly.c,v 1.11.2.1 2000/09/13 00:49:39 davem Exp $
  *
  *	Based on: net/ipv4/ip_fragment.c
  *
diff -urN linux-2.2.18-pre9/net/netsyms.c linux/net/netsyms.c
--- linux-2.2.18-pre9/net/netsyms.c	Wed Jun  7 14:26:44 2000
+++ linux/net/netsyms.c	Mon Dec  3 20:27:12 2001
@@ -33,6 +33,10 @@
 #include <net/br.h>
 #endif
 
+#ifdef CONFIG_NET_DIVERT
+#include <net/divert.h>
+#endif /* CONFIG_NET_DIVERT */
+
 #ifdef CONFIG_INET
 #include <linux/ip.h>
 #include <net/protocol.h>
@@ -224,6 +228,12 @@
 #ifdef CONFIG_BRIDGE 
 EXPORT_SYMBOL(br_ioctl);
 #endif
+
+#ifdef CONFIG_NET_DIVERT
+EXPORT_SYMBOL(alloc_divert_blk);
+EXPORT_SYMBOL(free_divert_blk);
+EXPORT_SYMBOL(divert_ioctl);
+#endif /* CONFIG_NET_DIVERT */
 
 #ifdef CONFIG_INET
 /* Internet layer registration */
diff -urN linux-2.2.18-pre9/net/packet/af_packet.c linux/net/packet/af_packet.c
--- linux-2.2.18-pre9/net/packet/af_packet.c	Wed May  3 17:16:54 2000
+++ linux/net/packet/af_packet.c	Mon Dec  3 20:27:12 2001
@@ -5,7 +5,7 @@
  *
  *		PACKET - implements raw packet sockets.
  *
- * Version:	$Id: af_packet.c,v 1.19.2.1 1999/12/04 05:45:02 davem Exp $
+ * Version:	$Id: af_packet.c,v 1.19.2.2 2000/09/20 01:47:40 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -72,6 +72,10 @@
 #include <net/br.h>
 #endif
 
+#ifdef CONFIG_NET_DIVERT
+#include <net/divert.h>
+#endif /* CONFIG_NET_DIVERT */
+
 #ifdef CONFIG_DLCI
 extern int dlci_ioctl(unsigned int, void*);
 #endif
@@ -1132,6 +1136,14 @@
 #else
 			return -ENOPKG;
 #endif						
+			
+		case SIOCGIFDIVERT:
+		case SIOCSIFDIVERT:
+#ifdef CONFIG_NET_DIVERT
+			return(divert_ioctl(cmd, (struct divert_cf *) arg));
+#else
+			return -ENOPKG;
+#endif /* CONFIG_NET_DIVERT */
 			
 #ifdef CONFIG_INET
 		case SIOCADDRT:
diff -urN linux-2.2.18-pre9/net/socket.c linux/net/socket.c
--- linux-2.2.18-pre9/net/socket.c	Mon Dec  3 20:26:40 2001
+++ linux/net/socket.c	Mon Dec  3 20:27:12 2001
@@ -579,7 +579,7 @@
 	 *	Check protocol is in range
 	 */
 	if(family<0||family>=NPROTO)
-		return -EINVAL;
+		return -EAFNOSUPPORT;
 		
 #if defined(CONFIG_KMOD) && defined(CONFIG_NET)
 	/* Attempt to load a protocol module if the find failed. 
diff -urN linux-2.2.18-pre9/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
--- linux-2.2.18-pre9/net/sunrpc/clnt.c	Mon Dec  3 20:26:40 2001
+++ linux/net/sunrpc/clnt.c	Mon Dec  3 20:27:12 2001
@@ -824,6 +824,7 @@
 		case RPC_AUTH_TOOWEAK:
 			printk(KERN_NOTICE "call_verify: server requires stronger "
 			       "authentication.\n");
+			break;
 		default:
 			printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
 			error = -EIO;
